aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-05-26 21:10:13 +0200
committerHarald Welte <laforge@gnumonks.org>2018-05-27 17:48:49 +0200
commit1c9b8b19176854ecf4a3d57e9eef6b495361557f (patch)
tree19f8e088476c42f1d29a17d5298339fc0d230251
parent7b897dfea5bdebba5ffba555c4ca29af96c35695 (diff)
remove remaining bits of osmo-bsc_nat
osmo-bsc_nat is too heavily tied into legacy SCCPlite code, as it is not using libosmo-sigtran/osmo_ss7 so far. It's also full of customer-specific code and it's shared use of some libbsc code here has been complicating osmo-bsc development. The current plan is to continue to use osmo-bsc_nat from openbsc.git for those legacy users that need it, and not use osmo-bsc_nat in new 3GPP AoIP setups. Should we ever get a strong demand for an AoIP based bsc_nat, we can still revisit this later. Change-Id: Ia05dc76336a64a7f08962843b9a7cc19f2c83387
-rw-r--r--configure.ac6
-rw-r--r--debian/control1
-rw-r--r--doc/examples/osmo-bsc_nat/black-list.cfg1
-rw-r--r--doc/examples/osmo-bsc_nat/bscs.cfg13
-rw-r--r--doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg66
-rw-r--r--include/osmocom/bsc/Makefile.am4
-rw-r--r--include/osmocom/bsc/bsc_nat.h469
-rw-r--r--include/osmocom/bsc/bsc_nat_callstats.h55
-rw-r--r--include/osmocom/bsc/bsc_nat_sccp.h105
-rw-r--r--include/osmocom/bsc/nat_rewrite_trie.h47
-rw-r--r--src/libfilter/bsc_msg_acc.c3
-rw-r--r--src/libfilter/bsc_msg_filter.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_msc.c1
-rw-r--r--src/osmo-bsc_nat/Makefile.am51
-rw-r--r--src/osmo-bsc_nat/bsc_filter.c220
-rw-r--r--src/osmo-bsc_nat/bsc_mgcp_utils.c1162
-rw-r--r--src/osmo-bsc_nat/bsc_nat.c1819
-rw-r--r--src/osmo-bsc_nat/bsc_nat_ctrl.c531
-rw-r--r--src/osmo-bsc_nat/bsc_nat_filter.c119
-rw-r--r--src/osmo-bsc_nat/bsc_nat_rewrite.c730
-rw-r--r--src/osmo-bsc_nat/bsc_nat_rewrite_trie.c259
-rw-r--r--src/osmo-bsc_nat/bsc_nat_utils.c535
-rw-r--r--src/osmo-bsc_nat/bsc_nat_vty.c1408
-rw-r--r--src/osmo-bsc_nat/bsc_sccp.c247
-rw-r--r--src/osmo-bsc_nat/bsc_ussd.c452
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/bsc-nat-trie/Makefile.am19
-rw-r--r--tests/bsc-nat-trie/bsc_nat_trie_test.c95
-rw-r--r--tests/bsc-nat-trie/bsc_nat_trie_test.ok20
-rw-r--r--tests/bsc-nat-trie/prefixes.csv25
-rw-r--r--tests/bsc-nat/Makefile.am58
-rw-r--r--tests/bsc-nat/barr.cfg12
-rw-r--r--tests/bsc-nat/barr_dup.cfg2
-rw-r--r--tests/bsc-nat/bsc_data.c275
-rw-r--r--tests/bsc-nat/bsc_nat_test.c1595
-rw-r--r--tests/bsc-nat/bsc_nat_test.ok39
-rw-r--r--tests/bsc-nat/prefixes.csv2
-rw-r--r--tests/testsuite.at7
-rwxr-xr-xtests/vty_test_runner.py352
39 files changed, 2 insertions, 10806 deletions
diff --git a/configure.ac b/configure.ac
index ccfce19b0..bcf890cee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,10 +49,6 @@ PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 0.9.0)
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.9.0)
PKG_CHECK_MODULES(LIBOSMOMGCPCLIENT, libosmo-mgcp-client >= 1.3.0)
-#NOTE: osmo-bsc does not depend on libosmo-legacy-mgcp anymore, but we still
-# need the dependancy for osmo-bsc-nat, which still uses the old API.
-PKG_CHECK_MODULES(LIBOSMOLEGACYMGCP, libosmo-legacy-mgcp >= 1.3.0)
-
dnl checks for header files
AC_HEADER_STDC
@@ -182,8 +178,6 @@ AC_OUTPUT(
tests/gsm0408/Makefile
tests/channel/Makefile
tests/bsc/Makefile
- tests/bsc-nat/Makefile
- tests/bsc-nat-trie/Makefile
tests/abis/Makefile
tests/subscr/Makefile
tests/nanobts_omlattr/Makefile
diff --git a/debian/control b/debian/control
index c2627a1c6..03e5a14e2 100644
--- a/debian/control
+++ b/debian/control
@@ -16,7 +16,6 @@ Build-Depends: debhelper (>=9),
libosmo-sigtran-dev (>= 0.8.0),
libosmo-abis-dev (>= 0.3.2),
libosmo-netif-dev (>= 0.1.0),
- libosmo-legacy-mgcp-dev (>= 1.0.0),
libosmo-mgcp-client-dev (>= 1.2.0)
Standards-Version: 3.9.8
Vcs-Git: git://git.osmocom.org/osmo-bsc.git
diff --git a/doc/examples/osmo-bsc_nat/black-list.cfg b/doc/examples/osmo-bsc_nat/black-list.cfg
deleted file mode 100644
index d36179d37..000000000
--- a/doc/examples/osmo-bsc_nat/black-list.cfg
+++ /dev/null
@@ -1 +0,0 @@
-678012512671923:6:6:
diff --git a/doc/examples/osmo-bsc_nat/bscs.cfg b/doc/examples/osmo-bsc_nat/bscs.cfg
deleted file mode 100644
index 176debe42..000000000
--- a/doc/examples/osmo-bsc_nat/bscs.cfg
+++ /dev/null
@@ -1,13 +0,0 @@
-nat
- bsc 0
- token lol
- location_area_code 1234
- description bsc
- max-endpoints 32
- paging forbidden 0
- bsc 1
- token wat
- location_area_code 5678
- description bsc
- max-endpoints 32
- paging forbidden 0
diff --git a/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg b/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg
deleted file mode 100644
index e835e068a..000000000
--- a/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg
+++ /dev/null
@@ -1,66 +0,0 @@
-!
-! OsmoBSCNAT (0.12.0.266-2daa9) configuration saved from vty
-!!
-!
-log stderr
- logging filter all 1
- logging color 1
- logging timestamp 0
- logging level all debug
- logging level rll notice
- logging level cc notice
- logging level mm notice
- logging level rr notice
- logging level rsl notice
- logging level nm info
- logging level mncc notice
- logging level pag notice
- logging level meas notice
- logging level sccp notice
- logging level msc notice
- logging level mgcp notice
- logging level ho notice
- logging level db notice
- logging level ref notice
- logging level gprs debug
- logging level ns info
- logging level bssgp debug
- logging level llc debug
- logging level sndcp debug
- logging level nat notice
- logging level ctrl notice
- logging level smpp debug
- logging level lglobal notice
- logging level llapd notice
- logging level linp notice
- logging level lmux notice
- logging level lmi notice
- logging level lmib notice
- logging level lsms notice
-!
-line vty
- no login
-!
-mgcp
- bind ip 0.0.0.0
- bind port 2427
- rtp bts-base 4000
- rtp net-base 16000
- rtp ip-dscp 0
- no rtcp-omit
- sdp audio-payload number 126
- sdp audio-payload name AMR/8000
- loop 0
- number endpoints 1
- call-agent ip 127.0.0.1
- rtp transcoder-base 0
- transcoder-remote-base 4000
-nat
- msc ip 127.0.0.1
- msc port 5000
- timeout auth 2
- timeout ping 20
- timeout pong 5
- ip-dscp 0
- bscs-config-file bscs.cfg
- access-list bla imsi-allow ^11$
diff --git a/include/osmocom/bsc/Makefile.am b/include/osmocom/bsc/Makefile.am
index b25dfd833..80f9b01ea 100644
--- a/include/osmocom/bsc/Makefile.am
+++ b/include/osmocom/bsc/Makefile.am
@@ -7,9 +7,6 @@ noinst_HEADERS = \
arfcn_range_encode.h \
bsc_msc.h \
bsc_msg_filter.h \
- bsc_nat.h \
- bsc_nat_callstats.h \
- bsc_nat_sccp.h \
bsc_rll.h \
bsc_subscriber.h \
bsc_subscr_conn_fsm.h \
@@ -32,7 +29,6 @@ noinst_HEADERS = \
meas_feed.h \
meas_rep.h \
misdn.h \
- nat_rewrite_trie.h \
network_listen.h \
openbscdefines.h \
osmo_bsc.h \
diff --git a/include/osmocom/bsc/bsc_nat.h b/include/osmocom/bsc/bsc_nat.h
deleted file mode 100644
index bd78b9d43..000000000
--- a/include/osmocom/bsc/bsc_nat.h
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2012 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BSC_NAT_H
-#define BSC_NAT_H
-
-#include <osmocom/legacy_mgcp/mgcp.h>
-
-#include "bsc_msg_filter.h"
-
-#include <osmocom/core/select.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/msgfile.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/statistics.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-
-#include <regex.h>
-#include <stdbool.h>
-
-#define DIR_BSC 1
-#define DIR_MSC 2
-
-#define PAGIN_GROUP_UNASSIGNED -1
-
-struct sccp_source_reference;
-struct nat_sccp_connection;
-struct bsc_nat_parsed;
-struct bsc_nat;
-struct bsc_nat_ussd_con;
-struct nat_rewrite_rule;
-
-/*
- * Is this terminated to the MSC, to the local machine (release
- * handling for IMSI filtering) or to a USSD provider?
- */
-enum {
- NAT_CON_END_MSC,
- NAT_CON_END_LOCAL,
- NAT_CON_END_USSD,
-};
-
-/*
- * Pending command entry
- */
-struct bsc_cmd_list {
- struct llist_head list_entry;
-
- struct osmo_timer_list timeout;
-
- /* The NATed ID used on the bsc_con*/
- int nat_id;
-
- /* The command from the control connection */
- struct ctrl_cmd *cmd;
-};
-
-/*
- * Per BSC data structure
- */
-struct bsc_connection {
- struct llist_head list_entry;
-
- /* do we know anything about this BSC? */
- int authenticated;
- uint8_t last_rand[16];
-
- /* the fd we use to communicate */
- struct osmo_wqueue write_queue;
-
- /* incoming message buffer */
- struct msgb *pending_msg;
-
- /* the BSS associated */
- struct bsc_config *cfg;
-
- /* a timeout node */
- struct osmo_timer_list id_timeout;
-
- /* pong timeout */
- struct osmo_timer_list ping_timeout;
- struct osmo_timer_list pong_timeout;
-
- /* mgcp related code */
- char *_endpoint_status;
- int number_multiplexes;
- int max_endpoints;
- int last_endpoint;
- int next_transaction;
- uint32_t pending_dlcx_count;
- struct llist_head pending_dlcx;
-
- /* track the pending commands for this BSC */
- struct llist_head cmd_pending;
- int last_id;
-
- /* a back pointer */
- struct bsc_nat *nat;
-};
-
-/**
- * Stats per BSC
- */
-struct bsc_config_stats {
- struct rate_ctr_group *ctrg;
-};
-
-enum bsc_cfg_ctr {
- BCFG_CTR_SCCP_CONN,
- BCFG_CTR_SCCP_CALLS,
- BCFG_CTR_NET_RECONN,
- BCFG_CTR_DROPPED_SCCP,
- BCFG_CTR_DROPPED_CALLS,
- BCFG_CTR_REJECTED_CR,
- BCFG_CTR_REJECTED_MSG,
- BCFG_CTR_ILL_PACKET,
- BCFG_CTR_CON_TYPE_LU,
- BCFG_CTR_CON_CMSERV_RQ,
- BCFG_CTR_CON_PAG_RESP,
- BCFG_CTR_CON_SSA,
- BCFG_CTR_CON_OTHER,
-};
-
-/**
- * One BSC entry in the config
- */
-struct bsc_config {
- struct llist_head entry;
-
- uint8_t key[16];
- uint8_t key_present;
- char *token;
- int nr;
-
- char *description;
-
- /* imsi white and blacklist */
- char *acc_lst_name;
-
- int forbid_paging;
- int paging_group;
-
- /* audio handling */
- int max_endpoints;
-
- /* used internally for reload handling */
- bool remove;
- bool token_updated;
-
- /* backpointer */
- struct bsc_nat *nat;
-
- struct bsc_config_stats stats;
-
- struct llist_head lac_list;
-
- /* Osmux is enabled/disabled per BSC */
- int osmux;
-
- /* Use a jitterbuffer on the bts-side receiver */
- bool bts_use_jibuf;
- /* Minimum and maximum buffer size for the jitter buffer, in ms */
- uint32_t bts_jitter_delay_min;
- uint32_t bts_jitter_delay_max;
- /* Enabled if explicitly configured through VTY: */
- bool bts_use_jibuf_override;
- bool bts_jitter_delay_min_override;
- bool bts_jitter_delay_max_override;
-};
-
-struct bsc_lac_entry {
- struct llist_head entry;
- uint16_t lac;
-};
-
-struct bsc_nat_paging_group {
- struct llist_head entry;
-
- /* list of lac entries */
- struct llist_head lists;
- int nr;
-};
-
-/**
- * BSCs point of view of endpoints
- */
-struct bsc_endpoint {
- /* the operation that is carried out */
- int transaction_state;
- /* the pending transaction id */
- char *transaction_id;
- /* the bsc we are talking to */
- struct bsc_connection *bsc;
-};
-
-/**
- * Statistic for the nat.
- */
-struct bsc_nat_statistics {
- struct {
- struct osmo_counter *conn;
- struct osmo_counter *calls;
- } sccp;
-
- struct {
- struct osmo_counter *reconn;
- struct osmo_counter *auth_fail;
- } bsc;
-
- struct {
- struct osmo_counter *reconn;
- } msc;
-
- struct {
- struct osmo_counter *reconn;
- } ussd;
-};
-
-/**
- * the structure of the "nat" network
- */
-struct bsc_nat {
- /* active SCCP connections that need patching */
- struct llist_head sccp_connections;
-
- /* active BSC connections that need patching */
- struct llist_head bsc_connections;
-
- /* access lists */
- struct llist_head access_lists;
-
- /* paging groups */
- struct llist_head paging_groups;
-
- /* known BSC's */
- struct llist_head bsc_configs;
- int num_bsc;
- int bsc_ip_dscp;
-
- /* MGCP config */
- struct mgcp_config *mgcp_cfg;
- uint8_t mgcp_msg[4096];
- int mgcp_length;
- int mgcp_ipa;
- int sdp_ensure_amr_mode_set;
-
- /* msc things */
- struct llist_head dests;
- struct bsc_msc_dest *main_dest;
- struct bsc_msc_connection *msc_con;
- char *token;
-
- /* timeouts */
- int auth_timeout;
- int ping_timeout;
- int pong_timeout;
-
- struct bsc_endpoint *bsc_endpoints;
-
- /* path to file with BSC config */
- char *include_file;
- char *include_base;
- char *resolved_path;
-
- /* filter */
- char *acc_lst_name;
-
- /* Barring of subscribers with a rb tree */
- struct rb_root imsi_black_list;
- char *imsi_black_list_fn;
-
- /* number rewriting */
- char *num_rewr_name;
- struct llist_head num_rewr;
- char *num_rewr_post_name;
- struct llist_head num_rewr_post;
-
- char *smsc_rewr_name;
- struct llist_head smsc_rewr;
- char *tpdest_match_name;
- struct llist_head tpdest_match;
- char *sms_clear_tp_srr_name;
- struct llist_head sms_clear_tp_srr;
- char *sms_num_rewr_name;
- struct llist_head sms_num_rewr;
-
- /* more rewriting */
- char *num_rewr_trie_name;
- struct nat_rewrite *num_rewr_trie;
-
- /* USSD messages we want to match */
- char *ussd_lst_name;
- char *ussd_query;
- regex_t ussd_query_re;
- char *ussd_token;
- char *ussd_local;
- struct osmo_fd ussd_listen;
- struct bsc_nat_ussd_con *ussd_con;
-
- /* for maintainenance */
- int blocked;
-
- /* statistics */
- struct bsc_nat_statistics stats;
-
- /* control interface */
- struct ctrl_handle *ctrl;
-};
-
-struct bsc_nat_ussd_con {
- struct osmo_wqueue queue;
- struct bsc_nat *nat;
- int authorized;
-
- struct msgb *pending_msg;
-
- struct osmo_timer_list auth_timeout;
-};
-
-/* create and init the structures */
-struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token,
- unsigned int number);
-struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
-struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len);
-void bsc_config_free(struct bsc_config *);
-void bsc_config_add_lac(struct bsc_config *cfg, int lac);
-void bsc_config_del_lac(struct bsc_config *cfg, int lac);
-int bsc_config_handles_lac(struct bsc_config *cfg, int lac);
-
-struct bsc_nat *bsc_nat_alloc(void);
-struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat);
-void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip);
-
-void sccp_connection_destroy(struct nat_sccp_connection *);
-void bsc_close_connection(struct bsc_connection *);
-
-const char *bsc_con_type_to_string(int type);
-
-/**
- * parse the given message into the above structure
- */
-struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg);
-
-/**
- * filter based on IP Access header in both directions
- */
-int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
-int bsc_nat_vty_init(struct bsc_nat *nat);
-int bsc_nat_find_paging(struct msgb *msg, const uint8_t **,int *len);
-
-/**
- * SCCP patching and handling
- */
-struct nat_sccp_connection *create_sccp_src_ref(struct bsc_connection *bsc, struct bsc_nat_parsed *parsed);
-int update_sccp_src_ref(struct nat_sccp_connection *sccp, struct bsc_nat_parsed *parsed);
-void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
-struct nat_sccp_connection *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
-struct nat_sccp_connection *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_connection *);
-struct nat_sccp_connection *bsc_nat_find_con_by_bsc(struct bsc_nat *, struct sccp_source_reference *);
-
-/**
- * MGCP/Audio handling
- */
-int bsc_mgcp_nr_multiplexes(int max_endpoints);
-int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
-int bsc_mgcp_assign_patch(struct nat_sccp_connection *, struct msgb *msg);
-void bsc_mgcp_init(struct nat_sccp_connection *);
-void bsc_mgcp_dlcx(struct nat_sccp_connection *);
-void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
-int bsc_mgcp_nat_init(struct bsc_nat *nat);
-
-struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
-struct msgb *bsc_mgcp_rewrite(char *input, int length, int endp, const char *ip,
- int port, int osmux, int *first_payload_type, int mode_set);
-void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
-
-void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc);
-int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);
-uint32_t bsc_mgcp_extract_ci(const char *resp);
-
-
-int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
-int bsc_do_write(struct osmo_wqueue *queue, struct msgb *msg, int id);
-int bsc_write_msg(struct osmo_wqueue *queue, struct msgb *msg);
-int bsc_write_cb(struct osmo_fd *bfd, struct msgb *msg);
-
-int bsc_nat_msc_is_connected(struct bsc_nat *nat);
-
-int bsc_conn_type_to_ctr(struct nat_sccp_connection *conn);
-
-struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed, struct msgb *msg, uint32_t *len);
-
-/** USSD filtering */
-int bsc_ussd_init(struct bsc_nat *nat);
-int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, struct msgb *msg);
-int bsc_ussd_close_connections(struct bsc_nat *nat);
-
-struct msgb *bsc_nat_rewrite_msg(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *, const char *imsi);
-
-/** paging group handling */
-struct bsc_nat_paging_group *bsc_nat_paging_group_num(struct bsc_nat *nat, int group);
-struct bsc_nat_paging_group *bsc_nat_paging_group_create(struct bsc_nat *nat, int group);
-void bsc_nat_paging_group_delete(struct bsc_nat_paging_group *);
-void bsc_nat_paging_group_add_lac(struct bsc_nat_paging_group *grp, int lac);
-void bsc_nat_paging_group_del_lac(struct bsc_nat_paging_group *grp, int lac);
-
-/**
- * Number rewriting support below
- */
-struct bsc_nat_num_rewr_entry {
- struct llist_head list;
-
- regex_t msisdn_reg;
- regex_t num_reg;
-
- char *replace;
- uint8_t is_prefix_lookup;
-};
-
-void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head, const struct osmo_config_list *);
-
-void bsc_nat_send_mgcp_to_msc(struct bsc_nat *bsc_nat, struct msgb *msg);
-void bsc_nat_handle_mgcp(struct bsc_nat *bsc, struct msgb *msg);
-
-struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat,
- const char *bind_addr, int port);
-void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending);
-int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg);
-
-int bsc_nat_extract_lac(struct bsc_connection *bsc, struct nat_sccp_connection *con,
- struct bsc_nat_parsed *parsed, struct msgb *msg);
-
-int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
- struct bsc_nat_parsed *, int *con_type, char **imsi,
- struct bsc_filter_reject_cause *cause);
-int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
- struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed,
- struct bsc_filter_reject_cause *cause);
-
-/**
- * CTRL interface helper
- */
-void bsc_nat_inform_reject(struct bsc_connection *bsc, const char *imsi);
-
-/*
- * Use for testing
- */
-void bsc_nat_free(struct bsc_nat *nat);
-
-#endif
diff --git a/include/osmocom/bsc/bsc_nat_callstats.h b/include/osmocom/bsc/bsc_nat_callstats.h
deleted file mode 100644
index 64f9bfc0a..000000000
--- a/include/osmocom/bsc/bsc_nat_callstats.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2012 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BSC_NAT_CALLSTATS_H
-#define BSC_NAT_CALLSTATS_H
-
-#include <osmocom/core/linuxlist.h>
-
-#include <osmocom/sccp/sccp_types.h>
-
-struct bsc_nat_call_stats {
- struct llist_head entry;
-
- struct sccp_source_reference remote_ref;
- struct sccp_source_reference src_ref; /* as seen by the MSC */
-
- /* mgcp options */
- uint32_t ci;
- int bts_rtp_port;
- int net_rtp_port;
- struct in_addr bts_addr;
- struct in_addr net_addr;
-
-
- /* as witnessed by the NAT */
- uint32_t net_ps;
- uint32_t net_os;
- uint32_t bts_pr;
- uint32_t bts_or;
- uint32_t bts_expected;
- uint32_t bts_jitter;
- int bts_loss;
-
- uint32_t trans_id;
- int msc_endpoint;
-};
-
-#endif
diff --git a/include/osmocom/bsc/bsc_nat_sccp.h b/include/osmocom/bsc/bsc_nat_sccp.h
deleted file mode 100644
index 082466408..000000000
--- a/include/osmocom/bsc/bsc_nat_sccp.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* NAT utilities using SCCP types */
-/*
- * (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 Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BSC_NAT_SCCP_H
-#define BSC_NAT_SCCP_H
-
-#include "bsc_msg_filter.h"
-
-#include <osmocom/sccp/sccp_types.h>
-
-/*
- * For the NAT we will need to analyze and later patch
- * the received message. This would require us to parse
- * the IPA and SCCP header twice. Instead of doing this
- * we will have one analyze structure and have the patching
- * and filter operate on the same structure.
- */
-struct bsc_nat_parsed {
- /* ip access prototype */
- int ipa_proto;
-
- /* source local reference */
- struct sccp_source_reference *src_local_ref;
-
- /* destination local reference */
- struct sccp_source_reference *dest_local_ref;
-
- /* original value */
- struct sccp_source_reference original_dest_ref;
-
- /* called ssn number */
- int called_ssn;
-
- /* calling ssn number */
- int calling_ssn;
-
- /* sccp message type */
- int sccp_type;
-
- /* bssap type, e.g. 0 for BSS Management */
- int bssap;
-
- /* the gsm0808 message type */
- int gsm_type;
-};
-
-/*
- * Per SCCP source local reference patch table. It needs to
- * be updated on new SCCP connections, connection confirm and reject,
- * and on the loss of the BSC connection.
- */
-struct nat_sccp_connection {
- struct llist_head list_entry;
-
- struct bsc_connection *bsc;
- struct bsc_msc_connection *msc_con;
-
- struct sccp_source_reference real_ref;
- struct sccp_source_reference patched_ref;
- struct sccp_source_reference remote_ref;
- int has_remote_ref;
-
- /* status */
- int con_local;
- int authorized;
-
- struct bsc_filter_state filter_state;
-
- uint16_t lac;
- uint16_t ci;
-
- /* remember which Transactions we run over the bypass */
- char ussd_ti[8];
-
- /*
- * audio handling. Remember if we have ever send a CRCX,
- * remember the endpoint used by the MSC and BSC.
- */
- int msc_endp;
- int bsc_endp;
-
- /* timeout handling */
- struct timespec creation_time;
-};
-
-
-#endif
diff --git a/include/osmocom/bsc/nat_rewrite_trie.h b/include/osmocom/bsc/nat_rewrite_trie.h
deleted file mode 100644
index 0571099c6..000000000
--- a/include/osmocom/bsc/nat_rewrite_trie.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * (C) 2013 by On-Waves
- * (C) 2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#ifndef NAT_REWRITE_FILE_H
-#define NAT_REWRITE_FILE_H
-
-#include <osmocom/core/linuxrbtree.h>
-
-struct vty;
-
-struct nat_rewrite_rule {
- /* For digits 0-9 and + */
- struct nat_rewrite_rule *rules[11];
-
- char empty;
- char prefix[14];
- char rewrite[6];
-};
-
-struct nat_rewrite {
- struct nat_rewrite_rule rule;
- size_t prefixes;
-};
-
-
-struct nat_rewrite *nat_rewrite_parse(void *ctx, const char *filename);
-struct nat_rewrite_rule *nat_rewrite_lookup(struct nat_rewrite *, const char *prefix);
-void nat_rewrite_dump(struct nat_rewrite *rewr);
-void nat_rewrite_dump_vty(struct vty *vty, struct nat_rewrite *rewr);
-
-#endif
diff --git a/src/libfilter/bsc_msg_acc.c b/src/libfilter/bsc_msg_acc.c
index d7b737bc7..6b048874f 100644
--- a/src/libfilter/bsc_msg_acc.c
+++ b/src/libfilter/bsc_msg_acc.c
@@ -19,9 +19,10 @@
*/
#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/bsc_nat.h>
#include <osmocom/bsc/debug.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
diff --git a/src/libfilter/bsc_msg_filter.c b/src/libfilter/bsc_msg_filter.c
index 56ddf670d..120169bf9 100644
--- a/src/libfilter/bsc_msg_filter.c
+++ b/src/libfilter/bsc_msg_filter.c
@@ -23,7 +23,6 @@
#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/bsc_nat.h>
#include <osmocom/bsc/bsc_msc.h>
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/debug.h>
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
index 612a00bb3..10f602a09 100644
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ b/src/osmo-bsc/osmo_bsc_msc.c
@@ -20,7 +20,6 @@
*
*/
-#include <osmocom/bsc/bsc_nat.h>
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/crypt/auth.h>
diff --git a/src/osmo-bsc_nat/Makefile.am b/src/osmo-bsc_nat/Makefile.am
deleted file mode 100644
index 267565147..000000000
--- a/src/osmo-bsc_nat/Makefile.am
+++ /dev/null
@@ -1,51 +0,0 @@
-AM_CPPFLAGS = \
- $(all_includes) \
- -I$(top_srcdir)/include \
- -I$(top_builddir) \
- $(NULL)
-
-AM_CFLAGS = \
- -Wall \
- $(LIBOSMOCORE_CFLAGS) \
- $(LIBOSMOGSM_CFLAGS) \
- $(LIBOSMOVTY_CFLAGS) \
- $(LIBOSMOCTRL_CFLAGS) \
- $(LIBOSMOSCCP_CFLAGS) \
- $(LIBOSMOLEGACYMGCP_CFLAGS) \
- $(COVERAGE_CFLAGS) \
- $(NULL)
-
-AM_LDFLAGS = \
- $(COVERAGE_LDFLAGS) \
- $(NULL)
-
-bin_PROGRAMS = \
- osmo-bsc_nat \
- $(NULL)
-
-osmo_bsc_nat_SOURCES = \
- bsc_filter.c \
- bsc_mgcp_utils.c \
- bsc_nat.c \
- bsc_nat_utils.c \
- bsc_nat_vty.c \
- bsc_sccp.c \
- bsc_ussd.c \
- bsc_nat_ctrl.c \
- bsc_nat_rewrite.c \
- bsc_nat_rewrite_trie.c \
- bsc_nat_filter.c \
- $(NULL)
-
-osmo_bsc_nat_LDADD = \
- $(top_builddir)/src/libfilter/libfilter.a \
- $(top_builddir)/src/libbsc/libbsc.a \
- $(LIBOSMOSCCP_LIBS) \
- $(LIBOSMOCORE_LIBS) \
- $(LIBOSMOGSM_LIBS) \
- $(LIBOSMOVTY_LIBS) \
- $(LIBOSMOCTRL_LIBS) \
- $(LIBOSMOSIGTRAN_LIBS) \
- $(LIBRARY_GSM) \
- -lrt \
- $(NULL)
diff --git a/src/osmo-bsc_nat/bsc_filter.c b/src/osmo-bsc_nat/bsc_filter.c
deleted file mode 100644
index 77ef5833f..000000000
--- a/src/osmo-bsc_nat/bsc_filter.c
+++ /dev/null
@@ -1,220 +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 Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <string.h>
-
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/ipaccess.h>
-#include <osmocom/bsc/debug.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <osmocom/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 */
- { IPAC_PROTO_MGCP_OLD, 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(DLINP, 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;
- if (parsed->dest_local_ref)
- parsed->original_dest_ref = *parsed->dest_local_ref;
- 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/src/osmo-bsc_nat/bsc_mgcp_utils.c b/src/osmo-bsc_nat/bsc_mgcp_utils.c
deleted file mode 100644
index ab06a5ee3..000000000
--- a/src/osmo-bsc_nat/bsc_mgcp_utils.c
+++ /dev/null
@@ -1,1162 +0,0 @@
-/**
- * This file contains helper routines for MGCP Gateway handling.
- *
- * The first thing to remember is that each BSC has its own namespace/range
- * of endpoints. Whenever a BSSMAP ASSIGNMENT REQUEST is received this code
- * will be called to select an endpoint on the BSC. The mapping from original
- * multiplex/timeslot to BSC multiplex'/timeslot' will be stored.
- *
- * The second part is to take messages on the public MGCP GW interface
- * and forward them to the right BSC. This requires the MSC to first
- * assign the timeslot. This assumption has been true so far. We are using
- * the policy_cb of the MGCP protocol code to decide if the request should
- * be immediately answered or delayed. An extension "Z: noanswer" is used
- * to request the BSC to not respond. This is saving some bytes of bandwidth
- * and as we are using TCP to forward the message we know it will arrive.
- * The mgcp_do_read method reads these messages and hands them to the protocol
- * parsing code which will call the mentioned policy_cb. The bsc_mgcp_forward
- * method is used on the way back from the BSC to the network.
- *
- * The third part is to patch messages forwarded to the BSC. This includes
- * the endpoint number, the ports to be used inside the SDP file and maybe
- * some other bits.
- *
- */
-/*
- * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2012 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_callstats.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/gsm_data.h>
-#include <osmocom/bsc/debug.h>
-#include <osmocom/bsc/ipaccess.h>
-#include <osmocom/legacy_mgcp/mgcp.h>
-#include <osmocom/legacy_mgcp/mgcp_internal.h>
-#include <osmocom/bsc/osmux.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <unistd.h>
-
-static void send_direct(struct bsc_nat *nat, struct msgb *output)
-{
- if (osmo_wqueue_enqueue(&nat->mgcp_cfg->gw_fd, output) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
- msgb_free(output);
- }
-}
-
-static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output)
-{
- if (nat->mgcp_ipa)
- bsc_nat_send_mgcp_to_msc(nat, output);
- else
- send_direct(nat, output);
-}
-
-int bsc_mgcp_nr_multiplexes(int max_endpoints)
-{
- int div = max_endpoints / 32;
-
- if ((max_endpoints % 32) != 0)
- div += 1;
-
- return div;
-}
-
-static int bsc_init_endps_if_needed(struct bsc_connection *con)
-{
- int multiplexes;
-
- /* we have done that */
- if (con->_endpoint_status)
- return 0;
-
- /* we have no config... */
- if (!con->cfg)
- return -1;
-
- multiplexes = bsc_mgcp_nr_multiplexes(con->cfg->max_endpoints);
- con->number_multiplexes = multiplexes;
- con->max_endpoints = con->cfg->max_endpoints;
- con->_endpoint_status = talloc_zero_array(con, char, 32 * multiplexes + 1);
- return con->_endpoint_status == NULL;
-}
-
-static int bsc_assign_endpoint(struct bsc_connection *bsc, struct nat_sccp_connection *con)
-{
- int multiplex;
- int timeslot;
- const int number_endpoints = bsc->max_endpoints;
- int i;
-
- mgcp_endpoint_to_timeslot(bsc->last_endpoint, &multiplex, &timeslot);
- timeslot += 1;
-
- for (i = 0; i < number_endpoints; ++i) {
- int endpoint;
-
- /* Wrap around timeslots */
- if (timeslot == 0)
- timeslot = 1;
-
- if (timeslot == 0x1f) {
- timeslot = 1;
- multiplex += 1;
- }
-
- /* Wrap around the multiplex */
- if (multiplex >= bsc->number_multiplexes)
- multiplex = 0;
-
- endpoint = mgcp_timeslot_to_endpoint(multiplex, timeslot);
-
- /* Now check if we are allowed to assign this one */
- if (endpoint >= bsc->max_endpoints) {
- multiplex = 0;
- timeslot = 1;
- endpoint = mgcp_timeslot_to_endpoint(multiplex, timeslot);
- }
-
-
- if (bsc->_endpoint_status[endpoint] == 0) {
- bsc->_endpoint_status[endpoint] = 1;
- con->bsc_endp = endpoint;
- bsc->last_endpoint = endpoint;
- return 0;
- }
-
- timeslot += 1;
- }
-
- return -1;
-}
-
-static uint16_t create_cic(int endpoint)
-{
- int timeslot, multiplex;
-
- mgcp_endpoint_to_timeslot(endpoint, &multiplex, &timeslot);
- return (multiplex << 5) | (timeslot & 0x1f);
-}
-
-int bsc_mgcp_assign_patch(struct nat_sccp_connection *con, struct msgb *msg)
-{
- struct nat_sccp_connection *mcon;
- struct tlv_parsed tp;
- uint16_t cic;
- uint8_t timeslot;
- uint8_t multiplex;
- unsigned int endp;
-
- 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(tlvp_val16_unal(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
- timeslot = cic & 0x1f;
- multiplex = (cic & ~0x1f) >> 5;
-
-
- endp = mgcp_timeslot_to_endpoint(multiplex, timeslot);
-
- if (endp >= con->bsc->nat->mgcp_cfg->trunk.number_endpoints) {
- LOGP(DNAT, LOGL_ERROR,
- "MSC attempted to assign bad endpoint 0x%x\n",
- endp);
- return -1;
- }
-
- /* find stale connections using that endpoint */
- llist_for_each_entry(mcon, &con->bsc->nat->sccp_connections, list_entry) {
- if (mcon->msc_endp == endp) {
- LOGP(DNAT, LOGL_ERROR,
- "Endpoint %d was assigned to 0x%x and now 0x%x\n",
- endp,
- sccp_src_ref_to_int(&mcon->patched_ref),
- sccp_src_ref_to_int(&con->patched_ref));
- bsc_mgcp_dlcx(mcon);
- }
- }
-
- con->msc_endp = endp;
- if (bsc_init_endps_if_needed(con->bsc) != 0)
- return -1;
- if (bsc_assign_endpoint(con->bsc, con) != 0)
- return -1;
-
- /*
- * now patch the message for the new CIC...
- * still assumed to be one multiplex only
- */
- cic = htons(create_cic(con->bsc_endp));
- memcpy((uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE),
- &cic, sizeof(cic));
-
- 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].transaction_state = 0;
- nat->bsc_endpoints[i].bsc = NULL;
-}
-
-void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
-{
- int i;
-
- for (i = 1; i < nat->mgcp_cfg->trunk.number_endpoints; ++i){
- bsc_mgcp_free_endpoint(nat, i);
- mgcp_release_endp(&nat->mgcp_cfg->trunk.endpoints[i]);
- }
-}
-
-/* send a MDCX where we do not want a response */
-static void bsc_mgcp_send_mdcx(struct bsc_connection *bsc, int port, 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",
- port, mgcp_bts_src_addr(endp),
- endp->bts_end.local_port);
- if (len < 0) {
- LOGP(DMGCP, LOGL_ERROR, "snprintf for MDCX failed.\n");
- return;
- }
-
- bsc_write_mgcp(bsc, (uint8_t *) buf, len);
-}
-
-static void bsc_mgcp_send_dlcx(struct bsc_connection *bsc, int endpoint, int trans)
-{
- char buf[2096];
- int len;
-
- /*
- * The following is a bit of a spec violation. According to the
- * MGCP grammar the transaction id is are upto 9 digits but we
- * prefix it with an alpha numeric value so we can easily recognize
- * it as a response.
- */
- len = snprintf(buf, sizeof(buf),
- "DLCX nat-%u %x@mgw MGCP 1.0\r\n",
- trans, endpoint);
- if (len < 0) {
- LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
- return;
- }
-
- bsc_write_mgcp(bsc, (uint8_t *) buf, len);
-}
-
-void bsc_mgcp_init(struct nat_sccp_connection *con)
-{
- con->msc_endp = -1;
- con->bsc_endp = -1;
-}
-
-/**
- * This code will remember the network side of the audio statistics and
- * once the internal DLCX response arrives this can be combined with the
- * the BSC side and forwarded as a trap.
- */
-static void remember_pending_dlcx(struct nat_sccp_connection *con, uint32_t transaction)
-{
- struct bsc_nat_call_stats *stats;
- struct bsc_connection *bsc = con->bsc;
- struct mgcp_endpoint *endp;
-
- stats = talloc_zero(bsc, struct bsc_nat_call_stats);
- if (!stats) {
- LOGP(DNAT, LOGL_NOTICE,
- "Failed to allocate statistics for endpoint 0x%x\n",
- con->msc_endp);
- return;
- }
-
- /* take the endpoint here */
- endp = &bsc->nat->mgcp_cfg->trunk.endpoints[con->msc_endp];
-
- stats->remote_ref = con->remote_ref;
- stats->src_ref = con->patched_ref;
-
- stats->ci = endp->ci;
- stats->bts_rtp_port = endp->bts_end.rtp_port;
- stats->bts_addr = endp->bts_end.addr;
- stats->net_rtp_port = endp->net_end.rtp_port;
- stats->net_addr = endp->net_end.addr;
-
- stats->net_ps = endp->net_end.packets;
- stats->net_os = endp->net_end.octets;
- stats->bts_pr = endp->bts_end.packets;
- stats->bts_or = endp->bts_end.octets;
- mgcp_state_calc_loss(&endp->bts_state, &endp->bts_end,
- &stats->bts_expected, &stats->bts_loss);
- stats->bts_jitter = mgcp_state_calc_jitter(&endp->bts_state);
-
- stats->trans_id = transaction;
- stats->msc_endpoint = con->msc_endp;
-
- /*
- * Too many pending requests.. let's remove the first two items.
- */
- if (!llist_empty(&bsc->pending_dlcx) &&
- bsc->pending_dlcx_count >= bsc->cfg->max_endpoints * 3) {
- struct bsc_nat_call_stats *tmp;
- LOGP(DNAT, LOGL_ERROR,
- "Too many(%d) pending DLCX responses on BSC: %d\n",
- bsc->pending_dlcx_count, bsc->cfg->nr);
- bsc->pending_dlcx_count -= 1;
- tmp = (struct bsc_nat_call_stats *) bsc->pending_dlcx.next;
- llist_del(&tmp->entry);
- talloc_free(tmp);
- }
-
- bsc->pending_dlcx_count += 1;
- llist_add_tail(&stats->entry, &bsc->pending_dlcx);
-}
-
-void bsc_mgcp_dlcx(struct nat_sccp_connection *con)
-{
- /* send a DLCX down the stream */
- if (con->bsc_endp != -1 && con->bsc->_endpoint_status) {
- LOGP(DNAT, LOGL_NOTICE,
- "Endpoint 0x%x was allocated for bsc: %d. Freeing it.\n",
- con->bsc_endp, con->bsc->cfg->nr);
- if (con->bsc->_endpoint_status[con->bsc_endp] != 1)
- LOGP(DNAT, LOGL_ERROR, "Endpoint 0x%x was not in use\n", con->bsc_endp);
- remember_pending_dlcx(con, con->bsc->next_transaction);
- con->bsc->_endpoint_status[con->bsc_endp] = 0;
- bsc_mgcp_send_dlcx(con->bsc, con->bsc_endp, con->bsc->next_transaction++);
- bsc_mgcp_free_endpoint(con->bsc->nat, con->msc_endp);
- }
-
- bsc_mgcp_init(con);
-
-}
-
-/*
- * Search for the pending request
- */
-static void handle_dlcx_response(struct bsc_connection *bsc, struct msgb *msg,
- int code, const char *transaction)
-{
- uint32_t trans_id = UINT32_MAX;
- uint32_t b_ps, b_os, n_pr, n_or, jitter;
- int loss;
- struct bsc_nat_call_stats *tmp, *stat = NULL;
- struct ctrl_cmd *cmd;
-
- /* parse the transaction identifier */
- int rc = sscanf(transaction, "nat-%u", &trans_id);
- if (rc != 1) {
- LOGP(DNAT, LOGL_ERROR, "Can not parse transaction id: '%s'\n",
- transaction);
- return;
- }
-
- /* find the answer for the request we made */
- llist_for_each_entry(tmp, &bsc->pending_dlcx, entry) {
- if (trans_id != tmp->trans_id)
- continue;
-
- stat = tmp;
- break;
- }
-
- if (!stat) {
- LOGP(DNAT, LOGL_ERROR,
- "Can not find transaction for: %u\n", trans_id);
- return;
- }
-
- /* attempt to parse the data now */
- rc = mgcp_parse_stats(msg, &b_ps, &b_os, &n_pr, &n_or, &loss, &jitter);
- if (rc != 0)
- LOGP(DNAT, LOGL_ERROR,
- "Can not parse connection statistics: %d\n", rc);
-
- /* send a trap now */
- cmd = ctrl_cmd_create(bsc, CTRL_TYPE_TRAP);
- if (!cmd) {
- LOGP(DNAT, LOGL_ERROR,
- "Creating a ctrl cmd failed.\n");
- goto free_stat;
- }
-
- cmd->id = "0";
- cmd->variable = talloc_asprintf(cmd, "net.0.bsc.%d.call_stats.v2",
- bsc->cfg->nr);
- cmd->reply = talloc_asprintf(cmd,
- "mg_ip_addr=%s,mg_port=%d,",
- inet_ntoa(stat->net_addr),
- stat->net_rtp_port);
- cmd->reply = talloc_asprintf_append(cmd->reply,
- "endpoint_ip_addr=%s,endpoint_port=%d,",
- inet_ntoa(stat->bts_addr),
- stat->bts_rtp_port);
- cmd->reply = talloc_asprintf_append(cmd->reply,
- "nat_pkt_in=%u,nat_pkt_out=%u,"
- "nat_bytes_in=%u,nat_bytes_out=%u,"
- "nat_jitter=%u,nat_pkt_lost=%d,",
- stat->bts_pr, stat->net_ps,
- stat->bts_or, stat->net_os,
- stat->bts_jitter, stat->bts_loss);
- cmd->reply = talloc_asprintf_append(cmd->reply,
- "bsc_pkt_in=%u,bsc_pkt_out=%u,"
- "bsc_bytes_in=%u,bsc_bytes_out=%u,"
- "bsc_jitter=%u,bsc_pkt_lost=%d,",
- n_pr, b_ps,
- n_or, b_os,
- jitter, loss);
- cmd->reply = talloc_asprintf_append(cmd->reply,
- "sccp_src_ref=%u,sccp_dst_ref=%u",
- sccp_src_ref_to_int(&stat->src_ref),
- sccp_src_ref_to_int(&stat->remote_ref));
-
- /* send it and be done */
- ctrl_cmd_send_to_all(bsc->nat->ctrl, cmd);
- talloc_free(cmd);
-
-free_stat:
- bsc->pending_dlcx_count -= 1;
- llist_del(&stat->entry);
- talloc_free(stat);
-}
-
-
-struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
-{
- struct nat_sccp_connection *con = NULL;
- struct nat_sccp_connection *sccp;
-
- llist_for_each_entry(sccp, &nat->sccp_connections, list_entry) {
- if (sccp->msc_endp == -1)
- continue;
- if (sccp->msc_endp != endpoint)
- continue;
-
- con = sccp;
- }
-
- if (con)
- return con;
-
- LOGP(DMGCP, LOGL_ERROR,
- "Failed to find the connection for endpoint: 0x%x\n", endpoint);
- return NULL;
-}
-
-static int nat_osmux_only(struct mgcp_config *mgcp_cfg, struct bsc_config *bsc_cfg)
-{
- if (mgcp_cfg->osmux == OSMUX_USAGE_ONLY)
- return 1;
- if (bsc_cfg->osmux == OSMUX_USAGE_ONLY)
- return 1;
- return 0;
-}
-
-static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int state, const char *transaction_id)
-{
- struct bsc_nat *nat;
- struct bsc_endpoint *bsc_endp;
- struct nat_sccp_connection *sccp;
- struct mgcp_endpoint *mgcp_endp;
- struct msgb *bsc_msg;
-
- nat = tcfg->cfg->data;
- bsc_endp = &nat->bsc_endpoints[endpoint];
- mgcp_endp = &nat->mgcp_cfg->trunk.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->transaction_state = 0;
- }
- 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;
- }
- }
-
- /* Allocate a Osmux circuit ID */
- if (state == MGCP_ENDP_CRCX) {
- if (nat->mgcp_cfg->osmux && sccp->bsc->cfg->osmux) {
- osmux_allocate_cid(mgcp_endp);
- if (mgcp_endp->osmux.allocated_cid < 0 &&
- nat_osmux_only(nat->mgcp_cfg, sccp->bsc->cfg)) {
- LOGP(DMGCP, LOGL_ERROR,
- "Rejecting usage of endpoint\n");
- return MGCP_POLICY_REJECT;
- }
- }
- }
-
- /* we need to generate a new and patched message */
- bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length,
- sccp->bsc_endp, mgcp_bts_src_addr(mgcp_endp),
- mgcp_endp->bts_end.local_port,
- mgcp_endp->osmux.allocated_cid,
- &mgcp_endp->net_end.codec.payload_type,
- nat->sdp_ensure_amr_mode_set);
- 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->transaction_state = state;
- bsc_endp->bsc = sccp->bsc;
-
- /* we need to update some bits */
- if (state == MGCP_ENDP_CRCX) {
- struct sockaddr_in sock;
-
- /* set up jitter buffer parameters */
- if (bsc_endp->bsc->cfg->bts_use_jibuf_override)
- mgcp_endp->bts_use_jibuf = bsc_endp->bsc->cfg->bts_use_jibuf;
-
- if (bsc_endp->bsc->cfg->bts_jitter_delay_min_override)
- mgcp_endp->bts_jitter_delay_min = bsc_endp->bsc->cfg->bts_jitter_delay_min;
-
- if (bsc_endp->bsc->cfg->bts_jitter_delay_max_override)
- mgcp_endp->bts_jitter_delay_max = bsc_endp->bsc->cfg->bts_jitter_delay_max;
-
-
- /* Annotate the allocated Osmux CID until the bsc confirms that
- * it agrees to use Osmux for this voice flow.
- */
- if (mgcp_endp->osmux.allocated_cid >= 0 &&
- mgcp_endp->osmux.state != OSMUX_STATE_ENABLED) {
- mgcp_endp->osmux.state = OSMUX_STATE_NEGOTIATING;
- mgcp_endp->osmux.cid = mgcp_endp->osmux.allocated_cid;
- }
-
- 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_end.addr = sock.sin_addr;
- }
-
- /* send the message and a fake MDCX to force sending of a dummy packet */
- bsc_write(sccp->bsc, bsc_msg, IPAC_PROTO_MGCP_OLD);
- bsc_mgcp_send_mdcx(sccp->bsc, sccp->bsc_endp, 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);
-
- /* libmgcp clears the MGCP endpoint for us */
- if (mgcp_endp->osmux.state == OSMUX_STATE_ENABLED)
- osmux_release_cid(mgcp_endp);
-
- return MGCP_POLICY_CONT;
- } else {
- bsc_write(sccp->bsc, bsc_msg, IPAC_PROTO_MGCP_OLD);
- return MGCP_POLICY_DEFER;
- }
-}
-
-/*
- * We do have a failure, free data downstream..
- */
-static void free_chan_downstream(struct mgcp_endpoint *endp, struct bsc_endpoint *bsc_endp,
- struct bsc_connection *bsc)
-{
- LOGP(DMGCP, LOGL_ERROR, "No CI, freeing endpoint 0x%x in state %d\n",
- ENDPOINT_NUMBER(endp), bsc_endp->transaction_state);
-
- /* if a CRCX failed... send a DLCX down the stream */
- if (bsc_endp->transaction_state == MGCP_ENDP_CRCX) {
- struct nat_sccp_connection *con;
- con = bsc_mgcp_find_con(bsc->nat, ENDPOINT_NUMBER(endp));
- if (!con) {
- LOGP(DMGCP, LOGL_ERROR,
- "No SCCP connection for endp 0x%x\n",
- ENDPOINT_NUMBER(endp));
- } else {
- if (con->bsc == bsc) {
- bsc_mgcp_send_dlcx(bsc, con->bsc_endp, con->bsc->next_transaction++);
- } else {
- LOGP(DMGCP, LOGL_ERROR,
- "Endpoint belongs to a different BSC\n");
- }
- }
- }
-
- bsc_mgcp_free_endpoint(bsc->nat, ENDPOINT_NUMBER(endp));
- mgcp_release_endp(endp);
-}
-
-static void bsc_mgcp_osmux_confirm(struct mgcp_endpoint *endp, const char *str)
-{
- unsigned int osmux_cid;
- char *res;
-
- res = strstr(str, "X-Osmux: ");
- if (!res) {
- LOGP(DMGCP, LOGL_INFO,
- "BSC doesn't want to use Osmux, failing back to RTP\n");
- goto err;
- }
-
- if (sscanf(res, "X-Osmux: %u", &osmux_cid) != 1) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to parse Osmux CID '%s'\n",
- str);
- goto err;
- }
-
- if (endp->osmux.cid != osmux_cid) {
- LOGP(DMGCP, LOGL_ERROR,
- "BSC sent us wrong CID %u, we expected %u",
- osmux_cid, endp->osmux.cid);
- goto err;
- }
-
- LOGP(DMGCP, LOGL_NOTICE, "bsc accepted to use Osmux (cid=%u)\n",
- osmux_cid);
- endp->osmux.state = OSMUX_STATE_ACTIVATING;
- return;
-err:
- osmux_release_cid(endp);
- endp->osmux.state = OSMUX_STATE_DISABLED;
-}
-
-/*
- * 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.
- *
- * Only responses to CRCX and DLCX should arrive here. The DLCX
- * needs to be handled specially to combine the two statistics.
- */
-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->trunk.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->trunk.endpoints[i];
- bsc_endp = &bsc->nat->bsc_endpoints[i];
- break;
- }
-
- if (!bsc_endp && strncmp("nat-", transaction_id, 4) == 0) {
- handle_dlcx_response(bsc, msg, code, transaction_id);
- return;
- }
-
- 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);
- if (endp->ci == CI_UNUSED) {
- free_chan_downstream(endp, bsc_endp, bsc);
- return;
- }
-
- if (endp->osmux.state == OSMUX_STATE_NEGOTIATING)
- bsc_mgcp_osmux_confirm(endp, (const char *) msg->l2h);
-
- /* If we require osmux and it is disabled.. fail */
- if (nat_osmux_only(bsc->nat->mgcp_cfg, bsc->cfg) &&
- endp->osmux.state == OSMUX_STATE_DISABLED) {
- LOGP(DMGCP, LOGL_ERROR,
- "Failed to activate osmux endpoint 0x%x\n",
- ENDPOINT_NUMBER(endp));
- free_chan_downstream(endp, bsc_endp, bsc);
- return;
- }
-
- /* free some stuff */
- talloc_free(bsc_endp->transaction_id);
- bsc_endp->transaction_id = NULL;
- bsc_endp->transaction_state = 0;
-
- /*
- * 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), -1,
- mgcp_net_src_addr(endp),
- endp->net_end.local_port, -1,
- &endp->bts_end.codec.payload_type,
- bsc->nat->sdp_ensure_amr_mode_set);
- if (!output) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n");
- return;
- }
-
- mgcp_queue_for_call_agent(bsc->nat, output);
-}
-
-int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60])
-{
- int rc;
- /* we want to parse two strings */
- rc = sscanf(str, "%3d %59s\n", code, transaction) != 2;
- transaction[59] = '\0';
- return rc;
-}
-
-uint32_t bsc_mgcp_extract_ci(const char *str)
-{
- unsigned int ci;
- char *res = strstr(str, "I: ");
- if (!res) {
- LOGP(DMGCP, LOGL_ERROR, "No CI in msg '%s'\n", str);
- return CI_UNUSED;
- }
-
- if (sscanf(res, "I: %u", &ci) != 1) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to parse CI in msg '%s'\n", str);
- return CI_UNUSED;
- }
-
- return ci;
-}
-
-/**
- * Create a new MGCPCommand based on the input and endpoint from a message
- */
-static void patch_mgcp(struct msgb *output, const char *op, const char *tok,
- int endp, int len, int cr, int osmux_cid)
-{
- int slen;
- int ret;
- char buf[40];
- char osmux_extension[strlen("\nX-Osmux: 255") + 1];
-
- buf[0] = buf[39] = '\0';
- ret = sscanf(tok, "%*s %s", buf);
- if (ret != 1) {
- LOGP(DMGCP, LOGL_ERROR,
- "Failed to find Endpoint in: %s\n", tok);
- return;
- }
-
- if (osmux_cid >= 0)
- sprintf(osmux_extension, "\nX-Osmux: %u", osmux_cid & 0xff);
- else
- osmux_extension[0] = '\0';
-
- slen = sprintf((char *) output->l3h, "%s %s %x@mgw MGCP 1.0%s%s",
- op, buf, endp, osmux_extension, cr ? "\r\n" : "\n");
- output->l3h = msgb_put(output, slen);
-}
-
-/* we need to replace some strings... */
-struct msgb *bsc_mgcp_rewrite(char *input, int length, int endpoint,
- const char *ip, int port, int osmux_cid,
- int *first_payload_type, int ensure_mode_set)
-{
- static const char crcx_str[] = "CRCX ";
- static const char dlcx_str[] = "DLCX ";
- static const char mdcx_str[] = "MDCX ";
-
- static const char ip_str[] = "c=IN IP4 ";
- static const char aud_str[] = "m=audio ";
- static const char fmt_str[] = "a=fmtp:";
-
- char buf[128];
- char *running, *token;
- struct msgb *output;
-
- /* keep state to add the a=fmtp line */
- int found_fmtp = 0;
- int payload = -1;
- int cr = 1;
-
- if (length > 4096 - 256) {
- 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;
- output->l3h = output->l2h;
- for (token = strsep(&running, "\n"); running; token = strsep(&running, "\n")) {
- int len = strlen(token);
- cr = len > 0 && token[len - 1] == '\r';
-
- if (strncmp(crcx_str, token, (sizeof crcx_str) - 1) == 0) {
- patch_mgcp(output, "CRCX", token, endpoint, len, cr, osmux_cid);
- } else if (strncmp(dlcx_str, token, (sizeof dlcx_str) - 1) == 0) {
- patch_mgcp(output, "DLCX", token, endpoint, len, cr, -1);
- } else if (strncmp(mdcx_str, token, (sizeof mdcx_str) - 1) == 0) {
- patch_mgcp(output, "MDCX", token, endpoint, len, cr, -1);
- } else 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 offset;
- if (sscanf(token, "m=audio %*d RTP/AVP %n%d", &offset, &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 %s\n",
- port, &token[offset]);
- buf[sizeof(buf)-1] = '\0';
-
- output->l3h = msgb_put(output, strlen(buf));
- memcpy(output->l3h, buf, strlen(buf));
- } else if (strncmp(fmt_str, token, (sizeof fmt_str) - 1) == 0) {
- found_fmtp = 1;
- goto copy;
- } else {
-copy:
- output->l3h = msgb_put(output, len + 1);
- memcpy(output->l3h, token, len);
- output->l3h[len] = '\n';
- }
- }
-
- /*
- * the above code made sure that we have 128 bytes lefts. So we can
- * safely append another line.
- */
- if (ensure_mode_set && !found_fmtp && payload != -1) {
- snprintf(buf, sizeof(buf) - 1, "a=fmtp:%d mode-set=2%s",
- payload, cr ? "\r\n" : "\n");
- buf[sizeof(buf) - 1] = '\0';
- output->l3h = msgb_put(output, strlen(buf));
- memcpy(output->l3h, buf, strlen(buf));
- }
-
- if (payload != -1 && first_payload_type)
- *first_payload_type = payload;
-
- return output;
-}
-
-/*
- * This comes from the MSC and we will now parse it. The caller needs
- * to free the msgb.
- */
-void bsc_nat_handle_mgcp(struct bsc_nat *nat, struct msgb *msg)
-{
- struct msgb *resp;
-
- if (!nat->mgcp_ipa) {
- LOGP(DMGCP, LOGL_ERROR, "MGCP message not allowed on IPA.\n");
- return;
- }
-
- if (msgb_l2len(msg) > sizeof(nat->mgcp_msg) - 1) {
- LOGP(DMGCP, LOGL_ERROR, "MGCP msg too big for handling.\n");
- return;
- }
-
- memcpy(nat->mgcp_msg, msg->l2h, msgb_l2len(msg));
- nat->mgcp_length = msgb_l2len(msg);
- nat->mgcp_msg[nat->mgcp_length] = '\0';
-
- /* now handle the message */
- resp = mgcp_handle_message(nat->mgcp_cfg, msg);
-
- /* we do have a direct answer... e.g. AUEP */
- if (resp)
- mgcp_queue_for_call_agent(nat, resp);
-
- return;
-}
-
-static int mgcp_do_read(struct osmo_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)
- mgcp_queue_for_call_agent(nat, resp);
-
- return 0;
-}
-
-static int mgcp_do_write(struct osmo_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;
-}
-
-static int init_mgcp_socket(struct bsc_nat *nat, struct mgcp_config *cfg)
-{
- struct sockaddr_in addr;
- int on;
-
- cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (cfg->gw_fd.bfd.fd < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to create MGCP socket. errno: %d\n", errno);
- return -1;
- }
-
- on = 1;
- setsockopt(cfg->gw_fd.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(cfg->source_port);
- inet_aton(cfg->source_addr, &addr.sin_addr);
-
- if (bind(cfg->gw_fd.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to bind on %s:%d errno: %d\n",
- cfg->source_addr, cfg->source_port, errno);
- close(cfg->gw_fd.bfd.fd);
- cfg->gw_fd.bfd.fd = -1;
- return -1;
- }
-
- addr.sin_port = htons(2727);
- inet_aton(cfg->call_agent_addr, &addr.sin_addr);
- if (connect(cfg->gw_fd.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
- cfg->call_agent_addr, errno);
- close(cfg->gw_fd.bfd.fd);
- cfg->gw_fd.bfd.fd = -1;
- return -1;
- }
-
- osmo_wqueue_init(&cfg->gw_fd, 10);
- cfg->gw_fd.bfd.when = BSC_FD_READ;
- cfg->gw_fd.bfd.data = nat;
- cfg->gw_fd.read_cb = mgcp_do_read;
- cfg->gw_fd.write_cb = mgcp_do_write;
-
- if (osmo_fd_register(&cfg->gw_fd.bfd) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to register MGCP fd.\n");
- close(cfg->gw_fd.bfd.fd);
- cfg->gw_fd.bfd.fd = -1;
- return -1;
- }
-
- return 0;
-}
-
-int bsc_mgcp_nat_init(struct bsc_nat *nat)
-{
- struct mgcp_config *cfg = nat->mgcp_cfg;
-
- if (!cfg->call_agent_addr) {
- LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
- return -1;
- }
-
- if (cfg->bts_ip) {
- LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
- return -1;
- }
-
- /* initialize the MGCP socket */
- if (!nat->mgcp_ipa) {
- int rc = init_mgcp_socket(nat, cfg);
- if (rc != 0)
- return rc;
- }
-
-
- /* some more MGCP config handling */
- cfg->data = nat;
- cfg->policy_cb = bsc_mgcp_policy_cb;
-
- if (cfg->bts_ip)
- talloc_free(cfg->bts_ip);
- cfg->bts_ip = "";
-
- nat->bsc_endpoints = talloc_zero_array(nat,
- struct bsc_endpoint,
- cfg->trunk.number_endpoints + 1);
- if (!nat->bsc_endpoints) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to allocate nat endpoints\n");
- close(cfg->gw_fd.bfd.fd);
- cfg->gw_fd.bfd.fd = -1;
- return -1;
- }
-
- if (mgcp_reset_transcoder(cfg) < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to send packet to the transcoder.\n");
- talloc_free(nat->bsc_endpoints);
- nat->bsc_endpoints = NULL;
- close(cfg->gw_fd.bfd.fd);
- cfg->gw_fd.bfd.fd = -1;
- return -1;
- }
-
- return 0;
-}
-
-void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc)
-{
- struct rate_ctr *ctr = NULL;
- int i;
-
- if (bsc->cfg)
- ctr = &bsc->cfg->stats.ctrg->ctr[BCFG_CTR_DROPPED_CALLS];
-
- for (i = 1; i < bsc->nat->mgcp_cfg->trunk.number_endpoints; ++i) {
- struct bsc_endpoint *bsc_endp = &bsc->nat->bsc_endpoints[i];
-
- if (bsc_endp->bsc != bsc)
- continue;
-
- if (ctr)
- rate_ctr_inc(ctr);
-
- bsc_mgcp_free_endpoint(bsc->nat, i);
- mgcp_release_endp(&bsc->nat->mgcp_cfg->trunk.endpoints[i]);
- }
-}
diff --git a/src/osmo-bsc_nat/bsc_nat.c b/src/osmo-bsc_nat/bsc_nat.c
deleted file mode 100644
index af97c5701..000000000
--- a/src/osmo-bsc_nat/bsc_nat.c
+++ /dev/null
@@ -1,1819 +0,0 @@
-/* BSC Multiplexer/NAT */
-
-/*
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 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 Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.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>
-#include <fcntl.h>
-#include <libgen.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <osmocom/bsc/debug.h>
-#include <osmocom/bsc/bsc_msc.h>
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/ipaccess.h>
-#include <osmocom/bsc/abis_nm.h>
-#include <osmocom/bsc/vty.h>
-#include <osmocom/bsc/gsm_04_08_utils.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/ports.h>
-#include <osmocom/ctrl/control_vty.h>
-
-#include <osmocom/crypt/auth.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/stats.h>
-#include <osmocom/core/socket.h>
-
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/stats.h>
-#include <osmocom/vty/ports.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/abis/ipa.h>
-
-#include "../../bscconfig.h"
-
-#define SCCP_CLOSE_TIME 20
-#define SCCP_CLOSE_TIME_TIMEOUT 19
-
-static const char *config_file = "bsc-nat.cfg";
-static const char *local_addr;
-static struct osmo_fd bsc_listen;
-static const char *msc_ip = NULL;
-static struct osmo_timer_list sccp_close;
-static int daemonize = 0;
-
-const char *openbsc_copyright =
- "Copyright (C) 2010 Holger Hans Peter Freyther and On-Waves\r\n"
- "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
- "This is free software: you are free to change and redistribute it.\r\n"
- "There is NO WARRANTY, to the extent permitted by law.\r\n";
-
-static struct bsc_nat *nat;
-static void bsc_send_data(struct bsc_connection *bsc, const uint8_t *data, unsigned int length, int);
-static void msc_send_reset(struct bsc_msc_connection *con);
-static void bsc_stat_reject(int filter, struct bsc_connection *bsc, int normal);
-
-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;
-}
-
-static void queue_for_msc(struct bsc_msc_connection *con, struct msgb *msg)
-{
- if (!con) {
- LOGP(DLINP, LOGL_ERROR, "No MSC Connection assigned. Check your code.\n");
- msgb_free(msg);
- return;
- }
-
-
- if (osmo_wqueue_enqueue(&con->write_queue, msg) != 0) {
- LOGP(DLINP, LOGL_ERROR, "Failed to enqueue the write.\n");
- msgb_free(msg);
- }
-}
-
-static void send_reset_ack(struct bsc_connection *bsc)
-{
- static const uint8_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 uint8_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 uint8_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 */
- osmo_timer_schedule(&bsc->ping_timeout, bsc->nat->ping_timeout, 0);
-
- /* also start a pong timer */
- osmo_timer_schedule(&bsc->pong_timeout, bsc->nat->pong_timeout, 0);
-}
-
-static void start_ping_pong(struct bsc_connection *bsc)
-{
- osmo_timer_setup(&bsc->pong_timeout, bsc_pong_timeout, bsc);
- osmo_timer_setup(&bsc->ping_timeout, bsc_ping_timeout, bsc);
-
- bsc_ping_timeout(bsc);
-}
-
-static void send_id_ack(struct bsc_connection *bsc)
-{
- static const uint8_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_nat *nat, struct bsc_connection *bsc)
-{
- static const uint8_t s_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,
- };
- int rc;
- uint8_t *mrand;
- uint8_t id_req[sizeof(s_id_req) + (2+16)];
- uint8_t *buf = &id_req[sizeof(s_id_req)];
-
- /* copy the static data */
- memcpy(id_req, s_id_req, sizeof(s_id_req));
-
- /* put the RAND with length, tag, value */
- buf = v_put(buf, 0x11);
- buf = v_put(buf, 0x23);
- mrand = bsc->last_rand;
-
- rc = osmo_get_rand_id(mrand, 16);
- if (rc < 0) {
- /* the timeout will trigger and close this connection */
- LOGP(DNAT, LOGL_ERROR, "osmo_get_rand_id() failed: %s\n", strerror(-rc));
- return;
- }
-
- memcpy(buf, mrand, 16);
- buf += 16;
-
- bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS);
-}
-
-static struct msgb *nat_create_rlsd(struct nat_sccp_connection *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 released.\n");
- return NULL;
- }
-
- 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;
-
- return msg;
-}
-
-static void nat_send_rlsd_ussd(struct bsc_nat *nat, struct nat_sccp_connection *conn)
-{
- struct msgb *msg;
-
- if (!nat->ussd_con)
- return;
-
- msg = nat_create_rlsd(conn);
- if (!msg)
- return;
-
- bsc_do_write(&nat->ussd_con->queue, msg, IPAC_PROTO_SCCP);
-}
-
-static void nat_send_rlsd_msc(struct nat_sccp_connection *conn)
-{
- struct msgb *msg;
-
- msg = nat_create_rlsd(conn);
- if (!msg)
- return;
-
- ipa_prepend_header(msg, IPAC_PROTO_SCCP);
- queue_for_msc(conn->msc_con, msg);
-}
-
-static void nat_send_rlsd_bsc(struct nat_sccp_connection *conn)
-{
- struct msgb *msg;
- struct sccp_connection_released *rel;
-
- 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->real_ref;
- rel->source_local_reference = conn->remote_ref;
-
- bsc_write(conn->bsc, msg, IPAC_PROTO_SCCP);
-}
-
-static struct msgb *nat_creat_clrc(struct nat_sccp_connection *conn, uint8_t cause)
-{
- struct msgb *msg;
- struct msgb *sccp;
-
- msg = gsm0808_create_clear_command(cause);
- if (!msg) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
- return NULL;
- }
-
- sccp = sccp_create_dt1(&conn->real_ref, msg->data, msg->len);
- if (!sccp) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate SCCP msg.\n");
- msgb_free(msg);
- return NULL;
- }
-
- msgb_free(msg);
- return sccp;
-}
-
-static int nat_send_clrc_bsc(struct nat_sccp_connection *conn)
-{
- struct msgb *sccp;
-
- sccp = nat_creat_clrc(conn, 0x20);
- if (!sccp)
- return -1;
- return bsc_write(conn->bsc, sccp, IPAC_PROTO_SCCP);
-}
-
-static void nat_send_rlc(struct bsc_msc_connection *msc_con,
- 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 sccp rlc.\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;
-
- ipa_prepend_header(msg, IPAC_PROTO_SCCP);
-
- queue_for_msc(msc_con, msg);
-}
-
-static void send_mgcp_reset(struct bsc_connection *bsc)
-{
- static const uint8_t mgcp_reset[] = {
- "RSIP 1 13@mgw MGCP 1.0\r\n"
- };
-
- bsc_write_mgcp(bsc, mgcp_reset, sizeof mgcp_reset - 1);
-}
-
-void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg)
-{
- ipa_prepend_header(msg, IPAC_PROTO_MGCP_OLD);
- queue_for_msc(nat->msc_con, msg);
-}
-
-/*
- * 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(struct bsc_msc_connection *msc_con)
-{
- if (msc_con->first_contact)
- return;
-
- msc_con->first_contact = 1;
- msc_send_reset(msc_con);
-}
-
-static void send_id_get_response(struct bsc_msc_connection *msc_con)
-{
- struct msgb *msg = bsc_msc_id_get_resp(0, nat->token, NULL, 0);
- if (!msg)
- return;
-
- ipa_prepend_header(msg, IPAC_PROTO_IPACCESS);
- queue_for_msc(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 uint8_t *data, unsigned int length, int proto)
-{
- struct msgb *msg;
-
- if (length > 4096 - 128) {
- LOGP(DLINP, LOGL_ERROR, "Can not send message of that size.\n");
- return;
- }
-
- msg = msgb_alloc_headroom(4096, 128, "to-bsc");
- if (!msg) {
- LOGP(DLINP, 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);
-}
-
-/*
- * Update the release statistics
- */
-static void bsc_stat_reject(int filter, struct bsc_connection *bsc, int normal)
-{
- if (!bsc->cfg) {
- LOGP(DNAT, LOGL_ERROR, "BSC is not authenticated.");
- return;
- }
-
- if (filter >= 0) {
- LOGP(DNAT, LOGL_ERROR, "Connection was not rejected");
- return;
- }
-
- if (filter == -1)
- rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_ILL_PACKET]);
- else if (normal)
- rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_REJECTED_MSG]);
- else
- rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_REJECTED_CR]);
-}
-
-/*
- * Release an established connection. We will have to release it to the BSC
- * and to the network and we do it the following way.
- * 1.) Give up on the MSC side
- * 1.1) Send a RLSD message, it is a bit non standard but should work, we
- * ignore the RLC... we might complain about it. Other options would
- * be to send a Release Request, handle the Release Complete..
- * 1.2) Mark the data structure to be con_local and wait for 2nd
- *
- * 2.) Give up on the BSC side
- * 2.1) Depending on the con type reject the service, or just close it
- */
-static void bsc_send_con_release(struct bsc_connection *bsc,
- struct nat_sccp_connection *con,
- struct bsc_filter_reject_cause *cause)
-{
- struct msgb *rlsd;
- /* 1. release the network */
- rlsd = sccp_create_rlsd(&con->patched_ref, &con->remote_ref,
- SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
- if (!rlsd)
- LOGP(DNAT, LOGL_ERROR, "Failed to create RLSD message.\n");
- else {
- ipa_prepend_header(rlsd, IPAC_PROTO_SCCP);
- queue_for_msc(con->msc_con, rlsd);
- }
- con->con_local = NAT_CON_END_LOCAL;
- con->msc_con = NULL;
-
- /* 2. release the BSC side */
- if (con->filter_state.con_type == FLT_CON_TYPE_LU) {
- struct msgb *payload, *udt;
- payload = gsm48_create_loc_upd_rej(cause->lu_reject_cause);
-
- if (payload) {
- gsm0808_prepend_dtap_header(payload, 0);
- udt = sccp_create_dt1(&con->real_ref, payload->data, payload->len);
- if (udt)
- bsc_write(bsc, udt, IPAC_PROTO_SCCP);
- else
- LOGP(DNAT, LOGL_ERROR, "Failed to create DT1\n");
-
- msgb_free(payload);
- } else {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate LU Reject.\n");
- }
- }
-
- nat_send_clrc_bsc(con);
-
- rlsd = sccp_create_rlsd(&con->remote_ref, &con->real_ref,
- SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
- if (!rlsd) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate RLSD for the BSC.\n");
- sccp_connection_destroy(con);
- return;
- }
-
- con->filter_state.con_type = FLT_CON_TYPE_LOCAL_REJECT;
- bsc_write(bsc, rlsd, IPAC_PROTO_SCCP);
-}
-
-static void bsc_send_con_refuse(struct bsc_connection *bsc,
- struct bsc_nat_parsed *parsed, int con_type,
- struct bsc_filter_reject_cause *cause)
-{
- struct msgb *payload;
- struct msgb *refuse;
-
- if (con_type == FLT_CON_TYPE_LU)
- payload = gsm48_create_loc_upd_rej(cause->lu_reject_cause);
- else if (con_type == FLT_CON_TYPE_CM_SERV_REQ || con_type == FLT_CON_TYPE_SSA)
- payload = gsm48_create_mm_serv_rej(cause->cm_reject_cause);
- else {
- LOGP(DNAT, LOGL_ERROR, "Unknown connection type: %d\n", con_type);
- payload = NULL;
- }
-
- /*
- * 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, *clear, *rlsd;
- struct nat_sccp_connection *con;
- con = create_sccp_src_ref(bsc, parsed);
- if (!con)
- goto send_refuse;
-
- /* declare it local and assign a unique remote_ref */
- con->filter_state.con_type = FLT_CON_TYPE_LOCAL_REJECT;
- con->con_local = NAT_CON_END_LOCAL;
- 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 Clear Command */
- clear = nat_creat_clrc(con, 0x20);
- if (!clear) {
- msgb_free(cc);
- msgb_free(udt);
- goto send_refuse;
- }
-
- /* 4. 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);
- msgb_free(clear);
- goto send_refuse;
- }
-
- bsc_write(bsc, cc, IPAC_PROTO_SCCP);
- bsc_write(bsc, udt, IPAC_PROTO_SCCP);
- bsc_write(bsc, clear, 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 void bsc_nat_send_paging(struct bsc_connection *bsc, struct msgb *msg)
-{
- if (bsc->cfg->forbid_paging) {
- LOGP(DNAT, LOGL_DEBUG, "Paging forbidden for BTS: %d\n", bsc->cfg->nr);
- return;
- }
-
- bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), IPAC_PROTO_SCCP);
-}
-
-static void bsc_nat_handle_paging(struct bsc_nat *nat, struct msgb *msg)
-{
- struct bsc_connection *bsc;
- const uint8_t *paging_start;
- int paging_length, i, ret;
-
- ret = bsc_nat_find_paging(msg, &paging_start, &paging_length);
- if (ret != 0) {
- LOGP(DNAT, LOGL_ERROR, "Could not parse paging message: %d\n", ret);
- return;
- }
-
- /* This is quite expensive now */
- for (i = 0; i < paging_length; i += 2) {
- unsigned int _lac = ntohs(*(unsigned int *) &paging_start[i]);
- unsigned int paged = 0;
- llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
- if (!bsc->cfg)
- continue;
- if (!bsc->authenticated)
- continue;
- if (!bsc_config_handles_lac(bsc->cfg, _lac))
- continue;
- bsc_nat_send_paging(bsc, msg);
- paged += 1;
- }
-
- /* highlight a possible config issue */
- if (paged == 0)
- LOGP(DNAT, LOGL_ERROR, "No BSC for LAC %d/0x%d\n", _lac, _lac);
-
- }
-}
-
-
-/*
- * Update the auth status. This can be either a CIPHER MODE COMMAND or
- * a CM Serivce Accept. Maybe also LU Accept or such in the future.
- */
-static void update_con_authorize(struct nat_sccp_connection *con,
- struct bsc_nat_parsed *parsed,
- struct msgb *msg)
-{
- if (!con)
- return;
- if (con->authorized)
- return;
-
- if (parsed->bssap == BSSAP_MSG_BSS_MANAGEMENT &&
- parsed->gsm_type == BSS_MAP_MSG_CIPHER_MODE_CMD) {
- con->authorized = 1;
- } else if (parsed->bssap == BSSAP_MSG_DTAP) {
- uint8_t msg_type, proto;
- uint32_t len;
- struct gsm48_hdr *hdr48;
- hdr48 = bsc_unpack_dtap(parsed, msg, &len);
- if (!hdr48)
- return;
-
- proto = gsm48_hdr_pdisc(hdr48);
- msg_type = gsm48_hdr_msg_type(hdr48);
- if (proto == GSM48_PDISC_MM &&
- msg_type == GSM48_MT_MM_CM_SERV_ACC)
- con->authorized = 1;
- }
-}
-
-static int forward_sccp_to_bts(struct bsc_msc_connection *msc_con, struct msgb *msg)
-{
- struct nat_sccp_connection *con = NULL;
- 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) {
- osmo_counter_inc(nat->stats.sccp.calls);
-
- if (con) {
- struct rate_ctr_group *ctrg;
- ctrg = con->bsc->cfg->stats.ctrg;
- rate_ctr_inc(&ctrg->ctr[BCFG_CTR_SCCP_CALLS]);
- if (bsc_mgcp_assign_patch(con, msg) != 0)
- LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
- } else
- LOGP(DNAT, LOGL_ERROR, "Assignment command but no BSC.\n");
- } else if (con && con->con_local == NAT_CON_END_USSD &&
- parsed->gsm_type == BSS_MAP_MSG_CLEAR_CMD) {
- LOGP(DNAT, LOGL_NOTICE, "Clear Command for USSD Connection. Ignoring.\n");
- con = NULL;
- }
- 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(msc_con, &parsed->original_dest_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);
- }
-
- if (!con) {
- talloc_free(parsed);
- return -1;
- }
- if (!con->bsc->authenticated) {
- talloc_free(parsed);
- LOGP(DNAT, LOGL_ERROR, "Selected BSC not authenticated.\n");
- return -1;
- }
-
- update_con_authorize(con, parsed, msg);
- talloc_free(parsed);
-
- 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) {
- bsc_nat_handle_paging(nat, msg);
- 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;
-
- 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);
-
- bsc_mgcp_free_endpoints(nat);
- bsc_msc_schedule_connect(con);
-}
-
-static void msc_connection_connected(struct bsc_msc_connection *con)
-{
- osmo_counter_inc(nat->stats.msc.reconn);
-}
-
-static void msc_send_reset(struct bsc_msc_connection *msc_con)
-{
- static const uint8_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(msc_con, msg);
-
- LOGP(DMSC, LOGL_NOTICE, "Scheduled GSM0808 reset msg for the MSC.\n");
-}
-
-static int ipaccess_msc_read_cb(struct osmo_fd *bfd)
-{
- struct bsc_msc_connection *msc_con;
- struct msgb *msg = NULL;
- struct ipaccess_head *hh;
- int ret;
-
- msc_con = (struct bsc_msc_connection *) bfd->data;
-
- ret = ipa_msg_recv_buffered(bfd->fd, &msg, &msc_con->pending_msg);
- if (ret <= 0) {
- if (ret == -EAGAIN)
- return 0;
- if (ret == 0)
- LOGP(DNAT, LOGL_FATAL,
- "The connection the MSC(%s) was lost, exiting\n",
- msc_con->name);
- else
- LOGP(DNAT, LOGL_ERROR,
- "Failed to parse ip access message on %s: %d\n",
- msc_con->name, ret);
-
- bsc_msc_lost(msc_con);
- return -1;
- }
-
- LOGP(DNAT, LOGL_DEBUG,
- "MSG from MSC(%s): %s proto: %d\n", msc_con->name,
- osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
-
- /* handle base message handling */
- hh = (struct ipaccess_head *) msg->data;
-
- /* initialize the networking. This includes sending a GSM08.08 message */
- if (hh->proto == IPAC_PROTO_IPACCESS) {
- ipa_ccm_rcvmsg_base(msg, bfd);
- if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
- initialize_msc_if_needed(msc_con);
- else if (msg->l2h[0] == IPAC_MSGT_ID_GET)
- send_id_get_response(msc_con);
- } else if (hh->proto == IPAC_PROTO_SCCP) {
- forward_sccp_to_bts(msc_con, msg);
- } else if (hh->proto == IPAC_PROTO_MGCP_OLD) {
- bsc_nat_handle_mgcp(nat, msg);
- }
-
- msgb_free(msg);
- return 0;
-}
-
-static int ipaccess_msc_write_cb(struct osmo_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 nat_sccp_connection *sccp_patch, *tmp;
- struct bsc_cmd_list *cmd_entry, *cmd_tmp;
- struct rate_ctr *ctr = NULL;
-
- /* stop the timeout timer */
- osmo_timer_del(&connection->id_timeout);
- osmo_timer_del(&connection->ping_timeout);
- osmo_timer_del(&connection->pong_timeout);
-
- if (connection->cfg)
- ctr = &connection->cfg->stats.ctrg->ctr[BCFG_CTR_DROPPED_SCCP];
-
- /* remove all SCCP connections */
- llist_for_each_entry_safe(sccp_patch, tmp, &nat->sccp_connections, list_entry) {
- if (sccp_patch->bsc != connection)
- continue;
-
- if (ctr)
- rate_ctr_inc(ctr);
- if (sccp_patch->has_remote_ref) {
- if (sccp_patch->con_local == NAT_CON_END_MSC)
- nat_send_rlsd_msc(sccp_patch);
- else if (sccp_patch->con_local == NAT_CON_END_USSD)
- nat_send_rlsd_ussd(nat, sccp_patch);
- }
-
- sccp_connection_destroy(sccp_patch);
- }
-
- /* Reply to all outstanding commands */
- llist_for_each_entry_safe(cmd_entry, cmd_tmp, &connection->cmd_pending, list_entry) {
- cmd_entry->cmd->type = CTRL_TYPE_ERROR;
- cmd_entry->cmd->reply = "BSC closed the connection";
- ctrl_cmd_send(&cmd_entry->cmd->ccon->write_queue, cmd_entry->cmd);
- bsc_nat_ctrl_del_pending(cmd_entry);
- }
-
- /* close endpoints allocated by this BSC */
- bsc_mgcp_clear_endpoints_for(connection);
-
- osmo_fd_unregister(&connection->write_queue.bfd);
- close(connection->write_queue.bfd.fd);
- osmo_wqueue_clear(&connection->write_queue);
- llist_del(&connection->list_entry);
-
- if (connection->pending_msg) {
- LOGP(DNAT, LOGL_ERROR, "Dropping partial message on connection %d.\n",
- connection->cfg ? connection->cfg->nr : -1);
- msgb_free(connection->pending_msg);
- connection->pending_msg = NULL;
- }
-
- talloc_free(connection);
-}
-
-static void bsc_maybe_close(struct bsc_connection *bsc)
-{
- struct nat_sccp_connection *sccp;
- if (!bsc->nat->blocked)
- return;
-
- /* are there any connections left */
- llist_for_each_entry(sccp, &bsc->nat->sccp_connections, list_entry)
- if (sccp->bsc == bsc)
- return;
-
- /* nothing left, close the BSC */
- LOGP(DNAT, LOGL_NOTICE, "Cleaning up BSC %d in blocking mode.\n",
- bsc->cfg ? bsc->cfg->nr : -1);
- bsc_close_connection(bsc);
-}
-
-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 int verify_key(struct bsc_connection *conn, struct bsc_config *conf, const uint8_t *key, const int keylen)
-{
- struct osmo_auth_vector vec;
-
- struct osmo_sub_auth_data auth = {
- .type = OSMO_AUTH_TYPE_GSM,
- .algo = OSMO_AUTH_ALG_MILENAGE,
- };
-
- /* expect a specific keylen */
- if (keylen != 8) {
- LOGP(DNAT, LOGL_ERROR, "Key length is wrong: %d for bsc nr %d\n",
- keylen, conf->nr);
- return 0;
- }
-
- memcpy(auth.u.umts.opc, conf->key, 16);
- memcpy(auth.u.umts.k, conf->key, 16);
- memset(auth.u.umts.amf, 0, 2);
- auth.u.umts.sqn = 0;
-
- memset(&vec, 0, sizeof(vec));
- osmo_auth_gen_vec(&vec, &auth, conn->last_rand);
-
- if (vec.res_len != 8) {
- LOGP(DNAT, LOGL_ERROR, "Res length is wrong: %d for bsc nr %d\n",
- vec.res_len, conf->nr);
- return 0;
- }
-
- return osmo_constant_time_cmp(vec.res, key, 8) == 0;
-}
-
-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);
- int len = TLVP_LEN(tvp, IPAC_IDTAG_UNITNAME);
- const uint8_t *xres = TLVP_VAL(tvp, 0x24);
- const int xlen = TLVP_LEN(tvp, 0x24);
-
- if (bsc->cfg) {
- LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
- bsc->write_queue.bfd.fd, bsc->cfg->nr);
- return;
- }
-
- if (len <= 0) {
- LOGP(DNAT, LOGL_ERROR, "Token with length zero on fd: %d\n",
- bsc->write_queue.bfd.fd);
- return;
- }
-
- if (token[len - 1] != '\0') {
- LOGP(DNAT, LOGL_ERROR, "Token not null terminated on fd: %d\n",
- bsc->write_queue.bfd.fd);
- return;
- }
-
- /*
- * New systems have fixed the structure of the message but
- * we need to support old ones too.
- */
- if (len >= 2 && token[len - 2] == '\0')
- len -= 1;
-
- conf = bsc_config_by_token(bsc->nat, token, len);
- if (!conf) {
- LOGP(DNAT, LOGL_ERROR,
- "No bsc found for token '%s' len %d on fd: %d.\n", token,
- bsc->write_queue.bfd.fd, len);
- bsc_close_connection(bsc);
- return;
- }
-
- /* We have set a key and expect it to be present */
- if (conf->key_present && !verify_key(bsc, conf, xres, xlen - 1)) {
- LOGP(DNAT, LOGL_ERROR,
- "Wrong key for bsc nr %d fd: %d.\n", conf->nr,
- bsc->write_queue.bfd.fd);
- bsc_close_connection(bsc);
- return;
- }
-
- rate_ctr_inc(&conf->stats.ctrg->ctr[BCFG_CTR_NET_RECONN]);
- bsc->authenticated = 1;
- bsc->cfg = conf;
- osmo_timer_del(&bsc->id_timeout);
- LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d on fd %d\n",
- conf->nr, bsc->write_queue.bfd.fd);
- start_ping_pong(bsc);
-}
-
-static void handle_con_stats(struct nat_sccp_connection *con)
-{
- struct rate_ctr_group *ctrg;
- int id = bsc_conn_type_to_ctr(con);
-
- if (id == -1)
- return;
-
- if (!con->bsc || !con->bsc->cfg)
- return;
-
- ctrg = con->bsc->cfg->stats.ctrg;
- rate_ctr_inc(&ctrg->ctr[id]);
-}
-
-static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
-{
- int con_filter = 0;
- char *imsi = NULL;
- struct bsc_msc_connection *con_msc = NULL;
- struct bsc_connection *con_bsc = NULL;
- int con_type;
- struct bsc_nat_parsed *parsed;
- struct bsc_filter_reject_cause cause;
-
- /* 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) {
- int filter;
- struct nat_sccp_connection *con;
- switch (parsed->sccp_type) {
- case SCCP_MSG_TYPE_CR:
- memset(&cause, 0, sizeof(cause));
- filter = bsc_nat_filter_sccp_cr(bsc, msg, parsed,
- &con_type, &imsi, &cause);
- if (filter < 0) {
- if (imsi)
- bsc_nat_inform_reject(bsc, imsi);
- bsc_stat_reject(filter, bsc, 0);
- goto exit3;
- }
-
- if (!create_sccp_src_ref(bsc, parsed))
- goto exit2;
- con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
- OSMO_ASSERT(con);
- con->msc_con = bsc->nat->msc_con;
- con_msc = con->msc_con;
- con->filter_state.con_type = con_type;
- con->filter_state.imsi_checked = filter;
- bsc_nat_extract_lac(bsc, con, parsed, msg);
- if (imsi)
- con->filter_state.imsi = talloc_steal(con, imsi);
- imsi = NULL;
- con_bsc = con->bsc;
- handle_con_stats(con);
- 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) {
- /* only filter non local connections */
- if (!con->con_local) {
- memset(&cause, 0, sizeof(cause));
- filter = bsc_nat_filter_dt(bsc, msg,
- con, parsed, &cause);
- if (filter < 0) {
- if (con->filter_state.imsi)
- bsc_nat_inform_reject(bsc,
- con->filter_state.imsi);
- bsc_stat_reject(filter, bsc, 1);
- bsc_send_con_release(bsc, con, &cause);
- con = NULL;
- goto exit2;
- }
-
- /* hand data to a side channel */
- if (bsc_ussd_check(con, parsed, msg) == 1)
- con->con_local = NAT_CON_END_USSD;
-
- /*
- * Optionally rewrite setup message. This can
- * replace the msg and the parsed structure becomes
- * invalid.
- */
- msg = bsc_nat_rewrite_msg(bsc->nat, msg, parsed,
- con->filter_state.imsi);
- talloc_free(parsed);
- parsed = NULL;
- } else if (con->con_local == NAT_CON_END_USSD) {
- bsc_ussd_check(con, parsed, msg);
- }
-
- con_bsc = con->bsc;
- con_msc = con->msc_con;
- con_filter = con->con_local;
- }
-
- break;
- case SCCP_MSG_TYPE_RLC:
- con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
- if (con) {
- con_bsc = con->bsc;
- con_msc = con->msc_con;
- con_filter = con->con_local;
- }
- remove_sccp_src_ref(bsc, msg, parsed);
- bsc_maybe_close(bsc);
- 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 == IPAC_PROTO_MGCP_OLD) {
- 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_msc && 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;
-
- if (!con_msc) {
- LOGP(DNAT, LOGL_ERROR, "Not forwarding data bsc_nr: %d ipa: %d type: 0x%x\n",
- bsc->cfg->nr,
- parsed ? parsed->ipa_proto : -1,
- parsed ? parsed->sccp_type : -1);
- goto exit2;
- }
-
- /* send the non-filtered but maybe modified msg */
- queue_for_msc(con_msc, msg);
- if (parsed)
- 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 && msgb_l2len(msg) > 2) {
- struct tlv_parsed tvp;
- int ret;
- ret = ipa_ccm_idtag_parse_off(&tvp,
- (unsigned char *) msg->l2h + 2,
- msgb_l2len(msg) - 2, 0);
- if (ret < 0) {
- LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
- "message with malformed TLVs\n");
- return ret;
- }
- if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
- ipaccess_auth_bsc(&tvp, bsc);
- }
-
- goto exit2;
- }
-
-exit2:
- if (imsi)
- talloc_free(imsi);
- talloc_free(parsed);
- msgb_free(msg);
- return -1;
-
-exit3:
- /* send a SCCP Connection Refused */
- if (imsi)
- talloc_free(imsi);
- bsc_send_con_refuse(bsc, parsed, con_type, &cause);
- talloc_free(parsed);
- msgb_free(msg);
- return -1;
-}
-
-static int ipaccess_bsc_read_cb(struct osmo_fd *bfd)
-{
- struct bsc_connection *bsc = bfd->data;
- struct msgb *msg = NULL;
- struct ipaccess_head *hh;
- struct ipaccess_head_ext *hh_ext;
- int ret;
-
- ret = ipa_msg_recv_buffered(bfd->fd, &msg, &bsc->pending_msg);
- if (ret <= 0) {
- if (ret == -EAGAIN)
- return 0;
- if (ret == 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 (%s)\n",
- bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret));
-
- bsc_close_connection(bsc);
- return -1;
- }
-
-
- LOGP(DNAT, LOGL_DEBUG, "MSG from BSC: %s proto: %d\n", osmo_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) {
- osmo_timer_del(&bsc->pong_timeout);
- msgb_free(msg);
- return 0;
- } else if (msg->l2h[0] == IPAC_MSGT_PING) {
- send_pong(bsc);
- msgb_free(msg);
- return 0;
- }
- /* Message contains the ipaccess_head_ext header, investigate further */
- } else if (hh->proto == IPAC_PROTO_OSMO &&
- msg->len > sizeof(*hh) + sizeof(*hh_ext)) {
-
- hh_ext = (struct ipaccess_head_ext *) hh->data;
- /* l2h is where the actual command data is expected */
- msg->l2h = hh_ext->data;
-
- if (hh_ext->proto == IPAC_PROTO_EXT_CTRL)
- return bsc_nat_handle_ctrlif_msg(bsc, msg);
- }
-
- /* 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_listen_bsc_cb(struct osmo_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 */
- osmo_counter_inc(nat->stats.bsc.reconn);
-
- /*
- * if we are not connected to a msc... just close the socket
- */
- if (!bsc_nat_msc_is_connected(nat)) {
- LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due lack of MSC connection.\n");
- close(fd);
- return 0;
- }
-
- if (nat->blocked) {
- LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due NAT being blocked.\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_dscp, sizeof(nat->bsc_ip_dscp));
- 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 = bsc_write_cb;
- bsc->write_queue.bfd.when = BSC_FD_READ;
- if (osmo_fd_register(&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);
- bsc->last_id = 0;
-
- send_id_ack(bsc);
- send_id_req(nat, bsc);
- send_mgcp_reset(bsc);
-
- /*
- * start the hangup timer
- */
- osmo_timer_setup(&bsc->id_timeout, ipaccess_close_bsc, bsc);
- osmo_timer_schedule(&bsc->id_timeout, nat->auth_timeout, 0);
- 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(" -D --daemonize Fork the process into a background daemon\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'},
- {"daemonize", 0, 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:D",
- long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c) {
- case 'h':
- print_usage();
- print_help();
- exit(0);
- case 's':
- log_set_use_color(osmo_stderr_target, 0);
- break;
- case 'd':
- log_parse_category_mask(osmo_stderr_target, optarg);
- break;
- case 'D':
- daemonize = 1;
- break;
- case 'c':
- config_file = optarg;
- break;
- case 'T':
- log_set_print_timestamp(osmo_stderr_target, 1);
- break;
- case 'm':
- msc_ip = optarg;
- break;
- case 'l':
- local_addr = optarg;
- 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)
-{
- int destroyed = 0;
- struct bsc_connection *bsc, *bsc_tmp;
- struct nat_sccp_connection *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 on bsc nr. %d\n",
- sccp_src_ref_to_int(&conn->real_ref),
- sccp_src_ref_to_int(&conn->patched_ref),
- conn->bsc->cfg->nr);
- sccp_connection_destroy(conn);
- destroyed = 1;
- }
-
- if (!destroyed)
- goto out;
-
- /* now close out any BSC */
- llist_for_each_entry_safe(bsc, bsc_tmp, &nat->bsc_connections, list_entry)
- bsc_maybe_close(bsc);
-
-out:
- osmo_timer_schedule(&sccp_close, SCCP_CLOSE_TIME, 0);
-}
-
-extern void *tall_sigh_ctx;
-extern void *tall_ctr_ctx;
-
-static void talloc_init_ctx()
-{
- tall_bsc_ctx = talloc_named_const(NULL, 0, "nat");
- msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-
- tall_sigh_ctx = talloc_named_const(tall_bsc_ctx, 0, "signal_handler");
- tall_ctr_ctx = talloc_named_const(tall_bsc_ctx, 0, "counter");
-}
-
-static int bsc_vty_go_parent(struct vty *vty)
-{
- switch (vty->node) {
- case NAT_BSC_NODE:
- vty->node = NAT_NODE;
- {
- struct bsc_config *bsc_config = vty->index;
- vty->index = bsc_config->nat;
- }
- break;
- case PGROUP_NODE:
- vty->node = NAT_NODE;
- vty->index = NULL;
- break;
- case TRUNK_NODE:
- vty->node = MGCP_NODE;
- vty->index = NULL;
- break;
- case NAT_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- break;
- default:
- osmo_ss7_vty_go_parent(vty);
- }
-
- return vty->node;
-}
-
-static int bsc_vty_is_config_node(struct vty *vty, int node)
-{
- /* Check if libosmo-sccp declares the node in
- * question as config node */
- if (osmo_ss7_is_config_node(vty, node))
- return 1;
-
- switch (node) {
- /* add items that are not config */
- case CONFIG_NODE:
- return 0;
-
- default:
- return 1;
- }
-}
-
-static struct vty_app_info vty_info = {
- .name = "OsmoBSCNAT",
- .version = PACKAGE_VERSION,
- .go_parent_cb = bsc_vty_go_parent,
- .is_config_node = bsc_vty_is_config_node,
-};
-
-static const struct log_info_cat log_categories[] = {
- [DNM] = {
- .name = "DNM",
- .description = "A-bis Network Management / O&M (NM/OML)",
- .color = "\033[1;36m",
- .enabled = 1, .loglevel = LOGL_INFO,
- },
- [DNAT] = {
- .name = "DNAT",
- .description = "GSM 08.08 NAT/Multiplexer",
- .enabled = 1, .loglevel = LOGL_NOTICE,
- },
- [DMSC] = {
- .name = "DMSC",
- .description = "Mobile Switching Center",
- .enabled = 1, .loglevel = LOGL_NOTICE,
- },
- [DCTRL] = {
- .name = "DCTRL",
- .description = "Control interface",
- .enabled = 1, .loglevel = LOGL_NOTICE,
- },
- [DFILTER] = {
- .name = "DFILTER",
- .description = "BSC/NAT IMSI based filtering",
- .enabled = 1, .loglevel = LOGL_DEBUG,
- },
-};
-
-static const struct log_info log_info = {
- .cat = log_categories,
- .num_cat = ARRAY_SIZE(log_categories),
-};
-
-int main(int argc, char **argv)
-{
- int rc;
-
- talloc_init_ctx();
-
- osmo_init_logging(&log_info);
-
- nat = bsc_nat_alloc();
- if (!nat) {
- fprintf(stderr, "Failed to allocate the BSC nat.\n");
- return -4;
- }
-
- nat->mgcp_cfg = mgcp_config_alloc();
- if (!nat->mgcp_cfg) {
- fprintf(stderr, "Failed to allocate MGCP cfg.\n");
- return -5;
- }
-
- /* We need to add mode-set for amr codecs */
- nat->sdp_ensure_amr_mode_set = 1;
-
- vty_info.copyright = openbsc_copyright;
- vty_init(&vty_info);
- logging_vty_add_cmds(NULL);
- osmo_stats_vty_add_cmds(&log_info);
- bsc_nat_vty_init(nat);
- ctrl_vty_init(tall_bsc_ctx);
-
-
- /* parse options */
- local_addr = NULL;
- handle_options(argc, argv);
-
- nat->include_base = dirname(talloc_strdup(tall_bsc_ctx, config_file));
-
- rate_ctr_init(tall_bsc_ctx);
- osmo_stats_init(tall_bsc_ctx);
-
- /* Ensure that forced enpoint allocation is turned on by default */
- nat->mgcp_cfg->trunk.force_realloc = 1;
-
- /* init vty and parse */
- if (mgcp_parse_config(config_file, nat->mgcp_cfg, MGCP_BSC_NAT) < 0) {
- fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
- return -3;
- }
-
- /* start telnet after reading config for vty_get_bind_addr() */
- if (telnet_init_dynif(tall_bsc_ctx, NULL, vty_get_bind_addr(),
- OSMO_VTY_PORT_BSC_NAT)) {
- fprintf(stderr, "Creating VTY telnet line failed\n");
- return -5;
- }
-
- /* over rule the VTY config for MSC IP */
- if (msc_ip)
- bsc_nat_set_msc_ip(nat, msc_ip);
-
- /* seed the PRNG */
- srand(time(NULL));
-
- LOGP(DNAT, LOGL_NOTICE, "BSCs configured from %s\n", nat->resolved_path);
-
- /*
- * Setup the MGCP code..
- */
- if (bsc_mgcp_nat_init(nat) != 0)
- return -4;
-
- /* connect to the MSC */
- nat->msc_con = bsc_msc_create(nat, &nat->dests);
- if (!nat->msc_con) {
- fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
- exit(1);
- }
-
- /* start control interface after reading config for
- * ctrl_vty_get_bind_addr() */
- nat->ctrl = bsc_nat_controlif_setup(nat, ctrl_vty_get_bind_addr(),
- OSMO_CTRL_PORT_BSC_NAT);
- if (!nat->ctrl) {
- fprintf(stderr, "Creating the control interface failed.\n");
- exit(1);
- }
-
- nat->msc_con->name = "main MSC";
- nat->msc_con->connection_loss = msc_connection_was_lost;
- nat->msc_con->connected = msc_connection_connected;
- nat->msc_con->write_queue.read_cb = ipaccess_msc_read_cb;
- nat->msc_con->write_queue.write_cb = ipaccess_msc_write_cb;;
- nat->msc_con->write_queue.bfd.data = nat->msc_con;
- bsc_msc_connect(nat->msc_con);
-
- /* wait for the BSC */
- bsc_listen.cb = ipaccess_listen_bsc_cb;
- bsc_listen.data = nat;
- rc = osmo_sock_init_ofd(&bsc_listen, AF_INET, SOCK_STREAM, IPPROTO_TCP,
- local_addr, 5000, OSMO_SOCK_F_BIND);
- if (rc != 0) {
- fprintf(stderr, "Failed to listen for BSC.\n");
- exit(1);
- }
-
- rc = bsc_ussd_init(nat);
- if (rc != 0) {
- LOGP(DNAT, LOGL_ERROR, "Failed to bind the USSD socket.\n");
- exit(1);
- }
-
- signal(SIGABRT, &signal_handler);
- signal(SIGUSR1, &signal_handler);
- osmo_init_ignore_signals();
-
- if (daemonize) {
- rc = osmo_daemonize();
- if (rc < 0) {
- perror("Error during daemonize");
- exit(1);
- }
- }
-
- /* recycle timer */
- sccp_set_log_area(DSCCP);
- osmo_timer_setup(&sccp_close, sccp_close_unconfirmed, NULL);
- osmo_timer_schedule(&sccp_close, SCCP_CLOSE_TIME, 0);
-
- while (1) {
- osmo_select_main(0);
- }
-
- return 0;
-}
-
-/* Close all connections handed out to the USSD module */
-int bsc_ussd_close_connections(struct bsc_nat *nat)
-{
- struct nat_sccp_connection *con;
- llist_for_each_entry(con, &nat->sccp_connections, list_entry) {
- if (con->con_local != NAT_CON_END_USSD)
- continue;
- if (!con->bsc)
- continue;
-
- nat_send_clrc_bsc(con);
- nat_send_rlsd_bsc(con);
- }
-
- return 0;
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_ctrl.c b/src/osmo-bsc_nat/bsc_nat_ctrl.c
deleted file mode 100644
index 75c0dfaa5..000000000
--- a/src/osmo-bsc_nat/bsc_nat_ctrl.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * (C) 2011-2012 by Holger Hans Peter Freyther
- * (C) 2011-2012 by On-Waves
- * (C) 2011 by Daniel Willmann
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/ports.h>
-
-#include <osmocom/vty/misc.h>
-
-#include <osmocom/bsc/ctrl.h>
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/vty.h>
-#include <osmocom/bsc/gsm_data.h>
-#include <osmocom/bsc/debug.h>
-
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-
-#define NAT_MAX_CTRL_ID 65535
-
-static struct bsc_nat *g_nat;
-
-static int bsc_id_unused(int id, struct bsc_connection *bsc)
-{
- struct bsc_cmd_list *pending;
-
- llist_for_each_entry(pending, &bsc->cmd_pending, list_entry) {
- if (pending->nat_id == id)
- return 0;
- }
- return 1;
-}
-
-static int get_next_free_bsc_id(struct bsc_connection *bsc)
-{
- int new_id, overflow = 0;
-
- new_id = bsc->last_id;
-
- do {
- new_id++;
- if (new_id == NAT_MAX_CTRL_ID) {
- new_id = 1;
- overflow++;
- }
-
- if (bsc_id_unused(new_id, bsc)) {
- bsc->last_id = new_id;
- return new_id;
- }
- } while (overflow != 2);
-
- return -1;
-}
-
-void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending)
-{
- llist_del(&pending->list_entry);
- osmo_timer_del(&pending->timeout);
- talloc_free(pending);
-}
-
-static struct bsc_cmd_list *bsc_get_pending(struct bsc_connection *bsc, char *id_str)
-{
- struct bsc_cmd_list *cmd_entry;
- int id = atoi(id_str);
- if (id == 0)
- return NULL;
-
- llist_for_each_entry(cmd_entry, &bsc->cmd_pending, list_entry) {
- if (cmd_entry->nat_id == id) {
- return cmd_entry;
- }
- }
- return NULL;
-}
-
-int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg)
-{
- struct ctrl_cmd *cmd;
- struct bsc_cmd_list *pending;
- char *var;
-
- cmd = ctrl_cmd_parse(bsc, msg);
- msgb_free(msg);
-
- if (!cmd) {
- cmd = talloc_zero(bsc, struct ctrl_cmd);
- if (!cmd) {
- LOGP(DNAT, LOGL_ERROR, "OOM!\n");
- return -ENOMEM;
- }
- cmd->type = CTRL_TYPE_ERROR;
- cmd->id = "err";
- cmd->reply = "Failed to parse command.";
- goto err;
- }
-
- if (bsc->cfg && !llist_empty(&bsc->cfg->lac_list)) {
- if (cmd->variable) {
- var = talloc_asprintf(cmd, "net.0.bsc.%i.%s", bsc->cfg->nr,
- cmd->variable);
- if (!var) {
- cmd->type = CTRL_TYPE_ERROR;
- cmd->reply = "OOM";
- goto err;
- }
- talloc_free(cmd->variable);
- cmd->variable = var;
- }
-
- /* We have to handle TRAPs before matching pending */
- if (cmd->type == CTRL_TYPE_TRAP) {
- ctrl_cmd_send_to_all(bsc->nat->ctrl, cmd);
- talloc_free(cmd);
- return 0;
- }
-
- /* Find the pending command */
- pending = bsc_get_pending(bsc, cmd->id);
- if (pending) {
- osmo_talloc_replace_string(cmd, &cmd->id, pending->cmd->id);
- if (!cmd->id) {
- cmd->type = CTRL_TYPE_ERROR;
- cmd->reply = "OOM";
- goto err;
- }
- ctrl_cmd_send(&pending->cmd->ccon->write_queue, cmd);
- bsc_nat_ctrl_del_pending(pending);
- } else {
- /* We need to handle TRAPS here */
- if ((cmd->type != CTRL_TYPE_ERROR) &&
- (cmd->type != CTRL_TYPE_TRAP)) {
- LOGP(DNAT, LOGL_NOTICE, "Got control message "
- "from BSC without pending entry\n");
- cmd->type = CTRL_TYPE_ERROR;
- cmd->reply = "No request outstanding";
- goto err;
- }
- }
- }
- talloc_free(cmd);
- return 0;
-err:
- ctrl_cmd_send(&bsc->write_queue, cmd);
- talloc_free(cmd);
- return 0;
-}
-
-static void pending_timeout_cb(void *data)
-{
- struct bsc_cmd_list *pending = data;
- LOGP(DNAT, LOGL_ERROR, "Command timed out\n");
- pending->cmd->type = CTRL_TYPE_ERROR;
- pending->cmd->reply = "Command timed out";
- ctrl_cmd_send(&pending->cmd->ccon->write_queue, pending->cmd);
-
- bsc_nat_ctrl_del_pending(pending);
-}
-
-static void ctrl_conn_closed_cb(struct ctrl_connection *connection)
-{
- struct bsc_connection *bsc;
- struct bsc_cmd_list *pending, *tmp;
-
- llist_for_each_entry(bsc, &g_nat->bsc_connections, list_entry) {
- llist_for_each_entry_safe(pending, tmp, &bsc->cmd_pending, list_entry) {
- if (pending->cmd->ccon == connection)
- bsc_nat_ctrl_del_pending(pending);
- }
- }
-}
-
-static int extract_bsc_nr_variable(char *variable, unsigned int *nr, char **bsc_variable)
-{
- char *nr_str, *tmp, *saveptr = NULL;
-
- tmp = strtok_r(variable, ".", &saveptr);
- tmp = strtok_r(NULL, ".", &saveptr);
- tmp = strtok_r(NULL, ".", &saveptr);
- nr_str = strtok_r(NULL, ".", &saveptr);
- if (!nr_str)
- return 0;
- *nr = atoi(nr_str);
-
- tmp = strtok_r(NULL, "\0", &saveptr);
- if (!tmp)
- return 0;
-
- *bsc_variable = tmp;
- return 1;
-}
-
-static int forward_to_bsc(struct ctrl_cmd *cmd)
-{
- int ret = CTRL_CMD_HANDLED;
- struct ctrl_cmd *bsc_cmd = NULL;
- struct bsc_connection *bsc;
- struct bsc_cmd_list *pending = NULL;
- unsigned int nr;
- char *bsc_variable;
-
- /* Skip over the beginning (bsc.) */
- if (!extract_bsc_nr_variable(cmd->variable, &nr, &bsc_variable)) {
- cmd->reply = "command incomplete";
- goto err;
- }
-
-
- llist_for_each_entry(bsc, &g_nat->bsc_connections, list_entry) {
- if (!bsc->cfg)
- continue;
- if (!bsc->authenticated)
- continue;
- if (bsc->cfg->nr != nr)
- continue;
-
- /* Add pending command to list */
- pending = talloc_zero(bsc, struct bsc_cmd_list);
- if (!pending) {
- cmd->reply = "OOM";
- goto err;
- }
-
- pending->nat_id = get_next_free_bsc_id(bsc);
- if (pending->nat_id < 0) {
- cmd->reply = "No free ID found";
- goto err;
- }
-
- bsc_cmd = ctrl_cmd_cpy(bsc, cmd);
- if (!bsc_cmd) {
- cmd->reply = "Could not forward command";
- goto err;
- }
-
- talloc_free(bsc_cmd->id);
- bsc_cmd->id = talloc_asprintf(bsc_cmd, "%i", pending->nat_id);
- if (!bsc_cmd->id) {
- cmd->reply = "OOM";
- goto err;
- }
-
- talloc_free(bsc_cmd->variable);
- bsc_cmd->variable = talloc_strdup(bsc_cmd, bsc_variable);
- if (!bsc_cmd->variable) {
- cmd->reply = "OOM";
- goto err;
- }
-
- if (ctrl_cmd_send(&bsc->write_queue, bsc_cmd)) {
- cmd->reply = "Sending failed";
- goto err;
- }
-
- /* caller owns cmd param and will destroy it after we return */
- pending->cmd = ctrl_cmd_cpy(pending, cmd);
- if (!pending->cmd) {
- cmd->reply = "Could not answer command";
- goto err;
- }
- cmd->ccon->closed_cb = ctrl_conn_closed_cb;
- pending->cmd->ccon = cmd->ccon;
-
- /* Setup the timeout */
- osmo_timer_setup(&pending->timeout, pending_timeout_cb,
- pending);
- /* TODO: Make timeout configurable */
- osmo_timer_schedule(&pending->timeout, 10, 0);
- llist_add_tail(&pending->list_entry, &bsc->cmd_pending);
-
- goto done;
- }
- /* We end up here if there's no bsc to handle our LAC */
- cmd->reply = "no BSC with this nr";
-err:
- ret = CTRL_CMD_ERROR;
- talloc_free(pending);
-done:
- talloc_free(bsc_cmd);
- return ret;
-
-}
-
-
-CTRL_CMD_DEFINE(fwd_cmd, "net 0 bsc *");
-static int get_fwd_cmd(struct ctrl_cmd *cmd, void *data)
-{
- return forward_to_bsc(cmd);
-}
-
-static int set_fwd_cmd(struct ctrl_cmd *cmd, void *data)
-{
- return forward_to_bsc(cmd);
-}
-
-static int verify_fwd_cmd(struct ctrl_cmd *cmd, const char *value, void *data)
-{
- return 0;
-}
-
-static int extract_bsc_cfg_variable(struct ctrl_cmd *cmd, struct bsc_config **cfg,
- char **bsc_variable)
-{
- unsigned int nr;
-
- if (!extract_bsc_nr_variable(cmd->variable, &nr, bsc_variable)) {
- cmd->reply = "command incomplete";
- return 0;
- }
-
- *cfg = bsc_config_num(g_nat, nr);
- if (!*cfg) {
- cmd->reply = "Unknown BSC";
- return 0;
- }
-
- return 1;
-}
-
-CTRL_CMD_DEFINE(net_cfg_cmd, "net 0 bsc_cfg *");
-static int get_net_cfg_cmd(struct ctrl_cmd *cmd, void *data)
-{
- char *bsc_variable;
- struct bsc_config *bsc_cfg;
-
- if (!extract_bsc_cfg_variable(cmd, &bsc_cfg, &bsc_variable))
- return CTRL_CMD_ERROR;
-
- if (strcmp(bsc_variable, "access-list-name") == 0) {
- cmd->reply = talloc_asprintf(cmd, "%s",
- bsc_cfg->acc_lst_name ? bsc_cfg->acc_lst_name : "");
- return CTRL_CMD_REPLY;
- }
-
- cmd->reply = "unknown command";
- return CTRL_CMD_ERROR;
-}
-
-static int set_net_cfg_cmd(struct ctrl_cmd *cmd, void *data)
-{
- char *bsc_variable;
- struct bsc_config *bsc_cfg;
-
- if (!extract_bsc_cfg_variable(cmd, &bsc_cfg, &bsc_variable))
- return CTRL_CMD_ERROR;
-
- if (strcmp(bsc_variable, "access-list-name") == 0) {
- osmo_talloc_replace_string(bsc_cfg, &bsc_cfg->acc_lst_name, cmd->value);
- cmd->reply = talloc_asprintf(cmd, "%s",
- bsc_cfg->acc_lst_name ? bsc_cfg->acc_lst_name : "");
- return CTRL_CMD_REPLY;
- } else if (strcmp(bsc_variable, "no-access-list-name") == 0) {
- talloc_free(bsc_cfg->acc_lst_name);
- bsc_cfg->acc_lst_name = NULL;
- cmd->reply = "";
- return CTRL_CMD_REPLY;
- }
-
- cmd->reply = "unknown command";
- return CTRL_CMD_ERROR;
-}
-
-static int verify_net_cfg_cmd(struct ctrl_cmd *cmd, const char *value, void *data)
-{
- return 0;
-}
-
-CTRL_CMD_DEFINE(net_cfg_acc_cmd, "net 0 add allow access-list *");
-static const char *extract_acc_name(const char *var)
-{
- char *str;
-
- str = strstr(var, "net.0.add.allow.access-list.");
- if (!str)
- return NULL;
- str += strlen("net.0.add.allow.access-list.");
- if (strlen(str) == 0)
- return NULL;
- return str;
-}
-
-static int get_net_cfg_acc_cmd(struct ctrl_cmd *cmd, void *data)
-{
- cmd->reply = "Append only";
- return CTRL_CMD_ERROR;
-}
-
-static int set_net_cfg_acc_cmd(struct ctrl_cmd *cmd, void *data)
-{
- const char *access_name = extract_acc_name(cmd->variable);
- struct bsc_msg_acc_lst *acc;
- struct bsc_msg_acc_lst_entry *entry;
- const char *value = cmd->value;
- int rc;
-
- /* Should have been caught by verify_net_cfg_acc_cmd */
- acc = bsc_msg_acc_lst_find(&g_nat->access_lists, access_name);
- if (!acc) {
- cmd->reply = "Access list not found";
- return CTRL_CMD_ERROR;
- }
-
- entry = bsc_msg_acc_lst_entry_create(acc);
- if (!entry) {
- cmd->reply = "OOM";
- return CTRL_CMD_ERROR;
- }
-
- rc = gsm_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, 1, &value);
- if (rc != 0) {
- cmd->reply = "Failed to compile expression";
- return CTRL_CMD_ERROR;
- }
-
- cmd->reply = "IMSI allow added to access list";
- return CTRL_CMD_REPLY;
-}
-
-static int verify_net_cfg_acc_cmd(struct ctrl_cmd *cmd, const char *value, void *data)
-{
- const char *access_name = extract_acc_name(cmd->variable);
- struct bsc_msg_acc_lst *acc = bsc_msg_acc_lst_find(&g_nat->access_lists, access_name);
-
- if (!acc) {
- cmd->reply = "Access list not known";
- return -1;
- }
-
- return 0;
-}
-
-CTRL_CMD_DEFINE_WO_NOVRF(net_save_cmd, "net 0 save-configuration");
-
-static int set_net_save_cmd(struct ctrl_cmd *cmd, void *data)
-{
- int rc = osmo_vty_save_config_file();
- cmd->reply = talloc_asprintf(cmd, "%d", rc);
- if (!cmd->reply) {
- cmd->reply = "OOM";
- return CTRL_CMD_ERROR;
- }
-
- return CTRL_CMD_REPLY;
-}
-
-struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat,
- const char *bind_addr, int port)
-{
- struct ctrl_handle *ctrl;
- int rc;
-
-
- ctrl = bsc_controlif_setup(NULL, bind_addr, OSMO_CTRL_PORT_BSC_NAT);
- if (!ctrl) {
- fprintf(stderr, "Failed to initialize the control interface. Exiting.\n");
- return NULL;
- }
-
- rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_fwd_cmd);
- if (rc) {
- fprintf(stderr, "Failed to install the control command. Exiting.\n");
- goto error;
- }
- rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_cfg_cmd);
- if (rc) {
- fprintf(stderr, "Failed to install the net cfg command. Exiting.\n");
- goto error;
- }
- rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_cfg_acc_cmd);
- if (rc) {
- fprintf(stderr, "Failed to install the net acc command. Exiting.\n");
- goto error;
- }
- rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_save_cmd);
- if (rc) {
- fprintf(stderr, "Failed to install the net save command. Exiting.\n");
- goto error;
- }
-
- g_nat = nat;
- return ctrl;
-
-error:
- osmo_fd_unregister(&ctrl->listen_fd);
- close(ctrl->listen_fd.fd);
- talloc_free(ctrl);
- return NULL;
-}
-
-void bsc_nat_inform_reject(struct bsc_connection *conn, const char *imsi)
-{
- struct ctrl_cmd *cmd;
-
- cmd = ctrl_cmd_create(conn, CTRL_TYPE_TRAP);
- if (!cmd) {
- LOGP(DCTRL, LOGL_ERROR, "Failed to create TRAP command.\n");
- return;
- }
-
- cmd->id = "0";
- cmd->variable = talloc_asprintf(cmd, "net.0.bsc.%d.notification-rejection-v1",
- conn->cfg->nr);
- cmd->reply = talloc_asprintf(cmd, "imsi=%s", imsi);
-
- ctrl_cmd_send_to_all(conn->cfg->nat->ctrl, cmd);
- talloc_free(cmd);
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_filter.c b/src/osmo-bsc_nat/bsc_nat_filter.c
deleted file mode 100644
index cd7ca25a4..000000000
--- a/src/osmo-bsc_nat/bsc_nat_filter.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * (C) 2010-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2012 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/debug.h>
-
-#include <osmocom/gsm/gsm0808.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-#include <osmocom/sccp/sccp.h>
-
-/* 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,
- char **imsi, struct bsc_filter_reject_cause *cause)
-{
- struct bsc_filter_request req;
- struct tlv_parsed tp;
- struct gsm48_hdr *hdr48;
- int hdr48_len;
- int len;
-
- *con_type = FLT_CON_TYPE_NONE;
- cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
- cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
- *imsi = NULL;
-
- 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);
- req.ctx = bsc;
- req.black_list = &bsc->nat->imsi_black_list;
- req.access_lists = &bsc->nat->access_lists;
- req.local_lst_name = bsc->cfg->acc_lst_name;
- req.global_lst_name = bsc->nat->acc_lst_name;
- req.bsc_nr = bsc->cfg->nr;
- return bsc_msg_filter_initial(hdr48, hdr48_len, &req, con_type, imsi, cause);
-}
-
-int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
- struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed,
- struct bsc_filter_reject_cause *cause)
-{
- uint32_t len;
- struct gsm48_hdr *hdr48;
- struct bsc_filter_request req;
-
- cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
- cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-
- if (con->filter_state.imsi_checked)
- return 0;
-
- /* only care about DTAP messages */
- if (parsed->bssap != BSSAP_MSG_DTAP)
- return 0;
-
- hdr48 = bsc_unpack_dtap(parsed, msg, &len);
- if (!hdr48)
- return -1;
-
- req.ctx = con;
- req.black_list = &bsc->nat->imsi_black_list;
- req.access_lists = &bsc->nat->access_lists;
- req.local_lst_name = bsc->cfg->acc_lst_name;
- req.global_lst_name = bsc->nat->acc_lst_name;
- req.bsc_nr = bsc->cfg->nr;
- return bsc_msg_filter_data(hdr48, len, &req, &con->filter_state, cause);
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_rewrite.c b/src/osmo-bsc_nat/bsc_nat_rewrite.c
deleted file mode 100644
index 7db9234ef..000000000
--- a/src/osmo-bsc_nat/bsc_nat_rewrite.c
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Message rewriting functionality
- */
-/*
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/bsc_msc.h>
-#include <osmocom/bsc/gsm_data.h>
-#include <osmocom/bsc/debug.h>
-#include <osmocom/bsc/ipaccess.h>
-#include <osmocom/bsc/nat_rewrite_trie.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/ipa.h>
-#include <osmocom/gsm/mncc.h>
-#include <osmocom/gsm/gsm48.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-#include <osmocom/sccp/sccp.h>
-
-static char *trie_lookup(struct nat_rewrite *trie, const char *number,
- regoff_t off, void *ctx)
-{
- struct nat_rewrite_rule *rule;
-
- if (!trie) {
- LOGP(DCC, LOGL_ERROR,
- "Asked to do a table lookup but no table.\n");
- return NULL;
- }
-
- rule = nat_rewrite_lookup(trie, number);
- if (!rule) {
- LOGP(DCC, LOGL_DEBUG,
- "Couldn't find a prefix rule for %s\n", number);
- return NULL;
- }
-
- return talloc_asprintf(ctx, "%s%s", rule->rewrite, &number[off]);
-}
-
-static char *match_and_rewrite_number(void *ctx, const char *number,
- const char *imsi, struct llist_head *list,
- struct nat_rewrite *trie)
-{
- struct bsc_nat_num_rewr_entry *entry;
- char *new_number = NULL;
-
- /* need to find a replacement and then fix it */
- llist_for_each_entry(entry, list, list) {
- regmatch_t matches[2];
-
- /* check the IMSI match */
- if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
- continue;
-
- /* this regexp matches... */
- if (regexec(&entry->num_reg, number, 2, matches, 0) == 0
- && matches[1].rm_eo != -1) {
- if (entry->is_prefix_lookup)
- new_number = trie_lookup(trie, number,
- matches[1].rm_so, ctx);
- else
- new_number = talloc_asprintf(ctx, "%s%s",
- entry->replace,
- &number[matches[1].rm_so]);
- }
-
- if (new_number)
- break;
- }
-
- return new_number;
-}
-
-static char *rewrite_isdn_number(struct bsc_nat *nat, struct llist_head *rewr_list,
- void *ctx, const char *imsi,
- struct gsm_mncc_number *called)
-{
- char int_number[sizeof(called->number) + 2];
- char *number = called->number;
-
- if (llist_empty(&nat->num_rewr)) {
- LOGP(DCC, LOGL_DEBUG, "Rewrite rules empty.\n");
- return NULL;
- }
-
- /* only ISDN plan */
- if (called->plan != 1) {
- LOGP(DCC, LOGL_DEBUG, "Called plan is not 1 it was %d\n",
- called->plan);
- return NULL;
- }
-
- /* international, prepend */
- if (called->type == 1) {
- int_number[0] = '+';
- memcpy(&int_number[1], number, strlen(number) + 1);
- number = int_number;
- }
-
- return match_and_rewrite_number(ctx, number,
- imsi, rewr_list, nat->num_rewr_trie);
-}
-
-static void update_called_number(struct gsm_mncc_number *called,
- const char *chosen_number)
-{
- if (strncmp(chosen_number, "00", 2) == 0) {
- called->type = 1;
- osmo_strlcpy(called->number, chosen_number + 2,
- sizeof(called->number));
- } else {
- /* rewrite international to unknown */
- if (called->type == 1)
- called->type = 0;
- osmo_strlcpy(called->number, chosen_number,
- sizeof(called->number));
- }
-}
-
-/**
- * Rewrite non global numbers... according to rules based on the IMSI
- */
-static struct msgb *rewrite_setup(struct bsc_nat *nat, struct msgb *msg,
- struct bsc_nat_parsed *parsed, const char *imsi,
- struct gsm48_hdr *hdr48, const uint32_t len)
-{
- struct tlv_parsed tp;
- unsigned int payload_len;
- struct gsm_mncc_number called;
- struct msgb *out;
- char *new_number_pre = NULL, *new_number_post = NULL, *chosen_number;
- uint8_t *outptr;
- const uint8_t *msgptr;
- int sec_len;
-
- /* decode and rewrite the message */
- payload_len = len - sizeof(*hdr48);
- tlv_parse(&tp, &gsm48_att_tlvdef, hdr48->data, payload_len, 0, 0);
-
- /* no number, well let us ignore it */
- if (!TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD))
- return NULL;
-
- memset(&called, 0, sizeof(called));
- gsm48_decode_called(&called,
- TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 1);
-
- /* check if it looks international and stop */
- LOGP(DCC, LOGL_DEBUG,
- "Pre-Rewrite for IMSI(%s) Plan(%d) Type(%d) Number(%s)\n",
- imsi, called.plan, called.type, called.number);
- new_number_pre = rewrite_isdn_number(nat, &nat->num_rewr, msg, imsi, &called);
-
- if (!new_number_pre) {
- LOGP(DCC, LOGL_DEBUG, "No IMSI(%s) match found, returning message.\n",
- imsi);
- return NULL;
- }
-
- if (strlen(new_number_pre) > sizeof(called.number)) {
- LOGP(DCC, LOGL_ERROR, "Number %s is too long for structure.\n",
- new_number_pre);
- talloc_free(new_number_pre);
- return NULL;
- }
- update_called_number(&called, new_number_pre);
-
- /* another run through the re-write engine with other rules */
- LOGP(DCC, LOGL_DEBUG,
- "Post-Rewrite for IMSI(%s) Plan(%d) Type(%d) Number(%s)\n",
- imsi, called.plan, called.type, called.number);
- new_number_post = rewrite_isdn_number(nat, &nat->num_rewr_post, msg,
- imsi, &called);
- chosen_number = new_number_post ? new_number_post : new_number_pre;
-
-
- if (strlen(chosen_number) > sizeof(called.number)) {
- LOGP(DCC, LOGL_ERROR, "Number %s is too long for structure.\n",
- chosen_number);
- talloc_free(new_number_pre);
- talloc_free(new_number_post);
- return NULL;
- }
-
- /*
- * Need to create a new message now based on the old onew
- * with a new number. We can sadly not patch this in place
- * so we will need to regenerate it.
- */
-
- out = msgb_alloc_headroom(4096, 128, "changed-setup");
- if (!out) {
- LOGP(DCC, LOGL_ERROR, "Failed to allocate.\n");
- talloc_free(new_number_pre);
- talloc_free(new_number_post);
- return NULL;
- }
-
- /* copy the header */
- outptr = msgb_put(out, sizeof(*hdr48));
- memcpy(outptr, hdr48, sizeof(*hdr48));
-
- /* copy everything up to the number */
- sec_len = TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 2 - &hdr48->data[0];
- outptr = msgb_put(out, sec_len);
- memcpy(outptr, &hdr48->data[0], sec_len);
-
- /* create the new number */
- update_called_number(&called, chosen_number);
- LOGP(DCC, LOGL_DEBUG,
- "Chosen number for IMSI(%s) is Plan(%d) Type(%d) Number(%s)\n",
- imsi, called.plan, called.type, called.number);
- gsm48_encode_called(out, &called);
-
- /* copy thre rest */
- msgptr = TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) +
- TLVP_LEN(&tp, GSM48_IE_CALLED_BCD);
- sec_len = payload_len - (msgptr - &hdr48->data[0]);
- outptr = msgb_put(out, sec_len);
- memcpy(outptr, msgptr, sec_len);
-
- talloc_free(new_number_pre);
- talloc_free(new_number_post);
- return out;
-}
-
-/**
- * Find a new SMSC address, returns an allocated string that needs to be
- * freed or is NULL.
- */
-static char *find_new_smsc(struct bsc_nat *nat, void *ctx, const char *imsi,
- const char *smsc_addr, const char *dest_nr)
-{
- struct bsc_nat_num_rewr_entry *entry;
- char *new_number = NULL;
- uint8_t dest_match = llist_empty(&nat->tpdest_match);
-
- /* We will find a new number now */
- llist_for_each_entry(entry, &nat->smsc_rewr, list) {
- regmatch_t matches[2];
-
- /* check the IMSI match */
- if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
- continue;
-
- /* this regexp matches... */
- if (regexec(&entry->num_reg, smsc_addr, 2, matches, 0) == 0 &&
- matches[1].rm_eo != -1)
- new_number = talloc_asprintf(ctx, "%s%s",
- entry->replace,
- &smsc_addr[matches[1].rm_so]);
- if (new_number)
- break;
- }
-
- if (!new_number)
- return NULL;
-
- /*
- * now match the number against another list
- */
- llist_for_each_entry(entry, &nat->tpdest_match, list) {
- /* check the IMSI match */
- if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
- continue;
-
- if (regexec(&entry->num_reg, dest_nr, 0, NULL, 0) == 0) {
- dest_match = 1;
- break;
- }
- }
-
- if (!dest_match) {
- talloc_free(new_number);
- return NULL;
- }
-
- return new_number;
-}
-
-/**
- * Clear the TP-SRR from the TPDU header
- */
-static uint8_t sms_new_tpdu_hdr(struct bsc_nat *nat, const char *imsi,
- const char *dest_nr, uint8_t hdr)
-{
- struct bsc_nat_num_rewr_entry *entry;
-
- /* We will find a new number now */
- llist_for_each_entry(entry, &nat->sms_clear_tp_srr, list) {
- /* check the IMSI match */
- if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
- continue;
- if (regexec(&entry->num_reg, dest_nr, 0, NULL, 0) != 0)
- continue;
-
- /* matched phone number and imsi */
- return hdr & ~0x20;
- }
-
- return hdr;
-}
-
-/**
- * Check if we need to rewrite the number. For this SMS.
- */
-static char *sms_new_dest_nr(struct bsc_nat *nat, void *ctx,
- const char *imsi, const char *dest_nr)
-{
- return match_and_rewrite_number(ctx, dest_nr, imsi,
- &nat->sms_num_rewr, NULL);
-}
-
-/**
- * This is a helper for GSM 04.11 8.2.5.2 Destination address element
- */
-static bool sms_encode_addr_element(struct msgb *out, const char *new_number,
- int format, int tp_data)
-{
- int new_addr_len;
- uint8_t new_addr[26];
-
- /*
- * Copy the new number. We let libosmocore encode it, then set
- * the extension followed after the length. Depending on if
- * we want to write RP we will let the TLV code add the
- * length for us or we need to use strlen... This is not very clear
- * as of 03.40 and 04.11.
- */
- new_addr_len = gsm48_encode_bcd_number(new_addr, ARRAY_SIZE(new_addr),
- 1, new_number);
- if (new_addr_len < 0)
- return false;
-
- new_addr[1] = format;
- if (tp_data) {
- uint8_t *data = msgb_put(out, new_addr_len);
- memcpy(data, new_addr, new_addr_len);
- data[0] = strlen(new_number);
- } else {
- msgb_lv_put(out, new_addr_len - 1, new_addr + 1);
- }
-
- return true;
-}
-
-static struct msgb *sms_create_new(uint8_t type, uint8_t ref,
- struct gsm48_hdr *old_hdr48,
- const uint8_t *orig_addr_ptr,
- int orig_addr_len, const char *new_number,
- const uint8_t *data_ptr, int data_len,
- uint8_t tpdu_first_byte,
- const int old_dest_len, const char *new_dest_nr)
-{
- struct gsm48_hdr *new_hdr48;
- struct msgb *out;
-
- /*
- * We need to re-create the patched structure. This is why we have
- * saved the above pointers.
- */
- out = msgb_alloc_headroom(4096, 128, "changed-smsc");
- if (!out) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n");
- return NULL;
- }
-
- out->l2h = out->data;
- msgb_v_put(out, GSM411_MT_RP_DATA_MO);
- msgb_v_put(out, ref);
- msgb_lv_put(out, orig_addr_len, orig_addr_ptr);
-
- if (!sms_encode_addr_element(out, new_number, 0x91, 0)) {
- LOGP(DNAT, LOGL_ERROR, "Failed to encode SMS address.\n");
- return NULL;
- }
-
-
- /* Patch the TPDU from here on */
-
- /**
- * Do we need to put a new TP-Destination-Address (TP-DA) here or
- * can we copy the old thing? For the TP-DA we need to find out the
- * new size.
- */
- if (new_dest_nr) {
- uint8_t *data, *new_size;
-
- /* reserve the size and write the header */
- new_size = msgb_put(out, 1);
- out->l3h = new_size + 1;
- msgb_v_put(out, tpdu_first_byte);
- msgb_v_put(out, data_ptr[1]);
-
- /* encode the new number and put it */
- if (strncmp(new_dest_nr, "00", 2) == 0) {
- if (!sms_encode_addr_element(out, new_dest_nr + 2, 0x91, 1)) {
- LOGP(DNAT, LOGL_ERROR, "Failed to encode SMS address.\n");
- return NULL;
- }
- } else {
- if (!sms_encode_addr_element(out, new_dest_nr, 0x81, 1)) {
- LOGP(DNAT, LOGL_ERROR, "Failed to encode SMS address.\n");
- return NULL;
- }
- }
- /* Copy the rest after the TP-DS */
- data = msgb_put(out, data_len - 2 - 1 - old_dest_len);
- memcpy(data, &data_ptr[2 + 1 + old_dest_len], data_len - 2 - 1 - old_dest_len);
-
- /* fill in the new size */
- new_size[0] = msgb_l3len(out);
- } else {
- msgb_v_put(out, data_len);
- msgb_tv_fixed_put(out, tpdu_first_byte, data_len - 1, &data_ptr[1]);
- }
-
- /* prepend GSM 04.08 header */
- new_hdr48 = (struct gsm48_hdr *) msgb_push(out, sizeof(*new_hdr48) + 1);
- memcpy(new_hdr48, old_hdr48, sizeof(*old_hdr48));
- new_hdr48->data[0] = msgb_l2len(out);
-
- return out;
-}
-
-/**
- * Parse the SMS and check if it needs to be rewritten
- */
-static struct msgb *rewrite_sms(struct bsc_nat *nat, struct msgb *msg,
- struct bsc_nat_parsed *parsed, const char *imsi,
- struct gsm48_hdr *hdr48, const uint32_t len)
-{
- unsigned int payload_len;
- unsigned int cp_len;
-
- uint8_t ref;
- uint8_t orig_addr_len, *orig_addr_ptr;
- uint8_t dest_addr_len, *dest_addr_ptr;
- uint8_t data_len, *data_ptr;
- char smsc_addr[30];
-
-
- uint8_t dest_len, orig_dest_len;
- char _dest_nr[30];
- char *dest_nr;
- char *new_dest_nr;
-
- char *new_number = NULL;
- uint8_t tpdu_hdr;
- struct msgb *out;
-
- payload_len = len - sizeof(*hdr48);
- if (payload_len < 1) {
- LOGP(DNAT, LOGL_ERROR, "SMS too short for things. %d\n", payload_len);
- return NULL;
- }
-
- cp_len = hdr48->data[0];
- if (payload_len + 1 < cp_len) {
- LOGP(DNAT, LOGL_ERROR, "SMS RPDU can not fit in: %d %d\n", cp_len, payload_len);
- return NULL;
- }
-
- if (hdr48->data[1] != GSM411_MT_RP_DATA_MO)
- return NULL;
-
- if (cp_len < 5) {
- LOGP(DNAT, LOGL_ERROR, "RD-DATA can not fit in the CP len: %d\n", cp_len);
- return NULL;
- }
-
- /* RP */
- ref = hdr48->data[2];
- orig_addr_len = hdr48->data[3];
- orig_addr_ptr = &hdr48->data[4];
-
- /* the +1 is for checking if the following element has some space */
- if (cp_len < 3 + orig_addr_len + 1) {
- LOGP(DNAT, LOGL_ERROR, "RP-Originator addr does not fit: %d\n", orig_addr_len);
- return NULL;
- }
-
- dest_addr_len = hdr48->data[3 + orig_addr_len + 1];
- dest_addr_ptr = &hdr48->data[3 + orig_addr_len + 2];
-
- if (cp_len < 3 + orig_addr_len + 1 + dest_addr_len + 1) {
- LOGP(DNAT, LOGL_ERROR, "RP-Destination addr does not fit: %d\n", dest_addr_len);
- return NULL;
- }
- gsm48_decode_bcd_number(smsc_addr, ARRAY_SIZE(smsc_addr), dest_addr_ptr - 1, 1);
-
- data_len = hdr48->data[3 + orig_addr_len + 1 + dest_addr_len + 1];
- data_ptr = &hdr48->data[3 + orig_addr_len + 1 + dest_addr_len + 2];
-
- if (cp_len < 3 + orig_addr_len + 1 + dest_addr_len + 1 + data_len) {
- LOGP(DNAT, LOGL_ERROR, "RP-Data does not fit: %d\n", data_len);
- return NULL;
- }
-
- if (data_len < 3) {
- LOGP(DNAT, LOGL_ERROR, "SMS-SUBMIT is too short.\n");
- return NULL;
- }
-
- /* TP-PDU starts here */
- if ((data_ptr[0] & 0x03) != GSM340_SMS_SUBMIT_MS2SC)
- return NULL;
-
- /*
- * look into the phone number. The length is in semi-octets, we will
- * need to add the byte for the number type as well.
- */
- orig_dest_len = data_ptr[2];
- dest_len = ((orig_dest_len + 1) / 2) + 1;
- if (data_len < dest_len + 3 || dest_len < 2) {
- LOGP(DNAT, LOGL_ERROR, "SMS-SUBMIT can not have TP-DestAddr.\n");
- return NULL;
- }
-
- if ((data_ptr[3] & 0x80) == 0) {
- LOGP(DNAT, LOGL_ERROR, "TP-DestAddr has extension. Not handled.\n");
- return NULL;
- }
-
- if ((data_ptr[3] & 0x0F) == 0) {
- LOGP(DNAT, LOGL_ERROR, "TP-DestAddr is of unknown type.\n");
- return NULL;
- }
-
- /**
- * Besides of what I think I read in GSM 03.40 and 04.11 the TP-DA
- * contains the semi-octets as length (strlen), change it to the
- * the number of bytes, but then change it back.
- */
- data_ptr[2] = dest_len;
- gsm48_decode_bcd_number(_dest_nr + 2, ARRAY_SIZE(_dest_nr) - 2,
- &data_ptr[2], 1);
- data_ptr[2] = orig_dest_len;
- if ((data_ptr[3] & 0x70) == 0x10) {
- _dest_nr[0] = _dest_nr[1] = '0';
- dest_nr = &_dest_nr[0];
- } else {
- dest_nr = &_dest_nr[2];
- }
-
- /**
- * Call functions to rewrite the data
- */
- tpdu_hdr = sms_new_tpdu_hdr(nat, imsi, dest_nr, data_ptr[0]);
- new_number = find_new_smsc(nat, msg, imsi, smsc_addr, dest_nr);
- new_dest_nr = sms_new_dest_nr(nat, msg, imsi, dest_nr);
-
- if (tpdu_hdr == data_ptr[0] && !new_number && !new_dest_nr)
- return NULL;
-
- out = sms_create_new(GSM411_MT_RP_DATA_MO, ref, hdr48,
- orig_addr_ptr, orig_addr_len,
- new_number ? new_number : smsc_addr,
- data_ptr, data_len, tpdu_hdr,
- dest_len, new_dest_nr);
- talloc_free(new_number);
- talloc_free(new_dest_nr);
- return out;
-}
-
-struct msgb *bsc_nat_rewrite_msg(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *parsed, const char *imsi)
-{
- struct gsm48_hdr *hdr48;
- uint32_t len;
- uint8_t msg_type, proto;
- struct msgb *new_msg = NULL, *sccp;
- uint8_t link_id;
-
- if (!imsi || strlen(imsi) < 5)
- return msg;
-
- /* only care about DTAP messages */
- if (parsed->bssap != BSSAP_MSG_DTAP)
- return msg;
- if (!parsed->dest_local_ref)
- return msg;
-
- hdr48 = bsc_unpack_dtap(parsed, msg, &len);
- if (!hdr48)
- return msg;
-
- link_id = msg->l3h[1];
- proto = gsm48_hdr_pdisc(hdr48);
- msg_type = gsm48_hdr_msg_type(hdr48);
-
- if (proto == GSM48_PDISC_CC && msg_type == GSM48_MT_CC_SETUP)
- new_msg = rewrite_setup(nat, msg, parsed, imsi, hdr48, len);
- else if (proto == GSM48_PDISC_SMS && msg_type == GSM411_MT_CP_DATA)
- new_msg = rewrite_sms(nat, msg, parsed, imsi, hdr48, len);
-
- if (!new_msg)
- return msg;
-
- /* wrap with DTAP, SCCP, then IPA. TODO: Stop copying */
- gsm0808_prepend_dtap_header(new_msg, link_id);
- sccp = sccp_create_dt1(parsed->dest_local_ref, new_msg->data, new_msg->len);
- talloc_free(new_msg);
-
- if (!sccp) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n");
- return msg;
- }
-
- ipa_prepend_header(sccp, IPAC_PROTO_SCCP);
-
- /* the parsed hangs off from msg but it needs to survive */
- talloc_steal(sccp, parsed);
- msgb_free(msg);
- return sccp;
-}
-
-static void num_rewr_free_data(struct bsc_nat_num_rewr_entry *entry)
-{
- regfree(&entry->msisdn_reg);
- regfree(&entry->num_reg);
- talloc_free(entry->replace);
-}
-
-void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head,
- const struct osmo_config_list *list)
-{
- struct bsc_nat_num_rewr_entry *entry, *tmp;
- struct osmo_config_entry *cfg_entry;
-
- /* free the old data */
- llist_for_each_entry_safe(entry, tmp, head, list) {
- num_rewr_free_data(entry);
- llist_del(&entry->list);
- talloc_free(entry);
- }
-
-
- if (!list)
- return;
-
- llist_for_each_entry(cfg_entry, &list->entry, list) {
- char *regexp;
- if (cfg_entry->text[0] == '+') {
- LOGP(DNAT, LOGL_ERROR,
- "Plus is not allowed in the number\n");
- continue;
- }
-
- entry = talloc_zero(ctx, struct bsc_nat_num_rewr_entry);
- if (!entry) {
- LOGP(DNAT, LOGL_ERROR,
- "Allocation of the num_rewr entry failed.\n");
- continue;
- }
-
- entry->replace = talloc_strdup(entry, cfg_entry->text);
- if (!entry->replace) {
- LOGP(DNAT, LOGL_ERROR,
- "Failed to copy the replacement text.\n");
- talloc_free(entry);
- continue;
- }
-
- if (strcmp("prefix_lookup", entry->replace) == 0)
- entry->is_prefix_lookup = 1;
-
- /* we will now build a regexp string */
- if (cfg_entry->mcc[0] == '^') {
- regexp = talloc_strdup(entry, cfg_entry->mcc);
- } else {
- regexp = talloc_asprintf(entry, "^%s%s",
- cfg_entry->mcc[0] == '*' ?
- "[0-9][0-9][0-9]" : cfg_entry->mcc,
- cfg_entry->mnc[0] == '*' ?
- "[0-9][0-9]" : cfg_entry->mnc);
- }
-
- if (!regexp) {
- LOGP(DNAT, LOGL_ERROR, "Failed to create a regexp string.\n");
- talloc_free(entry);
- continue;
- }
-
- if (regcomp(&entry->msisdn_reg, regexp, 0) != 0) {
- LOGP(DNAT, LOGL_ERROR,
- "Failed to compile regexp '%s'\n", regexp);
- talloc_free(regexp);
- talloc_free(entry);
- continue;
- }
-
- talloc_free(regexp);
- if (regcomp(&entry->num_reg, cfg_entry->option, REG_EXTENDED) != 0) {
- LOGP(DNAT, LOGL_ERROR,
- "Failed to compile regexp '%s'\n", cfg_entry->option);
- regfree(&entry->msisdn_reg);
- talloc_free(entry);
- continue;
- }
-
- /* we have copied the number */
- llist_add_tail(&entry->list, head);
- }
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c b/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c
deleted file mode 100644
index af346eff7..000000000
--- a/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Handling for loading a re-write file/database */
-/*
- * (C) 2013 by On-Waves
- * (C) 2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/nat_rewrite_trie.h>
-#include <osmocom/bsc/debug.h>
-#include <osmocom/bsc/vty.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#define CHECK_IS_DIGIT_OR_FAIL(prefix, pos) \
- if (!isdigit(prefix[pos]) && prefix[pos] != '+') { \
- LOGP(DNAT, LOGL_ERROR, \
- "Prefix(%s) contains non ascii text at(%d=%c)\n", \
- prefix, pos, prefix[pos]); \
- goto fail; \
- }
-#define TO_INT(c) \
- ((c) == '+' ? 10 : ((c - '0') % 10))
-
-static void insert_rewrite_node(struct nat_rewrite_rule *rule, struct nat_rewrite *root)
-{
- struct nat_rewrite_rule *new = &root->rule;
-
- const int len = strlen(rule->prefix);
- int i;
-
- if (len <= 0) {
- LOGP(DNAT, LOGL_ERROR, "An empty prefix does not make sense.\n");
- goto fail;
- }
-
- for (i = 0; i < len - 1; ++i) {
- int pos;
-
- /* check if the input is valid */
- CHECK_IS_DIGIT_OR_FAIL(rule->prefix, i);
-
- /* check if the next node is already valid */
- pos = TO_INT(rule->prefix[i]);
- if (!new->rules[pos]) {
- new->rules[pos] = talloc_zero(root, struct nat_rewrite_rule);
- if (!new->rules[pos]) {
- LOGP(DNAT, LOGL_ERROR,
- "Failed to allocate memory.\n");
- goto fail;
- }
-
- new->rules[pos]->empty = 1;
- }
-
- /* we continue here */
- new = new->rules[pos];
- }
-
- /* new now points to the place where we want to add it */
- int pos;
-
- /* check if the input is valid */
- CHECK_IS_DIGIT_OR_FAIL(rule->prefix, (len - 1));
-
- /* check if the next node is already valid */
- pos = TO_INT(rule->prefix[len - 1]);
- if (!new->rules[pos])
- new->rules[pos] = rule;
- else if (new->rules[pos]->empty) {
- /* copy over entries */
- new->rules[pos]->empty = 0;
- memcpy(new->rules[pos]->prefix, rule->prefix, sizeof(rule->prefix));
- memcpy(new->rules[pos]->rewrite, rule->rewrite, sizeof(rule->rewrite));
- talloc_free(rule);
- } else {
- LOGP(DNAT, LOGL_ERROR,
- "Prefix(%s) is already installed\n", rule->prefix);
- goto fail;
- }
-
- root->prefixes += 1;
- return;
-
-fail:
- talloc_free(rule);
- return;
-}
-
-static void handle_line(struct nat_rewrite *rewrite, char *line)
-{
- char *split;
- struct nat_rewrite_rule *rule;
- size_t size_prefix, size_end, len;
-
-
- /* Find the ',' in the line */
- len = strlen(line);
- split = strstr(line, ",");
- if (!split) {
- LOGP(DNAT, LOGL_ERROR, "Line doesn't contain ','\n");
- return;
- }
-
- /* Check if there is space for the rewrite rule */
- size_prefix = split - line;
- if (len - size_prefix <= 2) {
- LOGP(DNAT, LOGL_ERROR, "No rewrite available.\n");
- return;
- }
-
- /* Continue after the ',' to the end */
- split = &line[size_prefix + 1];
- size_end = strlen(split) - 1;
-
- /* Check if both strings can fit into the static array */
- if (size_prefix > sizeof(rule->prefix) - 1) {
- LOGP(DNAT, LOGL_ERROR,
- "Prefix is too long with %zu\n", size_prefix);
- return;
- }
-
- if (size_end > sizeof(rule->rewrite) - 1) {
- LOGP(DNAT, LOGL_ERROR,
- "Rewrite is too long with %zu on %s\n",
- size_end, &line[size_prefix + 1]);
- return;
- }
-
- /* Now create the entry and insert it into the trie */
- rule = talloc_zero(rewrite, struct nat_rewrite_rule);
- if (!rule) {
- LOGP(DNAT, LOGL_ERROR, "Can not allocate memory\n");
- return;
- }
-
- memcpy(rule->prefix, line, size_prefix);
- assert(size_prefix < sizeof(rule->prefix));
- rule->prefix[size_prefix] = '\0';
-
- memcpy(rule->rewrite, split, size_end);
- assert(size_end < sizeof(rule->rewrite));
- rule->rewrite[size_end] = '\0';
-
- /* now insert and balance the tree */
- insert_rewrite_node(rule, rewrite);
-}
-
-struct nat_rewrite *nat_rewrite_parse(void *ctx, const char *filename)
-{
- FILE *file;
- char *line = NULL;
- size_t n = 0;
- struct nat_rewrite *res;
-
- file = fopen(filename, "r");
- if (!file)
- return NULL;
-
- res = talloc_zero(ctx, struct nat_rewrite);
- if (!res) {
- fclose(file);
- return NULL;
- }
-
- /* mark the root as empty */
- res->rule.empty = 1;
-
- while (getline(&line, &n, file) != -1) {
- handle_line(res, line);
- }
-
- free(line);
- fclose(file);
- return res;
-}
-
-/**
- * Simple find that tries to do a longest match...
- */
-struct nat_rewrite_rule *nat_rewrite_lookup(struct nat_rewrite *rewrite,
- const char *prefix)
-{
- struct nat_rewrite_rule *rule = &rewrite->rule;
- struct nat_rewrite_rule *last = NULL;
- const int len = OSMO_MIN(strlen(prefix), (sizeof(rule->prefix) - 1));
- int i;
-
- for (i = 0; rule && i < len; ++i) {
- int pos;
-
- CHECK_IS_DIGIT_OR_FAIL(prefix, i);
- pos = TO_INT(prefix[i]);
-
- rule = rule->rules[pos];
- if (rule && !rule->empty)
- last = rule;
- }
-
- return last;
-
-fail:
- return NULL;
-}
-
-static void nat_rewrite_dump_rec(struct nat_rewrite_rule *rule)
-{
- int i;
- if (!rule->empty)
- printf("%s,%s\n", rule->prefix, rule->rewrite);
-
- for (i = 0; i < ARRAY_SIZE(rule->rules); ++i) {
- if (!rule->rules[i])
- continue;
- nat_rewrite_dump_rec(rule->rules[i]);
- }
-}
-
-void nat_rewrite_dump(struct nat_rewrite *rewrite)
-{
- nat_rewrite_dump_rec(&rewrite->rule);
-}
-
-static void nat_rewrite_dump_rec_vty(struct vty *vty, struct nat_rewrite_rule *rule)
-{
- int i;
- if (!rule->empty)
- vty_out(vty, "%s,%s%s", rule->prefix, rule->rewrite, VTY_NEWLINE);
-
- for (i = 0; i < ARRAY_SIZE(rule->rules); ++i) {
- if (!rule->rules[i])
- continue;
- nat_rewrite_dump_rec_vty(vty, rule->rules[i]);
- }
-}
-
-void nat_rewrite_dump_vty(struct vty *vty, struct nat_rewrite *rewrite)
-{
- nat_rewrite_dump_rec_vty(vty, &rewrite->rule);
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_utils.c b/src/osmo-bsc_nat/bsc_nat_utils.c
deleted file mode 100644
index 3094bbd6e..000000000
--- a/src/osmo-bsc_nat/bsc_nat_utils.c
+++ /dev/null
@@ -1,535 +0,0 @@
-
-/* BSC Multiplexer/NAT Utilities */
-
-/*
- * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/bsc_msc.h>
-#include <osmocom/bsc/gsm_data.h>
-#include <osmocom/bsc/debug.h>
-#include <osmocom/bsc/ipaccess.h>
-#include <osmocom/bsc/vty.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/stats.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/ipa.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-
-static const struct rate_ctr_desc bsc_cfg_ctr_description[] = {
- [BCFG_CTR_SCCP_CONN] = { "sccp.conn", "SCCP Connections "},
- [BCFG_CTR_SCCP_CALLS] = { "sccp.calls", "SCCP Assignment Commands "},
- [BCFG_CTR_NET_RECONN] = { "net.reconnects", "Network reconnects "},
- [BCFG_CTR_DROPPED_SCCP] = { "dropped.sccp", "Dropped SCCP connections."},
- [BCFG_CTR_DROPPED_CALLS] = { "dropped.calls", "Dropped active calls. "},
- [BCFG_CTR_REJECTED_CR] = { "rejected.cr", "Rejected CR due filter "},
- [BCFG_CTR_REJECTED_MSG] = { "rejected.msg", "Rejected MSG due filter "},
- [BCFG_CTR_ILL_PACKET] = { "rejected.ill", "Rejected due parse error "},
- [BCFG_CTR_CON_TYPE_LU] = { "conn.lu", "Conn Location Update "},
- [BCFG_CTR_CON_CMSERV_RQ] = { "conn.rq", "Conn CM Service Req "},
- [BCFG_CTR_CON_PAG_RESP] = { "conn.pag", "Conn Paging Response "},
- [BCFG_CTR_CON_SSA] = { "conn.ssa", "Conn USSD "},
- [BCFG_CTR_CON_OTHER] = { "conn.other", "Conn Other "},
-};
-
-static const struct rate_ctr_group_desc bsc_cfg_ctrg_desc = {
- .group_name_prefix = "nat.bsc",
- .group_description = "NAT BSC Statistics",
- .num_ctr = ARRAY_SIZE(bsc_cfg_ctr_description),
- .ctr_desc = bsc_cfg_ctr_description,
- .class_id = OSMO_STATS_CLASS_PEER,
-};
-
-struct bsc_nat *bsc_nat_alloc(void)
-{
- struct bsc_nat *nat = talloc_zero(tall_bsc_ctx, struct bsc_nat);
- if (!nat)
- return NULL;
-
- nat->main_dest = talloc_zero(nat, struct bsc_msc_dest);
- if (!nat->main_dest) {
- talloc_free(nat);
- return NULL;
- }
-
- INIT_LLIST_HEAD(&nat->sccp_connections);
- INIT_LLIST_HEAD(&nat->bsc_connections);
- INIT_LLIST_HEAD(&nat->paging_groups);
- INIT_LLIST_HEAD(&nat->bsc_configs);
- INIT_LLIST_HEAD(&nat->access_lists);
- INIT_LLIST_HEAD(&nat->dests);
- INIT_LLIST_HEAD(&nat->num_rewr);
- INIT_LLIST_HEAD(&nat->num_rewr_post);
- INIT_LLIST_HEAD(&nat->smsc_rewr);
- INIT_LLIST_HEAD(&nat->tpdest_match);
- INIT_LLIST_HEAD(&nat->sms_clear_tp_srr);
- INIT_LLIST_HEAD(&nat->sms_num_rewr);
-
- nat->stats.sccp.conn = osmo_counter_alloc("nat.sccp.conn");
- nat->stats.sccp.calls = osmo_counter_alloc("nat.sccp.calls");
- nat->stats.bsc.reconn = osmo_counter_alloc("nat.bsc.conn");
- nat->stats.bsc.auth_fail = osmo_counter_alloc("nat.bsc.auth_fail");
- nat->stats.msc.reconn = osmo_counter_alloc("nat.msc.conn");
- nat->stats.ussd.reconn = osmo_counter_alloc("nat.ussd.conn");
- nat->auth_timeout = 2;
- nat->ping_timeout = 20;
- nat->pong_timeout = 5;
-
- llist_add(&nat->main_dest->list, &nat->dests);
- nat->main_dest->ip = talloc_strdup(nat, "127.0.0.1");
- nat->main_dest->port = 5000;
-
- return nat;
-}
-
-void bsc_nat_free(struct bsc_nat *nat)
-{
- struct bsc_config *cfg, *tmp;
- struct bsc_msg_acc_lst *lst, *tmp_lst;
-
- llist_for_each_entry_safe(cfg, tmp, &nat->bsc_configs, entry)
- bsc_config_free(cfg);
- llist_for_each_entry_safe(lst, tmp_lst, &nat->access_lists, list)
- bsc_msg_acc_lst_delete(lst);
-
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, NULL);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr_post, NULL);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, NULL);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_num_rewr, NULL);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->tpdest_match, NULL);
-
- osmo_counter_free(nat->stats.sccp.conn);
- osmo_counter_free(nat->stats.sccp.calls);
- osmo_counter_free(nat->stats.bsc.reconn);
- osmo_counter_free(nat->stats.bsc.auth_fail);
- osmo_counter_free(nat->stats.msc.reconn);
- osmo_counter_free(nat->stats.ussd.reconn);
- talloc_free(nat->mgcp_cfg);
- talloc_free(nat);
-}
-
-void bsc_nat_set_msc_ip(struct bsc_nat *nat, const char *ip)
-{
- osmo_talloc_replace_string(nat, &nat->main_dest->ip, 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;
- osmo_wqueue_init(&con->write_queue, 100);
- INIT_LLIST_HEAD(&con->cmd_pending);
- INIT_LLIST_HEAD(&con->pending_dlcx);
- return con;
-}
-
-struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token,
- unsigned int number)
-{
- struct bsc_config *conf = talloc_zero(nat, struct bsc_config);
- if (!conf)
- return NULL;
-
- conf->token = talloc_strdup(conf, token);
- conf->nr = number;
- conf->nat = nat;
- conf->max_endpoints = 32;
- conf->paging_group = PAGIN_GROUP_UNASSIGNED;
-
- INIT_LLIST_HEAD(&conf->lac_list);
-
- llist_add_tail(&conf->entry, &nat->bsc_configs);
- ++nat->num_bsc;
-
- conf->stats.ctrg = rate_ctr_group_alloc(conf, &bsc_cfg_ctrg_desc, conf->nr);
- if (!conf->stats.ctrg) {
- llist_del(&conf->entry);
- talloc_free(conf);
- return NULL;
- }
-
- return conf;
-}
-
-struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len)
-{
- struct bsc_config *conf;
-
- llist_for_each_entry(conf, &nat->bsc_configs, entry) {
- /*
- * Add the '\0' of the token for the memcmp, the IPA messages
- * for some reason added null termination.
- */
- const int token_len = strlen(conf->token) + 1;
-
- if (token_len == len && memcmp(conf->token, token, token_len) == 0)
- return conf;
- }
-
- return NULL;
-}
-
-void bsc_config_free(struct bsc_config *cfg)
-{
- llist_del(&cfg->entry);
- rate_ctr_group_free(cfg->stats.ctrg);
- cfg->nat->num_bsc--;
- OSMO_ASSERT(cfg->nat->num_bsc >= 0);
- talloc_free(cfg);
-}
-
-static void _add_lac(void *ctx, struct llist_head *list, int _lac)
-{
- struct bsc_lac_entry *lac;
-
- llist_for_each_entry(lac, list, entry)
- if (lac->lac == _lac)
- return;
-
- lac = talloc_zero(ctx, struct bsc_lac_entry);
- if (!lac) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n");
- return;
- }
-
- lac->lac = _lac;
- llist_add_tail(&lac->entry, list);
-}
-
-static void _del_lac(struct llist_head *list, int _lac)
-{
- struct bsc_lac_entry *lac;
-
- llist_for_each_entry(lac, list, entry)
- if (lac->lac == _lac) {
- llist_del(&lac->entry);
- talloc_free(lac);
- return;
- }
-}
-
-void bsc_config_add_lac(struct bsc_config *cfg, int _lac)
-{
- _add_lac(cfg, &cfg->lac_list, _lac);
-}
-
-void bsc_config_del_lac(struct bsc_config *cfg, int _lac)
-{
- _del_lac(&cfg->lac_list, _lac);
-}
-
-struct bsc_nat_paging_group *bsc_nat_paging_group_create(struct bsc_nat *nat, int group)
-{
- struct bsc_nat_paging_group *pgroup;
-
- pgroup = talloc_zero(nat, struct bsc_nat_paging_group);
- if (!pgroup) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate a paging group.\n");
- return NULL;
- }
-
- pgroup->nr = group;
- INIT_LLIST_HEAD(&pgroup->lists);
- llist_add_tail(&pgroup->entry, &nat->paging_groups);
- return pgroup;
-}
-
-void bsc_nat_paging_group_delete(struct bsc_nat_paging_group *pgroup)
-{
- llist_del(&pgroup->entry);
- talloc_free(pgroup);
-}
-
-struct bsc_nat_paging_group *bsc_nat_paging_group_num(struct bsc_nat *nat, int group)
-{
- struct bsc_nat_paging_group *pgroup;
-
- llist_for_each_entry(pgroup, &nat->paging_groups, entry)
- if (pgroup->nr == group)
- return pgroup;
-
- return NULL;
-}
-
-void bsc_nat_paging_group_add_lac(struct bsc_nat_paging_group *pgroup, int lac)
-{
- _add_lac(pgroup, &pgroup->lists, lac);
-}
-
-void bsc_nat_paging_group_del_lac(struct bsc_nat_paging_group *pgroup, int lac)
-{
- _del_lac(&pgroup->lists, lac);
-}
-
-int bsc_config_handles_lac(struct bsc_config *cfg, int lac_nr)
-{
- struct bsc_nat_paging_group *pgroup;
- struct bsc_lac_entry *entry;
-
- llist_for_each_entry(entry, &cfg->lac_list, entry)
- if (entry->lac == lac_nr)
- return 1;
-
- /* now lookup the paging group */
- pgroup = bsc_nat_paging_group_num(cfg->nat, cfg->paging_group);
- if (!pgroup)
- return 0;
-
- llist_for_each_entry(entry, &pgroup->lists, entry)
- if (entry->lac == lac_nr)
- return 1;
-
- return 0;
-}
-
-void sccp_connection_destroy(struct nat_sccp_connection *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);
-}
-
-
-int bsc_nat_find_paging(struct msgb *msg,
- const uint8_t **out_data, int *out_leng)
-{
- int data_length;
- const uint8_t *data;
- struct tlv_parsed tp;
-
- if (!msg->l3h || msgb_l3len(msg) < 3) {
- LOGP(DNAT, LOGL_ERROR, "Paging message is too short.\n");
- return -1;
- }
-
- 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 -2;
- }
-
- 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 -3;
- } else if (data[0] != CELL_IDENT_LAC) {
- LOGP(DNAT, LOGL_ERROR, "Unhandled cell ident discrminator: %d\n", data[0]);
- return -4;
- }
-
- *out_data = &data[1];
- *out_leng = data_length - 1;
- return 0;
-}
-
-int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length)
-{
- struct msgb *msg;
-
- if (length > 4096 - 128) {
- LOGP(DLINP, LOGL_ERROR, "Can not send message of that size.\n");
- return -1;
- }
-
- msg = msgb_alloc_headroom(4096, 128, "to-bsc");
- if (!msg) {
- LOGP(DLINP, 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, IPAC_PROTO_MGCP_OLD);
-}
-
-int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int proto)
-{
- return bsc_do_write(&bsc->write_queue, msg, proto);
-}
-
-int bsc_do_write(struct osmo_wqueue *queue, struct msgb *msg, int proto)
-{
- /* prepend the header */
- ipa_prepend_header(msg, proto);
- return bsc_write_msg(queue, msg);
-}
-
-int bsc_write_msg(struct osmo_wqueue *queue, struct msgb *msg)
-{
- if (osmo_wqueue_enqueue(queue, msg) != 0) {
- LOGP(DLINP, LOGL_ERROR, "Failed to enqueue the write.\n");
- msgb_free(msg);
- return -1;
- }
-
- return 0;
-}
-
-struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed,
- struct msgb *msg, uint32_t *len)
-{
- /* gsm_type is actually the size of the dtap */
- *len = parsed->gsm_type;
- if (*len < msgb_l3len(msg) - 3) {
- LOGP(DNAT, LOGL_ERROR, "Not enough space for DTAP.\n");
- return NULL;
- }
-
- if (msgb_l3len(msg) - 3 < msg->l3h[2]) {
- LOGP(DNAT, LOGL_ERROR,
- "GSM48 payload does not fit: %d %d\n",
- msg->l3h[2], msgb_l3len(msg) - 3);
- return NULL;
- }
-
- msg->l4h = &msg->l3h[3];
- return (struct gsm48_hdr *) msg->l4h;
-}
-
-static const char *con_types [] = {
- [FLT_CON_TYPE_NONE] = "n/a",
- [FLT_CON_TYPE_LU] = "Location Update",
- [FLT_CON_TYPE_CM_SERV_REQ] = "CM Serv Req",
- [FLT_CON_TYPE_PAG_RESP] = "Paging Response",
- [FLT_CON_TYPE_SSA] = "Supplementar Service Activation",
- [FLT_CON_TYPE_LOCAL_REJECT] = "Local Reject",
- [FLT_CON_TYPE_OTHER] = "Other",
-};
-
-const char *bsc_con_type_to_string(int type)
-{
- return con_types[type];
-}
-
-int bsc_nat_msc_is_connected(struct bsc_nat *nat)
-{
- return nat->msc_con->is_connected;
-}
-
-static const int con_to_ctr[] = {
- [FLT_CON_TYPE_NONE] = -1,
- [FLT_CON_TYPE_LU] = BCFG_CTR_CON_TYPE_LU,
- [FLT_CON_TYPE_CM_SERV_REQ] = BCFG_CTR_CON_CMSERV_RQ,
- [FLT_CON_TYPE_PAG_RESP] = BCFG_CTR_CON_PAG_RESP,
- [FLT_CON_TYPE_SSA] = BCFG_CTR_CON_SSA,
- [FLT_CON_TYPE_LOCAL_REJECT] = -1,
- [FLT_CON_TYPE_OTHER] = BCFG_CTR_CON_OTHER,
-};
-
-int bsc_conn_type_to_ctr(struct nat_sccp_connection *conn)
-{
- return con_to_ctr[conn->filter_state.con_type];
-}
-
-int bsc_write_cb(struct osmo_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 void extract_lac(const uint8_t *data, uint16_t *lac, uint16_t *ci)
-{
- memcpy(lac, &data[0], sizeof(*lac));
- memcpy(ci, &data[2], sizeof(*ci));
-
- *lac = ntohs(*lac);
- *ci = ntohs(*ci);
-}
-
-int bsc_nat_extract_lac(struct bsc_connection *bsc,
- struct nat_sccp_connection *con,
- struct bsc_nat_parsed *parsed, struct msgb *msg)
-{
- int data_length;
- const uint8_t *data;
- struct tlv_parsed tp;
- uint16_t lac, ci;
-
- if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
- LOGP(DNAT, LOGL_ERROR, "Can only extract LAC from Complete Layer3\n");
- return -1;
- }
-
- if (!msg->l3h || msgb_l3len(msg) < 3) {
- LOGP(DNAT, LOGL_ERROR, "Complete Layer3 mssage is too short.\n");
- return -1;
- }
-
- tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
- if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER)) {
- LOGP(DNAT, LOGL_ERROR, "No CellIdentifier List inside paging msg.\n");
- return -2;
- }
-
- data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER);
- data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER);
-
- /* Attemt to get the LAC/CI from it */
- if (data[0] == CELL_IDENT_WHOLE_GLOBAL) {
- if (data_length != 8) {
- LOGP(DNAT, LOGL_ERROR,
- "Ident too short: %d\n", data_length);
- return -3;
- }
- extract_lac(&data[1 + 3], &lac, &ci);
- } else if (data[0] == CELL_IDENT_LAC_AND_CI) {
- if (data_length != 5) {
- LOGP(DNAT, LOGL_ERROR,
- "Ident too short: %d\n", data_length);
- return -3;
- }
- extract_lac(&data[1], &lac, &ci);
- } else {
- LOGP(DNAT, LOGL_ERROR,
- "Unhandled cell identifier: %d\n", data[0]);
- return -1;
- }
-
- con->lac = lac;
- con->ci = ci;
- return 0;
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_vty.c b/src/osmo-bsc_nat/bsc_nat_vty.c
deleted file mode 100644
index 5d8d0c79d..000000000
--- a/src/osmo-bsc_nat/bsc_nat_vty.c
+++ /dev/null
@@ -1,1408 +0,0 @@
-/* OpenBSC NAT interface to quagga VTY */
-/* (C) 2010-2015 by Holger Hans Peter Freyther
- * (C) 2010-2015 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/vty.h>
-#include <osmocom/bsc/gsm_data.h>
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/bsc_msc.h>
-#include <osmocom/legacy_mgcp/mgcp.h>
-#include <osmocom/bsc/vty.h>
-#include <osmocom/bsc/nat_rewrite_trie.h>
-#include <osmocom/bsc/debug.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/misc.h>
-#include <osmocom/bsc/osmux.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <stdlib.h>
-#include <stdbool.h>
-
-static struct bsc_nat *_nat;
-
-
-#define BSC_STR "Information about BSCs\n"
-#define MGCP_STR "MGCP related status\n"
-#define PAGING_STR "Paging\n"
-#define SMSC_REWRITE "SMSC Rewriting\n"
-
-static struct cmd_node nat_node = {
- NAT_NODE,
- "%s(config-nat)# ",
- 1,
-};
-
-static struct cmd_node bsc_node = {
- NAT_BSC_NODE,
- "%s(config-nat-bsc)# ",
- 1,
-};
-
-static struct cmd_node pgroup_node = {
- PGROUP_NODE,
- "%s(config-nat-paging-group)# ",
- 1,
-};
-
-static int config_write_pgroup(struct vty *vty)
-{
- return CMD_SUCCESS;
-}
-
-static void dump_lac(struct vty *vty, struct llist_head *head)
-{
- struct bsc_lac_entry *lac;
- llist_for_each_entry(lac, head, entry)
- vty_out(vty, " location_area_code %u%s", lac->lac, VTY_NEWLINE);
-}
-
-
-static void write_pgroup_lst(struct vty *vty, struct bsc_nat_paging_group *pgroup)
-{
- vty_out(vty, " paging-group %d%s", pgroup->nr, VTY_NEWLINE);
- dump_lac(vty, &pgroup->lists);
-}
-
-static int config_write_nat(struct vty *vty)
-{
- struct bsc_msg_acc_lst *lst;
- struct bsc_nat_paging_group *pgroup;
-
- vty_out(vty, "nat%s", VTY_NEWLINE);
- vty_out(vty, " msc ip %s%s", _nat->main_dest->ip, VTY_NEWLINE);
- vty_out(vty, " msc port %d%s", _nat->main_dest->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->include_file)
- vty_out(vty, " bscs-config-file %s%s", _nat->include_file, VTY_NEWLINE);
- if (_nat->token)
- vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
- vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE);
- if (_nat->acc_lst_name)
- vty_out(vty, " access-list-name %s%s", _nat->acc_lst_name, VTY_NEWLINE);
- if (_nat->imsi_black_list_fn)
- vty_out(vty, " imsi-black-list-file-name %s%s",
- _nat->imsi_black_list_fn, VTY_NEWLINE);
- if (_nat->ussd_lst_name)
- vty_out(vty, " ussd-list-name %s%s", _nat->ussd_lst_name, VTY_NEWLINE);
- if (_nat->ussd_query)
- vty_out(vty, " ussd-query %s%s", _nat->ussd_query, VTY_NEWLINE);
- if (_nat->ussd_token)
- vty_out(vty, " ussd-token %s%s", _nat->ussd_token, VTY_NEWLINE);
- if (_nat->ussd_local)
- vty_out(vty, " ussd-local-ip %s%s", _nat->ussd_local, VTY_NEWLINE);
-
- if (_nat->num_rewr_name)
- vty_out(vty, " number-rewrite %s%s", _nat->num_rewr_name, VTY_NEWLINE);
- if (_nat->num_rewr_post_name)
- vty_out(vty, " number-rewrite-post %s%s",
- _nat->num_rewr_post_name, VTY_NEWLINE);
-
- if (_nat->smsc_rewr_name)
- vty_out(vty, " rewrite-smsc addr %s%s",
- _nat->smsc_rewr_name, VTY_NEWLINE);
- if (_nat->tpdest_match_name)
- vty_out(vty, " rewrite-smsc tp-dest-match %s%s",
- _nat->tpdest_match_name, VTY_NEWLINE);
- if (_nat->sms_clear_tp_srr_name)
- vty_out(vty, " sms-clear-tp-srr %s%s",
- _nat->sms_clear_tp_srr_name, VTY_NEWLINE);
- if (_nat->sms_num_rewr_name)
- vty_out(vty, " sms-number-rewrite %s%s",
- _nat->sms_num_rewr_name, VTY_NEWLINE);
- if (_nat->num_rewr_trie_name)
- vty_out(vty, " prefix-tree %s%s",
- _nat->num_rewr_trie_name, VTY_NEWLINE);
-
- llist_for_each_entry(lst, &_nat->access_lists, list)
- bsc_msg_acc_lst_write(vty, lst);
- llist_for_each_entry(pgroup, &_nat->paging_groups, entry)
- write_pgroup_lst(vty, pgroup);
- if (_nat->mgcp_ipa)
- vty_out(vty, " use-msc-ipa-for-mgcp%s", VTY_NEWLINE);
- vty_out(vty, " %ssdp-ensure-amr-mode-set%s",
- _nat->sdp_ensure_amr_mode_set ? "" : "no ", VTY_NEWLINE);
-
- 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);
- if (bsc->key_present)
- vty_out(vty, " auth-key %s%s", osmo_hexdump(bsc->key, 16), VTY_NEWLINE);
- dump_lac(vty, &bsc->lac_list);
- 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);
- vty_out(vty, " max-endpoints %d%s", bsc->max_endpoints, VTY_NEWLINE);
- if (bsc->paging_group != -1)
- vty_out(vty, " paging group %d%s", bsc->paging_group, VTY_NEWLINE);
- vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
- switch (bsc->osmux) {
- case OSMUX_USAGE_ON:
- vty_out(vty, " osmux on%s", VTY_NEWLINE);
- break;
- case OSMUX_USAGE_ONLY:
- vty_out(vty, " osmux only%s", VTY_NEWLINE);
- break;
- }
- if (bsc->bts_use_jibuf_override)
- vty_out(vty, " %sbts-jitter-buffer%s", bsc->bts_use_jibuf? "" : "no ", VTY_NEWLINE);
- if (bsc->bts_jitter_delay_min_override)
- vty_out(vty, " bts-jitter-delay-min %"PRIu32"%s", bsc->bts_jitter_delay_min, VTY_NEWLINE);
- if (bsc->bts_jitter_delay_max_override)
- vty_out(vty, " bts-jitter-delay-max %"PRIu32"%s", bsc->bts_jitter_delay_max, 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_bscs, show_bscs_cmd, "show bscs-config",
- SHOW_STR "Show configured BSCs\n"
- "Both from included file and vty\n")
-{
- vty_out(vty, "BSCs configuration loaded from %s:%s", _nat->resolved_path,
- VTY_NEWLINE);
- return config_write_bsc(vty);
-}
-
-DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
- SHOW_STR "Display information about SCCP\n"
- "All active connections\n")
-{
- struct nat_sccp_connection *con;
- vty_out(vty, "Listing all open SCCP connections%s", VTY_NEWLINE);
-
- llist_for_each_entry(con, &_nat->sccp_connections, list_entry) {
- vty_out(vty, "For BSC Nr: %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,
- 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_endp, con->bsc_endp,
- bsc_con_type_to_string(con->filter_state.con_type),
- VTY_NEWLINE);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_nat_bsc, show_nat_bsc_cmd, "show nat num-bscs-configured",
- SHOW_STR "Display NAT configuration details\n"
- "BSCs-related\n")
-{
- vty_out(vty, "%d BSCs configured%s", _nat->num_bsc, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
- SHOW_STR BSC_STR
- "All active connections\n")
-{
- 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 auth: %d fd: %d peername: %s pending-stats: %u%s",
- con->cfg ? con->cfg->nr : -1,
- con->authenticated, con->write_queue.bfd.fd,
- inet_ntoa(sock.sin_addr), con->pending_dlcx_count,
- VTY_NEWLINE);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc_mgcp, show_bsc_mgcp_cmd, "show bsc mgcp NR",
- SHOW_STR BSC_STR MGCP_STR "Identifier of the BSC\n")
-{
- struct bsc_connection *con;
- int nr = atoi(argv[0]);
- int i, j, endp;
-
- llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
- int max;
- if (!con->cfg)
- continue;
- if (con->cfg->nr != nr)
- continue;
-
- /* this bsc has no audio endpoints yet */
- if (!con->_endpoint_status)
- continue;
-
- vty_out(vty, "MGCP Status for %d%s", con->cfg->nr, VTY_NEWLINE);
- max = bsc_mgcp_nr_multiplexes(con->max_endpoints);
- for (i = 0; i < max; ++i) {
- for (j = 1; j < 32; ++j) {
- endp = mgcp_timeslot_to_endpoint(i, j);
- vty_out(vty, " Endpoint 0x%x %s%s", endp,
- con->_endpoint_status[endp] == 0
- ? "free" : "allocated",
- VTY_NEWLINE);
- }
- }
- break;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
- SHOW_STR BSC_STR "Configuration of BSCs\n")
-{
- struct bsc_config *conf;
- llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
- vty_out(vty, "BSC token: '%s' nr: %u%s",
- conf->token, 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;
-}
-
-static void dump_stat_total(struct vty *vty, struct bsc_nat *nat)
-{
- vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
- vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
- osmo_counter_get(nat->stats.sccp.conn),
- osmo_counter_get(nat->stats.sccp.calls), VTY_NEWLINE);
- vty_out(vty, " MSC Connections %lu%s",
- osmo_counter_get(nat->stats.msc.reconn), VTY_NEWLINE);
- vty_out(vty, " MSC Connected: %d%s",
- bsc_nat_msc_is_connected(nat), VTY_NEWLINE);
- vty_out(vty, " BSC Connections %lu total, %lu auth failed.%s",
- osmo_counter_get(nat->stats.bsc.reconn),
- osmo_counter_get(nat->stats.bsc.auth_fail), VTY_NEWLINE);
-}
-
-static void dump_stat_bsc(struct vty *vty, struct bsc_config *conf)
-{
- int connected = 0;
- struct bsc_connection *con;
-
- vty_out(vty, " BSC nr: %d%s",
- conf->nr, VTY_NEWLINE);
- vty_out_rate_ctr_group(vty, " ", conf->stats.ctrg);
-
- llist_for_each_entry(con, &conf->nat->bsc_connections, list_entry) {
- if (con->cfg != conf)
- continue;
- connected = 1;
- break;
- }
-
- vty_out(vty, " Connected: %d%s", connected, VTY_NEWLINE);
-}
-
-DEFUN(show_stats,
- show_stats_cmd,
- "show statistics [NR]",
- SHOW_STR "Display network statistics\n"
- "Number of the BSC\n")
-{
- struct bsc_config *conf;
-
- int nr = -1;
-
- if (argc == 1)
- nr = atoi(argv[0]);
-
- dump_stat_total(vty, _nat);
- llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
- if (argc == 1 && nr != conf->nr)
- continue;
- dump_stat_bsc(vty, conf);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_stats_lac,
- show_stats_lac_cmd,
- "show statistics-by-lac <0-65535>",
- SHOW_STR "Display network statistics by lac\n"
- "The lac of the BSC\n")
-{
- int lac;
- struct bsc_config *conf;
-
- lac = atoi(argv[0]);
-
- dump_stat_total(vty, _nat);
- llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
- if (!bsc_config_handles_lac(conf, lac))
- continue;
- dump_stat_bsc(vty, conf);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_msc,
- show_msc_cmd,
- "show msc connection",
- SHOW_STR "MSC related information\n"
- "Status of the A-link connection\n")
-{
- if (!_nat->msc_con) {
- vty_out(vty, "The MSC is not yet configured.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty_out(vty, "MSC is connected: %d%s",
- bsc_nat_msc_is_connected(_nat), VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-DEFUN(close_bsc,
- close_bsc_cmd,
- "close bsc connection BSC_NR",
- "Close\n" "A-link\n" "Connection\n" "Identifier of the BSC\n")
-{
- 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", "Configure 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",
- "MSC related configuration\n"
- "Configure the IP address\n" IP_STR)
-{
- 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>",
- "MSC related configuration\n"
- "Configure the port\n"
- "Port number\n")
-{
- _nat->main_dest->port = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_auth_time,
- cfg_nat_auth_time_cmd,
- "timeout auth <1-256>",
- "Timeout configuration\n"
- "Authentication timeout\n"
- "Timeout in seconds\n")
-{
- _nat->auth_timeout = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ping_time,
- cfg_nat_ping_time_cmd,
- "timeout ping NR",
- "Timeout configuration\n"
- "Time between two pings\n"
- "Timeout in seconds\n")
-{
- _nat->ping_timeout = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_pong_time,
- cfg_nat_pong_time_cmd,
- "timeout pong NR",
- "Timeout configuration\n"
- "Waiting for pong timeout\n"
- "Timeout in seconds\n")
-{
- _nat->pong_timeout = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_token, cfg_nat_token_cmd,
- "token TOKEN",
- "Authentication token configuration\n"
- "Token of the BSC, currently transferred in cleartext\n")
-{
- osmo_talloc_replace_string(_nat, &_nat->token, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_bsc_ip_dscp, cfg_nat_bsc_ip_dscp_cmd,
- "ip-dscp <0-255>",
- "Set the IP DSCP for the BSCs to use\n" "Set the IP_TOS attribute")
-{
- _nat->bsc_ip_dscp = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_nat_bsc_ip_dscp, cfg_nat_bsc_ip_tos_cmd,
- "ip-tos <0-255>",
- "Use ip-dscp in the future.\n" "Set the DSCP\n")
-
-
-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.")
-{
- osmo_talloc_replace_string(_nat, &_nat->acc_lst_name, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_include,
- cfg_nat_include_cmd,
- "bscs-config-file NAME",
- "Set the filename of the BSC configuration to include.\n"
- "The filename to be included.")
-{
- char *path;
- int rc;
- struct bsc_config *cf1, *cf2;
- struct bsc_connection *con1, *con2;
-
- if ('/' == argv[0][0])
- osmo_talloc_replace_string(_nat, &_nat->resolved_path, argv[0]);
- else {
- path = talloc_asprintf(_nat, "%s/%s", _nat->include_base,
- argv[0]);
- osmo_talloc_replace_string(_nat, &_nat->resolved_path, path);
- talloc_free(path);
- }
-
- llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
- cf1->remove = true;
- cf1->token_updated = false;
- }
-
- rc = vty_read_config_file(_nat->resolved_path, NULL);
- if (rc < 0) {
- vty_out(vty, "Failed to parse the config file %s: %s%s",
- _nat->resolved_path, strerror(-rc), VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- osmo_talloc_replace_string(_nat, &_nat->include_file, argv[0]);
-
- llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections,
- list_entry) {
- if (con1->cfg)
- if (con1->cfg->token_updated || con1->cfg->remove)
- bsc_close_connection(con1);
- }
-
- llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
- if (cf1->remove)
- bsc_config_free(cf1);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_acc_lst_name,
- cfg_nat_no_acc_lst_name_cmd,
- "no access-list-name",
- NO_STR "Remove the access list from the NAT.\n")
-{
- if (_nat->acc_lst_name) {
- talloc_free(_nat->acc_lst_name);
- _nat->acc_lst_name = NULL;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_imsi_black_list_fn,
- cfg_nat_imsi_black_list_fn_cmd,
- "imsi-black-list-file-name NAME",
- "IMSI black listing\n" "Filename IMSI and reject-cause\n")
-{
-
- osmo_talloc_replace_string(_nat, &_nat->imsi_black_list_fn, argv[0]);
- if (_nat->imsi_black_list_fn) {
- int rc;
- struct osmo_config_list *rewr = NULL;
- rewr = osmo_config_list_parse(_nat, _nat->imsi_black_list_fn);
- rc = bsc_filter_barr_adapt(_nat, &_nat->imsi_black_list, rewr);
- if (rc != 0) {
- vty_out(vty, "%%There was an error parsing the list."
- " Please see the error log.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
- }
-
- bsc_filter_barr_adapt(_nat, &_nat->imsi_black_list, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_imsi_black_list_fn,
- cfg_nat_no_imsi_black_list_fn_cmd,
- "no imsi-black-list-file-name",
- NO_STR "Remove the imsi-black-list\n")
-{
- talloc_free(_nat->imsi_black_list_fn);
- _nat->imsi_black_list_fn = NULL;
- bsc_filter_barr_adapt(_nat, &_nat->imsi_black_list, NULL);
- return CMD_SUCCESS;
-}
-
-static int replace_rules(struct bsc_nat *nat, char **name,
- struct llist_head *head, const char *file)
-{
- struct osmo_config_list *rewr = NULL;
-
- osmo_talloc_replace_string(nat, name, file);
- if (*name) {
- rewr = osmo_config_list_parse(nat, *name);
- bsc_nat_num_rewr_entry_adapt(nat, head, rewr);
- talloc_free(rewr);
- return CMD_SUCCESS;
- } else {
- bsc_nat_num_rewr_entry_adapt(nat, head, NULL);
- return CMD_SUCCESS;
- }
-}
-
-DEFUN(cfg_nat_number_rewrite,
- cfg_nat_number_rewrite_cmd,
- "number-rewrite FILENAME",
- "Set the file with rewriting rules.\n" "Filename")
-{
- return replace_rules(_nat, &_nat->num_rewr_name,
- &_nat->num_rewr, argv[0]);
-}
-
-DEFUN(cfg_nat_no_number_rewrite,
- cfg_nat_no_number_rewrite_cmd,
- "no number-rewrite",
- NO_STR "Set the file with rewriting rules.\n")
-{
- talloc_free(_nat->num_rewr_name);
- _nat->num_rewr_name = NULL;
-
- bsc_nat_num_rewr_entry_adapt(NULL, &_nat->num_rewr, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_number_rewrite_post,
- cfg_nat_number_rewrite_post_cmd,
- "number-rewrite-post FILENAME",
- "Set the file with post-routing rewriting rules.\n" "Filename")
-{
- return replace_rules(_nat, &_nat->num_rewr_post_name,
- &_nat->num_rewr_post, argv[0]);
-}
-
-DEFUN(cfg_nat_no_number_rewrite_post,
- cfg_nat_no_number_rewrite_post_cmd,
- "no number-rewrite-post",
- NO_STR "Set the file with post-routing rewriting rules.\n")
-{
- talloc_free(_nat->num_rewr_post_name);
- _nat->num_rewr_post_name = NULL;
-
- bsc_nat_num_rewr_entry_adapt(NULL, &_nat->num_rewr_post, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_smsc_addr,
- cfg_nat_smsc_addr_cmd,
- "rewrite-smsc addr FILENAME",
- SMSC_REWRITE
- "The SMSC Address to match and replace in RP-DATA\n"
- "File with rules for the SMSC Address replacing\n")
-{
- return replace_rules(_nat, &_nat->smsc_rewr_name,
- &_nat->smsc_rewr, argv[0]);
-}
-
-DEFUN(cfg_nat_smsc_tpdest,
- cfg_nat_smsc_tpdest_cmd,
- "rewrite-smsc tp-dest-match FILENAME",
- SMSC_REWRITE
- "Match TP-Destination of a SMS.\n"
- "File with rules for matching MSISDN and TP-DEST\n")
-{
- return replace_rules(_nat, &_nat->tpdest_match_name,
- &_nat->tpdest_match, argv[0]);
-}
-
-DEFUN(cfg_nat_sms_clear_tpsrr,
- cfg_nat_sms_clear_tpsrr_cmd,
- "sms-clear-tp-srr FILENAME",
- "SMS TPDU Sender Report Request clearing\n"
- "Files with rules for matching MSISDN\n")
-{
- return replace_rules(_nat, &_nat->sms_clear_tp_srr_name,
- &_nat->sms_clear_tp_srr, argv[0]);
-}
-
-DEFUN(cfg_nat_no_sms_clear_tpsrr,
- cfg_nat_no_sms_clear_tpsrr_cmd,
- "no sms-clear-tp-srr",
- NO_STR
- "SMS TPDU Sender Report Request clearing\n")
-{
- talloc_free(_nat->sms_clear_tp_srr_name);
- _nat->sms_clear_tp_srr_name = NULL;
-
- bsc_nat_num_rewr_entry_adapt(NULL, &_nat->sms_clear_tp_srr, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_sms_number_rewrite,
- cfg_nat_sms_number_rewrite_cmd,
- "sms-number-rewrite FILENAME",
- "SMS TP-DA Number rewriting\n"
- "Files with rules for matching MSISDN\n")
-{
- return replace_rules(_nat, &_nat->sms_num_rewr_name,
- &_nat->sms_num_rewr, argv[0]);
-}
-
-DEFUN(cfg_nat_no_sms_number_rewrite,
- cfg_nat_no_sms_number_rewrite_cmd,
- "no sms-number-rewrite",
- NO_STR "Disable SMS TP-DA rewriting\n")
-{
- talloc_free(_nat->sms_num_rewr_name);
- _nat->sms_num_rewr_name = NULL;
-
- bsc_nat_num_rewr_entry_adapt(NULL, &_nat->sms_num_rewr, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_prefix_trie,
- cfg_nat_prefix_trie_cmd,
- "prefix-tree FILENAME",
- "Prefix tree for number rewriting\n" "File to load\n")
-{
- /* give up the old data */
- talloc_free(_nat->num_rewr_trie);
- _nat->num_rewr_trie = NULL;
-
- /* replace the file name */
- osmo_talloc_replace_string(_nat, &_nat->num_rewr_trie_name, argv[0]);
- if (!_nat->num_rewr_trie_name) {
- vty_out(vty, "%% prefix-tree no filename is present.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- _nat->num_rewr_trie = nat_rewrite_parse(_nat, _nat->num_rewr_trie_name);
- if (!_nat->num_rewr_trie) {
- vty_out(vty, "%% prefix-tree parsing has failed.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty_out(vty, "%% prefix-tree loaded %zu rules.%s",
- _nat->num_rewr_trie->prefixes, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_prefix_trie, cfg_nat_no_prefix_trie_cmd,
- "no prefix-tree",
- NO_STR "Prefix tree for number rewriting\n")
-{
- talloc_free(_nat->num_rewr_trie);
- _nat->num_rewr_trie = NULL;
- talloc_free(_nat->num_rewr_trie_name);
- _nat->num_rewr_trie_name = NULL;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(show_prefix_tree, show_prefix_tree_cmd,
- "show prefix-tree",
- SHOW_STR "Prefix tree for number rewriting\n")
-{
- if (!_nat->num_rewr_trie) {
- vty_out(vty, "%% there is now prefix tree loaded.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- nat_rewrite_dump_vty(vty, _nat->num_rewr_trie);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_lst_name,
- cfg_nat_ussd_lst_name_cmd,
- "ussd-list-name NAME",
- "Set the name of the access list to check for IMSIs for USSD message\n"
- "The name of the access list for HLR USSD handling")
-{
- osmo_talloc_replace_string(_nat, &_nat->ussd_lst_name, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_query,
- cfg_nat_ussd_query_cmd,
- "ussd-query REGEXP",
- "Set the USSD query to match with the ussd-list-name\n"
- "The query to match")
-{
- if (gsm_parse_reg(_nat, &_nat->ussd_query_re, &_nat->ussd_query, argc, argv) != 0)
- return CMD_WARNING;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_token,
- cfg_nat_ussd_token_cmd,
- "ussd-token TOKEN",
- "Set the token used to identify the USSD module\n" "Secret key\n")
-{
- osmo_talloc_replace_string(_nat, &_nat->ussd_token, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_local,
- cfg_nat_ussd_local_cmd,
- "ussd-local-ip A.B.C.D",
- "Set the IP to listen for the USSD Provider\n" "IP Address\n")
-{
- osmo_talloc_replace_string(_nat, &_nat->ussd_local, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_use_ipa_for_mgcp,
- cfg_nat_use_ipa_for_mgcp_cmd,
- "use-msc-ipa-for-mgcp",
- "This needs to be set at start. Handle MGCP messages through "
- "the IPA protocol and not through the UDP socket.\n")
-{
- if (_nat->mgcp_cfg->data)
- vty_out(vty,
- "%%the setting will not be applied right now.%s",
- VTY_NEWLINE);
- _nat->mgcp_ipa = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_sdp_amr_mode_set,
- cfg_nat_sdp_amr_mode_set_cmd,
- "sdp-ensure-amr-mode-set",
- "Ensure that SDP records include a mode-set\n")
-{
- _nat->sdp_ensure_amr_mode_set = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_sdp_amr_mode_set,
- cfg_nat_no_sdp_amr_mode_set_cmd,
- "no sdp-ensure-amr-mode-set",
- NO_STR "Ensure that SDP records include a mode-set\n")
-{
- _nat->sdp_ensure_amr_mode_set = 0;
- return CMD_SUCCESS;
-}
-
-/* per BSC configuration */
-DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR",
- "BSC configuration\n" "Identifier of the BSC\n")
-{
- int bsc_nr = atoi(argv[0]);
- struct bsc_config *bsc = bsc_config_num(_nat, bsc_nr);
-
- /* allocate a new one */
- if (!bsc)
- bsc = bsc_config_alloc(_nat, "unknown", bsc_nr);
-
- if (!bsc)
- return CMD_WARNING;
-
- bsc->remove = false;
- vty->index = bsc;
- vty->node = NAT_BSC_NODE;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN",
- "Authentication token configuration\n"
- "Token of the BSC, currently transferred in cleartext\n")
-{
- struct bsc_config *conf = vty->index;
-
- if (strncmp(conf->token, argv[0], 128) != 0)
- conf->token_updated = true;
-
- osmo_talloc_replace_string(conf, &conf->token, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_auth_key, cfg_bsc_auth_key_cmd,
- "auth-key KEY",
- "Authentication (secret) key configuration\n"
- "Non null security key\n")
-{
- struct bsc_config *conf = vty->index;
-
- memset(conf->key, 0, sizeof(conf->key));
- osmo_hexparse(argv[0], conf->key, sizeof(conf->key));
- conf->key_present = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_auth_key, cfg_bsc_no_auth_key_cmd,
- "no auth-key",
- NO_STR "Authentication (secret) key configuration\n")
-{
- struct bsc_config *conf = vty->index;
-
- memset(conf->key, 0, sizeof(conf->key));
- conf->key_present = 0;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
- "Add the Location Area Code (LAC) of this BSC\n" "LAC\n")
-{
- 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 (bsc_config_handles_lac(tmp, lac)) {
- if (tmp->nr != conf->nr) {
- vty_out(vty, "%% LAC %d is already used.%s", lac,
- VTY_NEWLINE);
- return CMD_ERR_INCOMPLETE;
- }
- }
- }
-
- bsc_config_add_lac(conf, lac);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_lac, cfg_bsc_no_lac_cmd,
- "no location_area_code <0-65535>",
- NO_STR "Remove the Location Area Code (LAC) of this BSC\n" "LAC\n")
-{
- int lac = atoi(argv[0]);
- struct bsc_config *conf = vty->index;
-
- bsc_config_del_lac(conf, lac);
- return CMD_SUCCESS;
-}
-
-DEFUN(show_bar_lst,
- show_bar_lst_cmd,
- "show imsi-black-list",
- SHOW_STR "IMSIs barred from the network\n")
-{
- struct rb_node *node;
-
- vty_out(vty, "IMSIs barred from the network:%s", VTY_NEWLINE);
-
- for (node = rb_first(&_nat->imsi_black_list); node; node = rb_next(node)) {
- struct bsc_filter_barr_entry *entry;
- entry = rb_entry(node, struct bsc_filter_barr_entry, node);
-
- vty_out(vty, " IMSI(%s) CM-Reject-Cause(%d) LU-Reject-Cause(%d)%s",
- entry->imsi, entry->cm_reject_cause, entry->lu_reject_cause,
- VTY_NEWLINE);
- }
-
- 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;
-
- osmo_talloc_replace_string(conf, &conf->acc_lst_name, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_acc_lst_name,
- cfg_bsc_no_acc_lst_name_cmd,
- "no access-list-name",
- NO_STR "Do not use an access-list for the BSC.\n")
-{
- struct bsc_config *conf = vty->index;
-
- if (conf->acc_lst_name) {
- talloc_free(conf->acc_lst_name);
- conf->acc_lst_name = NULL;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_max_endps, cfg_bsc_max_endps_cmd,
- "max-endpoints <1-1024>",
- "Highest endpoint to use (exclusively)\n" "Number of ports\n")
-{
- struct bsc_config *conf = vty->index;
-
- conf->max_endpoints = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_paging,
- cfg_bsc_paging_cmd,
- "paging forbidden (0|1)",
- PAGING_STR "Forbid sending PAGING REQUESTS to the BSC.\n"
- "Do not forbid\n" "Forbid\n")
-{
- 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.\n" "Description\n")
-{
- struct bsc_config *conf = vty->index;
-
- osmo_talloc_replace_string(conf, &conf->description, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_paging_grp,
- cfg_bsc_paging_grp_cmd,
- "paging group <0-1000>",
- PAGING_STR "Use a paging group\n" "Paging Group to use\n")
-{
- struct bsc_config *conf = vty->index;
- conf->paging_group = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_bsc_paging_grp, cfg_bsc_old_grp_cmd,
- "paging-group <0-1000>",
- "Use a paging group\n" "Paging Group to use\n")
-
-DEFUN(cfg_bsc_no_paging_grp,
- cfg_bsc_no_paging_grp_cmd,
- "no paging group",
- NO_STR PAGING_STR "Disable the usage of a paging group.\n")
-{
- struct bsc_config *conf = vty->index;
- conf->paging_group = PAGIN_GROUP_UNASSIGNED;
- return CMD_SUCCESS;
-}
-
-DEFUN(test_regex, test_regex_cmd,
- "test regex PATTERN STRING",
- "Test utilities\n"
- "Regexp testing\n" "The regexp pattern\n"
- "The string to match\n")
-{
- regex_t reg;
- char *str = NULL;
-
- memset(&reg, 0, sizeof(reg));
- if (gsm_parse_reg(_nat, &reg, &str, 1, argv) != 0)
- return CMD_WARNING;
-
- 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;
-}
-
-DEFUN(set_last_endp, set_last_endp_cmd,
- "set bsc last-used-endpoint <0-9999999999> <0-1024>",
- "Set a value\n" "Operate on a BSC\n"
- "Last used endpoint for an assignment\n" "BSC configuration number\n"
- "Endpoint number used\n")
-{
- struct bsc_connection *con;
- int nr = atoi(argv[0]);
- int endp = atoi(argv[1]);
-
-
- llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
- if (!con->cfg)
- continue;
- if (con->cfg->nr != nr)
- continue;
-
- con->last_endpoint = endp;
- vty_out(vty, "Updated the last endpoint for %d to %d.%s",
- con->cfg->nr, con->last_endpoint, VTY_NEWLINE);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(block_new_conn, block_new_conn_cmd,
- "nat-block (block|unblock)",
- "Block the NAT for new connections\n"
- "Block\n" "Unblock\n")
-{
- _nat->blocked = argv[0][0] == 'b';
- vty_out(vty, "%%Going to %s the NAT.%s",
- _nat->blocked ? "block" : "unblock", VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-/* paging group */
-DEFUN(cfg_nat_pgroup, cfg_nat_pgroup_cmd,
- "paging-group <0-1000>",
- "Create a Paging Group\n" "Number of the Group\n")
-{
- int group = atoi(argv[0]);
- struct bsc_nat_paging_group *pgroup;
- pgroup = bsc_nat_paging_group_num(_nat, group);
- if (!pgroup)
- pgroup = bsc_nat_paging_group_create(_nat, group);
- if (!pgroup) {
- vty_out(vty, "Failed to create the group.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty->index = pgroup;
- vty->node = PGROUP_NODE;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_pgroup, cfg_nat_no_pgroup_cmd,
- "no paging-group <0-1000>",
- NO_STR "Delete paging-group\n" "Paging-group number\n")
-{
- int group = atoi(argv[0]);
- struct bsc_nat_paging_group *pgroup;
- pgroup = bsc_nat_paging_group_num(_nat, group);
- if (!pgroup) {
- vty_out(vty, "No such paging group %d.%s", group, VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- bsc_nat_paging_group_delete(pgroup);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_pgroup_lac, cfg_pgroup_lac_cmd,
- "location_area_code <0-65535>",
- "Add the Location Area Code (LAC)\n" "LAC\n")
-{
- struct bsc_nat_paging_group *pgroup = 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;
- }
-
- bsc_nat_paging_group_add_lac(pgroup, lac);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_pgroup_no_lac, cfg_pgroup_no_lac_cmd,
- "no location_area_code <0-65535>",
- NO_STR "Remove the Location Area Code (LAC)\n" "LAC\n")
-{
- int lac = atoi(argv[0]);
- struct bsc_nat_paging_group *pgroup = vty->index;
-
- bsc_nat_paging_group_del_lac(pgroup, lac);
- return CMD_SUCCESS;
-}
-
-DEFUN(show_ussd_connection,
- show_ussd_connection_cmd,
- "show ussd-connection",
- SHOW_STR "USSD connection related information\n")
-{
- vty_out(vty, "The USSD side channel provider is %sconnected and %sauthorized.%s",
- _nat->ussd_con ? "" : "not ",
- _nat->ussd_con && _nat->ussd_con->authorized? "" : "not ",
- VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-#define OSMUX_STR "RTP multiplexing\n"
-DEFUN(cfg_bsc_osmux,
- cfg_bsc_osmux_cmd,
- "osmux (on|off|only)",
- OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only OSMUX\n")
-{
- struct bsc_config *conf = vty->index;
- int old = conf->osmux;
-
- if (strcmp(argv[0], "on") == 0)
- conf->osmux = OSMUX_USAGE_ON;
- else if (strcmp(argv[0], "off") == 0)
- conf->osmux = OSMUX_USAGE_OFF;
- else if (strcmp(argv[0], "only") == 0)
- conf->osmux = OSMUX_USAGE_ONLY;
-
- if (old == 0 && conf->osmux > 0 && !conf->nat->mgcp_cfg->osmux_init) {
- LOGP(DLMGCP, LOGL_NOTICE, "Setting up OSMUX socket\n");
- if (osmux_init(OSMUX_ROLE_BSC_NAT, conf->nat->mgcp_cfg) < 0) {
- LOGP(DLMGCP, LOGL_ERROR, "Cannot init OSMUX\n");
- vty_out(vty, "%% failed to create Osmux socket%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- } else if (old > 0 && conf->osmux == 0) {
- LOGP(DLMGCP, LOGL_NOTICE, "Disabling OSMUX socket\n");
- /* Don't stop the socket, we may already have ongoing voice
- * flows already using Osmux. This just switch indicates that
- * new upcoming flows should use RTP.
- */
- }
-
- return CMD_SUCCESS;
-}
-
-#define DEJITTER_STR "Uplink Jitter Buffer"
-DEFUN(cfg_bsc_bts_use_jibuf,
- cfg_bsc_bts_use_jibuf_cmd,
- "bts-jitter-buffer",
- DEJITTER_STR "\n")
-{
- struct bsc_config *conf = vty->index;
- conf->bts_use_jibuf = true;
- conf->bts_use_jibuf_override = true;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_bts_use_jibuf,
- cfg_bsc_no_bts_use_jibuf_cmd,
- "no bts-jitter-buffer",
- NO_STR DEJITTER_STR "\n")
-{
- struct bsc_config *conf = vty->index;
- conf->bts_use_jibuf = false;
- conf->bts_use_jibuf_override = true;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_bts_jitter_delay_min,
- cfg_bsc_bts_jitter_delay_min_cmd,
- "bts-jitter-buffer-delay-min <1-65535>",
- DEJITTER_STR " Minimum Delay in ms\n" "Minimum Delay in ms\n")
-{
- struct bsc_config *conf = vty->index;
- conf->bts_jitter_delay_min = atoi(argv[0]);
- if (!conf->bts_jitter_delay_min) {
- vty_out(vty, "bts-jitter-buffer-delay-min cannot be zero.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (conf->bts_jitter_delay_min && conf->bts_jitter_delay_max &&
- conf->bts_jitter_delay_min > conf->bts_jitter_delay_max) {
- vty_out(vty, "bts-jitter-buffer-delay-min cannot be bigger than " \
- "bts-jitter-buffer-delay-max.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- conf->bts_jitter_delay_min_override = true;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_bts_jitter_delay_max,
- cfg_bsc_bts_jitter_delay_max_cmd,
- "bts-jitter-buffer-delay-max <1-65535>",
- DEJITTER_STR " Maximum Delay in ms\n" "Maximum Delay in ms\n")
-{
- struct bsc_config *conf = vty->index;
- conf->bts_jitter_delay_max = atoi(argv[0]);
- if (!conf->bts_jitter_delay_max) {
- vty_out(vty, "bts-jitter-buffer-delay-max cannot be zero.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (conf->bts_jitter_delay_min && conf->bts_jitter_delay_max &&
- conf->bts_jitter_delay_min > conf->bts_jitter_delay_max) {
- vty_out(vty, "bts-jitter-buffer-delay-max cannot be smaller than " \
- "bts-jitter-buffer-delay-min.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- conf->bts_jitter_delay_max_override = true;
- return CMD_SUCCESS;
-}
-
-int bsc_nat_vty_init(struct bsc_nat *nat)
-{
- _nat = nat;
-
- /* show commands */
- install_element_ve(&show_sccp_cmd);
- install_element_ve(&show_bsc_cmd);
- install_element_ve(&show_nat_bsc_cmd);
- install_element_ve(&show_bsc_cfg_cmd);
- install_element_ve(&show_stats_cmd);
- install_element_ve(&show_stats_lac_cmd);
- install_element_ve(&close_bsc_cmd);
- install_element_ve(&show_msc_cmd);
- install_element_ve(&test_regex_cmd);
- install_element_ve(&show_bsc_mgcp_cmd);
- install_element_ve(&show_bscs_cmd);
- install_element_ve(&show_bar_lst_cmd);
- install_element_ve(&show_prefix_tree_cmd);
- install_element_ve(&show_ussd_connection_cmd);
-
- install_element(ENABLE_NODE, &set_last_endp_cmd);
- install_element(ENABLE_NODE, &block_new_conn_cmd);
-
- /* nat group */
- install_element(CONFIG_NODE, &cfg_nat_cmd);
- install_node(&nat_node, config_write_nat);
- 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_dscp_cmd);
- install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd);
- install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd);
- install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd);
- install_element(NAT_NODE, &cfg_nat_include_cmd);
- install_element(NAT_NODE, &cfg_nat_imsi_black_list_fn_cmd);
- install_element(NAT_NODE, &cfg_nat_no_imsi_black_list_fn_cmd);
- install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd);
- install_element(NAT_NODE, &cfg_nat_ussd_query_cmd);
- install_element(NAT_NODE, &cfg_nat_ussd_token_cmd);
- install_element(NAT_NODE, &cfg_nat_ussd_local_cmd);
- install_element(NAT_NODE, &cfg_nat_use_ipa_for_mgcp_cmd);
-
- bsc_msg_lst_vty_init(nat, &nat->access_lists, NAT_NODE);
-
- /* number rewriting */
- install_element(NAT_NODE, &cfg_nat_number_rewrite_cmd);
- install_element(NAT_NODE, &cfg_nat_no_number_rewrite_cmd);
- install_element(NAT_NODE, &cfg_nat_number_rewrite_post_cmd);
- install_element(NAT_NODE, &cfg_nat_no_number_rewrite_post_cmd);
- install_element(NAT_NODE, &cfg_nat_smsc_addr_cmd);
- install_element(NAT_NODE, &cfg_nat_smsc_tpdest_cmd);
- install_element(NAT_NODE, &cfg_nat_sms_clear_tpsrr_cmd);
- install_element(NAT_NODE, &cfg_nat_no_sms_clear_tpsrr_cmd);
- install_element(NAT_NODE, &cfg_nat_sms_number_rewrite_cmd);
- install_element(NAT_NODE, &cfg_nat_no_sms_number_rewrite_cmd);
- install_element(NAT_NODE, &cfg_nat_prefix_trie_cmd);
- install_element(NAT_NODE, &cfg_nat_no_prefix_trie_cmd);
-
- install_element(NAT_NODE, &cfg_nat_sdp_amr_mode_set_cmd);
- install_element(NAT_NODE, &cfg_nat_no_sdp_amr_mode_set_cmd);
-
- install_element(NAT_NODE, &cfg_nat_pgroup_cmd);
- install_element(NAT_NODE, &cfg_nat_no_pgroup_cmd);
- install_node(&pgroup_node, config_write_pgroup);
- install_element(PGROUP_NODE, &cfg_pgroup_lac_cmd);
- install_element(PGROUP_NODE, &cfg_pgroup_no_lac_cmd);
-
- /* BSC subgroups */
- install_element(NAT_NODE, &cfg_bsc_cmd);
- install_node(&bsc_node, NULL);
- install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_no_auth_key_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_desc_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_acc_lst_name_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_no_acc_lst_name_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_max_endps_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_old_grp_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_paging_grp_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_no_paging_grp_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_osmux_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_bts_use_jibuf_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_no_bts_use_jibuf_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_bts_jitter_delay_min_cmd);
- install_element(NAT_BSC_NODE, &cfg_bsc_bts_jitter_delay_max_cmd);
-
- mgcp_vty_init();
-
- return 0;
-}
-
-
-/* called by the telnet interface... we have our own init above */
-int bsc_vty_init(struct gsm_network *network)
-{
- logging_vty_add_cmds(NULL);
- return 0;
-}
diff --git a/src/osmo-bsc_nat/bsc_sccp.c b/src/osmo-bsc_nat/bsc_sccp.c
deleted file mode 100644
index bb882a664..000000000
--- a/src/osmo-bsc_nat/bsc_sccp.c
+++ /dev/null
@@ -1,247 +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 Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/debug.h>
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/core/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 nat_sccp_connection *conn;
-
- llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
- if (equal(ref, &conn->patched_ref))
- return -1;
- }
-
- return 0;
-}
-
-/* copied from sccp.c */
-static int assign_src_local_reference(struct sccp_source_reference *ref, struct bsc_nat *nat)
-{
- static uint32_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 nat_sccp_connection *create_sccp_src_ref(struct bsc_connection *bsc,
- struct bsc_nat_parsed *parsed)
-{
- struct nat_sccp_connection *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 (!equal(parsed->src_local_ref, &conn->real_ref))
- 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 nat_sccp_connection);
- 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);
- rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_SCCP_CONN]);
- osmo_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 nat_sccp_connection *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 nat_sccp_connection *conn;
-
- llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
- if (equal(parsed->src_local_ref, &conn->patched_ref)) {
- 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 nat_sccp_connection *patch_sccp_src_ref_to_bsc(struct msgb *msg,
- struct bsc_nat_parsed *parsed,
- struct bsc_nat *nat)
-{
- struct nat_sccp_connection *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 nat_sccp_connection *patch_sccp_src_ref_to_msc(struct msgb *msg,
- struct bsc_nat_parsed *parsed,
- struct bsc_connection *bsc)
-{
- struct nat_sccp_connection *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;
-}
-
-struct nat_sccp_connection *bsc_nat_find_con_by_bsc(struct bsc_nat *nat,
- struct sccp_source_reference *ref)
-{
- struct nat_sccp_connection *conn;
-
- llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
- if (equal(ref, &conn->real_ref))
- return conn;
- }
-
- return NULL;
-}
diff --git a/src/osmo-bsc_nat/bsc_ussd.c b/src/osmo-bsc_nat/bsc_ussd.c
deleted file mode 100644
index 985a558dc..000000000
--- a/src/osmo-bsc_nat/bsc_ussd.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/* USSD Filter Code */
-
-/*
- * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/core/socket.h>
-
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/ipaccess.h>
-#include <osmocom/bsc/debug.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/gsm0480.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/ipa.h>
-#include <osmocom/gsm/gsm0480.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/abis/ipa.h>
-
-#include <sys/socket.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define USSD_LAC_IE 0
-#define USSD_CI_IE 1
-
-static void ussd_auth_con(struct tlv_parsed *, struct bsc_nat_ussd_con *);
-
-static struct bsc_nat_ussd_con *bsc_nat_ussd_alloc(struct bsc_nat *nat)
-{
- struct bsc_nat_ussd_con *con;
-
- con = talloc_zero(nat, struct bsc_nat_ussd_con);
- if (!con)
- return NULL;
-
- con->nat = nat;
- return con;
-}
-
-static void bsc_nat_ussd_destroy(struct bsc_nat_ussd_con *con)
-{
- if (con->nat->ussd_con == con) {
- bsc_ussd_close_connections(con->nat);
- con->nat->ussd_con = NULL;
- }
-
- close(con->queue.bfd.fd);
- osmo_fd_unregister(&con->queue.bfd);
- osmo_timer_del(&con->auth_timeout);
- osmo_wqueue_clear(&con->queue);
-
- msgb_free(con->pending_msg);
- talloc_free(con);
-}
-
-static void ussd_pong(struct bsc_nat_ussd_con *conn)
-{
- struct msgb *msg;
-
- msg = msgb_alloc_headroom(4096, 128, "pong message");
- if (!msg) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate pong msg\n");
- return;
- }
-
- msgb_v_put(msg, IPAC_MSGT_PONG);
- bsc_do_write(&conn->queue, msg, IPAC_PROTO_IPACCESS);
-}
-
-static int forward_sccp(struct bsc_nat *nat, struct msgb *msg)
-{
- struct nat_sccp_connection *con;
- struct bsc_nat_parsed *parsed;
-
-
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- LOGP(DNAT, LOGL_ERROR, "Can not parse msg from USSD.\n");
- msgb_free(msg);
- return -1;
- }
-
- if (!parsed->dest_local_ref) {
- LOGP(DNAT, LOGL_ERROR, "No destination local reference.\n");
- msgb_free(msg);
- return -1;
- }
-
- con = bsc_nat_find_con_by_bsc(nat, parsed->dest_local_ref);
- if (!con || !con->bsc) {
- LOGP(DNAT, LOGL_ERROR, "No active connection found.\n");
- msgb_free(msg);
- return -1;
- }
-
- talloc_free(parsed);
- bsc_write_msg(&con->bsc->write_queue, msg);
- return 0;
-}
-
-static int ussd_read_cb(struct osmo_fd *bfd)
-{
- struct bsc_nat_ussd_con *conn = bfd->data;
- struct msgb *msg = NULL;
- struct ipaccess_head *hh;
- int ret;
-
- ret = ipa_msg_recv_buffered(bfd->fd, &msg, &conn->pending_msg);
- if (ret <= 0) {
- if (ret == -EAGAIN)
- return 0;
- LOGP(DNAT, LOGL_ERROR, "USSD Connection was lost.\n");
- bsc_nat_ussd_destroy(conn);
- return -1;
- }
-
- LOGP(DNAT, LOGL_NOTICE, "MSG from USSD: %s proto: %d\n",
- osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
- hh = (struct ipaccess_head *) msg->data;
-
- if (hh->proto == IPAC_PROTO_IPACCESS) {
- if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
- struct tlv_parsed tvp;
- int ret;
- ret = ipa_ccm_idtag_parse(&tvp,
- (unsigned char *) msg->l2h + 2,
- msgb_l2len(msg) - 2);
- if (ret < 0) {
- LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
- "message with malformed TLVs\n");
- msgb_free(msg);
- return ret;
- }
- if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
- ussd_auth_con(&tvp, conn);
- } else if (msg->l2h[0] == IPAC_MSGT_PING) {
- LOGP(DNAT, LOGL_DEBUG, "Got USSD ping request.\n");
- ussd_pong(conn);
- } else {
- LOGP(DNAT, LOGL_NOTICE, "Got unknown IPACCESS message 0x%02x.\n", msg->l2h[0]);
- }
-
- msgb_free(msg);
- } else if (hh->proto == IPAC_PROTO_SCCP) {
- forward_sccp(conn->nat, msg);
- } else {
- msgb_free(msg);
- }
-
- return 0;
-}
-
-static void ussd_auth_cb(void *_data)
-{
- LOGP(DNAT, LOGL_ERROR, "USSD module didn't authenticate\n");
- bsc_nat_ussd_destroy((struct bsc_nat_ussd_con *) _data);
-}
-
-static void ussd_auth_con(struct tlv_parsed *tvp, struct bsc_nat_ussd_con *conn)
-{
- const char *token;
- int len;
- if (!conn->nat->ussd_token) {
- LOGP(DNAT, LOGL_ERROR, "No USSD token set. Closing\n");
- bsc_nat_ussd_destroy(conn);
- return;
- }
-
- token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
- len = TLVP_LEN(tvp, IPAC_IDTAG_UNITNAME);
-
- /* last byte should be a NULL */
- if (strlen(conn->nat->ussd_token) != len - 1)
- goto disconnect;
- /* compare everything including the null byte */
- if (memcmp(conn->nat->ussd_token, token, len) != 0)
- goto disconnect;
-
- /* it is authenticated now */
- if (conn->nat->ussd_con && conn->nat->ussd_con != conn)
- bsc_nat_ussd_destroy(conn->nat->ussd_con);
-
- LOGP(DNAT, LOGL_ERROR, "USSD token specified. USSD provider is connected.\n");
- osmo_timer_del(&conn->auth_timeout);
- conn->authorized = 1;
- conn->nat->ussd_con = conn;
- return;
-
-disconnect:
- LOGP(DNAT, LOGL_ERROR, "Wrong USSD token by client: %d\n",
- conn->queue.bfd.fd);
- bsc_nat_ussd_destroy(conn);
-}
-
-static void ussd_start_auth(struct bsc_nat_ussd_con *conn)
-{
- struct msgb *msg;
-
- osmo_timer_setup(&conn->auth_timeout, ussd_auth_cb, conn);
- osmo_timer_schedule(&conn->auth_timeout, conn->nat->auth_timeout, 0);
-
- msg = msgb_alloc_headroom(4096, 128, "auth message");
- if (!msg) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate auth msg\n");
- return;
- }
-
- msgb_v_put(msg, IPAC_MSGT_ID_GET);
- bsc_do_write(&conn->queue, msg, IPAC_PROTO_IPACCESS);
-}
-
-static int ussd_listen_cb(struct osmo_fd *bfd, unsigned int what)
-{
- struct bsc_nat_ussd_con *conn;
- struct bsc_nat *nat;
- struct sockaddr_in sa;
- socklen_t sa_len = sizeof(sa);
- int fd;
-
- if (!(what & BSC_FD_READ))
- return 0;
-
- fd = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
- if (fd < 0) {
- perror("accept");
- return fd;
- }
-
- nat = (struct bsc_nat *) bfd->data;
- osmo_counter_inc(nat->stats.ussd.reconn);
-
- conn = bsc_nat_ussd_alloc(nat);
- if (!conn) {
- LOGP(DNAT, LOGL_ERROR, "Failed to allocate USSD con struct.\n");
- close(fd);
- return -1;
- }
-
- osmo_wqueue_init(&conn->queue, 10);
- conn->queue.bfd.data = conn;
- conn->queue.bfd.fd = fd;
- conn->queue.bfd.when = BSC_FD_READ;
- conn->queue.read_cb = ussd_read_cb;
- conn->queue.write_cb = bsc_write_cb;
-
- if (osmo_fd_register(&conn->queue.bfd) < 0) {
- LOGP(DNAT, LOGL_ERROR, "Failed to register USSD fd.\n");
- bsc_nat_ussd_destroy(conn);
- return -1;
- }
-
- LOGP(DNAT, LOGL_NOTICE, "USSD Connection on %d with IP: %s\n",
- fd, inet_ntoa(sa.sin_addr));
-
- /* do authentication */
- ussd_start_auth(conn);
- return 0;
-}
-
-int bsc_ussd_init(struct bsc_nat *nat)
-{
- nat->ussd_listen.cb = ussd_listen_cb;
- nat->ussd_listen.data = nat;
- return osmo_sock_init_ofd(&nat->ussd_listen, AF_INET, SOCK_STREAM, IPPROTO_TCP,
- nat->ussd_local, 5001, OSMO_SOCK_F_BIND);
-}
-
-static int forward_ussd_simple(struct nat_sccp_connection *con, struct msgb *input)
-{
- struct msgb *copy;
- struct bsc_nat_ussd_con *ussd;
-
- if (!con->bsc->nat->ussd_con)
- return -1;
-
- copy = msgb_alloc_headroom(4096, 128, "forward bts");
- if (!copy) {
- LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
- return -1;
- }
-
- /* copy the data into the copy */
- copy->l2h = msgb_put(copy, msgb_l2len(input));
- memcpy(copy->l2h, input->l2h, msgb_l2len(input));
-
- /* send it out */
- ussd = con->bsc->nat->ussd_con;
- bsc_do_write(&ussd->queue, copy, IPAC_PROTO_SCCP);
- return 0;
-}
-
-static int forward_ussd(struct nat_sccp_connection *con, const struct ussd_request *req,
- struct msgb *input)
-{
- struct msgb *msg, *copy;
- struct ipac_msgt_sccp_state *state;
- struct bsc_nat_ussd_con *ussd;
- uint16_t lac, ci;
-
- if (!con->bsc->nat->ussd_con)
- return -1;
-
- msg = msgb_alloc_headroom(4096, 128, "forward ussd");
- if (!msg) {
- LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
- return -1;
- }
-
- copy = msgb_alloc_headroom(4096, 128, "forward bts");
- if (!copy) {
- LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
- msgb_free(msg);
- return -1;
- }
-
- copy->l2h = msgb_put(copy, msgb_l2len(input));
- memcpy(copy->l2h, input->l2h, msgb_l2len(input));
-
- msg->l2h = msgb_put(msg, 1);
- msg->l2h[0] = IPAC_MSGT_SCCP_OLD;
-
- /* fill out the data */
- state = (struct ipac_msgt_sccp_state *) msgb_put(msg, sizeof(*state));
- state->trans_id = req->transaction_id;
- state->invoke_id = req->invoke_id;
- memcpy(&state->src_ref, &con->remote_ref, sizeof(con->remote_ref));
- memcpy(&state->dst_ref, &con->real_ref, sizeof(con->real_ref));
- memcpy(state->imsi, con->filter_state.imsi, strlen(con->filter_state.imsi));
-
- /* add additional tag/values */
- lac = htons(con->lac);
- ci = htons(con->ci);
- msgb_tv_fixed_put(msg, USSD_LAC_IE, sizeof(lac), (const uint8_t *) &lac);
- msgb_tv_fixed_put(msg, USSD_CI_IE, sizeof(ci), (const uint8_t *) &ci);
-
- ussd = con->bsc->nat->ussd_con;
- bsc_do_write(&ussd->queue, msg, IPAC_PROTO_IPACCESS);
- bsc_do_write(&ussd->queue, copy, IPAC_PROTO_SCCP);
-
- return 0;
-}
-
-int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed,
- struct msgb *msg)
-{
- uint32_t len;
- uint8_t msg_type;
- uint8_t proto;
- uint8_t ti;
- struct gsm48_hdr *hdr48;
- struct bsc_msg_acc_lst *lst;
- struct ussd_request req;
-
- /*
- * various checks to avoid the decoding work. Right now we only want to
- * decode if the connection was created for USSD, we do have a USSD access
- * list, a query, a IMSI and such...
- */
- if (con->filter_state.con_type != FLT_CON_TYPE_SSA)
- return 0;
-
- if (!con->filter_state.imsi)
- return 0;
-
- /* We have not verified the IMSI yet */
- if (!con->authorized)
- return 0;
-
- if (!con->bsc->nat->ussd_lst_name)
- return 0;
- if (!con->bsc->nat->ussd_query)
- return 0;
-
- if (parsed->bssap != BSSAP_MSG_DTAP)
- return 0;
-
- if (strlen(con->filter_state.imsi) > GSM23003_IMSI_MAX_DIGITS)
- return 0;
-
- hdr48 = bsc_unpack_dtap(parsed, msg, &len);
- if (!hdr48)
- return 0;
-
- proto = gsm48_hdr_pdisc(hdr48);
- msg_type = gsm48_hdr_msg_type(hdr48);
- ti = gsm48_hdr_trans_id_no_ti(hdr48);
- if (proto != GSM48_PDISC_NC_SS)
- return 0;
-
- if (msg_type == GSM0480_MTYPE_REGISTER) {
-
- /* now check if it is a IMSI we care about */
- lst = bsc_msg_acc_lst_find(&con->bsc->nat->access_lists,
- con->bsc->nat->ussd_lst_name);
- if (!lst)
- return 0;
-
- if (bsc_msg_acc_lst_check_allow(lst, con->filter_state.imsi) != 0)
- return 0;
-
- /* now decode the message and see if we really want to handle it */
- memset(&req, 0, sizeof(req));
- if (gsm0480_decode_ussd_request(hdr48, len, &req) != 1)
- return 0;
- if (req.text[0] == 0xff)
- return 0;
-
- if (regexec(&con->bsc->nat->ussd_query_re,
- req.text, 0, NULL, 0) == REG_NOMATCH)
- return 0;
-
- /* found a USSD query for our subscriber */
- LOGP(DNAT, LOGL_NOTICE, "Found USSD query for %s\n",
- con->filter_state.imsi);
- con->ussd_ti[ti] = 1;
- if (forward_ussd(con, &req, msg) != 0)
- return 0;
- return 1;
- } else if (msg_type == GSM0480_MTYPE_FACILITY && con->ussd_ti[ti]) {
- LOGP(DNAT, LOGL_NOTICE, "Forwarding message part of TI: %d %s\n",
- ti, con->filter_state.imsi);
- if (forward_ussd_simple(con, msg) != 0)
- return 0;
- return 1;
- }
-
- return 0;
-}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 652dfe194..20368ee2f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,8 +5,6 @@ SUBDIRS = \
abis \
subscr \
nanobts_omlattr \
- bsc-nat \
- bsc-nat-trie \
bssap \
handover \
$(NULL)
diff --git a/tests/bsc-nat-trie/Makefile.am b/tests/bsc-nat-trie/Makefile.am
deleted file mode 100644
index 4afa1a4d7..000000000
--- a/tests/bsc-nat-trie/Makefile.am
+++ /dev/null
@@ -1,19 +0,0 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) \
- $(LIBOSMOLEGACYMGCP_CFLAGS) \
- $(NULL)
-AM_LDFLAGS = $(COVERAGE_LDFLAGS)
-
-EXTRA_DIST = bsc_nat_trie_test.ok prefixes.csv
-
-noinst_PROGRAMS = bsc_nat_trie_test
-
-bsc_nat_trie_test_SOURCES = bsc_nat_trie_test.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c
-bsc_nat_trie_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
- $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lrt \
- $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) \
- $(LIBOSMOABIS_LIBS) \
- $(LIBOSMOLEGACYMGCP_LIBS) \
- $(LIBRARY_GSM) \
- $(NULL)
diff --git a/tests/bsc-nat-trie/bsc_nat_trie_test.c b/tests/bsc-nat-trie/bsc_nat_trie_test.c
deleted file mode 100644
index 32323d9fa..000000000
--- a/tests/bsc-nat-trie/bsc_nat_trie_test.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * (C) 2013 by On-Waves
- * (C) 2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <osmocom/bsc/nat_rewrite_trie.h>
-#include <osmocom/bsc/debug.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/backtrace.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <string.h>
-
-static const struct log_info_cat log_categories[] = {
-};
-
-static const struct log_info log_info = {
- .cat = log_categories,
- .num_cat = ARRAY_SIZE(log_categories),
-};
-
-int main(int argc, char **argv)
-{
- struct nat_rewrite *trie;
- void *tall_ctx = talloc_named_const(NULL, 1, "bsc_nat_trie_test");
- osmo_init_logging2(tall_ctx, &log_info);
-
- printf("Testing the trie\n");
-
- trie = nat_rewrite_parse(NULL, "prefixes.csv");
- OSMO_ASSERT(trie);
-
- /* verify that it has been parsed */
- OSMO_ASSERT(trie->prefixes == 17);
- printf("Dumping the internal trie\n");
- nat_rewrite_dump(trie);
-
- /* now do the matching... */
- OSMO_ASSERT(!nat_rewrite_lookup(trie, ""));
- OSMO_ASSERT(!nat_rewrite_lookup(trie, "2"));
-
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1")->rewrite, "1") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12")->rewrite, "2") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "123")->rewrite, "3") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1234")->rewrite, "4") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345")->rewrite, "5") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "123456")->rewrite, "6") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1234567")->rewrite, "7") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345678")->rewrite, "8") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "123456789")->rewrite, "9") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1234567890")->rewrite, "10") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "13")->rewrite, "11") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "14")->rewrite, "12") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "15")->rewrite, "13") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "16")->rewrite, "14") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "823455")->rewrite, "15") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "82")->rewrite, "16") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "+49123445")->rewrite, "17") == 0);
-
- /* match a prefix */
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "121")->rewrite, "2") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1292323")->rewrite, "2") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345678901")->rewrite, "10") == 0);
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "160")->rewrite, "14") == 0);
-
- OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345678901123452123123")->rewrite, "10") == 0);
-
- /* invalid input */
- OSMO_ASSERT(!nat_rewrite_lookup(trie, "12abc"));
-
- talloc_free(trie);
-
- trie = nat_rewrite_parse(NULL, "does_not_exist.csv");
- OSMO_ASSERT(!trie);
-
- printf("Done with the tests.\n");
- return 0;
-}
diff --git a/tests/bsc-nat-trie/bsc_nat_trie_test.ok b/tests/bsc-nat-trie/bsc_nat_trie_test.ok
deleted file mode 100644
index 4d4cc9949..000000000
--- a/tests/bsc-nat-trie/bsc_nat_trie_test.ok
+++ /dev/null
@@ -1,20 +0,0 @@
-Testing the trie
-Dumping the internal trie
-1,1
-12,2
-123,3
-1234,4
-12345,5
-123456,6
-1234567,7
-12345678,8
-123456789,9
-1234567890,10
-13,11
-14,12
-15,13
-16,14
-82,16
-823455,15
-+49123,17
-Done with the tests.
diff --git a/tests/bsc-nat-trie/prefixes.csv b/tests/bsc-nat-trie/prefixes.csv
deleted file mode 100644
index 35485b1a3..000000000
--- a/tests/bsc-nat-trie/prefixes.csv
+++ /dev/null
@@ -1,25 +0,0 @@
-1,1
-12,2
-123,3
-1234,4
-12345,5
-123456,6
-1234567,7
-12345678,8
-123456789,9
-1234567890,10
-13,11
-14,12
-15,13
-16,14
-823455,15
-82,16
-+49123,17
-1ABC,18
-12345678901234567890,19
-,20
-14A,21
-124,324324324234
-1234567890,10
-no line
-99,
diff --git a/tests/bsc-nat/Makefile.am b/tests/bsc-nat/Makefile.am
deleted file mode 100644
index c2ed6e44c..000000000
--- a/tests/bsc-nat/Makefile.am
+++ /dev/null
@@ -1,58 +0,0 @@
-AM_CPPFLAGS = \
- $(all_includes) \
- -I$(top_srcdir)/include \
- $(NULL)
-
-AM_CFLAGS = \
- -Wall \
- -ggdb3 \
- $(LIBOSMOCORE_CFLAGS) \
- $(LIBOSMOGSM_CFLAGS) \
- $(LIBOSMOCTRL_LIBS) \
- $(LIBOSMOSCCP_CFLAGS) \
- $(LIBOSMOABIS_CFLAGS) \
- $(LIBOSMONETIF_CFLAGS) \
- $(LIBOSMOLEGACYMGCP_CFLAGS) \
- $(COVERAGE_CFLAGS) \
- $(NULL)
-
-AM_LDFLAGS = \
- $(COVERAGE_LDFLAGS) \
- $(NULL)
-
-EXTRA_DIST = \
- bsc_nat_test.ok \
- bsc_data.c \
- barr.cfg \
- barr_dup.cfg \
- prefixes.csv \
- $(NULL)
-
-noinst_PROGRAMS = \
- bsc_nat_test \
- $(NULL)
-
-bsc_nat_test_SOURCES = \
- bsc_nat_test.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_filter.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_sccp.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_nat_utils.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_mgcp_utils.c \
- $(top_srcdir)/src/osmo-bsc_nat/bsc_nat_filter.c
-
-bsc_nat_test_LDADD = \
- $(top_builddir)/src/libfilter/libfilter.a \
- $(top_builddir)/src/libbsc/libbsc.a \
- $(LIBOSMOCORE_LIBS) \
- $(LIBOSMOGSM_LIBS) \
- $(LIBOSMOSCCP_LIBS) \
- $(LIBOSMOVTY_LIBS) \
- $(LIBOSMOABIS_LIBS) \
- $(LIBOSMONETIF_LIBS) \
- $(LIBOSMOCTRL_LIBS) \
- $(LIBOSMOLEGACYMGCP_LIBS) \
- $(LIBRARY_GSM) \
- -lrt \
- $(NULL)
diff --git a/tests/bsc-nat/barr.cfg b/tests/bsc-nat/barr.cfg
deleted file mode 100644
index a9a4a2b31..000000000
--- a/tests/bsc-nat/barr.cfg
+++ /dev/null
@@ -1,12 +0,0 @@
-12123124:3:2:
-12123123:3:1:
-12123128:3:6:
-12123125:3:3:
-12123127:3:5:
-12123126:3:4:
-12123120:3:4:
-12123119:3:4:
-12123118:3:4:
-12123117:3:4:
-12123116:3:4:
-12123115:3:4:
diff --git a/tests/bsc-nat/barr_dup.cfg b/tests/bsc-nat/barr_dup.cfg
deleted file mode 100644
index ea94631ce..000000000
--- a/tests/bsc-nat/barr_dup.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-12123124:3:2:
-12123124:3:2:
diff --git a/tests/bsc-nat/bsc_data.c b/tests/bsc-nat/bsc_data.c
deleted file mode 100644
index 3a9f1da62..000000000
--- a/tests/bsc-nat/bsc_data.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/* test data */
-
-/* BSC -> MSC, CR */
-static const uint8_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 uint8_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 uint8_t msc_cc[] = {
-0x00, 0x0a, 0xfd,
-0x02, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x02,
-0x01, 0x00 };
-static const uint8_t msc_cc_patched[] = {
-0x00, 0x0a, 0xfd,
-0x02, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x02,
-0x01, 0x00 };
-
-/* Classmark, BSC -> MSC */
-static const uint8_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 uint8_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 uint8_t msc_dtap[] = {
-0x00, 0x0d, 0xfd,
-0x06, 0x00, 0x00, 0x05, 0x00, 0x01, 0x06, 0x00,
-0x04, 0x20, 0x04, 0x01, 0x09 };
-static const uint8_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 uint8_t msc_rlsd[] = {
-0x00, 0x0a, 0xfd,
-0x04, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x00,
-0x01, 0x00 };
-static const uint8_t msc_rlsd_patched[] = {
-0x00, 0x0a, 0xfd,
-0x04, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x00,
-0x01, 0x00 };
-
-/* RLC, BSC -> MSC */
-static const uint8_t bsc_rlc[] = {
-0x00, 0x07, 0xfd,
-0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x15 };
-
-static const uint8_t bsc_rlc_patched[] = {
-0x00, 0x07, 0xfd,
-0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x05 };
-
-
-/* a paging command */
-static const uint8_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 uint8_t ass_cmd[] = {
-0x00, 0x12, 0xfd, 0x06,
-0x00, 0x00, 0x49, 0x00, 0x01, 0x0b, 0x00, 0x09,
-0x01, 0x0b, 0x03, 0x01, 0x0a, 0x11, 0x01, 0x00,
-0x01 };
-
-/* identity response */
-static const uint8_t id_resp[] = {
-0x00, 0x15, 0xfd, 0x06, 0x01, 0x1c, 0xdc,
-0x00, 0x01, 0x0e, 0x01, 0x00, 0x0b, 0x05, 0x59,
-0x08, 0x29, 0x40, 0x21, 0x03, 0x07, 0x48, 0x66,
-0x31
-};
-
-/* sms code msg */
-static const uint8_t smsc_rewrite[] = {
-0x00, 0x30, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x29, 0x01, 0x03, 0x26, 0x09, 0x01, 0x23,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x17, 0x21, 0x0c, 0x0f, 0x81,
-0x00, 0x94, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_patched[] = {
-0x00, 0x31, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x2a, 0x01, 0x03, 0x27, 0x09, 0x01, 0x24,
-0x00, 0x0c, 0x00, 0x08, 0x91, 0x66, 0x66, 0x66,
-0x66, 0x66, 0x66, 0xf7, 0x17, 0x01, 0x0c, 0x0f,
-0x81, 0x00, 0x94, 0x51, 0x87, 0x86, 0x78, 0x46,
-0xf5, 0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c,
-0xca, 0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_patched_hdr[] = {
-0x00, 0x30, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x29, 0x01, 0x03, 0x26, 0x09, 0x01, 0x23,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x17, 0x01, 0x0c, 0x0f, 0x81,
-0x00, 0x94, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_num_patched[] = {
-0x00, 0x2f, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x28, 0x01, 0x03, 0x25, 0x09, 0x01, 0x22,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x16, 0x21, 0x0c, 0x0d, 0x91,
- 0x23, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_num_patched_tp_srr[] = {
-0x00, 0x2f, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x28, 0x01, 0x03, 0x25, 0x09, 0x01, 0x22,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x16, 0x01, 0x0c, 0x0d, 0x91,
- 0x23, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-/*
- * 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 1e@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 3\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 3\r\na=rtpmap:98 AMR/8000\r\na=fmtp:98 mode-set=2\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 1e@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\na=fmtp:98 mode-set=2\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\na=fmtp:98 mode-set=2\n";
-static const char mdcx_resp_patched2_noamr[] = "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;
- const int payload_type;
- const int ensure_mode_set;
-};
-
-static const struct mgcp_patch_test mgcp_messages[] = {
- {
- .orig = crcx,
- .patch = crcx_patched,
- .ip = "0.0.0.0",
- .port = 2323,
- .ensure_mode_set = 1,
- },
- {
- .orig = crcx_resp,
- .patch = crcx_resp_patched,
- .ip = "10.0.0.1",
- .port = 999,
- .payload_type = 98,
- .ensure_mode_set = 1,
- },
- {
- .orig = mdcx,
- .patch = mdcx_patched,
- .ip = "10.0.0.23",
- .port = 6666,
- .payload_type = 126,
- .ensure_mode_set = 1,
- },
- {
- .orig = mdcx_resp,
- .patch = mdcx_resp_patched,
- .ip = "10.0.0.23",
- .port = 5555,
- .payload_type = 98,
- .ensure_mode_set = 1,
- },
- {
- .orig = mdcx_resp2,
- .patch = mdcx_resp_patched2,
- .ip = "10.0.0.23",
- .port = 5555,
- .payload_type = 98,
- .ensure_mode_set = 1,
- },
- {
- .orig = mdcx_resp2,
- .patch = mdcx_resp_patched2_noamr,
- .ip = "10.0.0.23",
- .port = 5555,
- .payload_type = 98,
- .ensure_mode_set = 0,
- },
-};
-
-/* CC Setup messages */
-static const uint8_t cc_setup_national[] = {
- 0x00, 0x20, 0xfd, 0x06, 0x01, 0x12,
- 0x6d, 0x00, 0x01, 0x19, 0x01, 0x00, 0x16, 0x03,
- 0x05, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
- 0x81, 0x5e, 0x06, 0x81, 0x10, 0x27, 0x33, 0x63,
- 0x66, 0x15, 0x02, 0x11, 0x01
-};
-
-static const uint8_t cc_setup_national_patched[] = {
- 0x00, 0x21, 0xfd, 0x06, 0x01, 0x12,
- 0x6d, 0x00, 0x01, 0x1a, 0x01, 0x00, 0x17, 0x03,
- 0x05, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
- 0x81, 0x5e, 0x07, 0x91, 0x94, 0x71, 0x32, 0x33,
- 0x66, 0xf6, 0x15, 0x02, 0x11, 0x01
-};
-
-/* patch the phone number of cc_setup_national_patched */
-static const uint8_t cc_setup_national_patched_patched[] = {
- 0x00, 0x21, 0xfd, 0x06, 0x01, 0x12,
- 0x6d, 0x00, 0x01, 0x1a, 0x01, 0x00, 0x17, 0x03,
- 0x05, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
- 0x81, 0x5e, 0x07, 0x91, 0x63, 0x71, 0x32, 0x33,
- 0x66, 0xf6, 0x15, 0x02, 0x11, 0x01
-};
-
-static const uint8_t cc_setup_international[] = {
- 0x00, 0x22, 0xfd, 0x06, 0x01, 0x13,
- 0xe7, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x18, 0x03,
- 0x45, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
- 0x81, 0x5e, 0x08, 0x81, 0x00, 0x94, 0x71, 0x33,
- 0x63, 0x66, 0x03, 0x15, 0x02, 0x11, 0x01
-};
-
-static const uint8_t cc_setup_national_again[] = {
- 0x00, 0x22, 0xfd, 0x06, 0x01, 0x12, 0x6d, 0x00,
- 0x01, 0x1b, 0x01, 0x00, 0x18, 0x03, 0x05, 0x04,
- 0x06, 0x60, 0x04, 0x02, 0x00, 0x05, 0x81, 0x5e,
- 0x08, 0x81, 0x63, 0x94, 0x71, 0x32, 0x33, 0x66,
- 0xf6, 0x15, 0x02, 0x11, 0x01
-};
diff --git a/tests/bsc-nat/bsc_nat_test.c b/tests/bsc-nat/bsc_nat_test.c
deleted file mode 100644
index 7aa39ece7..000000000
--- a/tests/bsc-nat/bsc_nat_test.c
+++ /dev/null
@@ -1,1595 +0,0 @@
-/*
- * BSC NAT Message filtering
- *
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 by On-Waves
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#include <osmocom/bsc/debug.h>
-#include <osmocom/bsc/gsm_data.h>
-#include <osmocom/bsc/bsc_nat.h>
-#include <osmocom/bsc/bsc_nat_sccp.h>
-#include <osmocom/bsc/bsc_msg_filter.h>
-#include <osmocom/bsc/nat_rewrite_trie.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/backtrace.h>
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/sccp/sccp.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <stdio.h>
-
-/* test messages for ipa */
-static uint8_t ipa_id[] = {
- 0x00, 0x01, 0xfe, 0x06,
-};
-
-/* SCCP messages are below */
-static uint8_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 uint8_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 uint8_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 uint8_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 uint8_t bssmap_cc[] = {
- 0x00, 0x0a, 0xfd,
- 0x02, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
-};
-
-/* MSC -> BSC released */
-static const uint8_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 uint8_t bssmap_release_complete[] = {
- 0x00, 0x07, 0xfd,
- 0x05, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03
-};
-
-/* both directions IT timer */
-static const uint8_t connnection_it[] = {
- 0x00, 0x0b, 0xfd,
- 0x10, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,
- 0x00, 0x00, 0x00, 0x00,
-};
-
-/* error in both directions */
-static const uint8_t proto_error[] = {
- 0x00, 0x05, 0xfd,
- 0x0f, 0x22, 0x33, 0x44, 0x00,
-};
-
-/* MGCP wrap... */
-static const uint8_t mgcp_msg[] = {
- 0x00, 0x03, 0xfc,
- 0x20, 0x20, 0x20,
-};
-
-/* location updating request */
-static const uint8_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 uint8_t *data;
- const uint16_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 */
- printf("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");
-
- printf("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) {
- printf("FAIL: Failed to parse the message\n");
- continue;
- }
-
- result = bsc_nat_filter_ipa(results[i].dir, msg, parsed);
- if (result != results[i].result) {
- printf("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 uint8_t *data, unsigned int length)
-{
- msgb_reset(msg);
- msg->l2h = msgb_put(msg, length);
- memcpy(msg->l2h, data, msgb_l2len(msg));
-}
-
-static void verify_msg(struct msgb *out, const uint8_t *ref, int ref_len)
-{
- if (out->len != ref_len) {
- printf("FAIL: The size should match: %d vs. %d\n",
- out->len, ref_len);
- printf("%s\n", osmo_hexdump(out->data, out->len));
- printf("Wanted\n");
- printf("%s\n", osmo_hexdump(ref, ref_len));
- abort();
- }
-
- if (memcmp(out->data, ref, out->len) != 0) {
- printf("FAIL: the data should be changed.\n");
- printf("%s\n", osmo_hexdump(out->data, out->len));
- printf("Wanted\n");
- printf("%s\n", osmo_hexdump(ref, ref_len));
- abort();
- }
-}
-
-
-#define VERIFY(con_found, con, msg, ver, str) \
- if (!con_found) { \
- printf("Failed to find connection.\n"); \
- abort(); \
- } \
- if (con_found->bsc != con) { \
- printf("Got connection of the wrong BSC: %d\n", \
- con_found->bsc->cfg->nr); \
- abort(); \
- } \
- if (memcmp(msg->data, ver, sizeof(ver)) != 0) { \
- printf("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 nat_sccp_connection *con_found;
- struct nat_sccp_connection *rc_con;
- struct bsc_nat_parsed *parsed;
- struct msgb *msg;
-
- printf("Testing connection tracking.\n");
- nat = bsc_nat_alloc();
- con = bsc_connection_alloc(nat);
- con->cfg = bsc_config_alloc(nat, "foo", 0);
- bsc_config_add_lac(con->cfg, 23);
- bsc_config_add_lac(con->cfg, 49);
- bsc_config_add_lac(con->cfg, 42);
- bsc_config_del_lac(con->cfg, 49);
- bsc_config_add_lac(con->cfg, 1111);
- 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) {
- printf("Con should not exist realref(%u)\n",
- sccp_src_ref_to_int(&con_found->real_ref));
- abort();
- }
- rc_con = create_sccp_src_ref(con, parsed);
- if (!rc_con) {
- printf("Failed to create a ref\n");
- abort();
- }
- con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
- if (!con_found) {
- printf("Failed to find connection.\n");
- abort();
- }
- if (con_found->bsc != con) {
- printf("Got connection of the wrong BSC: %d\n",
- con_found->bsc->cfg->nr);
- abort();
- }
- if (con_found != rc_con) {
- printf("Failed to find the right connection.\n");
- abort();
- }
- if (memcmp(msg->data, bsc_cr_patched, sizeof(bsc_cr_patched)) != 0) {
- printf("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) {
- printf("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) {
- printf("Failed to find connection.\n");
- abort();
- }
- if (con_found->bsc != con) {
- printf("Got connection of the wrong BSC: %d\n",
- con_found->bsc->cfg->nr);
- abort();
- }
- if (memcmp(msg->data, bsc_rlc_patched, sizeof(bsc_rlc_patched)) != 0) {
- printf("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) {
- printf("Con should not exist real_ref(%u)\n",
- sccp_src_ref_to_int(&con_found->real_ref));
- abort();
- }
- talloc_free(parsed);
-
-
- bsc_config_free(con->cfg);
- bsc_nat_free(nat);
- msgb_free(msg);
-}
-
-static void test_paging(void)
-{
- struct bsc_nat *nat;
- struct bsc_connection *con;
- struct bsc_config *cfg;
-
- printf("Testing paging by lac.\n");
-
- nat = bsc_nat_alloc();
- con = bsc_connection_alloc(nat);
- cfg = bsc_config_alloc(nat, "unknown", 0);
- con->cfg = cfg;
- bsc_config_add_lac(cfg, 23);
- con->authenticated = 1;
- llist_add(&con->list_entry, &nat->bsc_connections);
-
- /* Test it by not finding it */
- if (bsc_config_handles_lac(cfg, 8213) != 0) {
- printf("Should not be handled.\n");
- abort();
- }
-
- /* Test by finding it */
- bsc_config_del_lac(cfg, 23);
- bsc_config_add_lac(cfg, 8213);
- if (bsc_config_handles_lac(cfg, 8213) == 0) {
- printf("Should have found it.\n");
- abort();
- }
-
- bsc_nat_free(nat);
-}
-
-static void test_mgcp_allocations(void)
-{
-#if 0
- struct bsc_connection *bsc;
- struct bsc_nat *nat;
- struct nat_sccp_connection con;
- int i, j, multiplex;
-
- printf("Testing MGCP.\n");
- memset(&con, 0, sizeof(con));
-
- nat = bsc_nat_alloc();
- nat->bsc_endpoints = talloc_zero_array(nat,
- struct bsc_endpoint,
- 65);
- nat->mgcp_cfg = mgcp_config_alloc();
- nat->mgcp_cfg->trunk.number_endpoints = 64;
-
- bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo", 0);
- bsc->cfg->max_endpoints = 60;
- bsc_config_add_lac(bsc->cfg, 2323);
- bsc->last_endpoint = 0x22;
- con.bsc = bsc;
-
- bsc_init_endps_if_needed(bsc);
-
- i = 1;
- do {
- if (bsc_assign_endpoint(bsc, &con) != 0) {
- printf("failed to allocate... on iteration %d\n", i);
- break;
- }
- ++i;
- } while(1);
-
- multiplex = bsc_mgcp_nr_multiplexes(bsc->cfg->max_endpoints);
- for (i = 0; i < multiplex; ++i) {
- for (j = 0; j < 32; ++j)
- printf("%d", bsc->_endpoint_status[i*32 + j]);
- printf(": %d of %d\n", i*32 + 32, 32 * 8);
- }
-#endif
-}
-
-static void test_mgcp_ass_tracking(void)
-{
- struct bsc_connection *bsc;
- struct bsc_nat *nat;
- struct nat_sccp_connection con;
- struct bsc_nat_parsed *parsed;
- struct msgb *msg;
-
- printf("Testing MGCP.\n");
- memset(&con, 0, sizeof(con));
-
- nat = bsc_nat_alloc();
- nat->bsc_endpoints = talloc_zero_array(nat,
- struct bsc_endpoint,
- 33);
- nat->mgcp_cfg = mgcp_config_alloc();
- nat->mgcp_cfg->trunk.number_endpoints = 64;
- mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk);
-
- bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo", 0);
- bsc_config_add_lac(bsc->cfg, 2323);
- bsc->last_endpoint = 0x1e;
- con.bsc = bsc;
-
- msg = msgb_alloc(4096, "foo");
- copy_to_msg(msg, ass_cmd, sizeof(ass_cmd));
- parsed = bsc_nat_parse(msg);
-
- if (msg->l2h[16] != 0 ||
- msg->l2h[17] != 0x1) {
- printf("Input is not as expected.. %s 0x%x\n",
- osmo_hexdump(msg->l2h, msgb_l2len(msg)),
- msg->l2h[17]);
- abort();
- }
-
- if (bsc_mgcp_assign_patch(&con, msg) != 0) {
- printf("Failed to handle assignment.\n");
- abort();
- }
-
- if (con.msc_endp != 1) {
- printf("Timeslot should be 1.\n");
- abort();
- }
-
- if (con.bsc_endp != 0x1) {
- printf("Assigned timeslot should have been 1.\n");
- abort();
- }
- if (con.bsc->_endpoint_status[0x1] != 1) {
- printf("The status on the BSC is wrong.\n");
- abort();
- }
-
- int multiplex, timeslot;
- mgcp_endpoint_to_timeslot(0x1, &multiplex, &timeslot);
-
- uint16_t cic = htons(timeslot & 0x1f);
- if (memcmp(&cic, &msg->l2h[16], sizeof(cic)) != 0) {
- printf("Message was not patched properly\n");
- printf("data cic: 0x%x %s\n", cic, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
- abort();
- }
-
- talloc_free(parsed);
-
- bsc_mgcp_dlcx(&con);
- if (con.bsc_endp != -1 || con.msc_endp != -1 ||
- con.bsc->_endpoint_status[1] != 0 || con.bsc->last_endpoint != 0x1) {
- printf("Clearing should remove the mapping.\n");
- abort();
- }
-
- bsc_config_free(bsc->cfg);
- bsc_nat_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 nat_sccp_connection *sccp_con;
-
- printf("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 nat_sccp_connection);
- sccp_con->msc_endp = 12;
- sccp_con->bsc_endp = 12;
- sccp_con->bsc = con;
- llist_add(&sccp_con->list_entry, &nat->sccp_connections);
-
- if (bsc_mgcp_find_con(nat, 11) != NULL) {
- printf("Found the wrong connection.\n");
- abort();
- }
-
- if (bsc_mgcp_find_con(nat, 12) != sccp_con) {
- printf("Didn't find the connection\n");
- abort();
- }
-
- /* free everything */
- bsc_nat_free(nat);
-}
-
-static void test_mgcp_rewrite(void)
-{
- int i;
- struct msgb *output;
- printf("Testing 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;
- const int expected_payload_type = mgcp_messages[i].payload_type;
- const int ensure_mode_set = mgcp_messages[i].ensure_mode_set;
- int payload_type = -1;
-
- char *input = strdup(orig);
-
- output = bsc_mgcp_rewrite(input, strlen(input), 0x1e,
- ip, port, -1, &payload_type, ensure_mode_set);
-
- if (payload_type != -1) {
- fprintf(stderr, "Found media payload type %d in SDP data\n",
- payload_type);
- if (payload_type != expected_payload_type) {
- printf("Wrong payload type %d (expected %d)\n",
- payload_type, expected_payload_type);
- abort();
- }
- }
-
- if (msgb_l2len(output) != strlen(patc)) {
- printf("Wrong sizes for test: %d %u != %zu != %zu\n", i, msgb_l2len(output), strlen(patc), strlen(orig));
- printf("String '%s' vs '%s'\n", (const char *) output->l2h, patc);
- abort();
- }
-
- if (memcmp(output->l2h, patc, msgb_l2len(output)) != 0) {
- printf("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];
-
- printf("Testing MGCP response parsing.\n");
-
- if (bsc_mgcp_parse_response(crcx_resp, &code, transaction) != 0) {
- printf("Failed to parse CRCX resp.\n");
- abort();
- }
-
- if (code != 200) {
- printf("Failed to parse the CODE properly. Got: %d\n", code);
- abort();
- }
-
- if (strcmp(transaction, "23265295") != 0) {
- printf("Failed to parse transaction id: '%s'\n", transaction);
- abort();
- }
-
- ci = bsc_mgcp_extract_ci(crcx_resp);
- if (ci != 1) {
- printf("Failed to parse the CI. Got: %d\n", ci);
- abort();
- }
-}
-
-struct cr_filter {
- const uint8_t *data;
- int length;
- int result;
- int contype;
-
- const char *bsc_imsi_allow;
- const char *bsc_imsi_deny;
- const char *nat_imsi_deny;
- int nat_cm_reject_cause;
- int nat_lu_reject_cause;
- int bsc_cm_reject_cause;
- int bsc_lu_reject_cause;
- int want_cm_reject_cause;
- int want_lu_reject_cause;
-};
-
-static struct cr_filter cr_filter[] = {
- {
- .data = bssmap_cr,
- .length = sizeof(bssmap_cr),
- .result = 1,
- .contype = FLT_CON_TYPE_CM_SERV_REQ,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = 1,
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- .data = pag_resp,
- .length = sizeof(pag_resp),
- .result = 1,
- .contype = FLT_CON_TYPE_PAG_RESP,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- /* nat deny is before blank/null BSC */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = -3,
- .nat_imsi_deny = "[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- /* BSC allow is before NAT deny */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = 1,
- .nat_imsi_deny = "[0-9]*",
- .bsc_imsi_allow = "2440[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- /* BSC allow is before NAT deny */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = 1,
- .bsc_imsi_allow = "[0-9]*",
- .nat_imsi_deny = "[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- /* filter as deny is first */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = 1,
- .bsc_imsi_deny = "[0-9]*",
- .bsc_imsi_allow = "[0-9]*",
- .nat_imsi_deny = "[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- /* deny by nat rule */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = -3,
- .bsc_imsi_deny = "000[0-9]*",
- .nat_imsi_deny = "[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- /* deny by nat rule */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = -3,
- .bsc_imsi_deny = "000[0-9]*",
- .nat_imsi_deny = "[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = 0x23,
- .nat_lu_reject_cause = 0x42,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = 0x42,
- .want_cm_reject_cause = 0x23,
- },
- {
- /* deny by bsc rule */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = -2,
- .bsc_imsi_deny = "[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- },
- {
- /* deny by bsc rule */
- .data = bss_lu,
- .length = sizeof(bss_lu),
- .result = -2,
- .bsc_imsi_deny = "[0-9]*",
- .contype = FLT_CON_TYPE_LU,
- .nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
- .bsc_cm_reject_cause = 0x42,
- .bsc_lu_reject_cause = 0x23,
- .want_lu_reject_cause = 0x23,
- .want_cm_reject_cause = 0x42,
- },
-};
-
-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_msg_acc_lst *nat_lst, *bsc_lst;
- struct bsc_msg_acc_lst_entry *nat_entry, *bsc_entry;
- struct bsc_filter_reject_cause cause;
-
- struct bsc_nat *nat = bsc_nat_alloc();
- struct bsc_connection *bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo", 0);
- bsc_config_add_lac(bsc->cfg, 1234);
- bsc->cfg->acc_lst_name = "bsc";
- nat->acc_lst_name = "nat";
-
- nat_lst = bsc_msg_acc_lst_get(nat, &nat->access_lists, "nat");
- bsc_lst = bsc_msg_acc_lst_get(nat, &nat->access_lists, "bsc");
-
- bsc_entry = bsc_msg_acc_lst_entry_create(bsc_lst);
- nat_entry = bsc_msg_acc_lst_entry_create(nat_lst);
-
- /* test the default value as we are going to overwrite it */
- OSMO_ASSERT(bsc_entry->cm_reject_cause == GSM48_REJECT_PLMN_NOT_ALLOWED);
- OSMO_ASSERT(bsc_entry->lu_reject_cause == GSM48_REJECT_PLMN_NOT_ALLOWED);
-
- for (i = 0; i < ARRAY_SIZE(cr_filter); ++i) {
- char *imsi;
- msgb_reset(msg);
- copy_to_msg(msg, cr_filter[i].data, cr_filter[i].length);
-
- bsc_entry->cm_reject_cause = cr_filter[i].bsc_cm_reject_cause;
- bsc_entry->lu_reject_cause = cr_filter[i].bsc_lu_reject_cause;
- nat_entry->cm_reject_cause = cr_filter[i].nat_cm_reject_cause;
- nat_entry->lu_reject_cause = cr_filter[i].nat_lu_reject_cause;
-
- if (gsm_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) != 0)
- abort();
- if (gsm_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) != 0)
- abort();
- if (gsm_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) != 0)
- abort();
-
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Failed to parse the message\n");
- abort();
- }
-
- memset(&cause, 0, sizeof(cause));
- res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype, &imsi, &cause);
- if (res != cr_filter[i].result) {
- printf("FAIL: Wrong result %d for test %d.\n", res, i);
- abort();
- }
-
-
- OSMO_ASSERT(cause.cm_reject_cause == cr_filter[i].want_cm_reject_cause);
- OSMO_ASSERT(cause.lu_reject_cause == cr_filter[i].want_lu_reject_cause);
-
- if (contype != cr_filter[i].contype) {
- printf("FAIL: Wrong contype %d for test %d.\n", res, contype);
- abort();
- }
-
- talloc_steal(parsed, imsi);
- talloc_free(parsed);
- }
-
- msgb_free(msg);
- bsc_nat_free(nat);
-}
-
-static void test_dt_filter()
-{
- int i;
- struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
- struct bsc_nat_parsed *parsed;
- struct bsc_filter_reject_cause cause;
-
- struct bsc_nat *nat = bsc_nat_alloc();
- struct bsc_connection *bsc = bsc_connection_alloc(nat);
- struct nat_sccp_connection *con = talloc_zero(0, struct nat_sccp_connection);
-
- bsc->cfg = bsc_config_alloc(nat, "foo", 0);
- bsc_config_add_lac(bsc->cfg, 23);
- con->bsc = bsc;
-
- msgb_reset(msg);
- copy_to_msg(msg, id_resp, ARRAY_SIZE(id_resp));
-
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp\n");
- abort();
- }
-
- if (parsed->bssap != BSSAP_MSG_DTAP) {
- printf("FAIL: It should be dtap\n");
- abort();
- }
-
- /* gsm_type is actually the size of the dtap */
- if (parsed->gsm_type < msgb_l3len(msg) - 3) {
- printf("FAIL: Not enough space for the content\n");
- abort();
- }
-
- memset(&cause, 0, sizeof(cause));
- OSMO_ASSERT(!con->filter_state.imsi);
- if (bsc_nat_filter_dt(bsc, msg, con, parsed, &cause) != 1) {
- printf("FAIL: Should have passed..\n");
- abort();
- }
- OSMO_ASSERT(con->filter_state.imsi);
- OSMO_ASSERT(talloc_parent(con->filter_state.imsi) == con);
-
- /* just some basic length checking... */
- for (i = ARRAY_SIZE(id_resp); i >= 0; --i) {
- msgb_reset(msg);
- copy_to_msg(msg, id_resp, ARRAY_SIZE(id_resp));
-
- parsed = bsc_nat_parse(msg);
- if (!parsed)
- continue;
-
- con->filter_state.imsi_checked = 0;
- memset(&cause, 0, sizeof(cause));
- bsc_nat_filter_dt(bsc, msg, con, parsed, &cause);
- }
-
- msgb_free(msg);
- bsc_nat_free(nat);
-}
-
-static void test_setup_rewrite()
-{
- struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
- struct msgb *out;
- struct bsc_nat_parsed *parsed;
- const char *imsi = "27408000001234";
-
- struct bsc_nat *nat = bsc_nat_alloc();
-
- /* a fake list */
- struct osmo_config_list entries;
- struct osmo_config_entry entry;
-
- INIT_LLIST_HEAD(&entries.entry);
- entry.mcc = "274";
- entry.mnc = "08";
- entry.option = "^0([1-9])";
- entry.text = "0049";
- llist_add_tail(&entry.list, &entries.entry);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-
- /* verify that nothing changed */
- msgb_reset(msg);
- copy_to_msg(msg, cc_setup_international, ARRAY_SIZE(cc_setup_international));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (msg != out) {
- printf("FAIL: The message should not have been changed\n");
- abort();
- }
-
- verify_msg(out, cc_setup_international, ARRAY_SIZE(cc_setup_international));
- talloc_free(parsed);
-
- /* verify that something in the message changes */
- msgb_reset(msg);
- copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (!out) {
- printf("FAIL: A new message should be created.\n");
- abort();
- }
-
- if (msg == out) {
- printf("FAIL: The message should have changed\n");
- abort();
- }
-
- verify_msg(out, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
- msgb_free(out);
-
- /* Make sure that a wildcard is matching */
- entry.mnc = "*";
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
- msg = msgb_alloc(4096, "test_dt_filter");
- copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (!out) {
- printf("FAIL: A new message should be created.\n");
- abort();
- }
-
- if (msg == out) {
- printf("FAIL: The message should have changed\n");
- abort();
- }
-
- verify_msg(out, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
- msgb_free(out);
-
- /* Make sure that a wildcard is matching */
- entry.mnc = "09";
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
- msg = msgb_alloc(4096, "test_dt_filter");
- copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (out != msg) {
- printf("FAIL: The message should be unchanged.\n");
- abort();
- }
-
- verify_msg(out, cc_setup_national, ARRAY_SIZE(cc_setup_national));
- msgb_free(out);
-
- /* Now see what happens to an international number */
- entry.mnc = "*";
- entry.option = "^\\+[0-9][0-9]([1-9])";
- entry.text = "0036";
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
- msg = msgb_alloc(4096, "test_dt_filter");
- copy_to_msg(msg, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp %d\n", __LINE__);
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (!out) {
- printf("FAIL: A new message should be created %d.\n", __LINE__);
- abort();
- }
-
- if (msg == out) {
- printf("FAIL: The message should have changed %d\n", __LINE__);
- abort();
- }
-
- verify_msg(out, cc_setup_national_patched_patched,
- ARRAY_SIZE(cc_setup_national_patched_patched));
- msgb_free(out);
-
- /* go from international back to national */
- entry.mnc = "*";
- entry.option = "^\\+([0-9])";
- entry.text = "36";
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
- msg = msgb_alloc(4096, "test_dt_filter");
- copy_to_msg(msg, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp %d\n", __LINE__);
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (!out) {
- printf("FAIL: A new message should be created %d.\n", __LINE__);
- abort();
- }
-
- if (msg == out) {
- printf("FAIL: The message should have changed %d\n", __LINE__);
- abort();
- }
-
- verify_msg(out, cc_setup_national_again,
- ARRAY_SIZE(cc_setup_national_again));
- msgb_free(out);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, NULL);
- bsc_nat_free(nat);
-}
-
-static void test_setup_rewrite_prefix(void)
-{
- struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
- struct msgb *out;
- struct bsc_nat_parsed *parsed;
- const char *imsi = "27408000001234";
-
- struct bsc_nat *nat = bsc_nat_alloc();
-
- /* a fake list */
- struct osmo_config_list entries;
- struct osmo_config_entry entry;
-
- INIT_LLIST_HEAD(&entries.entry);
- entry.mcc = "274";
- entry.mnc = "08";
- entry.option = "^0([1-9])";
- entry.text = "prefix_lookup";
- llist_add_tail(&entry.list, &entries.entry);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-
- nat->num_rewr_trie = nat_rewrite_parse(nat, "prefixes.csv");
-
- msgb_reset(msg);
- copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (!out) {
- printf("FAIL: A new message should be created.\n");
- abort();
- }
-
- if (msg == out) {
- printf("FAIL: The message should have changed\n");
- abort();
- }
-
- verify_msg(out, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
- msgb_free(out);
-
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, NULL);
- bsc_nat_free(nat);
-}
-
-static void test_setup_rewrite_post(void)
-{
- struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
- struct msgb *out;
- struct bsc_nat_parsed *parsed;
- const char *imsi = "27408000001234";
-
- struct bsc_nat *nat = bsc_nat_alloc();
-
- /* a fake list */
- struct osmo_config_list entries;
- struct osmo_config_entry entry;
- struct osmo_config_list entries_post;
- struct osmo_config_entry entry_post;
-
- INIT_LLIST_HEAD(&entries.entry);
- entry.mcc = "274";
- entry.mnc = "08";
- entry.option = "^0([1-9])";
- entry.text = "0049";
- llist_add_tail(&entry.list, &entries.entry);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-
- /* attempt to undo the previous one */
- INIT_LLIST_HEAD(&entries_post.entry);
- entry_post.mcc = "274";
- entry_post.mnc = "08";
- entry_post.option = "^\\+49([1-9])";
- entry_post.text = "prefix_lookup";
- llist_add_tail(&entry_post.list, &entries_post.entry);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr_post, &entries_post);
-
- nat->num_rewr_trie = nat_rewrite_parse(nat, "prefixes.csv");
-
- msgb_reset(msg);
- copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse ID resp\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (!out) {
- printf("FAIL: A new message should be created.\n");
- abort();
- }
-
- if (msg == out) {
- printf("FAIL: The message should have changed\n");
- abort();
- }
-
- verify_msg(out, cc_setup_national, ARRAY_SIZE(cc_setup_national));
- msgb_free(out);
-
- bsc_nat_free(nat);
-}
-
-static void test_sms_smsc_rewrite()
-{
- struct msgb *msg = msgb_alloc(4096, "SMSC rewrite"), *out;
- struct bsc_nat_parsed *parsed;
- const char *imsi = "515039900406700";
-
- struct bsc_nat *nat = bsc_nat_alloc();
-
- /* a fake list */
- struct osmo_config_list smsc_entries, dest_entries, clear_entries;
- struct osmo_config_entry smsc_entry, dest_entry, clear_entry;
-
- INIT_LLIST_HEAD(&smsc_entries.entry);
- INIT_LLIST_HEAD(&dest_entries.entry);
- INIT_LLIST_HEAD(&clear_entries.entry);
- smsc_entry.mcc = "^515039";
- smsc_entry.option = "639180000105()";
- smsc_entry.text = "6666666666667";
- llist_add_tail(&smsc_entry.list, &smsc_entries.entry);
- dest_entry.mcc = "515";
- dest_entry.mnc = "03";
- dest_entry.option = "^0049";
- dest_entry.text = "";
- llist_add_tail(&dest_entry.list, &dest_entries.entry);
- clear_entry.mcc = "^515039";
- clear_entry.option = "^0049";
- clear_entry.text = "";
- llist_add_tail(&clear_entry.list, &clear_entries.entry);
-
- bsc_nat_num_rewr_entry_adapt(nat, &nat->smsc_rewr, &smsc_entries);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->tpdest_match, &dest_entries);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, &clear_entries);
-
- printf("Testing SMSC rewriting.\n");
-
- /*
- * Check if the SMSC address is changed
- */
- copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse SMS\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (out == msg) {
- printf("FAIL: This should have changed.\n");
- abort();
- }
-
- verify_msg(out, smsc_rewrite_patched, ARRAY_SIZE(smsc_rewrite_patched));
- msgb_free(out);
-
- /* clear out the filter for SMSC */
- printf("Attempting to only rewrite the HDR\n");
- bsc_nat_num_rewr_entry_adapt(nat, &nat->smsc_rewr, NULL);
- msg = msgb_alloc(4096, "SMSC rewrite");
- copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse SMS\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (out == msg) {
- printf("FAIL: This should have changed.\n");
- abort();
- }
-
- verify_msg(out, smsc_rewrite_patched_hdr, ARRAY_SIZE(smsc_rewrite_patched_hdr));
- msgb_free(out);
-
- /* clear out the next filter */
- printf("Attempting to change nothing.\n");
- bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, NULL);
- msg = msgb_alloc(4096, "SMSC rewrite");
- copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse SMS\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (out != msg) {
- printf("FAIL: This should not have changed.\n");
- abort();
- }
-
- verify_msg(out, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
- msgb_free(out);
- bsc_nat_free(nat);
-}
-
-static void test_sms_number_rewrite(void)
-{
- struct msgb *msg, *out;
- struct bsc_nat_parsed *parsed;
- const char *imsi = "515039900406700";
-
- struct bsc_nat *nat = bsc_nat_alloc();
-
- /* a fake list */
- struct osmo_config_list num_entries, clear_entries;
- struct osmo_config_entry num_entry, clear_entry;
-
- INIT_LLIST_HEAD(&num_entries.entry);
- num_entry.mcc = "^515039";
- num_entry.option = "^0049()";
- num_entry.text = "0032";
- llist_add_tail(&num_entry.list, &num_entries.entry);
-
- bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_num_rewr, &num_entries);
-
- printf("Testing SMS TP-DA rewriting.\n");
-
- /*
- * Check if the SMSC address is changed
- */
- msg = msgb_alloc(4096, "SMSC rewrite");
- copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse SMS\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (out == msg) {
- printf("FAIL: This should have changed.\n");
- abort();
- }
-
- verify_msg(out, smsc_rewrite_num_patched,
- ARRAY_SIZE(smsc_rewrite_num_patched));
- msgb_free(out);
-
- /*
- * Now with TP-SRR rewriting enabled
- */
- INIT_LLIST_HEAD(&clear_entries.entry);
- clear_entry.mcc = "^515039";
- clear_entry.option = "";
- clear_entry.text = "";
- llist_add_tail(&clear_entry.list, &clear_entries.entry);
- bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, &clear_entries);
-
- msg = msgb_alloc(4096, "SMSC rewrite");
- copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
- parsed = bsc_nat_parse(msg);
- if (!parsed) {
- printf("FAIL: Could not parse SMS\n");
- abort();
- }
-
- out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
- if (out == msg) {
- printf("FAIL: This should have changed.\n");
- abort();
- }
-
- verify_msg(out, smsc_rewrite_num_patched_tp_srr,
- ARRAY_SIZE(smsc_rewrite_num_patched_tp_srr));
- msgb_free(out);
- bsc_nat_free(nat);
-}
-
-static void test_barr_list_parsing(void)
-{
- int rc;
- int cm, lu;
- struct rb_node *node;
- struct rb_root root = RB_ROOT;
- struct osmo_config_list *lst = osmo_config_list_parse(NULL, "barr.cfg");
- if (lst == NULL)
- abort();
-
- rc = bsc_filter_barr_adapt(NULL, &root, lst);
- if (rc != 0)
- abort();
- talloc_free(lst);
-
-
- for (node = rb_first(&root); node; node = rb_next(node)) {
- struct bsc_filter_barr_entry *entry;
- entry = rb_entry(node, struct bsc_filter_barr_entry, node);
- printf("IMSI: %s CM: %d LU: %d\n", entry->imsi,
- entry->cm_reject_cause, entry->lu_reject_cause);
- }
-
- /* do the look up now.. */
- rc = bsc_filter_barr_find(&root, "12123119", &cm, &lu);
- if (!rc) {
- printf("Failed to find the IMSI.\n");
- abort();
- }
-
- if (cm != 3 || lu != 4) {
- printf("Found CM(%d) and LU(%d)\n", cm, lu);
- abort();
- }
-
- /* empty and check that it is empty */
- bsc_filter_barr_adapt(NULL, &root, NULL);
- if (!RB_EMPTY_ROOT(&root)) {
- printf("Failed to empty the list.\n");
- abort();
- }
-
- /* check that dup results in an error */
- lst = osmo_config_list_parse(NULL, "barr_dup.cfg");
- if (lst == NULL) {
- printf("Failed to parse list with dups\n");
- abort();
- }
-
- rc = bsc_filter_barr_adapt(NULL, &root, lst);
- if (rc != -1) {
- printf("It should have failed due dup\n");
- abort();
- }
- talloc_free(lst);
-
- /* dump for reference */
- for (node = rb_first(&root); node; node = rb_next(node)) {
- struct bsc_filter_barr_entry *entry;
- entry = rb_entry(node, struct bsc_filter_barr_entry, node);
- printf("IMSI: %s CM: %d LU: %d\n", entry->imsi,
- entry->cm_reject_cause, entry->lu_reject_cause);
-
- }
- rc = bsc_filter_barr_adapt(NULL, &root, NULL);
-}
-
-static void test_nat_extract_lac()
-{
- int res;
- struct bsc_connection *bsc;
- struct bsc_nat *nat;
- struct nat_sccp_connection con;
- struct bsc_nat_parsed *parsed;
- struct msgb *msg = msgb_alloc(4096, "test-message");
-
- printf("Testing LAC extraction from SCCP CR\n");
-
- /* initialize the testcase */
- nat = bsc_nat_alloc();
- bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo", 0);
-
- memset(&con, 0, sizeof(con));
- con.bsc = bsc;
-
- /* create the SCCP CR */
- msg->l2h = msgb_put(msg, ARRAY_SIZE(bssmap_cr));
- memcpy(msg->l2h, bssmap_cr, ARRAY_SIZE(bssmap_cr));
-
- /* parse it and pass it on */
- parsed = bsc_nat_parse(msg);
- res = bsc_nat_extract_lac(bsc, &con, parsed, msg);
- OSMO_ASSERT(res == 0);
-
- /* verify the LAC */
- OSMO_ASSERT(con.lac == 8210);
- OSMO_ASSERT(con.ci == 50000);
-
- bsc_nat_free(nat);
-}
-
-static const struct log_info_cat log_categories[] = {
-};
-
-static const struct log_info log_info = {
- .cat = log_categories,
- .num_cat = ARRAY_SIZE(log_categories),
-};
-
-int main(int argc, char **argv)
-{
- void *tall_ctx = talloc_named_const(NULL, 1, "bsc_nat_test");
- msgb_talloc_ctx_init(tall_ctx, 0);
- sccp_set_log_area(DLSCCP);
- osmo_init_logging2(tall_ctx, &log_info);
-
- test_filter();
- test_contrack();
- test_paging();
- test_mgcp_ass_tracking();
- test_mgcp_find();
- test_mgcp_rewrite();
- test_mgcp_parse();
- test_cr_filter();
- test_dt_filter();
- test_setup_rewrite();
- test_setup_rewrite_prefix();
- test_setup_rewrite_post();
- test_sms_smsc_rewrite();
- test_sms_number_rewrite();
- test_mgcp_allocations();
- test_barr_list_parsing();
- test_nat_extract_lac();
-
- printf("Testing execution completed.\n");
- return 0;
-}
-
-/* stub */
-void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg)
-{
- abort();
-}
-
-struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_network *network) { return NULL; }
diff --git a/tests/bsc-nat/bsc_nat_test.ok b/tests/bsc-nat/bsc_nat_test.ok
deleted file mode 100644
index ab04f4273..000000000
--- a/tests/bsc-nat/bsc_nat_test.ok
+++ /dev/null
@@ -1,39 +0,0 @@
-Testing BSS Filtering.
-Going to test item: 0
-Going to test item: 1
-Going to test item: 2
-Going to test item: 3
-Going to test item: 4
-Going to test item: 5
-Going to test item: 6
-Going to test item: 7
-Going to test item: 8
-Going to test item: 9
-Going to test item: 10
-Going to test item: 11
-Going to test item: 12
-Testing connection tracking.
-Testing paging by lac.
-Testing MGCP.
-Testing finding of a BSC Connection
-Testing rewriting MGCP messages.
-Testing MGCP response parsing.
-Testing SMSC rewriting.
-Attempting to only rewrite the HDR
-Attempting to change nothing.
-Testing SMS TP-DA rewriting.
-IMSI: 12123115 CM: 3 LU: 4
-IMSI: 12123116 CM: 3 LU: 4
-IMSI: 12123117 CM: 3 LU: 4
-IMSI: 12123118 CM: 3 LU: 4
-IMSI: 12123119 CM: 3 LU: 4
-IMSI: 12123120 CM: 3 LU: 4
-IMSI: 12123123 CM: 3 LU: 1
-IMSI: 12123124 CM: 3 LU: 2
-IMSI: 12123125 CM: 3 LU: 3
-IMSI: 12123126 CM: 3 LU: 4
-IMSI: 12123127 CM: 3 LU: 5
-IMSI: 12123128 CM: 3 LU: 6
-IMSI: 12123124 CM: 3 LU: 2
-Testing LAC extraction from SCCP CR
-Testing execution completed.
diff --git a/tests/bsc-nat/prefixes.csv b/tests/bsc-nat/prefixes.csv
deleted file mode 100644
index 0c7660f10..000000000
--- a/tests/bsc-nat/prefixes.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-0172,0049
-+49,0
diff --git a/tests/testsuite.at b/tests/testsuite.at
index f0f6fd137..07bd85f8a 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -20,13 +20,6 @@ cat $abs_srcdir/channel/channel_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/channel/channel_test], [], [expout], [ignore])
AT_CLEANUP
-AT_SETUP([bsc-nat-trie])
-AT_KEYWORDS([bsc-nat-trie])
-cp $abs_srcdir/bsc-nat-trie/prefixes.csv .
-cat $abs_srcdir/bsc-nat-trie/bsc_nat_trie_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/bsc-nat-trie/bsc_nat_trie_test], [], [expout], [ignore])
-AT_CLEANUP
-
AT_SETUP([abis])
AT_KEYWORDS([abis])
cat $abs_srcdir/abis/abis_test.ok > expout
diff --git a/tests/vty_test_runner.py b/tests/vty_test_runner.py
index 3b73ce7db..d2b3da4ff 100755
--- a/tests/vty_test_runner.py
+++ b/tests/vty_test_runner.py
@@ -249,357 +249,6 @@ class TestVTYBSC(TestVTYGenericBSC):
self.assert_(res.find("core-location-area-code 666") > 0)
self.assert_(res.find("core-cell-identity 333") > 0)
-class TestVTYNAT(TestVTYGenericBSC):
-
- def vty_command(self):
- return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-l", "127.0.0.1", "-c",
- "doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"]
-
- def vty_app(self):
- return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat")
-
- def testBSCreload(self):
- # Use different port for the mock msc to avoid clashing with
- # the osmo-bsc_nat itself
- ip = "127.0.0.1"
- port = 5522
- self.vty.enable()
- bscs1 = self.vty.command("show bscs-config")
- nat_bsc_reload(self)
- bscs2 = self.vty.command("show bscs-config")
- # check that multiple calls to bscs-config-file give the same result
- self.assertEquals(bscs1, bscs2)
-
- # add new bsc
- self.vty.command("configure terminal")
- self.vty.command("nat")
- self.vty.command("bsc 5")
- self.vty.command("token key")
- self.vty.command("location_area_code 666")
- self.vty.command("end")
-
- # update bsc token
- self.vty.command("configure terminal")
- self.vty.command("nat")
- self.vty.command("bsc 1")
- self.vty.command("token xyu")
- self.vty.command("end")
-
- nat_msc_ip(self, ip, port)
- msc_socket, msc = nat_msc_test(self, ip, port, verbose=True)
- try:
- b0 = nat_bsc_sock_test(0, "lol", verbose=True, proc=self.proc)
- b1 = nat_bsc_sock_test(1, "xyu", verbose=True, proc=self.proc)
- b2 = nat_bsc_sock_test(5, "key", verbose=True, proc=self.proc)
-
- self.assertEquals("3 BSCs configured", self.vty.command("show nat num-bscs-configured"))
- self.assertTrue(3 == nat_bsc_num_con(self))
- self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection"))
-
- nat_bsc_reload(self)
- bscs2 = self.vty.command("show bscs-config")
- # check that the reset to initial config succeeded
- self.assertEquals(bscs1, bscs2)
-
- self.assertEquals("2 BSCs configured", self.vty.command("show nat num-bscs-configured"))
- self.assertTrue(1 == nat_bsc_num_con(self))
- rem = self.vty.command("show bsc connections").split(' ')
- # remaining connection is for BSC0
- self.assertEquals('0', rem[2])
- # remaining connection is authorized
- self.assertEquals('1', rem[4])
- self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection"))
- finally:
- msc.close()
- msc_socket.close()
-
- def testVtyTree(self):
- self.vty.enable()
- self.assertTrue(self.vty.verify('configure terminal', ['']))
- self.assertEquals(self.vty.node(), 'config')
- self.checkForEndAndExit()
- self.assertTrue(self.vty.verify('mgcp', ['']))
- self.assertEquals(self.vty.node(), 'config-mgcp')
- self.checkForEndAndExit()
- self.assertTrue(self.vty.verify('exit', ['']))
- self.assertEquals(self.vty.node(), 'config')
- self.assertTrue(self.vty.verify('nat', ['']))
- self.assertEquals(self.vty.node(), 'config-nat')
- self.checkForEndAndExit()
- self.assertTrue(self.vty.verify('bsc 0', ['']))
- self.assertEquals(self.vty.node(), 'config-nat-bsc')
- self.checkForEndAndExit()
- self.assertTrue(self.vty.verify('exit', ['']))
- self.assertEquals(self.vty.node(), 'config-nat')
- self.assertTrue(self.vty.verify('exit', ['']))
- self.assertEquals(self.vty.node(), 'config')
- self.assertTrue(self.vty.verify('exit', ['']))
- self.assertTrue(self.vty.node() is None)
-
- def testRewriteNoRewrite(self):
- self.vty.enable()
- res = self.vty.command("configure terminal")
- res = self.vty.command("nat")
- res = self.vty.command("number-rewrite rewrite.cfg")
- res = self.vty.command("no number-rewrite")
-
- def testEnsureNoEnsureModeSet(self):
- self.vty.enable()
- res = self.vty.command("configure terminal")
- res = self.vty.command("nat")
-
- # Ensure the default
- res = self.vty.command("show running-config")
- self.assert_(res.find('\n sdp-ensure-amr-mode-set') > 0)
-
- self.vty.command("sdp-ensure-amr-mode-set")
- res = self.vty.command("show running-config")
- self.assert_(res.find('\n sdp-ensure-amr-mode-set') > 0)
-
- self.vty.command("no sdp-ensure-amr-mode-set")
- res = self.vty.command("show running-config")
- self.assert_(res.find('\n no sdp-ensure-amr-mode-set') > 0)
-
- def testRewritePostNoRewrite(self):
- self.vty.enable()
- self.vty.command("configure terminal")
- self.vty.command("nat")
- self.vty.verify("number-rewrite-post rewrite.cfg", [''])
- self.vty.verify("no number-rewrite-post", [''])
-
-
- def testPrefixTreeLoading(self):
- cfg = os.path.join(confpath, "tests/bsc-nat-trie/prefixes.csv")
-
- self.vty.enable()
- self.vty.command("configure terminal")
- self.vty.command("nat")
- res = self.vty.command("prefix-tree %s" % cfg)
- self.assertEqual(res, "% prefix-tree loaded 17 rules.")
- self.vty.command("end")
-
- res = self.vty.command("show prefix-tree")
- self.assertEqual(res, '1,1\r\n12,2\r\n123,3\r\n1234,4\r\n12345,5\r\n123456,6\r\n1234567,7\r\n12345678,8\r\n123456789,9\r\n1234567890,10\r\n13,11\r\n14,12\r\n15,13\r\n16,14\r\n82,16\r\n823455,15\r\n+49123,17')
-
- self.vty.command("configure terminal")
- self.vty.command("nat")
- self.vty.command("no prefix-tree")
- self.vty.command("end")
-
- res = self.vty.command("show prefix-tree")
- self.assertEqual(res, "% there is now prefix tree loaded.")
-
- def testUssdSideChannelProvider(self):
- self.vty.command("end")
- self.vty.enable()
- self.vty.command("configure terminal")
- self.vty.command("nat")
- self.vty.command("ussd-token key")
- self.vty.command("end")
-
- res = self.vty.verify("show ussd-connection", ['The USSD side channel provider is not connected and not authorized.'])
- self.assertTrue(res)
-
- ussdSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- ussdSocket.connect(('127.0.0.1', 5001))
- ussdSocket.settimeout(2.0)
- print "Connected to %s:%d" % ussdSocket.getpeername()
-
- print "Expecting ID_GET request"
- data = ussdSocket.recv(4)
- self.assertEqual(data, "\x00\x01\xfe\x04")
-
- print "Going to send ID_RESP response"
- res = ussdSocket.send(IPA().id_resp(IPA().tag_name('key')))
- self.assertEqual(res, 10)
-
- # initiating PING/PONG cycle to know, that the ID_RESP message has been processed
-
- print "Going to send PING request"
- res = ussdSocket.send(IPA().ping())
- self.assertEqual(res, 4)
-
- print "Expecting PONG response"
- data = ussdSocket.recv(4)
- self.assertEqual(data, "\x00\x01\xfe\x01")
-
- res = self.vty.verify("show ussd-connection", ['The USSD side channel provider is connected and authorized.'])
- self.assertTrue(res)
-
- print "Going to shut down connection"
- ussdSocket.shutdown(socket.SHUT_WR)
-
- print "Expecting EOF"
- data = ussdSocket.recv(4)
- self.assertEqual(data, "")
-
- ussdSocket.close()
-
- res = self.vty.verify("show ussd-connection", ['The USSD side channel provider is not connected and not authorized.'])
- self.assertTrue(res)
-
- def testAccessList(self):
- """
- Verify that the imsi-deny can have a reject cause or no reject cause
- """
- self.vty.enable()
- self.vty.command("configure terminal")
- self.vty.command("nat")
-
- # Old default
- self.vty.command("access-list test-default imsi-deny ^123[0-9]*$")
- res = self.vty.command("show running-config").split("\r\n")
- asserted = False
- for line in res:
- if line.startswith(" access-list test-default"):
- self.assertEqual(line, " access-list test-default imsi-deny ^123[0-9]*$ 11 11")
- asserted = True
- self.assert_(asserted)
-
- # Check the optional CM Service Reject Cause
- self.vty.command("access-list test-cm-deny imsi-deny ^123[0-9]*$ 42").split("\r\n")
- res = self.vty.command("show running-config").split("\r\n")
- asserted = False
- for line in res:
- if line.startswith(" access-list test-cm"):
- self.assertEqual(line, " access-list test-cm-deny imsi-deny ^123[0-9]*$ 42 11")
- asserted = True
- self.assert_(asserted)
-
- # Check the optional LU Reject Cause
- self.vty.command("access-list test-lu-deny imsi-deny ^123[0-9]*$ 23 42").split("\r\n")
- res = self.vty.command("show running-config").split("\r\n")
- asserted = False
- for line in res:
- if line.startswith(" access-list test-lu"):
- self.assertEqual(line, " access-list test-lu-deny imsi-deny ^123[0-9]*$ 23 42")
- asserted = True
- self.assert_(asserted)
-
-
-def add_nat_test(suite, workdir):
- if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")):
- print("Skipping the NAT test")
- return
- test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT)
- suite.addTest(test)
-
-def nat_bsc_reload(x):
- x.vty.command("configure terminal")
- x.vty.command("nat")
- x.vty.command("bscs-config-file bscs.cfg")
- x.vty.command("end")
-
-def nat_msc_ip(x, ip, port):
- x.vty.command("configure terminal")
- x.vty.command("nat")
- x.vty.command("msc ip " + ip)
- x.vty.command("msc port " + str(port))
- x.vty.command("end")
-
-def data2str(d):
- return d.encode('hex').lower()
-
-def nat_msc_test(x, ip, port, verbose = False):
- msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- msc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- msc.settimeout(5)
- msc.bind((ip, port))
- msc.listen(5)
- if (verbose):
- print "MSC is ready at " + ip
- conn = None
- while True:
- vty_response = x.vty.command("show msc connection")
- print "'show msc connection' says: %r" % vty_response
- if vty_response == "MSC is connected: 1":
- # success
- break;
- if vty_response != "MSC is connected: 0":
- raise Exception("Unexpected response to 'show msc connection'"
- " vty command: %r" % vty_response)
-
- timeout_retries = 6
- while timeout_retries > 0:
- try:
- conn, addr = msc.accept()
- print "MSC got connection from ", addr
- break
- except socket.timeout:
- print "socket timed out."
- timeout_retries -= 1
- continue
-
- if not conn:
- raise Exception("VTY reports MSC is connected, but I haven't"
- " connected yet: %r %r" % (ip, port))
- return msc, conn
-
-def ipa_handle_small(x, verbose = False):
- s = data2str(x.recv(4))
- if len(s) != 4*2:
- raise Exception("expected to receive 4 bytes, but got %d (%r)" % (len(s)/2, s))
- if "0001fe00" == s:
- if (verbose):
- print "\tBSC <- NAT: PING?"
- x.send(IPA().pong())
- elif "0001fe06" == s:
- if (verbose):
- print "\tBSC <- NAT: IPA ID ACK"
- x.send(IPA().id_ack())
- elif "0001fe00" == s:
- if (verbose):
- print "\tBSC <- NAT: PONG!"
- else:
- if (verbose):
- print "\tBSC <- NAT: ", s
-
-def ipa_handle_resp(x, tk, verbose = False, proc=None):
- s = data2str(x.recv(38))
- if "0023fe040108010701020103010401050101010011" in s:
- retries = 3
- while True:
- print "\tsending IPA identity(%s) at %s" % (tk, time.strftime("%T"))
- try:
- x.send(IPA().id_resp(IPA().identity(name = tk.encode('utf-8'))))
- print "\tdone sending IPA identity(%s) at %s" % (tk,
- time.strftime("%T"))
- break
- except:
- print "\tfailed sending IPA identity at", time.strftime("%T")
- if proc:
- print "\tproc.poll() = %r" % proc.poll()
- if retries < 1:
- print "\tgiving up"
- raise
- print "\tretrying (%d attempts left)" % retries
- retries -= 1
- else:
- if (verbose):
- print "\tBSC <- NAT: ", s
-
-def nat_bsc_num_con(x):
- return len(x.vty.command("show bsc connections").split('\n'))
-
-def nat_bsc_sock_test(nr, tk, verbose = False, proc=None):
- bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- bsc.bind(('127.0.0.1', 0))
- bsc.connect(('127.0.0.1', 5000))
- if (verbose):
- print "BSC%d " %nr
- print "\tconnected to %s:%d" % bsc.getpeername()
- if proc:
- print "\tproc.poll() = %r" % proc.poll()
- print "\tproc.pid = %r" % proc.pid
- ipa_handle_small(bsc, verbose)
- ipa_handle_resp(bsc, tk, verbose, proc=proc)
- if proc:
- print "\tproc.poll() = %r" % proc.poll()
- bsc.recv(27) # MGCP msg
- if proc:
- print "\tproc.poll() = %r" % proc.poll()
- ipa_handle_small(bsc, verbose)
- return bsc
def add_bsc_test(suite, workdir):
if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")):
@@ -639,7 +288,6 @@ if __name__ == '__main__':
print "Running tests for specific VTY commands"
suite = unittest.TestSuite()
add_bsc_test(suite, workdir)
- add_nat_test(suite, workdir)
if args.test_name:
osmoutil.pick_tests(suite, *args.test_name)