9
0
Fork 0

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.
This commit is contained in:
Holger Hans Peter Freyther 2011-09-15 19:30:20 +02:00
parent 588754c7d3
commit b1dfc462df
9 changed files with 237 additions and 4 deletions

View File

@ -50,4 +50,5 @@ AC_OUTPUT(
tests/mtp/Makefile
tests/patching/Makefile
tests/isup/Makefile
tests/mgcp/Makefile
Makefile)

View File

@ -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

9
include/mgcp_patch.h Normal file
View File

@ -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

View File

@ -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

111
src/mgcp_patch.c Normal file
View File

@ -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;
}

View File

@ -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);

View File

@ -1 +1 @@
SUBDIRS = mtp patching isup
SUBDIRS = mtp patching isup mgcp

6
tests/mgcp/Makefile.am Normal file
View File

@ -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)

View File

@ -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;
}