aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-07-27 21:00:21 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-07-27 21:01:18 +0800
commitf1bb05fbef79fc4f112f3a9604d2f8e03d0aa652 (patch)
treec94511fea882b6b9e15765af713353a728cf861b
parent0c4f7ecabc439bdb9d3d8494be55c0dfba92bf8f (diff)
nat: Remove the nat code from the On-Waves branch... new code is in master
-rw-r--r--openbsc/configure.in1
-rw-r--r--openbsc/include/vty/command.h2
-rw-r--r--openbsc/src/Makefile.am7
-rw-r--r--openbsc/src/nat/bsc_filter.c216
-rw-r--r--openbsc/src/nat/bsc_mgcp_utils.c559
-rw-r--r--openbsc/src/nat/bsc_nat.c1148
-rw-r--r--openbsc/src/nat/bsc_nat_utils.c491
-rw-r--r--openbsc/src/nat/bsc_nat_vty.c565
-rw-r--r--openbsc/src/nat/bsc_sccp.c237
-rw-r--r--openbsc/src/vty/command.c16
-rw-r--r--openbsc/tests/Makefile.am2
-rw-r--r--openbsc/tests/bsc-nat/Makefile.am17
-rw-r--r--openbsc/tests/bsc-nat/bsc_data.c154
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c728
14 files changed, 2 insertions, 4141 deletions
diff --git a/openbsc/configure.in b/openbsc/configure.in
index 14df0c751..a59e67cd4 100644
--- a/openbsc/configure.in
+++ b/openbsc/configure.in
@@ -51,5 +51,4 @@ AC_OUTPUT(
tests/db/Makefile
tests/channel/Makefile
tests/sccp/Makefile
- tests/bsc-nat/Makefile
Makefile)
diff --git a/openbsc/include/vty/command.h b/openbsc/include/vty/command.h
index 31dd7f3b2..03b071f70 100644
--- a/openbsc/include/vty/command.h
+++ b/openbsc/include/vty/command.h
@@ -107,8 +107,6 @@ enum node_type {
TS_NODE,
SUBSCR_NODE,
MGCP_NODE,
- NAT_NODE,
- BSC_NODE,
};
/* Node which has some commands and prompt string and configuration
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 44b0027ec..d4c37b8c1 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -4,7 +4,7 @@ AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \
isdnsync bsc_mgcp ipaccess-proxy \
- bsc_msc_ip bsc_nat
+ bsc_msc_ip
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a
noinst_HEADERS = vty/cardshell.h
@@ -52,8 +52,3 @@ 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 nat/bsc_mgcp_utils.c \
- mgcp/mgcp_protocol.c mgcp/mgcp_network.c mgcp/mgcp_vty.c \
- bsc_msc.c bssap.c
-bsc_nat_LDADD = libvty.a libbsc.a libsccp.a -lrt
diff --git a/openbsc/src/nat/bsc_filter.c b/openbsc/src/nat/bsc_filter.c
deleted file mode 100644
index 891d4555d..000000000
--- a/openbsc/src/nat/bsc_filter.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* BSC Multiplexer/NAT */
-
-/*
- * (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/bssap.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/debug.h>
-
-#include <osmocore/talloc.h>
-
-#include <sccp/sccp.h>
-
-/*
- * The idea is to have a simple struct describing a IPA packet with
- * SCCP SSN and the GSM 08.08 payload and decide. We will both have
- * a white and a blacklist of packets we want to handle.
- *
- * TODO: Implement a "NOT" in the filter language.
- */
-
-#define ALLOW_ANY -1
-
-#define FILTER_TO_BSC 1
-#define FILTER_TO_MSC 2
-#define FILTER_TO_BOTH 3
-
-
-struct bsc_pkt_filter {
- int ipa_proto;
- int dest_ssn;
- int bssap;
- int gsm;
- int filter_dir;
-};
-
-static struct bsc_pkt_filter black_list[] = {
- /* filter reset messages to the MSC */
- { IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET, FILTER_TO_MSC },
-
- /* filter reset ack messages to the BSC */
- { IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET_ACKNOWLEDGE, FILTER_TO_BSC },
-
- /* filter ip access */
- { IPAC_PROTO_IPACCESS, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_MSC },
-};
-
-static struct bsc_pkt_filter white_list[] = {
- /* allow IPAC_PROTO_SCCP messages to both sides */
- { IPAC_PROTO_SCCP, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
-
- /* allow MGCP messages to both sides */
- { NAT_IPAC_PROTO_MGCP, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
-};
-
-struct bsc_nat_parsed* bsc_nat_parse(struct msgb *msg)
-{
- struct sccp_parse_result result;
- struct bsc_nat_parsed *parsed;
- struct ipaccess_head *hh;
-
- /* quick fail */
- if (msg->len < 4)
- return NULL;
-
- parsed = talloc_zero(msg, struct bsc_nat_parsed);
- if (!parsed)
- return NULL;
-
- /* more init */
- parsed->ipa_proto = parsed->called_ssn = parsed->calling_ssn = -1;
- parsed->sccp_type = parsed->bssap = parsed->gsm_type = -1;
-
- /* start parsing */
- hh = (struct ipaccess_head *) msg->data;
- parsed->ipa_proto = hh->proto;
-
- msg->l2h = &hh->data[0];
-
- /* do a size check on the input */
- if (ntohs(hh->len) != msgb_l2len(msg)) {
- LOGP(DINP, LOGL_ERROR, "Wrong input length?\n");
- talloc_free(parsed);
- return NULL;
- }
-
- /* analyze sccp down here */
- if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
- memset(&result, 0, sizeof(result));
- if (sccp_parse_header(msg, &result) != 0) {
- talloc_free(parsed);
- return 0;
- }
-
- if (msg->l3h && msgb_l3len(msg) < 3) {
- LOGP(DNAT, LOGL_ERROR, "Not enough space or GSM payload\n");
- talloc_free(parsed);
- return 0;
- }
-
- parsed->sccp_type = sccp_determine_msg_type(msg);
- parsed->src_local_ref = result.source_local_reference;
- parsed->dest_local_ref = result.destination_local_reference;
- parsed->called_ssn = result.called.ssn;
- parsed->calling_ssn = result.calling.ssn;
-
- /* in case of connection confirm we have no payload */
- if (msg->l3h) {
- parsed->bssap = msg->l3h[0];
- parsed->gsm_type = msg->l3h[2];
- }
- }
-
- return parsed;
-}
-
-int bsc_nat_filter_ipa(int dir, struct msgb *msg, struct bsc_nat_parsed *parsed)
-{
- int i;
-
- /* go through the blacklist now */
- for (i = 0; i < ARRAY_SIZE(black_list); ++i) {
- /* ignore the rule? */
- if (black_list[i].filter_dir != FILTER_TO_BOTH
- && black_list[i].filter_dir != dir)
- continue;
-
- /* the proto is not blacklisted */
- if (black_list[i].ipa_proto != ALLOW_ANY
- && black_list[i].ipa_proto != parsed->ipa_proto)
- continue;
-
- if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
- /* the SSN is not blacklisted */
- if (black_list[i].dest_ssn != ALLOW_ANY
- && black_list[i].dest_ssn != parsed->called_ssn)
- continue;
-
- /* bssap */
- if (black_list[i].bssap != ALLOW_ANY
- && black_list[i].bssap != parsed->bssap)
- continue;
-
- /* gsm */
- if (black_list[i].gsm != ALLOW_ANY
- && black_list[i].gsm != parsed->gsm_type)
- continue;
-
- /* blacklisted */
- LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
- return 1;
- } else {
- /* blacklisted, we have no content sniffing yet */
- LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
- return 1;
- }
- }
-
- /* go through the whitelust now */
- for (i = 0; i < ARRAY_SIZE(white_list); ++i) {
- /* ignore the rule? */
- if (white_list[i].filter_dir != FILTER_TO_BOTH
- && white_list[i].filter_dir != dir)
- continue;
-
- /* the proto is not whitelisted */
- if (white_list[i].ipa_proto != ALLOW_ANY
- && white_list[i].ipa_proto != parsed->ipa_proto)
- continue;
-
- if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
- /* the SSN is not whitelisted */
- if (white_list[i].dest_ssn != ALLOW_ANY
- && white_list[i].dest_ssn != parsed->called_ssn)
- continue;
-
- /* bssap */
- if (white_list[i].bssap != ALLOW_ANY
- && white_list[i].bssap != parsed->bssap)
- continue;
-
- /* gsm */
- if (white_list[i].gsm != ALLOW_ANY
- && white_list[i].gsm != parsed->gsm_type)
- continue;
-
- /* whitelisted */
- LOGP(DNAT, LOGL_INFO, "Whitelisted with rule %d\n", i);
- return 0;
- } else {
- /* whitelisted */
- return 0;
- }
- }
-
- return 1;
-}
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
deleted file mode 100644
index 5d77c2bd9..000000000
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * (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 <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-
-#include <sccp/sccp.h>
-
-#include <osmocore/talloc.h>
-#include <osmocore/gsm0808.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <unistd.h>
-
-int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
-{
- struct sccp_connections *mcon;
- struct tlv_parsed tp;
- u_int16_t cic;
- u_int8_t timeslot;
- u_int8_t multiplex;
- int combined;
-
- 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;
-
-
- combined = (32 * multiplex) + timeslot;
-
- /* find stale connections using that endpoint */
- llist_for_each_entry(mcon, &con->bsc->nat->sccp_connections, list_entry) {
- if (mcon->msc_timeslot == combined) {
- LOGP(DNAT, LOGL_ERROR,
- "Timeslot %d was assigned to 0x%x and now 0x%x\n",
- combined,
- sccp_src_ref_to_int(&mcon->patched_ref),
- sccp_src_ref_to_int(&con->patched_ref));
- bsc_mgcp_dlcx(mcon);
- }
- }
-
- con->msc_timeslot = combined;
- con->bsc_timeslot = con->msc_timeslot;
- return 0;
-}
-
-static void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
-{
- if (nat->bsc_endpoints[i].transaction_id) {
- talloc_free(nat->bsc_endpoints[i].transaction_id);
- nat->bsc_endpoints[i].transaction_id = NULL;
- }
-
- nat->bsc_endpoints[i].bsc = NULL;
-}
-
-void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
-{
- int i;
-
- for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i){
- bsc_mgcp_free_endpoint(nat, i);
- mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
- }
-}
-
-/* send a MDCX where we do not want a response */
-static void bsc_mgcp_send_mdcx(struct bsc_connection *bsc, struct mgcp_endpoint *endp)
-{
- char buf[2096];
- int len;
-
- len = snprintf(buf, sizeof(buf),
- "MDCX 23 %x@mgw MGCP 1.0\r\n"
- "Z: noanswer\r\n"
- "\r\n"
- "c=IN IP4 %s\r\n"
- "m=audio %d RTP/AVP 255\r\n",
- ENDPOINT_NUMBER(endp),
- bsc->nat->mgcp_cfg->source_addr,
- endp->rtp_port);
- if (len < 0) {
- LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
- return;
- }
-}
-
-static void bsc_mgcp_send_dlcx(struct bsc_connection *bsc, int endpoint)
-{
- char buf[2096];
- int len;
-
- len = snprintf(buf, sizeof(buf),
- "DLCX 23 %x@mgw MGCP 1.0\r\n"
- "Z: noanswer\r\n", endpoint);
- if (len < 0) {
- LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
- return;
- }
-
- bsc_write_mgcp(bsc, (u_int8_t *) buf, len);
-}
-
-void bsc_mgcp_init(struct sccp_connections *con)
-{
- con->msc_timeslot = -1;
- con->bsc_timeslot = -1;
- con->crcx = 0;
-}
-
-void bsc_mgcp_dlcx(struct sccp_connections *con)
-{
- /* send a DLCX down the stream */
- if (con->bsc_timeslot != -1 && con->crcx) {
- int endp = mgcp_timeslot_to_endpoint(0, con->msc_timeslot);
- bsc_mgcp_send_dlcx(con->bsc, endp);
- bsc_mgcp_free_endpoint(con->bsc->nat, endp);
- }
-
- bsc_mgcp_init(con);
-}
-
-
-struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
-{
- struct sccp_connections *con = NULL;
- struct sccp_connections *sccp;
-
- llist_for_each_entry(sccp, &nat->sccp_connections, list_entry) {
- if (sccp->msc_timeslot == -1)
- continue;
- if (mgcp_timeslot_to_endpoint(0, sccp->msc_timeslot) != endpoint)
- continue;
-
- con = sccp;
- }
-
- if (con)
- return con;
-
- LOGP(DMGCP, LOGL_ERROR, "Failed to find the connection.\n");
- return NULL;
-}
-
-int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const char *transaction_id)
-{
- struct bsc_nat *nat;
- struct bsc_endpoint *bsc_endp;
- struct sccp_connections *sccp;
- struct mgcp_endpoint *mgcp_endp;
- struct msgb *bsc_msg;
-
- nat = cfg->data;
- bsc_endp = &nat->bsc_endpoints[endpoint];
- mgcp_endp = &nat->mgcp_cfg->endpoints[endpoint];
-
- if (bsc_endp->transaction_id) {
- LOGP(DMGCP, LOGL_ERROR, "Endpoint 0x%x had pending transaction: '%s'\n",
- endpoint, bsc_endp->transaction_id);
- talloc_free(bsc_endp->transaction_id);
- bsc_endp->transaction_id = NULL;
- }
- bsc_endp->bsc = NULL;
-
- sccp = bsc_mgcp_find_con(nat, endpoint);
-
- if (!sccp) {
- LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for change on endpoint: 0x%x state: %d\n", endpoint, state);
-
- switch (state) {
- case MGCP_ENDP_CRCX:
- return MGCP_POLICY_REJECT;
- break;
- case MGCP_ENDP_DLCX:
- return MGCP_POLICY_CONT;
- break;
- case MGCP_ENDP_MDCX:
- return MGCP_POLICY_CONT;
- break;
- default:
- LOGP(DMGCP, LOGL_FATAL, "Unhandled state: %d\n", state);
- return MGCP_POLICY_CONT;
- break;
- }
- }
-
- /* we need to generate a new and patched message */
- bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length,
- nat->mgcp_cfg->source_addr, mgcp_endp->rtp_port);
- if (!bsc_msg) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to patch the msg.\n");
- return MGCP_POLICY_CONT;
- }
-
-
- bsc_endp->transaction_id = talloc_strdup(nat, transaction_id);
- bsc_endp->bsc = sccp->bsc;
-
- /* we need to update some bits */
- if (state == MGCP_ENDP_CRCX) {
- struct sockaddr_in sock;
- socklen_t len = sizeof(sock);
- if (getpeername(sccp->bsc->write_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Can not get the peername...%d/%s\n",
- errno, strerror(errno));
- } else {
- mgcp_endp->bts = sock.sin_addr;
- }
-
- /* send the message and a fake MDCX for force sending of a dummy packet */
- sccp->crcx = 1;
- bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
- bsc_mgcp_send_mdcx(sccp->bsc, mgcp_endp);
- return MGCP_POLICY_DEFER;
- } else if (state == MGCP_ENDP_DLCX) {
- /* we will free the endpoint now and send a DLCX to the BSC */
- msgb_free(bsc_msg);
- bsc_mgcp_dlcx(sccp);
- return MGCP_POLICY_CONT;
- } else {
- bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
- return MGCP_POLICY_DEFER;
- }
-}
-
-/*
- * We have received a msg from the BSC. We will see if we know
- * this transaction and if it belongs to the BSC. Then we will
- * need to patch the content to point to the local network and we
- * need to update the I: that was assigned by the BSS.
- */
-void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
-{
- struct msgb *output;
- struct bsc_endpoint *bsc_endp = NULL;
- struct mgcp_endpoint *endp = NULL;
- int i, code;
- char transaction_id[60];
-
- /* Some assumption that our buffer is big enough.. and null terminate */
- if (msgb_l2len(msg) > 2000) {
- LOGP(DMGCP, LOGL_ERROR, "MGCP message too long.\n");
- return;
- }
-
- msg->l2h[msgb_l2len(msg)] = '\0';
-
- if (bsc_mgcp_parse_response((const char *) msg->l2h, &code, transaction_id) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to parse response code.\n");
- return;
- }
-
- for (i = 1; i < bsc->nat->mgcp_cfg->number_endpoints; ++i) {
- if (bsc->nat->bsc_endpoints[i].bsc != bsc)
- continue;
- /* no one listening? a bug? */
- if (!bsc->nat->bsc_endpoints[i].transaction_id)
- continue;
- if (strcmp(transaction_id, bsc->nat->bsc_endpoints[i].transaction_id) != 0)
- continue;
-
- endp = &bsc->nat->mgcp_cfg->endpoints[i];
- bsc_endp = &bsc->nat->bsc_endpoints[i];
- break;
- }
-
- if (!bsc_endp) {
- LOGP(DMGCP, LOGL_ERROR, "Could not find active endpoint: %s for msg: '%s'\n",
- transaction_id, (const char *) msg->l2h);
- return;
- }
-
- endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h);
-
- /* free some stuff */
- talloc_free(bsc_endp->transaction_id);
- bsc_endp->transaction_id = NULL;
-
- /*
- * rewrite the information. In case the endpoint was deleted
- * there should be nothing for us to rewrite so putting endp->rtp_port
- * with the value of 0 should be no problem.
- */
- output = bsc_mgcp_rewrite((char * ) msg->l2h, msgb_l2len(msg),
- bsc->nat->mgcp_cfg->source_addr, endp->rtp_port);
-
- if (!output) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n");
- return;
- }
-
- if (write_queue_enqueue(&bsc->nat->mgcp_queue, output) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
- msgb_free(output);
- }
-}
-
-int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60])
-{
- /* we want to parse two strings */
- return sscanf(str, "%3d %59s\n", code, transaction) != 2;
-}
-
-int bsc_mgcp_extract_ci(const char *str)
-{
- int ci;
- char *res = strstr(str, "I: ");
- if (!res)
- return CI_UNUSED;
-
- if (sscanf(res, "I: %d", &ci) != 1)
- return CI_UNUSED;
- return ci;
-}
-
-/* we need to replace some strings... */
-struct msgb *bsc_mgcp_rewrite(char *input, int length, const char *ip, int port)
-{
- static const char *ip_str = "c=IN IP4 ";
- static const char *aud_str = "m=audio ";
-
- char buf[128];
- char *running, *token;
- struct msgb *output;
-
- if (length > 4096 - 128) {
- LOGP(DMGCP, LOGL_ERROR, "Input is too long.\n");
- return NULL;
- }
-
- output = msgb_alloc_headroom(4096, 128, "MGCP rewritten");
- if (!output) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to allocate new MGCP msg.\n");
- return NULL;
- }
-
- running = input;
- output->l2h = output->data;
- for (token = strsep(&running, "\n"); running; token = strsep(&running, "\n")) {
- int len = strlen(token);
- int cr = len > 0 && token[len - 1] == '\r';
-
- if (strncmp(ip_str, token, (sizeof ip_str) - 1) == 0) {
- output->l3h = msgb_put(output, strlen(ip_str));
- memcpy(output->l3h, ip_str, strlen(ip_str));
- output->l3h = msgb_put(output, strlen(ip));
- memcpy(output->l3h, ip, strlen(ip));
-
- if (cr) {
- output->l3h = msgb_put(output, 2);
- output->l3h[0] = '\r';
- output->l3h[1] = '\n';
- } else {
- output->l3h = msgb_put(output, 1);
- output->l3h[0] = '\n';
- }
- } else if (strncmp(aud_str, token, (sizeof aud_str) - 1) == 0) {
- int payload;
- if (sscanf(token, "m=audio %*d RTP/AVP %d", &payload) != 1) {
- LOGP(DMGCP, LOGL_ERROR, "Could not parsed audio line.\n");
- msgb_free(output);
- return NULL;
- }
-
- snprintf(buf, sizeof(buf)-1, "m=audio %d RTP/AVP %d%s",
- port, payload, cr ? "\r\n" : "\n");
- buf[sizeof(buf)-1] = '\0';
-
- output->l3h = msgb_put(output, strlen(buf));
- memcpy(output->l3h, buf, strlen(buf));
- } else {
- output->l3h = msgb_put(output, len + 1);
- memcpy(output->l3h, token, len);
- output->l3h[len] = '\n';
- }
- }
-
- return output;
-}
-
-static int mgcp_do_read(struct bsc_fd *fd)
-{
- struct bsc_nat *nat;
- struct msgb *msg, *resp;
- int rc;
-
- nat = fd->data;
-
- rc = read(fd->fd, nat->mgcp_msg, sizeof(nat->mgcp_msg) - 1);
- if (rc <= 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to read errno: %d\n", errno);
- return -1;
- }
-
- nat->mgcp_msg[rc] = '\0';
- nat->mgcp_length = rc;
-
- msg = msgb_alloc(sizeof(nat->mgcp_msg), "MGCP GW Read");
- if (!msg) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to create buffer.\n");
- return -1;
- }
-
- msg->l2h = msgb_put(msg, rc);
- memcpy(msg->l2h, nat->mgcp_msg, msgb_l2len(msg));
- resp = mgcp_handle_message(nat->mgcp_cfg, msg);
- msgb_free(msg);
-
- /* we do have a direct answer... e.g. AUEP */
- if (resp) {
- if (write_queue_enqueue(&nat->mgcp_queue, resp) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to enqueue msg.\n");
- msgb_free(resp);
- }
- }
-
- return 0;
-}
-
-static int mgcp_do_write(struct bsc_fd *bfd, struct msgb *msg)
-{
- int rc;
-
- rc = write(bfd->fd, msg->data, msg->len);
-
- if (rc != msg->len) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to write msg to MGCP CallAgent.\n");
- return -1;
- }
-
- return rc;
-}
-
-int bsc_mgcp_nat_init(struct bsc_nat *nat)
-{
- int on;
- struct sockaddr_in addr;
-
- if (!nat->mgcp_cfg->call_agent_addr) {
- LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
- return -1;
- }
-
- if (nat->mgcp_cfg->bts_ip) {
- LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
- return -1;
- }
-
- nat->mgcp_queue.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (nat->mgcp_queue.bfd.fd < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to create MGCP socket. errno: %d\n", errno);
- return -1;
- }
-
- on = 1;
- setsockopt(nat->mgcp_queue.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
- addr.sin_family = AF_INET;
- addr.sin_port = htons(nat->mgcp_cfg->source_port);
- inet_aton(nat->mgcp_cfg->source_addr, &addr.sin_addr);
-
- if (bind(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to bind. errno: %d\n", errno);
- close(nat->mgcp_queue.bfd.fd);
- nat->mgcp_queue.bfd.fd = -1;
- return -1;
- }
-
- addr.sin_port = htons(2727);
- inet_aton(nat->mgcp_cfg->call_agent_addr, &addr.sin_addr);
- if (connect(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
- nat->mgcp_cfg->call_agent_addr, errno);
- close(nat->mgcp_queue.bfd.fd);
- nat->mgcp_queue.bfd.fd = -1;
- return -1;
- }
-
- write_queue_init(&nat->mgcp_queue, 10);
- nat->mgcp_queue.bfd.when = BSC_FD_READ;
- nat->mgcp_queue.bfd.data = nat;
- nat->mgcp_queue.read_cb = mgcp_do_read;
- nat->mgcp_queue.write_cb = mgcp_do_write;
-
- if (bsc_register_fd(&nat->mgcp_queue.bfd) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to register MGCP fd.\n");
- close(nat->mgcp_queue.bfd.fd);
- nat->mgcp_queue.bfd.fd = -1;
- return -1;
- }
-
- /* some more MGCP config handling */
- nat->mgcp_cfg->audio_payload = -1;
- nat->mgcp_cfg->data = nat;
- nat->mgcp_cfg->policy_cb = bsc_mgcp_policy_cb;
- nat->mgcp_cfg->force_realloc = 1;
- nat->mgcp_cfg->bts_ip = "";
- nat->bsc_endpoints = talloc_zero_array(nat,
- struct bsc_endpoint,
- nat->mgcp_cfg->number_endpoints + 1);
-
- return 0;
-}
-
-void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc)
-{
- int i;
- for (i = 1; i < bsc->nat->mgcp_cfg->number_endpoints; ++i) {
- struct bsc_endpoint *bsc_endp = &bsc->nat->bsc_endpoints[i];
-
- if (bsc_endp->bsc != bsc)
- continue;
-
- bsc_mgcp_free_endpoint(bsc->nat, i);
- mgcp_free_endp(&bsc->nat->mgcp_cfg->endpoints[i]);
- }
-}
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
deleted file mode 100644
index de24fd3f5..000000000
--- a/openbsc/src/nat/bsc_nat.c
+++ /dev/null
@@ -1,1148 +0,0 @@
-/* BSC Multiplexer/NAT */
-
-/*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
- * (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * 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 <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/bsc_msc.h>
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bssap.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/telnet_interface.h>
-
-#include <osmocore/talloc.h>
-#include <osmocore/gsm0808.h>
-
-#include <vty/vty.h>
-
-#include <sccp/sccp.h>
-
-#define SCCP_CLOSE_TIME 20
-#define SCCP_CLOSE_TIME_TIMEOUT 19
-
-struct log_target *stderr_target;
-static const char *config_file = "bsc-nat.cfg";
-static struct in_addr local_addr;
-static struct bsc_fd bsc_listen;
-static const char *msc_ip = NULL;
-static struct timer_list sccp_close;
-
-
-static struct bsc_nat *nat;
-static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length, int);
-static void msc_send_reset(struct bsc_msc_connection *con);
-
-struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num)
-{
- struct bsc_config *conf;
-
- llist_for_each_entry(conf, &nat->bsc_configs, entry)
- if (conf->nr == num)
- return conf;
-
- return NULL;
-}
-
-/*
- * below are stubs we need to link
- */
-int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
- struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
- struct abis_om_obj_inst *obj_ins)
-{
- return -1;
-}
-
-void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
-{}
-
-int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
-{
- return -1;
-}
-
-static void queue_for_msc(struct bsc_msc_connection *con, struct msgb *msg)
-{
- if (write_queue_enqueue(&nat->msc_con->write_queue, msg) != 0) {
- LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
- msgb_free(msg);
- }
-}
-
-static void send_reset_ack(struct bsc_connection *bsc)
-{
- static const u_int8_t gsm_reset_ack[] = {
- 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
- 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
- 0x00, 0x01, 0x31,
- };
-
- bsc_send_data(bsc, gsm_reset_ack, sizeof(gsm_reset_ack), IPAC_PROTO_SCCP);
-}
-
-static void send_ping(struct bsc_connection *bsc)
-{
- static const u_int8_t id_ping[] = {
- IPAC_MSGT_PING,
- };
-
- bsc_send_data(bsc, id_ping, sizeof(id_ping), IPAC_PROTO_IPACCESS);
-}
-
-static void send_pong(struct bsc_connection *bsc)
-{
- static const u_int8_t id_pong[] = {
- IPAC_MSGT_PONG,
- };
-
- bsc_send_data(bsc, id_pong, sizeof(id_pong), IPAC_PROTO_IPACCESS);
-}
-
-static void bsc_pong_timeout(void *_bsc)
-{
- struct bsc_connection *bsc = _bsc;
-
- LOGP(DNAT, LOGL_ERROR, "BSC Nr: %d PONG timeout.\n", bsc->cfg->nr);
- bsc_close_connection(bsc);
-}
-
-static void bsc_ping_timeout(void *_bsc)
-{
- struct bsc_connection *bsc = _bsc;
-
- if (bsc->nat->ping_timeout < 0)
- return;
-
- send_ping(bsc);
-
- /* send another ping in 20 seconds */
- bsc_schedule_timer(&bsc->ping_timeout, bsc->nat->ping_timeout, 0);
-
- /* also start a pong timer */
- bsc_schedule_timer(&bsc->pong_timeout, bsc->nat->pong_timeout, 0);
-}
-
-static void start_ping_pong(struct bsc_connection *bsc)
-{
- bsc->pong_timeout.data = bsc;
- bsc->pong_timeout.cb = bsc_pong_timeout;
- bsc->ping_timeout.data = bsc;
- bsc->ping_timeout.cb = bsc_ping_timeout;
-
- bsc_ping_timeout(bsc);
-}
-
-static void send_id_ack(struct bsc_connection *bsc)
-{
- static const u_int8_t id_ack[] = {
- IPAC_MSGT_ID_ACK
- };
-
- bsc_send_data(bsc, id_ack, sizeof(id_ack), IPAC_PROTO_IPACCESS);
-}
-
-static void send_id_req(struct bsc_connection *bsc)
-{
- static const u_int8_t id_req[] = {
- IPAC_MSGT_ID_GET,
- 0x01, IPAC_IDTAG_UNIT,
- 0x01, IPAC_IDTAG_MACADDR,
- 0x01, IPAC_IDTAG_LOCATION1,
- 0x01, IPAC_IDTAG_LOCATION2,
- 0x01, IPAC_IDTAG_EQUIPVERS,
- 0x01, IPAC_IDTAG_SWVERSION,
- 0x01, IPAC_IDTAG_UNITNAME,
- 0x01, IPAC_IDTAG_SERNR,
- };
-
- bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS);
-}
-
-static void nat_send_rlsd(struct sccp_connections *conn)
-{
- struct sccp_connection_released *rel;
- struct msgb *msg;
-
- msg = msgb_alloc_headroom(4096, 128, "rlsd");
- if (!msg) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
- return;
- }
-
- msg->l2h = msgb_put(msg, sizeof(*rel));
- rel = (struct sccp_connection_released *) msg->l2h;
- rel->type = SCCP_MSG_TYPE_RLSD;
- rel->release_cause = SCCP_RELEASE_CAUSE_SCCP_FAILURE;
- rel->destination_local_reference = conn->remote_ref;
- rel->source_local_reference = conn->patched_ref;
-
- ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
-
- queue_for_msc(nat->msc_con, msg);
-}
-
-static void nat_send_rlc(struct sccp_source_reference *src,
- struct sccp_source_reference *dst)
-{
- struct sccp_connection_release_complete *rlc;
- struct msgb *msg;
-
- msg = msgb_alloc_headroom(4096, 128, "rlc");
- if (!msg) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
- return;
- }
-
- msg->l2h = msgb_put(msg, sizeof(*rlc));
- rlc = (struct sccp_connection_release_complete *) msg->l2h;
- rlc->type = SCCP_MSG_TYPE_RLC;
- rlc->destination_local_reference = *dst;
- rlc->source_local_reference = *src;
-
- ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
-
- queue_for_msc(nat->msc_con, msg);
-}
-
-static void send_mgcp_reset(struct bsc_connection *bsc)
-{
- static const u_int8_t mgcp_reset[] = {
- "RSIP 1 13@mgw MGCP 1.0\r\n"
- };
-
- bsc_write_mgcp(bsc, mgcp_reset, sizeof mgcp_reset - 1);
-}
-
-/*
- * Below is the handling of messages coming
- * from the MSC and need to be forwarded to
- * a real BSC.
- */
-static void initialize_msc_if_needed()
-{
- if (nat->first_contact)
- return;
-
- nat->first_contact = 1;
- msc_send_reset(nat->msc_con);
-}
-
-static void send_id_get_response()
-{
- struct msgb *msg = bsc_msc_id_get_resp(nat->token);
- if (!msg)
- return;
-
- ipaccess_prepend_header(msg, IPAC_PROTO_IPACCESS);
- queue_for_msc(nat->msc_con, msg);
-}
-
-/*
- * Currently we are lacking refcounting so we need to copy each message.
- */
-static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length, int proto)
-{
- struct msgb *msg;
-
- if (length > 4096 - 128) {
- LOGP(DINP, LOGL_ERROR, "Can not send message of that size.\n");
- return;
- }
-
- msg = msgb_alloc_headroom(4096, 128, "to-bsc");
- if (!msg) {
- LOGP(DINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
- return;
- }
-
- msg->l2h = msgb_put(msg, length);
- memcpy(msg->data, data, length);
-
- bsc_write(bsc, msg, proto);
-}
-
-static void bsc_send_con_refuse(struct bsc_connection *bsc,
- struct bsc_nat_parsed *parsed, int con_type)
-{
- struct msgb *payload;
- struct msgb *refuse;
-
- if (con_type == NAT_CON_TYPE_LU)
- payload = gsm48_create_loc_upd_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
- else if (con_type == NAT_CON_TYPE_CM_SERV_REQ)
- payload = gsm48_create_mm_serv_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
-
- /*
- * Some BSCs do not handle the payload inside a SCCP CREF msg
- * so we will need to:
- * 1.) Allocate a local connection and mark it as local..
- * 2.) queue data for downstream.. and the RLC should delete everything
- */
- if (payload) {
- struct msgb *cc, *udt, *rlsd;
- struct sccp_connections *con;
- con = create_sccp_src_ref(bsc, parsed);
- if (!con)
- goto send_refuse;
-
- /* declare it local and assign a unique remote_ref */
- con->con_type = NAT_CON_TYPE_LOCAL_REJECT;
- con->con_local = 1;
- con->has_remote_ref = 1;
- con->remote_ref = con->patched_ref;
-
- /* 1. create a confirmation */
- cc = sccp_create_cc(&con->remote_ref, &con->real_ref);
- if (!cc)
- goto send_refuse;
-
- /* 2. create the DT1 */
- gsm0808_prepend_dtap_header(payload, 0);
- udt = sccp_create_dt1(&con->real_ref, payload->data, payload->len);
- if (!udt) {
- msgb_free(cc);
- goto send_refuse;
- }
-
- /* 3. send a RLSD */
- rlsd = sccp_create_rlsd(&con->remote_ref, &con->real_ref,
- SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
- if (!rlsd) {
- msgb_free(cc);
- msgb_free(udt);
- goto send_refuse;
- }
-
- bsc_write(bsc, cc, IPAC_PROTO_SCCP);
- bsc_write(bsc, udt, IPAC_PROTO_SCCP);
- bsc_write(bsc, rlsd, IPAC_PROTO_SCCP);
- msgb_free(payload);
- return;
- }
-
-
-send_refuse:
- if (payload)
- msgb_free(payload);
-
- refuse = sccp_create_refuse(parsed->src_local_ref,
- SCCP_REFUSAL_SCCP_FAILURE, NULL, 0);
- if (!refuse) {
- LOGP(DNAT, LOGL_ERROR,
- "Creating refuse msg failed for SCCP 0x%x on BSC Nr: %d.\n",
- sccp_src_ref_to_int(parsed->src_local_ref), bsc->cfg->nr);
- return;
- }
-
- bsc_write(bsc, refuse, IPAC_PROTO_SCCP);
-}
-
-
-static int forward_sccp_to_bts(struct msgb *msg)
-{
- struct sccp_connections *con;
- struct bsc_connection *bsc;
- struct bsc_nat_parsed *parsed;
- int proto;
-
- /* filter, drop, patch the message? */
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- LOGP(DNAT, LOGL_ERROR, "Can not parse msg from BSC.\n");
- return -1;
- }
-
- if (bsc_nat_filter_ipa(DIR_BSC, msg, parsed))
- goto exit;
-
- proto = parsed->ipa_proto;
-
- /* Route and modify the SCCP packet */
- if (proto == IPAC_PROTO_SCCP) {
- switch (parsed->sccp_type) {
- case SCCP_MSG_TYPE_UDT:
- /* forward UDT messages to every BSC */
- goto send_to_all;
- break;
- case SCCP_MSG_TYPE_RLSD:
- case SCCP_MSG_TYPE_CREF:
- case SCCP_MSG_TYPE_DT1:
- case SCCP_MSG_TYPE_IT:
- con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
- if (parsed->gsm_type == BSS_MAP_MSG_ASSIGMENT_RQST) {
- counter_inc(nat->stats.sccp.calls);
-
- if (con) {
- counter_inc(con->bsc->cfg->stats.sccp.calls);
- 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);
- if (!con || update_sccp_src_ref(con, parsed) != 0)
- goto exit;
- break;
- case SCCP_MSG_TYPE_RLC:
- LOGP(DNAT, LOGL_ERROR, "Unexpected release complete from MSC.\n");
- goto exit;
- break;
- case SCCP_MSG_TYPE_CR:
- /* MSC never opens a SCCP connection, fall through */
- default:
- goto exit;
- }
-
- if (!con && parsed->sccp_type == SCCP_MSG_TYPE_RLSD) {
- LOGP(DNAT, LOGL_NOTICE, "Sending fake RLC on RLSD message to network.\n");
- /* Exchange src/dest for the reply */
- nat_send_rlc(parsed->dest_local_ref, parsed->src_local_ref);
- } else if (!con)
- LOGP(DNAT, LOGL_ERROR, "Unknown connection for msg type: 0x%x from the MSC.\n", parsed->sccp_type);
- }
-
- talloc_free(parsed);
- if (!con)
- return -1;
- if (!con->bsc->authenticated) {
- LOGP(DNAT, LOGL_ERROR, "Selected BSC not authenticated.\n");
- return -1;
- }
-
- bsc_send_data(con->bsc, msg->l2h, msgb_l2len(msg), proto);
- return 0;
-
-send_to_all:
- /*
- * Filter Paging from the network. We do not want to send a PAGING
- * Command to every BSC in our network. We will analys the PAGING
- * message and then send it to the authenticated messages...
- */
- if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
- int lac;
- bsc = bsc_nat_find_bsc(nat, msg, &lac);
- if (bsc && bsc->cfg->forbid_paging)
- LOGP(DNAT, LOGL_DEBUG, "Paging forbidden for BTS: %d\n", bsc->cfg->nr);
- else if (bsc)
- bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
- else
- LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging on lac: %d/0x%x\n",
- lac, lac);
-
- goto exit;
- }
- /* currently send this to every BSC connected */
- llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
- if (!bsc->authenticated)
- continue;
-
- bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
- }
-
-exit:
- talloc_free(parsed);
- return 0;
-}
-
-static void msc_connection_was_lost(struct bsc_msc_connection *con)
-{
- struct bsc_connection *bsc, *tmp;
-
- counter_inc(nat->stats.msc.reconn);
-
- LOGP(DMSC, LOGL_ERROR, "Closing all connections downstream.\n");
- llist_for_each_entry_safe(bsc, tmp, &nat->bsc_connections, list_entry)
- bsc_close_connection(bsc);
-
- nat->first_contact = 0;
- bsc_mgcp_free_endpoints(nat);
- bsc_msc_schedule_connect(con);
-}
-
-static void msc_send_reset(struct bsc_msc_connection *msc_con)
-{
- static const u_int8_t reset[] = {
- 0x00, 0x12, 0xfd,
- 0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
- 0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
- 0x01, 0x20
- };
-
- struct msgb *msg;
-
- msg = msgb_alloc_headroom(4096, 128, "08.08 reset");
- if (!msg) {
- LOGP(DMSC, LOGL_ERROR, "Failed to allocate reset msg.\n");
- return;
- }
-
- msg->l2h = msgb_put(msg, sizeof(reset));
- memcpy(msg->l2h, reset, msgb_l2len(msg));
-
- queue_for_msc(nat->msc_con, msg);
-
- LOGP(DMSC, LOGL_NOTICE, "Scheduled GSM0808 reset msg for the MSC.\n");
-}
-
-static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
-{
- int error;
- struct msgb *msg = ipaccess_read_msg(bfd, &error);
- struct ipaccess_head *hh;
-
- if (!msg) {
- if (error == 0)
- LOGP(DNAT, LOGL_FATAL, "The connection the MSC was lost, exiting\n");
- else
- LOGP(DNAT, LOGL_ERROR, "Failed to parse ip access message: %d\n", error);
-
- bsc_msc_lost(nat->msc_con);
- return -1;
- }
-
- LOGP(DNAT, LOGL_DEBUG, "MSG from MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
-
- /* handle base message handling */
- hh = (struct ipaccess_head *) msg->data;
- ipaccess_rcvmsg_base(msg, bfd);
-
- /* initialize the networking. This includes sending a GSM08.08 message */
- if (hh->proto == IPAC_PROTO_IPACCESS) {
- if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
- initialize_msc_if_needed();
- else if (msg->l2h[0] == IPAC_MSGT_ID_GET)
- send_id_get_response();
- } else if (hh->proto == IPAC_PROTO_SCCP)
- forward_sccp_to_bts(msg);
-
- msgb_free(msg);
- return 0;
-}
-
-static int ipaccess_msc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
-{
- int rc;
- rc = write(bfd->fd, msg->data, msg->len);
-
- if (rc != msg->len) {
- LOGP(DNAT, LOGL_ERROR, "Failed to write MSG to MSC.\n");
- return -1;
- }
-
- return rc;
-}
-
-/*
- * Below is the handling of messages coming
- * from the BSC and need to be forwarded to
- * a real BSC.
- */
-
-/*
- * Remove the connection from the connections list,
- * remove it from the patching of SCCP header lists
- * as well. Maybe in the future even close connection..
- */
-void bsc_close_connection(struct bsc_connection *connection)
-{
- struct sccp_connections *sccp_patch, *tmp;
-
- /* stop the timeout timer */
- bsc_del_timer(&connection->id_timeout);
- bsc_del_timer(&connection->ping_timeout);
- bsc_del_timer(&connection->pong_timeout);
-
- /* remove all SCCP connections */
- llist_for_each_entry_safe(sccp_patch, tmp, &nat->sccp_connections, list_entry) {
- if (sccp_patch->bsc != connection)
- continue;
-
- if (sccp_patch->has_remote_ref)
- nat_send_rlsd(sccp_patch);
- sccp_connection_destroy(sccp_patch);
- }
-
- /* close endpoints allocated by this BSC */
- bsc_mgcp_clear_endpoints_for(connection);
-
- bsc_unregister_fd(&connection->write_queue.bfd);
- close(connection->write_queue.bfd.fd);
- write_queue_clear(&connection->write_queue);
- llist_del(&connection->list_entry);
-
- talloc_free(connection);
-}
-
-static void ipaccess_close_bsc(void *data)
-{
- struct sockaddr_in sock;
- socklen_t len = sizeof(sock);
- struct bsc_connection *conn = data;
-
-
- getpeername(conn->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
- LOGP(DNAT, LOGL_ERROR, "BSC on %s didn't respond to identity request. Closing.\n",
- inet_ntoa(sock.sin_addr));
- bsc_close_connection(conn);
-}
-
-static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
-{
- struct bsc_config *conf;
- const char* token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
-
- if (bsc->cfg) {
- LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
- bsc->write_queue.bfd.fd, bsc->cfg->nr);
- return;
- }
-
- llist_for_each_entry(conf, &bsc->nat->bsc_configs, entry) {
- if (strcmp(conf->token, token) == 0) {
- counter_inc(conf->stats.net.reconn);
- bsc->authenticated = 1;
- bsc->cfg = conf;
- bsc_del_timer(&bsc->id_timeout);
- LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d on fd %d\n",
- conf->nr, conf->lac, bsc->write_queue.bfd.fd);
- start_ping_pong(bsc);
- return;
- }
- }
-
- LOGP(DNAT, LOGL_ERROR, "No bsc found for token %s on fd: %d.\n", token,
- bsc->write_queue.bfd.fd);
-}
-
-static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
-{
- int con_found = 0;
- int con_filter = 0;
- struct bsc_connection *con_bsc = NULL;
- int con_type;
- struct bsc_nat_parsed *parsed;
-
- /* Parse and filter messages */
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- LOGP(DNAT, LOGL_ERROR, "Can not parse msg from BSC.\n");
- msgb_free(msg);
- return -1;
- }
-
- if (bsc_nat_filter_ipa(DIR_MSC, msg, parsed))
- goto exit;
-
- /*
- * check authentication after filtering to not reject auth
- * responses coming from the BSC. We have to make sure that
- * nothing from the exit path will forward things to the MSC
- */
- if (!bsc->authenticated) {
- LOGP(DNAT, LOGL_ERROR, "BSC is not authenticated.\n");
- msgb_free(msg);
- return -1;
- }
-
-
- /* modify the SCCP entries */
- if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
- struct sccp_connections *con;
- switch (parsed->sccp_type) {
- case SCCP_MSG_TYPE_CR:
- if (bsc_nat_filter_sccp_cr(bsc, msg, parsed, &con_type) != 0)
- goto exit3;
- if (!create_sccp_src_ref(bsc, parsed))
- goto exit2;
- con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
- con->con_type = con_type;
- con_found = 1;
- con_bsc = con->bsc;
- break;
- case SCCP_MSG_TYPE_RLSD:
- case SCCP_MSG_TYPE_CREF:
- case SCCP_MSG_TYPE_DT1:
- case SCCP_MSG_TYPE_CC:
- case SCCP_MSG_TYPE_IT:
- con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
- if (con) {
- con_found = 1;
- con_bsc = con->bsc;
- con_filter = con->con_local;
- }
- break;
- case SCCP_MSG_TYPE_RLC:
- con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
- if (con) {
- con_found = 1;
- con_bsc = con->bsc;
- con_filter = con->con_local;
- }
- remove_sccp_src_ref(bsc, msg, parsed);
- break;
- case SCCP_MSG_TYPE_UDT:
- /* simply forward everything */
- con = NULL;
- break;
- default:
- LOGP(DNAT, LOGL_ERROR, "Not forwarding to msc sccp type: 0x%x\n", parsed->sccp_type);
- con = NULL;
- goto exit2;
- break;
- }
- } else if (parsed->ipa_proto == NAT_IPAC_PROTO_MGCP) {
- bsc_mgcp_forward(bsc, msg);
- goto exit2;
- } else {
- LOGP(DNAT, LOGL_ERROR, "Not forwarding unknown stream id: 0x%x\n", parsed->ipa_proto);
- goto exit2;
- }
-
- if (con_found && con_bsc != bsc) {
- LOGP(DNAT, LOGL_ERROR, "The connection belongs to a different BTS: input: %d con: %d\n",
- bsc->cfg->nr, con_bsc->cfg->nr);
- goto exit2;
- }
-
- /* do not forward messages to the MSC */
- if (con_filter)
- goto exit2;
-
- /* send the non-filtered but maybe modified msg */
- queue_for_msc(nat->msc_con, msg);
- talloc_free(parsed);
- return 0;
-
-exit:
- /* if we filter out the reset send an ack to the BSC */
- if (parsed->bssap == 0 && parsed->gsm_type == BSS_MAP_MSG_RESET) {
- send_reset_ack(bsc);
- send_reset_ack(bsc);
- } else if (parsed->ipa_proto == IPAC_PROTO_IPACCESS) {
- /* do we know who is handling this? */
- if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
- struct tlv_parsed tvp;
- ipaccess_idtag_parse(&tvp,
- (unsigned char *) msg->l2h + 2,
- msgb_l2len(msg) - 2);
- if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
- ipaccess_auth_bsc(&tvp, bsc);
- }
-
- goto exit2;
- }
-
-exit2:
- talloc_free(parsed);
- msgb_free(msg);
- return -1;
-
-exit3:
- /* send a SCCP Connection Refused */
- bsc_send_con_refuse(bsc, parsed, con_type);
- talloc_free(parsed);
- msgb_free(msg);
- return -1;
-}
-
-static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)
-{
- int error;
- struct bsc_connection *bsc = bfd->data;
- struct msgb *msg = ipaccess_read_msg(bfd, &error);
- struct ipaccess_head *hh;
-
- if (!msg) {
- if (error == 0)
- LOGP(DNAT, LOGL_ERROR,
- "The connection to the BSC Nr: %d was lost. Cleaning it\n",
- bsc->cfg ? bsc->cfg->nr : -1);
- else
- LOGP(DNAT, LOGL_ERROR,
- "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n",
- bsc->cfg ? bsc->cfg->nr : -1, error);
-
- bsc_close_connection(bsc);
- return -1;
- }
-
-
- LOGP(DNAT, LOGL_DEBUG, "MSG from BSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
-
- /* Handle messages from the BSC */
- hh = (struct ipaccess_head *) msg->data;
-
- /* stop the pong timeout */
- if (hh->proto == IPAC_PROTO_IPACCESS) {
- if (msg->l2h[0] == IPAC_MSGT_PONG) {
- bsc_del_timer(&bsc->pong_timeout);
- msgb_free(msg);
- return 0;
- } else if (msg->l2h[0] == IPAC_MSGT_PING) {
- send_pong(bsc);
- msgb_free(msg);
- return 0;
- }
- }
-
- /* FIXME: Currently no PONG is sent to the BSC */
- /* FIXME: Currently no ID ACK is sent to the BSC */
- forward_sccp_to_msc(bsc, msg);
-
- return 0;
-}
-
-static int ipaccess_bsc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
-{
- int rc;
-
- rc = write(bfd->fd, msg->data, msg->len);
- if (rc != msg->len)
- LOGP(DNAT, LOGL_ERROR, "Failed to write message to the BSC.\n");
-
- return rc;
-}
-
-static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
-{
- struct bsc_connection *bsc;
- int fd, rc, on;
- struct sockaddr_in sa;
- socklen_t sa_len = sizeof(sa);
-
- if (!(what & BSC_FD_READ))
- return 0;
-
- fd = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
- if (fd < 0) {
- perror("accept");
- return fd;
- }
-
- /* count the reconnect */
- counter_inc(nat->stats.bsc.reconn);
-
- /*
- * if we are not connected to a msc... just close the socket
- */
- if (!nat->msc_con->is_connected) {
- LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due lack of MSC connection.\n");
- close(fd);
- return 0;
- }
-
- on = 1;
- rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
- if (rc != 0)
- LOGP(DNAT, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
-
- rc = setsockopt(fd, IPPROTO_IP, IP_TOS,
- &nat->bsc_ip_tos, sizeof(nat->bsc_ip_tos));
- if (rc != 0)
- LOGP(DNAT, LOGL_ERROR, "Failed to set IP_TOS: %s\n", strerror(errno));
-
- /* todo... do something with the connection */
- /* todo... use GNUtls to see if we want to trust this as a BTS */
-
- /*
- *
- */
- bsc = bsc_connection_alloc(nat);
- if (!bsc) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate BSC struct.\n");
- close(fd);
- return -1;
- }
-
- bsc->write_queue.bfd.data = bsc;
- bsc->write_queue.bfd.fd = fd;
- bsc->write_queue.read_cb = ipaccess_bsc_read_cb;
- bsc->write_queue.write_cb = ipaccess_bsc_write_cb;
- bsc->write_queue.bfd.when = BSC_FD_READ;
- if (bsc_register_fd(&bsc->write_queue.bfd) < 0) {
- LOGP(DNAT, LOGL_ERROR, "Failed to register BSC fd.\n");
- close(fd);
- talloc_free(bsc);
- return -2;
- }
-
- LOGP(DNAT, LOGL_NOTICE, "BSC connection on %d with IP: %s\n",
- fd, inet_ntoa(sa.sin_addr));
- llist_add(&bsc->list_entry, &nat->bsc_connections);
- send_id_ack(bsc);
- send_id_req(bsc);
- send_mgcp_reset(bsc);
-
- /*
- * start the hangup timer
- */
- bsc->id_timeout.data = bsc;
- bsc->id_timeout.cb = ipaccess_close_bsc;
- bsc_schedule_timer(&bsc->id_timeout, nat->auth_timeout, 0);
- return 0;
-}
-
-static int listen_for_bsc(struct bsc_fd *bfd, struct in_addr *in_addr, int port)
-{
- struct sockaddr_in addr;
- int ret, on = 1;
-
- bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- bfd->cb = ipaccess_listen_bsc_cb;
- bfd->when = BSC_FD_READ;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = in_addr->s_addr;
-
- setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
- ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
- if (ret < 0) {
- fprintf(stderr, "Could not bind the BSC socket %s\n",
- strerror(errno));
- return -EIO;
- }
-
- ret = listen(bfd->fd, 1);
- if (ret < 0) {
- perror("listen");
- return ret;
- }
-
- ret = bsc_register_fd(bfd);
- if (ret < 0) {
- perror("register_listen_fd");
- return ret;
- }
- return 0;
-}
-
-static void print_usage()
-{
- printf("Usage: bsc_nat\n");
-}
-
-static void print_help()
-{
- printf(" Some useful help...\n");
- printf(" -h --help this text\n");
- printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
- printf(" -s --disable-color\n");
- printf(" -c --config-file filename The config file to use.\n");
- printf(" -m --msc=IP. The address of the MSC.\n");
- printf(" -l --local=IP. The local address of this BSC.\n");
-}
-
-static void handle_options(int argc, char** argv)
-{
- while (1) {
- int option_index = 0, c;
- static struct option long_options[] = {
- {"help", 0, 0, 'h'},
- {"debug", 1, 0, 'd'},
- {"config-file", 1, 0, 'c'},
- {"disable-color", 0, 0, 's'},
- {"timestamp", 0, 0, 'T'},
- {"msc", 1, 0, 'm'},
- {"local", 1, 0, 'l'},
- {0, 0, 0, 0}
- };
-
- c = getopt_long(argc, argv, "hd:sTPc:m:l:",
- long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c) {
- case 'h':
- print_usage();
- print_help();
- exit(0);
- case 's':
- log_set_use_color(stderr_target, 0);
- break;
- case 'd':
- log_parse_category_mask(stderr_target, optarg);
- break;
- case 'c':
- config_file = strdup(optarg);
- break;
- case 'T':
- log_set_print_timestamp(stderr_target, 1);
- break;
- case 'm':
- msc_ip = optarg;
- break;
- case 'l':
- inet_aton(optarg, &local_addr);
- break;
- default:
- /* ignore */
- break;
- }
- }
-}
-
-static void signal_handler(int signal)
-{
- switch (signal) {
- case SIGABRT:
- /* in case of abort, we want to obtain a talloc report
- * and then return to the caller, who will abort the process */
- case SIGUSR1:
- talloc_report_full(tall_bsc_ctx, stderr);
- break;
- default:
- break;
- }
-}
-
-static void sccp_close_unconfirmed(void *_data)
-{
- struct sccp_connections *conn, *tmp1;
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
-
- llist_for_each_entry_safe(conn, tmp1, &nat->sccp_connections, list_entry) {
- if (conn->has_remote_ref)
- continue;
-
- int diff = (now.tv_sec - conn->creation_time.tv_sec) / 60;
- if (diff < SCCP_CLOSE_TIME_TIMEOUT)
- continue;
-
- LOGP(DNAT, LOGL_ERROR, "SCCP connection 0x%x/0x%x was never confirmed.\n",
- sccp_src_ref_to_int(&conn->real_ref),
- sccp_src_ref_to_int(&conn->patched_ref));
- sccp_connection_destroy(conn);
- }
-
- bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
-}
-
-extern void *tall_msgb_ctx;
-extern void *tall_ctr_ctx;
-static void talloc_init_ctx()
-{
- tall_bsc_ctx = talloc_named_const(NULL, 0, "nat");
- tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
- tall_ctr_ctx = talloc_named_const(tall_bsc_ctx, 0, "counter");
-}
-
-int main(int argc, char** argv)
-{
- talloc_init_ctx();
- log_init(&log_info);
-
- stderr_target = log_target_create_stderr();
- log_add_target(stderr_target);
- log_set_all_filter(stderr_target, 1);
-
- nat = bsc_nat_alloc();
- if (!nat) {
- fprintf(stderr, "Failed to allocate the BSC nat.\n");
- return -4;
- }
-
- nat->mgcp_cfg = talloc_zero(nat, struct mgcp_config);
- if (!nat->mgcp_cfg) {
- fprintf(stderr, "Failed to allocate MGCP cfg.\n");
- return -5;
- }
-
- /* parse options */
- local_addr.s_addr = INADDR_ANY;
- handle_options(argc, argv);
-
- /* init vty and parse */
- bsc_nat_vty_init(nat);
- telnet_init(NULL, 4244);
- if (mgcp_parse_config(config_file, nat->mgcp_cfg) < 0) {
- fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
- return -3;
- }
-
- /* over rule the VTY config */
- if (msc_ip)
- bsc_nat_set_msc_ip(nat, msc_ip);
-
- /* seed the PRNG */
- srand(time(NULL));
-
- /*
- * Setup the MGCP code..
- */
- if (bsc_mgcp_nat_init(nat) != 0)
- return -4;
-
- /* connect to the MSC */
- nat->msc_con = bsc_msc_create(nat->msc_ip, nat->msc_port, 0);
- if (!nat->msc_con) {
- fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
- exit(1);
- }
-
- nat->msc_con->connection_loss = msc_connection_was_lost;
- nat->msc_con->write_queue.read_cb = ipaccess_msc_read_cb;
- nat->msc_con->write_queue.write_cb = ipaccess_msc_write_cb;;
- bsc_msc_connect(nat->msc_con);
-
- /* wait for the BSC */
- if (listen_for_bsc(&bsc_listen, &local_addr, 5000) < 0) {
- fprintf(stderr, "Failed to listen for BSC.\n");
- exit(1);
- }
-
- signal(SIGABRT, &signal_handler);
- signal(SIGUSR1, &signal_handler);
- signal(SIGPIPE, SIG_IGN);
-
- /* recycle timer */
- sccp_close.cb = sccp_close_unconfirmed;
- sccp_close.data = NULL;
- bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
-
- while (1) {
- bsc_select_main(0);
- }
-
- return 0;
-}
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
deleted file mode 100644
index 6cbf4a511..000000000
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ /dev/null
@@ -1,491 +0,0 @@
-
-/* BSC Multiplexer/NAT Utilities */
-
-/*
- * (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 <openbsc/ipaccess.h>
-
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/gsm0808.h>
-
-#include <sccp/sccp.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-struct bsc_nat *bsc_nat_alloc(void)
-{
- struct bsc_nat *nat = talloc_zero(tall_bsc_ctx, struct bsc_nat);
- if (!nat)
- return NULL;
-
- INIT_LLIST_HEAD(&nat->sccp_connections);
- INIT_LLIST_HEAD(&nat->bsc_connections);
- INIT_LLIST_HEAD(&nat->bsc_configs);
- INIT_LLIST_HEAD(&nat->access_lists);
-
- nat->stats.sccp.conn = counter_alloc("nat.sccp.conn");
- nat->stats.sccp.calls = counter_alloc("nat.sccp.calls");
- nat->stats.bsc.reconn = counter_alloc("nat.bsc.conn");
- nat->stats.bsc.auth_fail = counter_alloc("nat.bsc.auth_fail");
- nat->stats.msc.reconn = counter_alloc("nat.msc.conn");
- nat->msc_ip = talloc_strdup(nat, "127.0.0.1");
- nat->msc_port = 5000;
- nat->auth_timeout = 2;
- nat->ping_timeout = 20;
- nat->pong_timeout = 5;
- return nat;
-}
-
-void bsc_nat_set_msc_ip(struct bsc_nat *nat, const char *ip)
-{
- if (nat->msc_ip)
- talloc_free(nat->msc_ip);
- nat->msc_ip = talloc_strdup(nat, ip);
-}
-
-struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
-{
- struct bsc_connection *con = talloc_zero(nat, struct bsc_connection);
- if (!con)
- return NULL;
-
- con->nat = nat;
- write_queue_init(&con->write_queue, 100);
- return con;
-}
-
-struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsigned int lac)
-{
- struct bsc_config *conf = talloc_zero(nat, struct bsc_config);
- if (!conf)
- return NULL;
-
- conf->token = talloc_strdup(conf, token);
- conf->lac = lac;
- conf->nr = nat->num_bsc;
- conf->nat = nat;
-
- llist_add_tail(&conf->entry, &nat->bsc_configs);
- ++nat->num_bsc;
-
- conf->stats.sccp.conn = counter_alloc("nat.bsc.sccp.conn");
- conf->stats.sccp.calls = counter_alloc("nat.bsc.sccp.calls");
- conf->stats.net.reconn = counter_alloc("nat.bsc.net.reconnects");
-
- return conf;
-}
-
-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_dlcx(conn);
- llist_del(&conn->list_entry);
- talloc_free(conn);
-}
-
-struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *lac_out)
-{
- struct bsc_connection *bsc;
- int data_length;
- const u_int8_t *data;
- struct tlv_parsed tp;
- int i = 0;
-
- *lac_out = -1;
-
- if (!msg->l3h || msgb_l3len(msg) < 3) {
- LOGP(DNAT, LOGL_ERROR, "Paging message is too short.\n");
- return NULL;
- }
-
- tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
- if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
- LOGP(DNAT, LOGL_ERROR, "No CellIdentifier List inside paging msg.\n");
- return NULL;
- }
-
- data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
- data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
-
- /* No need to try a different BSS */
- if (data[0] == CELL_IDENT_BSS) {
- return NULL;
- } else if (data[0] != CELL_IDENT_LAC) {
- LOGP(DNAT, LOGL_ERROR, "Unhandled cell ident discrminator: %d\n", data[0]);
- return NULL;
- }
-
- /* Currently we only handle one BSC */
- for (i = 1; i < data_length - 1; i += 2) {
- unsigned int _lac = ntohs(*(unsigned int *) &data[i]);
- *lac_out = _lac;
- llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
- if (!bsc->cfg)
- continue;
- if (!bsc->authenticated || _lac != bsc->cfg->lac)
- continue;
-
- return bsc;
- }
- }
-
- return NULL;
-}
-
-int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length)
-{
- struct msgb *msg;
-
- if (length > 4096 - 128) {
- LOGP(DINP, LOGL_ERROR, "Can not send message of that size.\n");
- return -1;
- }
-
- msg = msgb_alloc_headroom(4096, 128, "to-bsc");
- if (!msg) {
- LOGP(DINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
- return -1;
- }
-
- /* copy the data */
- msg->l3h = msgb_put(msg, length);
- memcpy(msg->l3h, data, length);
-
- return bsc_write(bsc, msg, NAT_IPAC_PROTO_MGCP);
-}
-
-int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int proto)
-{
- /* prepend the header */
- ipaccess_prepend_header(msg, proto);
-
- if (write_queue_enqueue(&bsc->write_queue, msg) != 0) {
- LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
- msgb_free(msg);
- return -1;
- }
-
- return 0;
-}
-
-static int lst_check_allow(struct bsc_nat_acc_lst *lst, const char *mi_string)
-{
- struct bsc_nat_acc_lst_entry *entry;
-
- llist_for_each_entry(entry, &lst->fltr_list, list) {
- if (!entry->imsi_allow)
- continue;
- if (regexec(&entry->imsi_allow_re, mi_string, 0, NULL, 0) == 0)
- return 0;
- }
-
- return 1;
-}
-
-static int lst_check_deny(struct bsc_nat_acc_lst *lst, const char *mi_string)
-{
- struct bsc_nat_acc_lst_entry *entry;
-
- llist_for_each_entry(entry, &lst->fltr_list, list) {
- if (!entry->imsi_deny)
- continue;
- if (regexec(&entry->imsi_deny_re, mi_string, 0, NULL, 0) == 0)
- return 0;
- }
-
- return 1;
-}
-
-/* apply white/black list */
-static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
-{
- /*
- * Now apply blacklist/whitelist of the BSC and the NAT.
- * 1.) Reject if the IMSI is not allowed at the BSC
- * 2.) Allow directly if the IMSI is allowed at the BSC
- * 3.) Reject if the IMSI not allowed at the global level.
- * 4.) Allow directly if the IMSI is allowed at the global level
- */
- struct bsc_nat_acc_lst *nat_lst = NULL;
- struct bsc_nat_acc_lst *bsc_lst = NULL;
-
- bsc_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->cfg->acc_lst_name);
- nat_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->nat->acc_lst_name);
-
-
- if (bsc_lst) {
- /* 1. BSC deny */
- if (lst_check_deny(bsc_lst, mi_string) == 0) {
- LOGP(DNAT, LOGL_ERROR,
- "Filtering %s by imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
- return -2;
- }
-
- /* 2. BSC allow */
- if (lst_check_allow(bsc_lst, mi_string) == 0)
- return 0;
- }
-
- /* 3. NAT deny */
- if (nat_lst) {
- if (lst_check_deny(nat_lst, mi_string) == 0) {
- LOGP(DNAT, LOGL_ERROR,
- "Filtering %s by nat imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
- return -3;
- }
- }
-
- return 0;
-}
-
-static int _cr_check_loc_upd(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
-{
- u_int8_t mi_type;
- struct gsm48_loc_upd_req *lu;
- char mi_string[GSM48_MI_SIZE];
-
- if (length < sizeof(*lu)) {
- LOGP(DNAT, LOGL_ERROR,
- "LU does not fit. Length is %d \n", length);
- return -1;
- }
-
- lu = (struct gsm48_loc_upd_req *) data;
- mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
-
- /*
- * We can only deal with the IMSI. This will fail for a phone that
- * will send the TMSI of a previous network to us.
- */
- if (mi_type != GSM_MI_TYPE_IMSI)
- return 0;
-
- gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
- return auth_imsi(bsc, mi_string);
-}
-
-static int _cr_check_cm_serv_req(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
-{
- static const uint32_t classmark_offset =
- offsetof(struct gsm48_service_request, classmark);
-
- char mi_string[GSM48_MI_SIZE];
- uint8_t mi_type;
- int rc;
- struct gsm48_service_request *req;
-
- /* unfortunately in Phase1 the classmark2 length is variable */
-
- if (length < sizeof(*req)) {
- LOGP(DNAT, LOGL_ERROR,
- "CM Serv Req does not fit. Length is %d\n", length);
- return -1;
- }
-
- req = (struct gsm48_service_request *) data;
- rc = gsm48_extract_mi((uint8_t *) &req->classmark,
- length - classmark_offset, mi_string, &mi_type);
- if (rc < 0) {
- LOGP(DNAT, LOGL_ERROR, "Failed to parse the classmark2/mi. error: %d\n", rc);
- return -1;
- }
-
- /* we have to let the TMSI or such pass */
- if (mi_type != GSM_MI_TYPE_IMSI)
- return 0;
-
- return auth_imsi(bsc, mi_string);
-}
-
-static int _cr_check_pag_resp(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
-{
- struct gsm48_pag_resp *resp;
- char mi_string[GSM48_MI_SIZE];
- u_int8_t mi_type;
-
- if (length < sizeof(*resp)) {
- LOGP(DNAT, LOGL_ERROR, "PAG RESP does not fit. Length was %d.\n", length);
- return -1;
- }
-
- resp = (struct gsm48_pag_resp *) data;
- if (gsm48_paging_extract_mi(resp, length, mi_string, &mi_type) < 0) {
- LOGP(DNAT, LOGL_ERROR, "Failed to extract the MI.\n");
- return -1;
- }
-
- /* we need to let it pass for now */
- if (mi_type != GSM_MI_TYPE_IMSI)
- return 0;
-
- return auth_imsi(bsc, mi_string);
-}
-
-/* Filter out CR data... */
-int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed, int *con_type)
-{
- struct tlv_parsed tp;
- struct gsm48_hdr *hdr48;
- int hdr48_len;
- int len;
-
- *con_type = NAT_CON_TYPE_NONE;
-
- if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
- LOGP(DNAT, LOGL_ERROR,
- "Rejecting CR message due wrong GSM Type %d\n", parsed->gsm_type);
- return -1;
- }
-
- /* the parsed has had some basic l3 length check */
- len = msg->l3h[1];
- if (msgb_l3len(msg) - 3 < len) {
- LOGP(DNAT, LOGL_ERROR,
- "The CR Data has not enough space...\n");
- return -1;
- }
-
- msg->l4h = &msg->l3h[3];
- len -= 1;
-
- tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h, len, 0, 0);
-
- if (!TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_INFORMATION)) {
- LOGP(DNAT, LOGL_ERROR, "CR Data does not contain layer3 information.\n");
- return -1;
- }
-
- hdr48_len = TLVP_LEN(&tp, GSM0808_IE_LAYER_3_INFORMATION);
-
- if (hdr48_len < sizeof(*hdr48)) {
- LOGP(DNAT, LOGL_ERROR, "GSM48 header does not fit.\n");
- return -1;
- }
-
- hdr48 = (struct gsm48_hdr *) TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION);
-
- if (hdr48->proto_discr == GSM48_PDISC_MM &&
- hdr48->msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) {
- *con_type = NAT_CON_TYPE_LU;
- return _cr_check_loc_upd(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
- } else if (hdr48->proto_discr == GSM48_PDISC_MM &&
- hdr48->msg_type == GSM48_MT_MM_CM_SERV_REQ) {
- *con_type = NAT_CON_TYPE_CM_SERV_REQ;
- return _cr_check_cm_serv_req(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
- } else if (hdr48->proto_discr == GSM48_PDISC_RR &&
- hdr48->msg_type == GSM48_MT_RR_PAG_RESP) {
- *con_type = NAT_CON_TYPE_PAG_RESP;
- return _cr_check_pag_resp(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
- } else {
- /* We only want to filter the above, let other things pass */
- *con_type = NAT_CON_TYPE_OTHER;
- return 0;
- }
-}
-
-void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
-{
- if (*imsi) {
- talloc_free(*imsi);
- *imsi = NULL;
- }
- regfree(reg);
-
- if (argc > 0) {
- *imsi = talloc_strdup(ctx, argv[0]);
- regcomp(reg, argv[0], 0);
- }
-}
-
-static const char *con_types [] = {
- [NAT_CON_TYPE_NONE] = "n/a",
- [NAT_CON_TYPE_LU] = "Location Update",
- [NAT_CON_TYPE_CM_SERV_REQ] = "CM Serv Req",
- [NAT_CON_TYPE_PAG_RESP] = "Paging Response",
- [NAT_CON_TYPE_LOCAL_REJECT] = "Local Reject",
- [NAT_CON_TYPE_OTHER] = "Other",
-};
-
-const char *bsc_con_type_to_string(int type)
-{
- return con_types[type];
-}
-
-struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct bsc_nat *nat, const char *name)
-{
- struct bsc_nat_acc_lst *lst;
-
- if (!name)
- return NULL;
-
- llist_for_each_entry(lst, &nat->access_lists, list)
- if (strcmp(lst->name, name) == 0)
- return lst;
-
- return NULL;
-}
-
-struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *name)
-{
- struct bsc_nat_acc_lst *lst;
-
- lst = bsc_nat_acc_lst_find(nat, name);
- if (lst)
- return lst;
-
- lst = talloc_zero(nat, struct bsc_nat_acc_lst);
- if (!lst) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate access list");
- return NULL;
- }
-
- INIT_LLIST_HEAD(&lst->fltr_list);
- lst->name = talloc_strdup(lst, name);
- llist_add_tail(&lst->list, &nat->access_lists);
- return lst;
-}
-
-void bsc_nat_acc_lst_delete(struct bsc_nat_acc_lst *lst)
-{
- llist_del(&lst->list);
- talloc_free(lst);
-}
-
-struct bsc_nat_acc_lst_entry *bsc_nat_acc_lst_entry_create(struct bsc_nat_acc_lst *lst)
-{
- struct bsc_nat_acc_lst_entry *entry;
-
- entry = talloc_zero(lst, struct bsc_nat_acc_lst_entry);
- if (!entry)
- return NULL;
-
- llist_add_tail(&entry->list, &lst->fltr_list);
- return entry;
-}
diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c
deleted file mode 100644
index a7478920f..000000000
--- a/openbsc/src/nat/bsc_nat_vty.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/* OpenBSC NAT interface to quagga VTY */
-/* (C) 2010 by Holger Hans Peter Freyther
- * (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 <vty/command.h>
-#include <vty/buffer.h>
-#include <vty/vty.h>
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_msc.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/vty.h>
-
-#include <osmocore/talloc.h>
-
-#include <sccp/sccp.h>
-
-#include <stdlib.h>
-
-static struct bsc_nat *_nat;
-
-static struct cmd_node nat_node = {
- NAT_NODE,
- "%s(nat)#",
- 1,
-};
-
-static struct cmd_node bsc_node = {
- BSC_NODE,
- "%s(bsc)#",
- 1,
-};
-
-static void write_acc_lst(struct vty *vty, struct bsc_nat_acc_lst *lst)
-{
- struct bsc_nat_acc_lst_entry *entry;
-
- llist_for_each_entry(entry, &lst->fltr_list, list) {
- if (entry->imsi_allow)
- vty_out(vty, " access-list %s imsi-allow %s%s",
- lst->name, entry->imsi_allow, VTY_NEWLINE);
- if (entry->imsi_deny)
- vty_out(vty, " access-list %s imsi-deny %s%s",
- lst->name, entry->imsi_deny, VTY_NEWLINE);
- }
-}
-
-static int config_write_nat(struct vty *vty)
-{
- struct bsc_nat_acc_lst *lst;
-
- vty_out(vty, "nat%s", VTY_NEWLINE);
- vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
- vty_out(vty, " msc port %d%s", _nat->msc_port, VTY_NEWLINE);
- vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
- vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE);
- vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE);
- if (_nat->token)
- vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
- vty_out(vty, " ip-tos %d%s", _nat->bsc_ip_tos, VTY_NEWLINE);
- if (_nat->acc_lst_name)
- vty_out(vty, " access-list-name %s%s", _nat->acc_lst_name, VTY_NEWLINE);
-
- llist_for_each_entry(lst, &_nat->access_lists, list) {
- write_acc_lst(vty, lst);
- }
-
- return CMD_SUCCESS;
-}
-
-static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
-{
- vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
- vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
- vty_out(vty, " location_area_code %u%s", bsc->lac, VTY_NEWLINE);
- vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
- if (bsc->description)
- vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
- if (bsc->acc_lst_name)
- vty_out(vty, " access-list-name %s%s", bsc->acc_lst_name, VTY_NEWLINE);
-}
-
-static int config_write_bsc(struct vty *vty)
-{
- struct bsc_config *bsc;
-
- llist_for_each_entry(bsc, &_nat->bsc_configs, entry)
- config_write_bsc_single(vty, bsc);
- return CMD_SUCCESS;
-}
-
-
-DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
- SHOW_STR "Display information about current SCCP connections")
-{
- struct sccp_connections *con;
- vty_out(vty, "Listing all opening SCCP connections%s", VTY_NEWLINE);
-
- llist_for_each_entry(con, &_nat->sccp_connections, list_entry) {
- vty_out(vty, "For BSC Nr: %d lac: %d; BSC ref: 0x%x; MUX ref: 0x%x; Network has ref: %d ref: 0x%x MSC/BSC mux: 0x%x/0x%x type: %s%s",
- con->bsc->cfg ? con->bsc->cfg->nr : -1,
- con->bsc->cfg ? con->bsc->cfg->lac : -1,
- sccp_src_ref_to_int(&con->real_ref),
- sccp_src_ref_to_int(&con->patched_ref),
- con->has_remote_ref,
- sccp_src_ref_to_int(&con->remote_ref),
- con->msc_timeslot, con->bsc_timeslot,
- bsc_con_type_to_string(con->con_type),
- VTY_NEWLINE);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
- SHOW_STR "Display information about current BSCs")
-{
- struct bsc_connection *con;
- struct sockaddr_in sock;
- socklen_t len = sizeof(sock);
-
- llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
- getpeername(con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
- vty_out(vty, "BSC nr: %d lac: %d auth: %d fd: %d peername: %s%s",
- con->cfg ? con->cfg->nr : -1,
- con->cfg ? con->cfg->lac : -1,
- con->authenticated, con->write_queue.bfd.fd,
- inet_ntoa(sock.sin_addr), VTY_NEWLINE);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
- SHOW_STR "Display information about known BSC configs")
-{
- struct bsc_config *conf;
- llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
- vty_out(vty, "BSC token: '%s' lac: %u nr: %u%s",
- conf->token, conf->lac, conf->nr, VTY_NEWLINE);
- if (conf->acc_lst_name)
- vty_out(vty, " access-list: %s%s",
- conf->acc_lst_name, VTY_NEWLINE);
- vty_out(vty, " paging forbidden: %d%s",
- conf->forbid_paging, VTY_NEWLINE);
- if (conf->description)
- vty_out(vty, " description: %s%s", conf->description, VTY_NEWLINE);
- else
- vty_out(vty, " No description.%s", VTY_NEWLINE);
-
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_stats,
- show_stats_cmd,
- "show statistics [NR]",
- SHOW_STR "Display network statistics")
-{
- struct bsc_config *conf;
-
- int nr = -1;
-
- if (argc == 1)
- nr = atoi(argv[0]);
-
- vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
- vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
- counter_get(_nat->stats.sccp.conn),
- counter_get(_nat->stats.sccp.calls), VTY_NEWLINE);
- vty_out(vty, " MSC Connections %lu%s",
- counter_get(_nat->stats.msc.reconn), VTY_NEWLINE);
- vty_out(vty, " BSC Connections %lu total, %lu auth failed.%s",
- counter_get(_nat->stats.bsc.reconn),
- counter_get(_nat->stats.bsc.auth_fail), VTY_NEWLINE);
-
- llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
- if (argc == 1 && nr != conf->nr)
- continue;
-
- vty_out(vty, " BSC lac: %d nr: %d%s",
- conf->lac, conf->nr, VTY_NEWLINE);
- vty_out(vty, " SCCP Connnections %lu total, %lu calls%s",
- counter_get(conf->stats.sccp.conn),
- counter_get(conf->stats.sccp.calls), VTY_NEWLINE);
- vty_out(vty, " BSC Connections %lu total%s",
- counter_get(conf->stats.net.reconn), VTY_NEWLINE);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_msc,
- show_msc_cmd,
- "show msc connection",
- SHOW_STR "Show the status of the MSC connection.")
-{
- if (!_nat->msc_con) {
- vty_out(vty, "The MSC is not yet configured.\n");
- return CMD_WARNING;
- }
-
- vty_out(vty, "MSC on %s:%d is connected: %d%s\n",
- _nat->msc_con->ip, _nat->msc_con->port,
- _nat->msc_con->is_connected, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-DEFUN(close_bsc,
- close_bsc_cmd,
- "close bsc connection BSC_NR",
- "Close the connection with the BSC identified by the config number.")
-{
- struct bsc_connection *bsc;
- int bsc_nr = atoi(argv[0]);
-
- llist_for_each_entry(bsc, &_nat->bsc_connections, list_entry) {
- if (!bsc->cfg || bsc->cfg->nr != bsc_nr)
- continue;
- bsc_close_connection(bsc);
- break;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
-{
- vty->index = _nat;
- vty->node = NAT_NODE;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_msc_ip,
- cfg_nat_msc_ip_cmd,
- "msc ip A.B.C.D",
- "Set the IP address of the MSC.")
-{
- bsc_nat_set_msc_ip(_nat, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_msc_port,
- cfg_nat_msc_port_cmd,
- "msc port <1-65500>",
- "Set the port of the MSC.")
-{
- _nat->msc_port = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_auth_time,
- cfg_nat_auth_time_cmd,
- "timeout auth <1-256>",
- "The time to wait for an auth response.")
-{
- _nat->auth_timeout = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ping_time,
- cfg_nat_ping_time_cmd,
- "timeout ping NR",
- "Send a ping every NR seconds. Negative to disable.")
-{
- _nat->ping_timeout = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_pong_time,
- cfg_nat_pong_time_cmd,
- "timeout pong NR",
- "Wait NR seconds for the PONG response. Should be smaller than ping.")
-{
- _nat->pong_timeout = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_token, cfg_nat_token_cmd,
- "token TOKEN",
- "Set a token for the NAT")
-{
- if (_nat->token)
- talloc_free(_nat->token);
- _nat->token = talloc_strdup(_nat, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_bsc_ip_tos, cfg_nat_bsc_ip_tos_cmd,
- "ip-tos <0-255>",
- "Set the IP_TOS for the BSCs to use\n" "Set the IP_TOS attribute")
-{
- _nat->bsc_ip_tos = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_acc_lst_name,
- cfg_nat_acc_lst_name_cmd,
- "access-list-name NAME",
- "Set the name of the access list to use.\n"
- "The name of the to be used access list.")
-{
- if (_nat->acc_lst_name)
- talloc_free(_nat->acc_lst_name);
- _nat->acc_lst_name = talloc_strdup(_nat, argv[0]);
- return CMD_SUCCESS;
-}
-
-/* per BSC configuration */
-DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure")
-{
- int bsc_nr = atoi(argv[0]);
- struct bsc_config *bsc;
-
- if (bsc_nr > _nat->num_bsc) {
- vty_out(vty, "%% The next unused BSC number is %u%s",
- _nat->num_bsc, VTY_NEWLINE);
- return CMD_WARNING;
- } else if (bsc_nr == _nat->num_bsc) {
- /* allocate a new one */
- bsc = bsc_config_alloc(_nat, "unknown", 0);
- } else
- bsc = bsc_config_num(_nat, bsc_nr);
-
- if (!bsc)
- return CMD_WARNING;
-
- vty->index = bsc;
- vty->node = BSC_NODE;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", "Set the token")
-{
- struct bsc_config *conf = vty->index;
-
- if (conf->token)
- talloc_free(conf->token);
- conf->token = talloc_strdup(conf, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
- "Set the Location Area Code (LAC) of this BSC")
-{
- struct bsc_config *tmp;
- struct bsc_config *conf = vty->index;
-
- int lac = atoi(argv[0]);
-
- if (lac == GSM_LAC_RESERVED_DETACHED || lac == GSM_LAC_RESERVED_ALL_BTS) {
- vty_out(vty, "%% LAC %d is reserved by GSM 04.08%s",
- lac, VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* verify that the LACs are unique */
- llist_for_each_entry(tmp, &_nat->bsc_configs, entry) {
- if (tmp->lac == lac) {
- vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE);
- return CMD_ERR_INCOMPLETE;
- }
- }
-
- conf->lac = lac;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_lst_imsi_allow,
- cfg_lst_imsi_allow_cmd,
- "access-list NAME imsi-allow [REGEXP]",
- "Allow IMSIs matching the REGEXP\n"
- "The name of the access-list\n"
- "The regexp of allowed IMSIs\n")
-{
- struct bsc_nat_acc_lst *acc;
- struct bsc_nat_acc_lst_entry *entry;
-
- acc = bsc_nat_acc_lst_get(_nat, argv[0]);
- if (!acc)
- return CMD_WARNING;
-
- entry = bsc_nat_acc_lst_entry_create(acc);
- if (!entry)
- return CMD_WARNING;
-
- bsc_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, argc - 1, &argv[1]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_lst_imsi_deny,
- cfg_lst_imsi_deny_cmd,
- "access-list NAME imsi-deny [REGEXP]",
- "Allow IMSIs matching the REGEXP\n"
- "The name of the access-list\n"
- "The regexp of to be denied IMSIs\n")
-{
- struct bsc_nat_acc_lst *acc;
- struct bsc_nat_acc_lst_entry *entry;
-
- acc = bsc_nat_acc_lst_get(_nat, argv[0]);
- if (!acc)
- return CMD_WARNING;
-
- entry = bsc_nat_acc_lst_entry_create(acc);
- if (!entry)
- return CMD_WARNING;
-
- bsc_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]);
- return CMD_SUCCESS;
-}
-
-/* naming to follow Zebra... */
-DEFUN(cfg_lst_no,
- cfg_lst_no_cmd,
- "no access-list NAME",
- NO_STR "Remove an access-list by name\n"
- "The access-list to remove\n")
-{
- struct bsc_nat_acc_lst *acc;
- acc = bsc_nat_acc_lst_find(_nat, argv[0]);
- if (!acc)
- return CMD_WARNING;
-
- bsc_nat_acc_lst_delete(acc);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_acc_lst_name,
- cfg_bsc_acc_lst_name_cmd,
- "access-list-name NAME",
- "Set the name of the access list to use.\n"
- "The name of the to be used access list.")
-{
- struct bsc_config *conf = vty->index;
-
- if (conf->acc_lst_name)
- talloc_free(conf->acc_lst_name);
- conf->acc_lst_name = talloc_strdup(conf, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_paging,
- cfg_bsc_paging_cmd,
- "paging forbidden (0|1)",
- "Forbid sending PAGING REQUESTS to the BSC.")
-{
- struct bsc_config *conf = vty->index;
-
- if (strcmp("1", argv[0]) == 0)
- conf->forbid_paging = 1;
- else
- conf->forbid_paging = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_desc,
- cfg_bsc_desc_cmd,
- "description DESC",
- "Provide a description for the given BSC.")
-{
- struct bsc_config *conf = vty->index;
-
- if (conf->description)
- talloc_free(conf->description);
- conf->description = talloc_strdup(conf, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(test_regex, test_regex_cmd,
- "test regex PATTERN STRING",
- "Check if the string is matching the current pattern.")
-{
- regex_t reg;
- char *str = NULL;
-
- memset(&reg, 0, sizeof(reg));
- bsc_parse_reg(_nat, &reg, &str, 1, argv);
-
- vty_out(vty, "String matches allow pattern: %d%s",
- regexec(&reg, argv[1], 0, NULL, 0) == 0, VTY_NEWLINE);
-
- talloc_free(str);
- regfree(&reg);
- return CMD_SUCCESS;
-}
-
-int bsc_nat_vty_init(struct bsc_nat *nat)
-{
- _nat = nat;
-
- cmd_init(1);
- vty_init();
-
- /* show commands */
- install_element(VIEW_NODE, &show_sccp_cmd);
- install_element(VIEW_NODE, &show_bsc_cmd);
- install_element(VIEW_NODE, &show_bsc_cfg_cmd);
- install_element(VIEW_NODE, &show_stats_cmd);
- install_element(VIEW_NODE, &close_bsc_cmd);
- install_element(VIEW_NODE, &show_msc_cmd);
- install_element(VIEW_NODE, &test_regex_cmd);
-
- openbsc_vty_add_cmds();
-
- /* nat group */
- install_element(CONFIG_NODE, &cfg_nat_cmd);
- install_node(&nat_node, config_write_nat);
- install_default(NAT_NODE);
- install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
- install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
- install_element(NAT_NODE, &cfg_nat_auth_time_cmd);
- install_element(NAT_NODE, &cfg_nat_ping_time_cmd);
- install_element(NAT_NODE, &cfg_nat_pong_time_cmd);
- install_element(NAT_NODE, &cfg_nat_token_cmd);
- install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd);
- install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd);
-
- /* access-list */
- install_element(NAT_NODE, &cfg_lst_imsi_allow_cmd);
- install_element(NAT_NODE, &cfg_lst_imsi_deny_cmd);
- install_element(NAT_NODE, &cfg_lst_no_cmd);
-
- /* BSC subgroups */
- install_element(NAT_NODE, &cfg_bsc_cmd);
- install_node(&bsc_node, config_write_bsc);
- install_default(BSC_NODE);
- install_element(BSC_NODE, &cfg_bsc_token_cmd);
- install_element(BSC_NODE, &cfg_bsc_lac_cmd);
- install_element(BSC_NODE, &cfg_bsc_paging_cmd);
- install_element(BSC_NODE, &cfg_bsc_desc_cmd);
- install_element(BSC_NODE, &cfg_bsc_acc_lst_name_cmd);
-
- mgcp_vty_init();
-
- return 0;
-}
-
-
-/* called by the telnet interface... we have our own init above */
-void bsc_vty_init()
-{}
diff --git a/openbsc/src/nat/bsc_sccp.c b/openbsc/src/nat/bsc_sccp.c
deleted file mode 100644
index d6b0bdb7f..000000000
--- a/openbsc/src/nat/bsc_sccp.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/* SCCP patching and handling routines */
-/*
- * (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/debug.h>
-#include <openbsc/bsc_nat.h>
-
-#include <sccp/sccp.h>
-
-#include <osmocore/talloc.h>
-
-#include <string.h>
-#include <time.h>
-
-static int equal(struct sccp_source_reference *ref1, struct sccp_source_reference *ref2)
-{
- return memcmp(ref1, ref2, sizeof(*ref1)) == 0;
-}
-
-/*
- * SCCP patching below
- */
-
-/* check if we are using this ref for patched already */
-static int sccp_ref_is_free(struct sccp_source_reference *ref, struct bsc_nat *nat)
-{
- struct sccp_connections *conn;
-
- llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
- if (memcmp(ref, &conn->patched_ref, sizeof(*ref)) == 0)
- return -1;
- }
-
- return 0;
-}
-
-/* copied from sccp.c */
-static int assign_src_local_reference(struct sccp_source_reference *ref, struct bsc_nat *nat)
-{
- static u_int32_t last_ref = 0x50000;
- int wrapped = 0;
-
- do {
- struct sccp_source_reference reference;
- reference.octet1 = (last_ref >> 0) & 0xff;
- reference.octet2 = (last_ref >> 8) & 0xff;
- reference.octet3 = (last_ref >> 16) & 0xff;
-
- ++last_ref;
- /* do not use the reversed word and wrap around */
- if ((last_ref & 0x00FFFFFF) == 0x00FFFFFF) {
- LOGP(DNAT, LOGL_NOTICE, "Wrapped searching for a free code\n");
- last_ref = 0;
- ++wrapped;
- }
-
- if (sccp_ref_is_free(&reference, nat) == 0) {
- *ref = reference;
- return 0;
- }
- } while (wrapped != 2);
-
- LOGP(DNAT, LOGL_ERROR, "Finding a free reference failed\n");
- return -1;
-}
-
-struct sccp_connections *create_sccp_src_ref(struct bsc_connection *bsc,
- struct bsc_nat_parsed *parsed)
-{
- struct sccp_connections *conn;
-
- /* Some commercial BSCs like to reassign there SRC ref */
- llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
- if (conn->bsc != bsc)
- continue;
- if (memcmp(&conn->real_ref, parsed->src_local_ref, sizeof(conn->real_ref)) != 0)
- continue;
-
- /* the BSC has reassigned the SRC ref and we failed to keep track */
- memset(&conn->remote_ref, 0, sizeof(conn->remote_ref));
- if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
- LOGP(DNAT, LOGL_ERROR, "BSC %d reused src ref: %d and we failed to generate a new id.\n",
- bsc->cfg->nr, sccp_src_ref_to_int(parsed->src_local_ref));
- bsc_mgcp_dlcx(conn);
- llist_del(&conn->list_entry);
- talloc_free(conn);
- return NULL;
- } else {
- clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
- bsc_mgcp_dlcx(conn);
- return conn;
- }
- }
-
-
- conn = talloc_zero(bsc->nat, struct sccp_connections);
- if (!conn) {
- LOGP(DNAT, LOGL_ERROR, "Memory allocation failure.\n");
- return NULL;
- }
-
- conn->bsc = bsc;
- clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
- conn->real_ref = *parsed->src_local_ref;
- if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
- LOGP(DNAT, LOGL_ERROR, "Failed to assign a ref.\n");
- talloc_free(conn);
- return NULL;
- }
-
- bsc_mgcp_init(conn);
- llist_add_tail(&conn->list_entry, &bsc->nat->sccp_connections);
- counter_inc(bsc->cfg->stats.sccp.conn);
- counter_inc(bsc->cfg->nat->stats.sccp.conn);
-
- LOGP(DNAT, LOGL_DEBUG, "Created 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), bsc);
-
- return conn;
-}
-
-int update_sccp_src_ref(struct sccp_connections *sccp, struct bsc_nat_parsed *parsed)
-{
- if (!parsed->dest_local_ref || !parsed->src_local_ref) {
- LOGP(DNAT, LOGL_ERROR, "CC MSG should contain both local and dest address.\n");
- return -1;
- }
-
- sccp->remote_ref = *parsed->src_local_ref;
- sccp->has_remote_ref = 1;
- LOGP(DNAT, LOGL_DEBUG, "Updating 0x%x to remote 0x%x on %p\n",
- sccp_src_ref_to_int(&sccp->patched_ref),
- sccp_src_ref_to_int(&sccp->remote_ref), sccp->bsc);
-
- return 0;
-}
-
-void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed)
-{
- struct sccp_connections *conn;
-
- llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
- if (memcmp(parsed->src_local_ref,
- &conn->patched_ref, sizeof(conn->patched_ref)) == 0) {
-
- sccp_connection_destroy(conn);
- return;
- }
- }
-
- LOGP(DNAT, LOGL_ERROR, "Can not remove connection: 0x%x\n",
- sccp_src_ref_to_int(parsed->src_local_ref));
-}
-
-/*
- * We have a message from the MSC to the BSC. The MSC is using
- * an address that was assigned by the MUX, we need to update the
- * dest reference to the real network.
- */
-struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *msg,
- struct bsc_nat_parsed *parsed,
- struct bsc_nat *nat)
-{
- struct sccp_connections *conn;
-
- if (!parsed->dest_local_ref) {
- LOGP(DNAT, LOGL_ERROR, "MSG should contain dest_local_ref.\n");
- return NULL;
- }
-
-
- llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
- if (!equal(parsed->dest_local_ref, &conn->patched_ref))
- continue;
-
- /* Change the dest address to the real one */
- *parsed->dest_local_ref = conn->real_ref;
- return conn;
- }
-
- return NULL;
-}
-
-/*
- * These are message to the MSC. We will need to find the BSC
- * Connection by either the SRC or the DST local reference.
- *
- * In case of a CR we need to work by the SRC local reference
- * in all other cases we need to work by the destination local
- * reference..
- */
-struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *msg,
- struct bsc_nat_parsed *parsed,
- struct bsc_connection *bsc)
-{
- struct sccp_connections *conn;
-
- llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
- if (conn->bsc != bsc)
- continue;
-
- if (parsed->src_local_ref) {
- if (equal(parsed->src_local_ref, &conn->real_ref)) {
- *parsed->src_local_ref = conn->patched_ref;
- return conn;
- }
- } else if (parsed->dest_local_ref) {
- if (equal(parsed->dest_local_ref, &conn->remote_ref))
- return conn;
- } else {
- LOGP(DNAT, LOGL_ERROR, "Header has neither loc/dst ref.\n");
- return NULL;
- }
- }
-
- return NULL;
-}
-
diff --git a/openbsc/src/vty/command.c b/openbsc/src/vty/command.c
index d46a1bedb..310a74e28 100644
--- a/openbsc/src/vty/command.c
+++ b/openbsc/src/vty/command.c
@@ -47,7 +47,6 @@ Boston, MA 02111-1307, USA. */
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
-#include <openbsc/bsc_nat.h>
#include <osmocore/talloc.h>
void *tall_vty_cmd_ctx;
@@ -1950,13 +1949,6 @@ enum node_type vty_go_parent(struct vty *vty)
subscr_put(vty->index);
vty->index = NULL;
break;
- case BSC_NODE:
- vty->node = NAT_NODE;
- {
- struct bsc_config *bsc = vty->index;
- vty->index = bsc->nat;
- }
- break;
default:
vty->node = CONFIG_NODE;
}
@@ -2373,14 +2365,6 @@ DEFUN(config_exit,
case MGCP_NODE:
vty->node = CONFIG_NODE;
vty->index = NULL;
- case NAT_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- break;
- case BSC_NODE:
- vty->node = NAT_NODE;
- vty->index = NULL;
- break;
default:
break;
diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am
index b469832fc..3b1b93120 100644
--- a/openbsc/tests/Makefile.am
+++ b/openbsc/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS = debug gsm0408 db channel sccp bsc-nat
+SUBDIRS = debug gsm0408 db channel sccp
diff --git a/openbsc/tests/bsc-nat/Makefile.am b/openbsc/tests/bsc-nat/Makefile.am
deleted file mode 100644
index 091c8fec7..000000000
--- a/openbsc/tests/bsc-nat/Makefile.am
+++ /dev/null
@@ -1,17 +0,0 @@
-INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS)
-
-EXTRA_DIST = bsc_data.c
-
-noinst_PROGRAMS = bsc_nat_test
-
-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/mgcp/mgcp_protocol.c \
- $(top_srcdir)/src/mgcp/mgcp_network.c \
- $(top_srcdir)/src/bssap.c
-bsc_nat_test_LDADD = $(top_builddir)/src/libbsc.a $(top_builddir)/src/libsccp.a $(LIBOSMOCORE_LIBS) -lrt
-
diff --git a/openbsc/tests/bsc-nat/bsc_data.c b/openbsc/tests/bsc-nat/bsc_data.c
deleted file mode 100644
index 34242db8c..000000000
--- a/openbsc/tests/bsc-nat/bsc_data.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* test data */
-
-/* BSC -> MSC, CR */
-static const u_int8_t bsc_cr[] = {
-0x00, 0x2e, 0xfd,
-0x01, 0x00, 0x00, 0x15, 0x02, 0x02, 0x04, 0x02,
-0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
-0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x1c, 0xc3,
-0x51, 0x17, 0x12, 0x05, 0x08, 0x20, 0x72, 0xf4,
-0x90, 0x20, 0x1d, 0x50, 0x08, 0x29, 0x47, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
-
-static const u_int8_t bsc_cr_patched[] = {
-0x00, 0x2e, 0xfd,
-0x01, 0x00, 0x00, 0x05, 0x02, 0x02, 0x04, 0x02,
-0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
-0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x1c, 0xc3,
-0x51, 0x17, 0x12, 0x05, 0x08, 0x20, 0x72, 0xf4,
-0x90, 0x20, 0x1d, 0x50, 0x08, 0x29, 0x47, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
-
-/* CC, MSC -> BSC */
-static const u_int8_t msc_cc[] = {
-0x00, 0x0a, 0xfd,
-0x02, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x02,
-0x01, 0x00 };
-static const u_int8_t msc_cc_patched[] = {
-0x00, 0x0a, 0xfd,
-0x02, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x02,
-0x01, 0x00 };
-
-/* Classmark, BSC -> MSC */
-static const u_int8_t bsc_dtap[] = {
-0x00, 0x17, 0xfd,
-0x06, 0x01, 0x1f, 0xe4, 0x00, 0x01, 0x10, 0x00,
-0x0e, 0x54, 0x12, 0x03, 0x50, 0x18, 0x93, 0x13,
-0x06, 0x60, 0x14, 0x45, 0x00, 0x81, 0x00 };
-
-static const u_int8_t bsc_dtap_patched[] = {
-0x00, 0x17, 0xfd,
-0x06, 0x01, 0x1f, 0xe4, 0x00, 0x01, 0x10, 0x00,
-0x0e, 0x54, 0x12, 0x03, 0x50, 0x18, 0x93, 0x13,
-0x06, 0x60, 0x14, 0x45, 0x00, 0x81, 0x00 };
-
-/* Clear command, MSC -> BSC */
-static const u_int8_t msc_dtap[] = {
-0x00, 0x0d, 0xfd,
-0x06, 0x00, 0x00, 0x05, 0x00, 0x01, 0x06, 0x00,
-0x04, 0x20, 0x04, 0x01, 0x09 };
-static const u_int8_t msc_dtap_patched[] = {
-0x00, 0x0d, 0xfd,
-0x06, 0x00, 0x00, 0x15, 0x00, 0x01, 0x06, 0x00,
-0x04, 0x20, 0x04, 0x01, 0x09 };
-
-/*RLSD, MSC -> BSC */
-static const u_int8_t msc_rlsd[] = {
-0x00, 0x0a, 0xfd,
-0x04, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x00,
-0x01, 0x00 };
-static const u_int8_t msc_rlsd_patched[] = {
-0x00, 0x0a, 0xfd,
-0x04, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x00,
-0x01, 0x00 };
-
-/* RLC, BSC -> MSC */
-static const u_int8_t bsc_rlc[] = {
-0x00, 0x07, 0xfd,
-0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x15 };
-
-static const u_int8_t bsc_rlc_patched[] = {
-0x00, 0x07, 0xfd,
-0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x05 };
-
-
-/* a paging command */
-static const u_int8_t paging_by_lac_cmd[] = {
-0x00, 0x22, 0xfd, 0x09,
-0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x02, 0x00,
-0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x12, 0x00,
-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 };
-
-/*
- * MGCP messages
- */
-
-/* nothing to patch */
-static const char crcx[] = "CRCX 23265295 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n";
-static const char crcx_patched[] = "CRCX 23265295 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n";
-
-
-/* patch the ip and port */
-static const char crcx_resp[] = "200 23265295\r\nI: 1\r\n\r\nv=0\r\nc=IN IP4 172.16.18.2\r\nm=audio 4002 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
-static const char crcx_resp_patched[] = "200 23265295\r\nI: 1\r\n\r\nv=0\r\nc=IN IP4 10.0.0.1\r\nm=audio 999 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
-
-/* patch the ip and port */
-static const char mdcx[] = " MDCX 23330829 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nI: 1\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 1049380491 0 IN IP4 172.16.18.2\r\ns=-\r\nc=IN IP4 172.16.18.2\r\nt=0 0\r\nm=audio 4410 RTP/AVP 126\r\na=rtpmap:126 AMR/8000/1\r\na=fmtp:126 mode-set=2;start-mode=0\r\na=ptime:20\r\na=recvonly\r\nm=image 4412 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n";
-static const char mdcx_patched[] = " MDCX 23330829 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nI: 1\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 1049380491 0 IN IP4 172.16.18.2\r\ns=-\r\nc=IN IP4 10.0.0.23\r\nt=0 0\r\nm=audio 6666 RTP/AVP 126\r\na=rtpmap:126 AMR/8000/1\r\na=fmtp:126 mode-set=2;start-mode=0\r\na=ptime:20\r\na=recvonly\r\nm=image 4412 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n";
-
-
-static const char mdcx_resp[] = "200 23330829\r\n\r\nv=0\r\nc=IN IP4 172.16.18.2\r\nm=audio 4002 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
-static const char mdcx_resp_patched[] = "200 23330829\r\n\r\nv=0\r\nc=IN IP4 10.0.0.23\r\nm=audio 5555 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
-
-/* different line ending */
-static const char mdcx_resp2[] = "200 33330829\n\nv=0\nc=IN IP4 172.16.18.2\nm=audio 4002 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
-static const char mdcx_resp_patched2[] = "200 33330829\n\nv=0\nc=IN IP4 10.0.0.23\nm=audio 5555 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
-
-struct mgcp_patch_test {
- const char *orig;
- const char *patch;
- const char *ip;
- const int port;
-};
-
-static const struct mgcp_patch_test mgcp_messages[] = {
- {
- .orig = crcx,
- .patch = crcx_patched,
- .ip = "0.0.0.0",
- .port = 2323,
- },
- {
- .orig = crcx_resp,
- .patch = crcx_resp_patched,
- .ip = "10.0.0.1",
- .port = 999,
- },
- {
- .orig = mdcx,
- .patch = mdcx_patched,
- .ip = "10.0.0.23",
- .port = 6666,
- },
- {
- .orig = mdcx_resp,
- .patch = mdcx_resp_patched,
- .ip = "10.0.0.23",
- .port = 5555,
- },
- {
- .orig = mdcx_resp2,
- .patch = mdcx_resp_patched2,
- .ip = "10.0.0.23",
- .port = 5555,
- },
-};
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
deleted file mode 100644
index 0c5b8fd51..000000000
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * BSC NAT Message filtering
- *
- * (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/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/bsc_nat.h>
-
-#include <osmocore/talloc.h>
-
-#include <stdio.h>
-
-/* test messages for ipa */
-static u_int8_t ipa_id[] = {
- 0x00, 0x01, 0xfe, 0x06,
-};
-
-/* SCCP messages are below */
-static u_int8_t gsm_reset[] = {
- 0x00, 0x12, 0xfd,
- 0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
- 0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
- 0x01, 0x20,
-};
-
-static const u_int8_t gsm_reset_ack[] = {
- 0x00, 0x13, 0xfd,
- 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
- 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
- 0x00, 0x01, 0x31,
-};
-
-static const u_int8_t gsm_paging[] = {
- 0x00, 0x20, 0xfd,
- 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
- 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x10,
- 0x00, 0x0e, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10,
- 0x02, 0x01, 0x31, 0x97, 0x61, 0x1a, 0x01, 0x06,
-};
-
-/* BSC -> MSC connection open */
-static const u_int8_t bssmap_cr[] = {
- 0x00, 0x2c, 0xfd,
- 0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x04, 0x02,
- 0x42, 0xfe, 0x0f, 0x1f, 0x00, 0x1d, 0x57, 0x05,
- 0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x12, 0xc3,
- 0x50, 0x17, 0x10, 0x05, 0x24, 0x11, 0x03, 0x33,
- 0x19, 0xa2, 0x08, 0x29, 0x47, 0x10, 0x02, 0x01,
- 0x31, 0x97, 0x61, 0x00
-};
-
-/* MSC -> BSC connection confirm */
-static const u_int8_t bssmap_cc[] = {
- 0x00, 0x0a, 0xfd,
- 0x02, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
-};
-
-/* MSC -> BSC released */
-static const u_int8_t bssmap_released[] = {
- 0x00, 0x0e, 0xfd,
- 0x04, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00, 0x01, 0x0f,
- 0x02, 0x23, 0x42, 0x00,
-};
-
-/* BSC -> MSC released */
-static const u_int8_t bssmap_release_complete[] = {
- 0x00, 0x07, 0xfd,
- 0x05, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03
-};
-
-/* both directions IT timer */
-static const u_int8_t connnection_it[] = {
- 0x00, 0x0b, 0xfd,
- 0x10, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,
- 0x00, 0x00, 0x00, 0x00,
-};
-
-/* error in both directions */
-static const u_int8_t proto_error[] = {
- 0x00, 0x05, 0xfd,
- 0x0f, 0x22, 0x33, 0x44, 0x00,
-};
-
-/* MGCP wrap... */
-static const u_int8_t mgcp_msg[] = {
- 0x00, 0x03, 0xfc,
- 0x20, 0x20, 0x20,
-};
-
-/* location updating request */
-static const u_int8_t bss_lu[] = {
- 0x00, 0x2e, 0xfd,
- 0x01, 0x91, 0x45, 0x14, 0x02, 0x02, 0x04, 0x02,
- 0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
- 0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x14, 0xc3,
- 0x50, 0x17, 0x12, 0x05, 0x08, 0x70, 0x72, 0xf4,
- 0x80, 0xff, 0xfe, 0x30, 0x08, 0x29, 0x44, 0x50,
- 0x12, 0x03, 0x24, 0x01, 0x95, 0x00
-};
-
-/* paging response */
-static const uint8_t pag_resp[] = {
- 0x00, 0x2c, 0xfd, 0x01, 0xe5, 0x68,
- 0x14, 0x02, 0x02, 0x04, 0x02, 0x42, 0xfe, 0x0f,
- 0x1f, 0x00, 0x1d, 0x57, 0x05, 0x08, 0x00, 0x72,
- 0xf4, 0x80, 0x20, 0x16, 0xc3, 0x50, 0x17, 0x10,
- 0x06, 0x27, 0x01, 0x03, 0x30, 0x18, 0x96, 0x08,
- 0x29, 0x26, 0x30, 0x32, 0x11, 0x42, 0x01, 0x19,
- 0x00
-};
-
-struct filter_result {
- const u_int8_t *data;
- const u_int16_t length;
- const int dir;
- const int result;
-};
-
-static const struct filter_result results[] = {
- {
- .data = ipa_id,
- .length = ARRAY_SIZE(ipa_id),
- .dir = DIR_MSC,
- .result = 1,
- },
- {
- .data = gsm_reset,
- .length = ARRAY_SIZE(gsm_reset),
- .dir = DIR_MSC,
- .result = 1,
- },
- {
- .data = gsm_reset_ack,
- .length = ARRAY_SIZE(gsm_reset_ack),
- .dir = DIR_BSC,
- .result = 1,
- },
- {
- .data = gsm_paging,
- .length = ARRAY_SIZE(gsm_paging),
- .dir = DIR_BSC,
- .result = 0,
- },
- {
- .data = bssmap_cr,
- .length = ARRAY_SIZE(bssmap_cr),
- .dir = DIR_MSC,
- .result = 0,
- },
- {
- .data = bssmap_cc,
- .length = ARRAY_SIZE(bssmap_cc),
- .dir = DIR_BSC,
- .result = 0,
- },
- {
- .data = bssmap_released,
- .length = ARRAY_SIZE(bssmap_released),
- .dir = DIR_MSC,
- .result = 0,
- },
- {
- .data = bssmap_release_complete,
- .length = ARRAY_SIZE(bssmap_release_complete),
- .dir = DIR_BSC,
- .result = 0,
- },
- {
- .data = mgcp_msg,
- .length = ARRAY_SIZE(mgcp_msg),
- .dir = DIR_MSC,
- .result = 0,
- },
- {
- .data = connnection_it,
- .length = ARRAY_SIZE(connnection_it),
- .dir = DIR_BSC,
- .result = 0,
- },
- {
- .data = connnection_it,
- .length = ARRAY_SIZE(connnection_it),
- .dir = DIR_MSC,
- .result = 0,
- },
- {
- .data = proto_error,
- .length = ARRAY_SIZE(proto_error),
- .dir = DIR_BSC,
- .result = 0,
- },
- {
- .data = proto_error,
- .length = ARRAY_SIZE(proto_error),
- .dir = DIR_MSC,
- .result = 0,
- },
-
-};
-
-static void test_filter(void)
-{
- int i;
-
-
- /* start testinh with proper messages */
- fprintf(stderr, "Testing BSS Filtering.\n");
- for (i = 0; i < ARRAY_SIZE(results); ++i) {
- int result;
- struct bsc_nat_parsed *parsed;
- struct msgb *msg = msgb_alloc(4096, "test-message");
-
- fprintf(stderr, "Going to test item: %d\n", i);
- memcpy(msg->data, results[i].data, results[i].length);
- msg->l2h = msgb_put(msg, results[i].length);
-
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- fprintf(stderr, "FAIL: Failed to parse the message\n");
- continue;
- }
-
- result = bsc_nat_filter_ipa(results[i].dir, msg, parsed);
- if (result != results[i].result) {
- fprintf(stderr, "FAIL: Not the expected result got: %d wanted: %d\n",
- result, results[i].result);
- }
-
- msgb_free(msg);
- }
-}
-
-#include "bsc_data.c"
-
-static void copy_to_msg(struct msgb *msg, const u_int8_t *data, unsigned int length)
-{
- msgb_reset(msg);
- msg->l2h = msgb_put(msg, length);
- memcpy(msg->l2h, data, msgb_l2len(msg));
-}
-
-#define VERIFY(con_found, con, msg, ver, str) \
- if (!con_found || con_found->bsc != con) { \
- fprintf(stderr, "Failed to find the con: %p\n", con_found); \
- abort(); \
- } \
- if (memcmp(msg->data, ver, sizeof(ver)) != 0) { \
- fprintf(stderr, "Failed to patch the %s msg.\n", str); \
- abort(); \
- }
-
-/* test conn tracking once */
-static void test_contrack()
-{
- struct bsc_nat *nat;
- struct bsc_connection *con;
- struct sccp_connections *con_found;
- struct sccp_connections *rc_con;
- struct bsc_nat_parsed *parsed;
- struct msgb *msg;
-
- fprintf(stderr, "Testing connection tracking.\n");
- nat = bsc_nat_alloc();
- con = bsc_connection_alloc(nat);
- con->cfg = bsc_config_alloc(nat, "foo", 23);
- msg = msgb_alloc(4096, "test");
-
- /* 1.) create a connection */
- copy_to_msg(msg, bsc_cr, sizeof(bsc_cr));
- parsed = bsc_nat_parse(msg);
- con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
- if (con_found != NULL) {
- fprintf(stderr, "Con should not exist %p\n", con_found);
- abort();
- }
- rc_con = create_sccp_src_ref(con, parsed);
- if (!rc_con) {
- fprintf(stderr, "Failed to create a ref\n");
- abort();
- }
- con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
- if (!con_found || con_found->bsc != con) {
- fprintf(stderr, "Failed to find the con: %p\n", con_found);
- abort();
- }
- if (con_found != rc_con) {
- fprintf(stderr, "Failed to find the right connection.\n");
- abort();
- }
- if (memcmp(msg->data, bsc_cr_patched, sizeof(bsc_cr_patched)) != 0) {
- fprintf(stderr, "Failed to patch the BSC CR msg.\n");
- abort();
- }
- talloc_free(parsed);
-
- /* 2.) get the cc */
- copy_to_msg(msg, msc_cc, sizeof(msc_cc));
- parsed = bsc_nat_parse(msg);
- con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
- VERIFY(con_found, con, msg, msc_cc_patched, "MSC CC");
- if (update_sccp_src_ref(con_found, parsed) != 0) {
- fprintf(stderr, "Failed to update the SCCP con.\n");
- abort();
- }
-
- /* 3.) send some data */
- copy_to_msg(msg, bsc_dtap, sizeof(bsc_dtap));
- parsed = bsc_nat_parse(msg);
- con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
- VERIFY(con_found, con, msg, bsc_dtap_patched, "BSC DTAP");
-
- /* 4.) receive some data */
- copy_to_msg(msg, msc_dtap, sizeof(msc_dtap));
- parsed = bsc_nat_parse(msg);
- con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
- VERIFY(con_found, con, msg, msc_dtap_patched, "MSC DTAP");
-
- /* 5.) close the connection */
- copy_to_msg(msg, msc_rlsd, sizeof(msc_rlsd));
- parsed = bsc_nat_parse(msg);
- con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
- VERIFY(con_found, con, msg, msc_rlsd_patched, "MSC RLSD");
-
- /* 6.) confirm the connection close */
- copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
- parsed = bsc_nat_parse(msg);
- con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
- if (!con_found || con_found->bsc != con) {
- fprintf(stderr, "Failed to find the con: %p\n", con_found);
- abort();
- }
- if (memcmp(msg->data, bsc_rlc_patched, sizeof(bsc_rlc_patched)) != 0) {
- fprintf(stderr, "Failed to patch the BSC CR msg.\n");
- abort();
- }
- remove_sccp_src_ref(con, msg, parsed);
- talloc_free(parsed);
-
- copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
- parsed = bsc_nat_parse(msg);
- con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
-
- /* verify that it is gone */
- if (con_found != NULL) {
- fprintf(stderr, "Con should be gone. %p\n", con_found);
- abort();
- }
- talloc_free(parsed);
-
-
- talloc_free(nat);
- msgb_free(msg);
-}
-
-static void test_paging(void)
-{
- int lac;
- struct bsc_nat *nat;
- struct bsc_connection *con;
- struct bsc_nat_parsed *parsed;
- struct bsc_config cfg;
- struct msgb *msg;
-
- fprintf(stderr, "Testing paging by lac.\n");
-
- nat = bsc_nat_alloc();
- con = bsc_connection_alloc(nat);
- con->cfg = &cfg;
- cfg.lac = 23;
- con->authenticated = 1;
- llist_add(&con->list_entry, &nat->bsc_connections);
- msg = msgb_alloc(4096, "test");
-
- /* Test completely bad input */
- copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
- if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
- fprintf(stderr, "Should have not found anything.\n");
- abort();
- }
-
- /* Test it by not finding it */
- copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
- parsed = bsc_nat_parse(msg);
- if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
- fprintf(stderr, "Should have not found aynthing.\n");
- abort();
- }
- talloc_free(parsed);
-
- /* Test by finding it */
- cfg.lac = 8213;
- copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
- parsed = bsc_nat_parse(msg);
- if (bsc_nat_find_bsc(nat, msg, &lac) != con) {
- fprintf(stderr, "Should have found it.\n");
- abort();
- }
- talloc_free(parsed);
-}
-
-static void test_mgcp_ass_tracking(void)
-{
- struct bsc_connection *bsc;
- struct bsc_nat *nat;
- struct sccp_connections con;
- struct bsc_nat_parsed *parsed;
- struct msgb *msg;
-
- fprintf(stderr, "Testing MGCP.\n");
- memset(&con, 0, sizeof(con));
-
- nat = bsc_nat_alloc();
- nat->bsc_endpoints = talloc_zero_array(nat,
- struct bsc_endpoint,
- 33);
- bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo", 2323);
- con.bsc = bsc;
-
- 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_dlcx(&con);
- if (con.bsc_timeslot != -1 || con.msc_timeslot != -1) {
- fprintf(stderr, "Clearing should remove the mapping.\n");
- abort();
- }
-
- talloc_free(nat);
-}
-
-/* test the code to find a given connection */
-static void test_mgcp_find(void)
-{
- struct bsc_nat *nat;
- struct bsc_connection *con;
- struct sccp_connections *sccp_con;
-
- fprintf(stderr, "Testing finding of a BSC Connection\n");
-
- nat = bsc_nat_alloc();
- con = bsc_connection_alloc(nat);
- llist_add(&con->list_entry, &nat->bsc_connections);
-
- sccp_con = talloc_zero(con, struct sccp_connections);
- sccp_con->msc_timeslot = 12;
- sccp_con->bsc_timeslot = 12;
- sccp_con->bsc = con;
- llist_add(&sccp_con->list_entry, &nat->sccp_connections);
-
- if (bsc_mgcp_find_con(nat, 11) != NULL) {
- fprintf(stderr, "Found the wrong connection.\n");
- abort();
- }
-
- if (bsc_mgcp_find_con(nat, 12) != sccp_con) {
- fprintf(stderr, "Didn't find the connection\n");
- abort();
- }
-
- sccp_con->msc_timeslot = 0;
- sccp_con->bsc_timeslot = 0;
- if (bsc_mgcp_find_con(nat, 1) != sccp_con) {
- fprintf(stderr, "Didn't find the connection\n");
- abort();
- }
-
- /* free everything */
- talloc_free(nat);
-}
-
-static void test_mgcp_rewrite(void)
-{
- int i;
- struct msgb *output;
- fprintf(stderr, "Test rewriting MGCP messages.\n");
-
- for (i = 0; i < ARRAY_SIZE(mgcp_messages); ++i) {
- const char *orig = mgcp_messages[i].orig;
- const char *patc = mgcp_messages[i].patch;
- const char *ip = mgcp_messages[i].ip;
- const int port = mgcp_messages[i].port;
-
- char *input = strdup(orig);
-
- output = bsc_mgcp_rewrite(input, strlen(input), ip, port);
- if (msgb_l2len(output) != strlen(patc)) {
- fprintf(stderr, "Wrong sizes for test: %d %d != %d != %d\n", i, msgb_l2len(output), strlen(patc), strlen(orig));
- fprintf(stderr, "String '%s' vs '%s'\n", (const char *) output->l2h, patc);
- abort();
- }
-
- if (memcmp(output->l2h, patc, msgb_l2len(output)) != 0) {
- fprintf(stderr, "Broken on %d msg: '%s'\n", i, (const char *) output->l2h);
- abort();
- }
-
- msgb_free(output);
- free(input);
- }
-}
-
-static void test_mgcp_parse(void)
-{
- int code, ci;
- char transaction[60];
-
- fprintf(stderr, "Test MGCP response parsing.\n");
-
- if (bsc_mgcp_parse_response(crcx_resp, &code, transaction) != 0) {
- fprintf(stderr, "Failed to parse CRCX resp.\n");
- abort();
- }
-
- if (code != 200) {
- fprintf(stderr, "Failed to parse the CODE properly. Got: %d\n", code);
- abort();
- }
-
- if (strcmp(transaction, "23265295") != 0) {
- fprintf(stderr, "Failed to parse transaction id: '%s'\n", transaction);
- abort();
- }
-
- ci = bsc_mgcp_extract_ci(crcx_resp);
- if (ci != 1) {
- fprintf(stderr, "Failed to parse the CI. Got: %d\n", ci);
- abort();
- }
-}
-
-struct cr_filter {
- const u_int8_t *data;
- int length;
- int result;
- int contype;
-
- const char *bsc_imsi_allow;
- const char *bsc_imsi_deny;
- const char *nat_imsi_deny;
-};
-
-static struct cr_filter cr_filter[] = {
- {
- .data = bssmap_cr,
- .length = sizeof(bssmap_cr),
- .result = 0,
- .contype = NAT_CON_TYPE_CM_SERV_REQ,
- },
- {
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = 0,
- .contype = NAT_CON_TYPE_LU,
- },
- {
- .data = pag_resp,
- .length = sizeof(pag_resp),
- .result = 0,
- .contype = NAT_CON_TYPE_PAG_RESP,
- },
- {
- /* nat deny is before blank/null BSC */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = -3,
- .nat_imsi_deny = "[0-9]*",
- .contype = NAT_CON_TYPE_LU,
- },
- {
- /* BSC allow is before NAT deny */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = 0,
- .nat_imsi_deny = "[0-9]*",
- .bsc_imsi_allow = "2440[0-9]*",
- .contype = NAT_CON_TYPE_LU,
- },
- {
- /* BSC allow is before NAT deny */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = 0,
- .bsc_imsi_allow = "[0-9]*",
- .nat_imsi_deny = "[0-9]*",
- .contype = NAT_CON_TYPE_LU,
- },
- {
- /* filter as deny is first */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = -2,
- .bsc_imsi_deny = "[0-9]*",
- .bsc_imsi_allow = "[0-9]*",
- .nat_imsi_deny = "[0-9]*",
- .contype = NAT_CON_TYPE_LU,
- },
-
-};
-
-static void test_cr_filter()
-{
- int i, res, contype;
- struct msgb *msg = msgb_alloc(4096, "test_cr_filter");
- struct bsc_nat_parsed *parsed;
- struct bsc_nat_acc_lst *nat_lst, *bsc_lst;
- struct bsc_nat_acc_lst_entry *nat_entry, *bsc_entry;
-
- struct bsc_nat *nat = bsc_nat_alloc();
- struct bsc_connection *bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo", 1234);
- bsc->cfg->acc_lst_name = "bsc";
- nat->acc_lst_name = "nat";
-
- nat_lst = bsc_nat_acc_lst_get(nat, "nat");
- bsc_lst = bsc_nat_acc_lst_get(nat, "bsc");
-
- bsc_entry = bsc_nat_acc_lst_entry_create(bsc_lst);
- nat_entry = bsc_nat_acc_lst_entry_create(nat_lst);
-
- for (i = 0; i < ARRAY_SIZE(cr_filter); ++i) {
- msgb_reset(msg);
- copy_to_msg(msg, cr_filter[i].data, cr_filter[i].length);
-
- nat_lst = bsc_nat_acc_lst_get(nat, "nat");
- bsc_lst = bsc_nat_acc_lst_get(nat, "bsc");
-
- bsc_parse_reg(nat_entry, &nat_entry->imsi_deny_re, &nat_entry->imsi_deny,
- cr_filter[i].nat_imsi_deny ? 1 : 0,
- &cr_filter[i].nat_imsi_deny);
- bsc_parse_reg(bsc_entry, &bsc_entry->imsi_allow_re, &bsc_entry->imsi_allow,
- cr_filter[i].bsc_imsi_allow ? 1 : 0,
- &cr_filter[i].bsc_imsi_allow);
- bsc_parse_reg(bsc_entry, &bsc_entry->imsi_deny_re, &bsc_entry->imsi_deny,
- cr_filter[i].bsc_imsi_deny ? 1 : 0,
- &cr_filter[i].bsc_imsi_deny);
-
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- fprintf(stderr, "FAIL: Failed to parse the message\n");
- abort();
- }
-
- res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype);
- if (res != cr_filter[i].result) {
- fprintf(stderr, "FAIL: Wrong result %d for test %d.\n", res, i);
- abort();
- }
-
- if (contype != cr_filter[i].contype) {
- fprintf(stderr, "FAIL: Wrong contype %d for test %d.\n", res, contype);
- abort();
- }
-
- talloc_free(parsed);
- }
-
- msgb_free(msg);
-}
-
-int main(int argc, char **argv)
-{
- struct log_target *stderr_target;
-
- log_init(&log_info);
- stderr_target = log_target_create_stderr();
- log_add_target(stderr_target);
- log_set_all_filter(stderr_target, 1);
-
- test_filter();
- test_contrack();
- test_paging();
- test_mgcp_ass_tracking();
- test_mgcp_find();
- test_mgcp_rewrite();
- test_mgcp_parse();
- test_cr_filter();
- return 0;
-}
-
-void input_event()
-{}
-int nm_state_event()
-{
- return -1;
-}
-
-int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
-{
- return -1;
-}