aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_nat.h10
-rw-r--r--openbsc/src/Makefile.am3
-rw-r--r--openbsc/src/nat/bsc_mgcp_utils.c66
-rw-r--r--openbsc/src/nat/bsc_nat.c12
-rw-r--r--openbsc/src/nat/bsc_nat_utils.c1
-rw-r--r--openbsc/tests/bsc-nat/Makefile.am1
-rw-r--r--openbsc/tests/bsc-nat/bsc_data.c7
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c38
8 files changed, 134 insertions, 4 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index bdea43492..638791a8b 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -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
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 615758bed..b552d2f83 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -53,5 +53,6 @@ bsc_mgcp_LDADD = libvty.a
ipaccess_proxy_SOURCES = ipaccess/ipaccess-proxy.c debug.c
bsc_nat_SOURCES = nat/bsc_nat.c nat/bsc_filter.c nat/bsc_sccp.c \
- nat/bsc_nat_utils.c nat/bsc_nat_vty.c bsc_msc.c bssap.c
+ nat/bsc_nat_utils.c nat/bsc_nat_vty.c nat/bsc_mgcp_utils.c \
+ bsc_msc.c bssap.c
bsc_nat_LDADD = libvty.a libbsc.a libsccp.a
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
new file mode 100644
index 000000000..55dad380a
--- /dev/null
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -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;
+}
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index 4ad6b1abf..4a25dc39c 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -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 */
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index 08e9e8f8b..dc6cfec5c 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -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);
}
diff --git a/openbsc/tests/bsc-nat/Makefile.am b/openbsc/tests/bsc-nat/Makefile.am
index 7011fbd45..80fb0046c 100644
--- a/openbsc/tests/bsc-nat/Makefile.am
+++ b/openbsc/tests/bsc-nat/Makefile.am
@@ -9,6 +9,7 @@ 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)
diff --git a/openbsc/tests/bsc-nat/bsc_data.c b/openbsc/tests/bsc-nat/bsc_data.c
index b73aff118..ca170e2ac 100644
--- a/openbsc/tests/bsc-nat/bsc_data.c
+++ b/openbsc/tests/bsc-nat/bsc_data.c
@@ -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 };
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 3a1096001..70e98d721 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -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;
}