aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-09-15 19:30:20 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-09-15 19:30:20 +0200
commitb1dfc462dfa308d62b939847dbee2218c3a25fc1 (patch)
tree45e37d40b8cb870873a66586217e04ca7d0e84fa
parent588754c7d391482de6b903e3a80a0df103d314d8 (diff)
cellmgr: Patch the MGCP messages and replace the domain name
Replace the domain name with a new name domain that can be configured via the VTY interface.
-rw-r--r--configure.ac1
-rw-r--r--include/Makefile.am3
-rw-r--r--include/mgcp_patch.h9
-rw-r--r--src/Makefile.am4
-rw-r--r--src/mgcp_patch.c111
-rw-r--r--src/msc_conn.c2
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/mgcp/Makefile.am6
-rw-r--r--tests/mgcp/mgcp_patch_test.c103
9 files changed, 237 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index de0b1ba..5bc39b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,4 +50,5 @@ AC_OUTPUT(
tests/mtp/Makefile
tests/patching/Makefile
tests/isup/Makefile
+ tests/mgcp/Makefile
Makefile)
diff --git a/include/Makefile.am b/include/Makefile.am
index a4cdfb3..acaf137 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,6 +1,7 @@
noinst_HEADERS = mtp_level3.h mtp_data.h ipaccess.h thread.h mtp_pcap.h \
mgcp_ss7.h bss_patch.h bssap_sccp.h bsc_data.h udp_input.h \
snmp_mtp.h cellmgr_debug.h bsc_sccp.h bsc_ussd.h sctp_m2ua.h \
- isup_types.h counter.h msc_connection.h ss7_application.h
+ isup_types.h counter.h msc_connection.h ss7_application.h \
+ mgcp_patch.h
SUBDIRS = mgcp
diff --git a/include/mgcp_patch.h b/include/mgcp_patch.h
new file mode 100644
index 0000000..5b1e5dc
--- /dev/null
+++ b/include/mgcp_patch.h
@@ -0,0 +1,9 @@
+#ifndef MGCP_PATCH_H
+#define MGCP_PATCH_H
+
+#include <osmocom/core/msgb.h>
+
+struct ss7_application;
+struct msgb *mgcp_patch(struct ss7_application *app, struct msgb *msg);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 4d68f30..5684a8a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,7 +14,7 @@ cellmgr_ng_SOURCES = main.c mtp_layer3.c thread.c input/ipaccess.c pcap.c \
bss_patch.c bssap_sccp.c bsc_sccp.c bsc_ussd.c links.c \
msc_conn.c link_udp.c snmp_mtp.c debug.c isup.c \
mtp_link.c counter.c sccp_state.c bsc.c ss7_application.c \
- vty_interface_legacy.c vty_interface_cmds.c
+ vty_interface_legacy.c vty_interface_cmds.c mgcp_patch.c
cellmgr_ng_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \
$(LIBOSMOSCCP_LIBS) $(NEXUSWARE_C7_LIBS) \
-lpthread -lnetsnmp -lcrypto
@@ -23,7 +23,7 @@ osmo_stp_SOURCES = main_stp.c mtp_layer3.c thread.c pcap.c link_udp.c snmp_mtp.c
debug.c links.c isup.c sctp_m2ua.c msc_conn.c sccp_state.c \
bss_patch.c bssap_sccp.c bsc_sccp.c bsc_ussd.c input/ipaccess.c \
mtp_link.c counter.c bsc.c ss7_application.c \
- vty_interface.c vty_interface_cmds.c
+ vty_interface.c vty_interface_cmds.c mgcp_patch.c
osmo_stp_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \
$(LIBOSMOSCCP_LIBS) $(NEXUSWARE_C7_LIBS) \
-lpthread -lnetsnmp -lcrypto -lm2ua -lsctp
diff --git a/src/mgcp_patch.c b/src/mgcp_patch.c
new file mode 100644
index 0000000..f4a8579
--- /dev/null
+++ b/src/mgcp_patch.c
@@ -0,0 +1,111 @@
+/* MGCP message patching */
+/*
+ * (C) 2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2011 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 Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <mgcp_patch.h>
+#include <cellmgr_debug.h>
+#include <ss7_application.h>
+#include <string.h>
+
+#include <osmocom/gsm/tlv.h>
+
+
+struct msgb *mgcp_patch(struct ss7_application *app, struct msgb *msg)
+{
+ char *token, *remaining;
+ struct msgb *out;
+ int len, out_len, state, i;
+
+ if (!app->mgcp_domain_name)
+ return msg;
+
+ if (msgb_tailroom(msg) <= strlen(app->mgcp_domain_name)) {
+ LOGP(DMGCP, LOGL_ERROR, "Not enough space to add a zero line.\n");
+ return msg;
+ }
+
+ msg->l2h[msgb_l2len(msg)] = '\0';
+
+ /**
+ * We now need to rewrite the message, but actually only the first
+ * line and the rest can be copied.
+ */
+ out = msgb_alloc_headroom(4096, 128, "MGCP Patch Copy");
+ if (!out) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to create the MSGB copy.\n");
+ return NULL;
+ }
+
+
+ remaining = (char *) msg->l2h;
+ token = strsep(&remaining, "\n");
+ if (!token) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to split the MGCP.\n");
+ msgb_free(out);
+ return msg;
+ }
+
+ len = strlen(token);
+ out->l2h = msgb_put(out, 0);
+
+ /*
+ * State machine for copying and modifying the MGCP line, first find
+ * half of the endpoint, put ours, copy the rest of the line
+ */
+ state = 0;
+ for (i = 0; i < len; ++i) {
+ switch (state) {
+ case 2:
+ if (token[i] == '@')
+ state += 1;
+ msgb_v_put(out, token[i]);
+ break;
+ case 3:
+ /* copy the new name */
+ out->l3h = msgb_put(out, strlen(app->mgcp_domain_name));
+ memcpy(out->l3h, app->mgcp_domain_name, msgb_l3len(out));
+
+ /* skip everything to the next whitespace */
+ for (; i < len; ++i) {
+ if (token[i] == ' ') {
+ break;
+ }
+ }
+
+ for (; i < len; ++i)
+ msgb_v_put(out, token[i]);
+ msgb_v_put(out, '\n');
+ break;
+ default:
+ if (token[i] == ' ')
+ state += 1;
+ msgb_v_put(out, token[i]);
+ break;
+ }
+ }
+
+ /* append the rest */
+ out_len = msgb_l2len(msg) - len - 1;
+ out->l3h = msgb_put(out, out_len);
+ memcpy(out->l3h, &msg->l2h[len + 1], out_len);
+
+ msgb_free(msg);
+ return out;
+}
+
diff --git a/src/msc_conn.c b/src/msc_conn.c
index 551a781..0e61dd3 100644
--- a/src/msc_conn.c
+++ b/src/msc_conn.c
@@ -27,6 +27,7 @@
#include <mtp_data.h>
#include <cellmgr_debug.h>
#include <ss7_application.h>
+#include <mgcp_patch.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gsm/tlv.h>
@@ -158,6 +159,7 @@ static int ipaccess_a_fd_cb(struct osmo_fd *bfd)
} else if (hh->proto == IPAC_PROTO_SCCP) {
msc_dispatch_sccp(fw, msg);
} else if (hh->proto == NAT_MUX) {
+ msg = mgcp_patch(fw->app, msg);
mgcp_forward(fw, msg->l2h, msgb_l2len(msg));
} else {
LOGP(DMSC, LOGL_ERROR, "Unknown IPA proto 0x%x\n", hh->proto);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6ffa86d..d7cebd8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS = mtp patching isup
+SUBDIRS = mtp patching isup mgcp
diff --git a/tests/mgcp/Makefile.am b/tests/mgcp/Makefile.am
new file mode 100644
index 0000000..2e8db48
--- /dev/null
+++ b/tests/mgcp/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS)
+noinst_PROGRAMS = mgcp_patch_test
+
+mgcp_patch_test_SOURCES = mgcp_patch_test.c $(top_srcdir)/src/mgcp_patch.c
+mgcp_patch_test_LDADD = $(LIBOSMOCORE_LIBS)
diff --git a/tests/mgcp/mgcp_patch_test.c b/tests/mgcp/mgcp_patch_test.c
new file mode 100644
index 0000000..335cfcf
--- /dev/null
+++ b/tests/mgcp/mgcp_patch_test.c
@@ -0,0 +1,103 @@
+/*
+ * (C) 2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2011 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 Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <mgcp_patch.h>
+#include <ss7_application.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static const char mgcp_in[] =
+ "MDCX 23213 14@mgw MGCP 1.0\r\n"
+ "C: 4a84ad5d25f\r\n"
+ "I: %d\r\n"
+ "L: p:20, a:GSM-EFR, nt:IN\r\n"
+ "M: recvonly\r\n\r\n"
+ "v=0\r\n"
+ "o=- 258696477 0 IN IP4 172.16.1.107\r\n"
+ "s=-\r\n"
+ "c=IN IP4 172.16.1.107\r\n"
+ "t=0 0\r\n"
+ "m=audio 6666 RTP/AVP 127\r\n"
+ "a=rtpmap:127 GSM-EFR/8000/1\r\n"
+ "a=ptime:20\r\n"
+ "a=recvonly\r\n"
+ "m=image 4402 udptl t38\r\n"
+ "a=T38FaxVersion:0\r\n"
+ "a=T38MaxBitRate:14400\r\n";
+
+static const char mgcp_out[] =
+ "MDCX 23213 14@foo2 MGCP 1.0\r\n"
+ "C: 4a84ad5d25f\r\n"
+ "I: %d\r\n"
+ "L: p:20, a:GSM-EFR, nt:IN\r\n"
+ "M: recvonly\r\n\r\n"
+ "v=0\r\n"
+ "o=- 258696477 0 IN IP4 172.16.1.107\r\n"
+ "s=-\r\n"
+ "c=IN IP4 172.16.1.107\r\n"
+ "t=0 0\r\n"
+ "m=audio 6666 RTP/AVP 127\r\n"
+ "a=rtpmap:127 GSM-EFR/8000/1\r\n"
+ "a=ptime:20\r\n"
+ "a=recvonly\r\n"
+ "m=image 4402 udptl t38\r\n"
+ "a=T38FaxVersion:0\r\n"
+ "a=T38MaxBitRate:14400\r\n";
+
+#define ASSERT(a, cmp, b, text) \
+ if (!((a) cmp (b))) { \
+ fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, text); \
+ abort(); \
+ }
+
+static void test_endp_name_rewriting()
+{
+ struct ss7_application app;
+ memset(&app, 0, sizeof(app));
+
+ app.mgcp_domain_name = "foo2";
+
+ /* prepare */
+ struct msgb *msg = msgb_alloc_headroom(4096, 128, "test");
+ msg->l2h = msgb_put(msg, strlen(mgcp_in));
+ memcpy(msg->l2h, mgcp_in, msgb_l2len(msg));
+
+ /* patch it now */
+ struct msgb *msg_out = mgcp_patch(&app, msg);
+ msg_out->l2h[msgb_l2len(msg_out)] = '\0';
+#ifdef DEBUG
+ printf("Want : '%s'\n", mgcp_out);
+ printf("Outpu: '%s'\n", (const char *) msg_out->l2h);
+ printf("%s\n", osmo_hexdump(mgcp_out, strlen(mgcp_out)));
+ printf("%s\n", osmo_hexdump(msg_out->l2h, msgb_l2len(msg_out)));
+#endif
+ ASSERT(msg_out, !=, msg, "msg should not be the same");
+
+ ASSERT(msgb_l2len(msg_out), ==, strlen(mgcp_out), "Output size wrong");
+ ASSERT(strcmp((const char *)msg_out->l2h, mgcp_out), ==, 0, "Text don't match");
+}
+
+int main(int argc, char **argv)
+{
+ test_endp_name_rewriting();
+
+ return 0;
+}