nat: Look at the assignment command and remember on which timeslot the data is

This information will be needed when we are trying to forward
MGCP connections to and from the BSC through the IPA protocol.
This commit is contained in:
Holger Hans Peter Freyther 2010-06-15 18:49:53 +08:00
parent 23fe7be1ca
commit 465313e48c
7 changed files with 132 additions and 3 deletions

View File

@ -103,6 +103,10 @@ struct sccp_connections {
struct sccp_source_reference real_ref;
struct sccp_source_reference patched_ref;
struct sccp_source_reference remote_ref;
/* GSM audio handling. That is 32 * multiplex + ts */
int msc_timeslot;
int bsc_timeslot;
};
/**
@ -162,4 +166,10 @@ void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bs
struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
/**
* MGCP/Audio handling
*/
int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_clear(struct sccp_connections *);
#endif

View File

@ -0,0 +1,66 @@
/*
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <openbsc/bsc_nat.h>
#include <openbsc/gsm_data.h>
#include <openbsc/bssap.h>
#include <openbsc/debug.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
{
struct tlv_parsed tp;
u_int16_t cic;
u_int8_t timeslot;
u_int8_t multiplex;
if (!msg->l3h) {
LOGP(DNAT, LOGL_ERROR, "Assignment message should have l3h pointer.\n");
return -1;
}
if (msgb_l3len(msg) < 3) {
LOGP(DNAT, LOGL_ERROR, "Assignment message has not enough space for GSM0808.\n");
return -1;
}
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
LOGP(DNAT, LOGL_ERROR, "Circuit identity code not found in assignment message.\n");
return -1;
}
cic = ntohs(*(u_int16_t *)TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
timeslot = cic & 0x1f;
multiplex = (cic & ~0x1f) >> 5;
con->msc_timeslot = (32 * multiplex) + timeslot;
con->bsc_timeslot = con->msc_timeslot;
return 0;
}
void bsc_mgcp_clear(struct sccp_connections *con)
{
con->msc_timeslot = -1;
con->bsc_timeslot = -1;
}

View File

@ -193,6 +193,13 @@ static int forward_sccp_to_bts(struct msgb *msg)
case SCCP_MSG_TYPE_CREF:
case SCCP_MSG_TYPE_DT1:
con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
if (parsed->gsm_type == BSS_MAP_MSG_ASSIGMENT_RQST) {
if (con) {
if (bsc_mgcp_assign(con, msg) != 0)
LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
} else
LOGP(DNAT, LOGL_ERROR, "Assignment command but no BSC.\n");
}
break;
case SCCP_MSG_TYPE_CC:
con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
@ -401,7 +408,10 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
break;
case SCCP_MSG_TYPE_RLC:
con = patch_sccp_src_ref_to_msc(msg, parsed, nat);
remove_sccp_src_ref(bsc, msg, parsed);
if (con) {
remove_sccp_src_ref(bsc, msg, parsed);
bsc_mgcp_clear(con);
}
break;
case SCCP_MSG_TYPE_UDT:
/* simply forward everything */

View File

@ -79,6 +79,7 @@ void sccp_connection_destroy(struct sccp_connections *conn)
LOGP(DNAT, LOGL_DEBUG, "Destroy 0x%x <-> 0x%x mapping for con %p\n",
sccp_src_ref_to_int(&conn->real_ref),
sccp_src_ref_to_int(&conn->patched_ref), conn->bsc);
bsc_mgcp_clear(conn);
llist_del(&conn->list_entry);
talloc_free(conn);
}

View File

@ -9,5 +9,6 @@ bsc_nat_test_SOURCES = bsc_nat_test.c \
$(top_srcdir)/src/nat/bsc_filter.c \
$(top_srcdir)/src/nat/bsc_sccp.c \
$(top_srcdir)/src/nat/bsc_nat_utils.c \
$(top_srcdir)/src/nat/bsc_mgcp_utils.c \
$(top_srcdir)/src/bssap.c
bsc_nat_test_LDADD = $(top_builddir)/src/libbsc.a $(top_builddir)/src/libsccp.a $(LIBOSMOCORE_LIBS)

View File

@ -80,3 +80,10 @@ static const u_int8_t paging_by_lac_cmd[] = {
0x10, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10, 0x02,
0x01, 0x50, 0x02, 0x30, 0x1a, 0x03, 0x05, 0x20,
0x15 };
/* an assignment command */
static const u_int8_t ass_cmd[] = {
0x00, 0x12, 0xfd, 0x06,
0x00, 0x00, 0x49, 0x00, 0x01, 0x0b, 0x00, 0x09,
0x01, 0x0b, 0x03, 0x01, 0x0a, 0x11, 0x01, 0x00,
0x15 };

View File

@ -335,6 +335,41 @@ static void test_paging(void)
talloc_free(parsed);
}
static void test_mgcp(void)
{
struct sccp_connections con;
struct bsc_nat_parsed *parsed;
struct msgb *msg;
fprintf(stderr, "Testing MGCP.\n");
memset(&con, 0, sizeof(con));
msg = msgb_alloc(4096, "foo");
copy_to_msg(msg, ass_cmd, sizeof(ass_cmd));
parsed = bsc_nat_parse(msg);
if (bsc_mgcp_assign(&con, msg) != 0) {
fprintf(stderr, "Failed to handle assignment.\n");
abort();
}
if (con.msc_timeslot != 21) {
fprintf(stderr, "Timeslot should be 21.\n");
abort();
}
if (con.bsc_timeslot != 21) {
fprintf(stderr, "Assigned timeslot should have been 21.\n");
abort();
}
talloc_free(parsed);
bsc_mgcp_clear(&con);
if (con.bsc_timeslot != -1 || con.msc_timeslot != -1) {
fprintf(stderr, "Clearing should remove the mapping.\n");
abort();
}
}
int main(int argc, char **argv)
{
struct debug_target *stderr_target;
@ -345,9 +380,8 @@ int main(int argc, char **argv)
test_filter();
test_contrack();
debug_set_log_level(stderr_target, 1);
test_paging();
test_mgcp();
return 0;
}