Compare commits

..

39 Commits

Author SHA1 Message Date
Holger Hans Peter Freyther
fceee8779e Bump the version. 2010-05-16 01:37:49 +08:00
Holger Hans Peter Freyther
e27740a0e2 [nat] Use the new gsm48 method to parse the MI followed by a classmark. 2010-05-16 01:13:28 +08:00
Holger Hans Peter Freyther
95defd542d gsm48: Add a generic MI from classmark+mi extraction.
This is a generic MI extraction for the MI if it is followed
after a classmark. For the Phase1 Phones the classmark2 is not
four bytes but it might be different. This code can be used
by the CM Service Request handling as well.
2010-05-16 01:07:20 +08:00
Holger Hans Peter Freyther
2d2a43f3d6 [nat] Let IMSI DETACH and other messages pass by. 2010-05-16 01:05:47 +08:00
Holger Hans Peter Freyther
a9aab6a9ca [nat] Print on which BSC config this happend. 2010-05-16 00:45:07 +08:00
Holger Hans Peter Freyther
775b3dc566 [nat] Parse the PAGING RESPONSE inside a CR message as well.
Now we are parsing a CM Service Request, Location Updating Request
and the Paging Response. For all other messages we claim to not
support it and force a refuse.
2010-05-15 23:55:28 +08:00
Holger Hans Peter Freyther
45bb8bfc1a gsm48: Add size checks to the paging response mi parsing.
We go from no size checks to some content checking. We should
refactor the whole classmark2 + mi parsing that is used throughout
the code into one place with proper size checking. This is the
start and requires a new libosmocore as well.
2010-05-15 23:55:28 +08:00
Holger Hans Peter Freyther
57900f0008 [nat] Check proto descriptor and the message type 2010-05-15 23:55:28 +08:00
Holger Hans Peter Freyther
66ac860f62 [nat] Add code to filter the CM Service Request by IMSI.
The code should be shared among the GSM0408 implementation
and this one, and like the LU we are not handling a TMSI
properly as we have no idea where it is coming from.
2010-05-15 23:55:28 +08:00
Holger Hans Peter Freyther
ec82426c5e [nat] Mention where the MSG is coming from. 2010-05-15 19:13:52 +08:00
Holger Hans Peter Freyther
60fa0efcc8 [sccp] Make it optional to send data on a SCCP Connection Refuse
This can be used to send a Location Updating Reject down to the
BSC when it is clear that a subscriber is not allowed.
2010-05-15 01:04:42 +08:00
Holger Hans Peter Freyther
3dfcd4636a [nat] Remove the imsi allow option on the nat level.
For now we have:
1.) bsc imsi deny to deny at the BSC level
2.) bsc imsi allow to allow a SIM at the BSC level
3.) nat imsi deny to deny at the global level
2010-05-15 00:36:54 +08:00
Holger Hans Peter Freyther
50818d0c20 [nat] Separate exit2/exit3 as this can not be shared...
We have tried to send a refuse for arbitary things and ended
up with a segfault... separate the exi2 and exit3 label to have
separate exits and cleanups.
2010-05-15 00:29:50 +08:00
Holger Hans Peter Freyther
317934a2ba [nat] Add a token to the nat config and handle ID GET
This allows to chain a nat with a nat by answering to the
id get code and sending the token.
2010-05-15 00:14:58 +08:00
Holger Hans Peter Freyther
565b355c82 [bsc_msc] Move the id get response into the bsc_msc.c
Create the message in a common place and then it can be used
by tools having an a link or such.
2010-05-15 00:12:19 +08:00
Holger Hans Peter Freyther
be9201a272 [nat] Add a regexp test command to the VTY.
This allows to test the regexp to be used for allo/deny of
the imsi filter.
2010-05-14 23:43:12 +08:00
Holger Hans Peter Freyther
a43c56637d [nat] Fix the regexp of the test and the command line. 2010-05-14 23:07:58 +08:00
Holger Hans Peter Freyther
980c84f0a3 [nat] Fix the imsi deny config write. 2010-05-14 23:06:09 +08:00
Holger Hans Peter Freyther
1ae7b7c372 [nat] We do not want to see the actual matches. 2010-05-14 22:24:36 +08:00
Holger Hans Peter Freyther
e265db68b0 [nat] Allow to set the description for the bsc.
This will allow to add description to each BSC.
2010-05-14 22:06:28 +08:00
Holger Hans Peter Freyther
fdc4a9386f [nat] Implement IMSI filtering... 2010-05-14 19:49:35 +08:00
Holger Hans Peter Freyther
023ac93377 [nat] Fix the size check of the LU Request. 2010-05-14 19:24:06 +08:00
Holger Hans Peter Freyther
fa53aba62c [nat] Make the string -> regexp parsing public
This way it can be used from within a test case to test
the regexps..
2010-05-14 18:38:29 +08:00
Holger Hans Peter Freyther
34c0b245fb nat: Add code to parse the SCCP optional data.
First we have the Complete Layer3 Information, then we have
the IE for the Layer3 information, then the GSM48 hdr, then
the actual content with data. Right now we are parsing the
LU but we are not filtering anything yet.
2010-05-14 08:14:09 +08:00
Holger Hans Peter Freyther
4c4d2d48ec nat: Start to add a test case.. with one CR message. 2010-05-14 08:12:57 +08:00
Holger Hans Peter Freyther
13441a1c50 gsm48: Typo fix. 2010-05-14 08:02:08 +08:00
Holger Hans Peter Freyther
8ff74e8c24 nat: Introduce a nat filter that is working on the CR message.
Currently there is no implementation but the refusal code is
in place and will send a refusal back to the BSC.
2010-05-14 03:47:52 +08:00
Holger Hans Peter Freyther
a202342d64 [sccp] Export function to create SCCP Refuse message. 2010-05-14 03:34:35 +08:00
Holger Hans Peter Freyther
d275cf6407 [bsc_msc_ip] Use A.B.C.D for the VTY code. 2010-05-14 02:37:54 +08:00
Holger Hans Peter Freyther
c00e9ce09f [nat] Use A.B.C.D for the IP address
The VTY code will then be able to validate the IP Address.
2010-05-14 02:36:42 +08:00
Holger Hans Peter Freyther
5d645bf984 [nat] Remove range checks inside the VTY command.
The ranges are enforced by the VTY code.
2010-05-14 02:35:51 +08:00
Holger Hans Peter Freyther
723fb87a6c [mgcp] Clean up VTY code, the ranges are checked by the VTY code. 2010-05-14 02:34:35 +08:00
Holger Hans Peter Freyther
9da4492655 [mgcp] Use A.B.C.D for the ip addresses inside the vty config
Make the vty code parse the ip addresses for us and validate
them for us.
2010-05-14 02:27:50 +08:00
Holger Hans Peter Freyther
1927e93ce5 [mgcp] Improve the language of the comments. 2010-05-14 02:18:59 +08:00
Holger Hans Peter Freyther
7bbd416a52 [mgcp] Include stdlib.h for abs. 2010-05-14 02:14:09 +08:00
Holger Hans Peter Freyther
efd38dd015 [vty] Add power measurements to the one line summary. 2010-05-14 01:58:17 +08:00
Holger Hans Peter Freyther
e8d8811b12 [vty] Add a one line show lchan summary command. 2010-05-14 01:45:52 +08:00
Holger Hans Peter Freyther
39cb9f2a3c [vty] Move "show lchan" into a parameterized method
I want to have a shorter lchan summary but with the same
config parameters. Change the current code to be a method
that takes a dump routine as parameter.
2010-05-14 01:45:45 +08:00
Holger Hans Peter Freyther
0558a5a0dd [vty] Remove unfinished code from the VTY... 2010-05-14 00:58:11 +08:00
17 changed files with 549 additions and 121 deletions

View File

@@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT(openbsc, 0.3.99.11onwaves)
AC_INIT(openbsc, 0.3.99.12onwaves)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
dnl kernel style compile messages
@@ -15,7 +15,7 @@ dnl checks for libraries
AC_SEARCH_LIBS(crypt, crypt,
[LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])])
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.3)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.7)
dnl checks for header files
AC_HEADER_STDC

View File

@@ -45,4 +45,6 @@ void bsc_msc_schedule_connect(struct bsc_msc_connection *);
void bsc_msc_lost(struct bsc_msc_connection *);
struct msgb *bsc_msc_id_get_resp(const char *token);
#endif

View File

@@ -149,6 +149,8 @@ struct bsc_config {
unsigned int lac;
int nr;
char *description;
/* imsi white and blacklist */
char *imsi_allow;
regex_t imsi_allow_re;
@@ -217,6 +219,7 @@ struct bsc_nat {
int msc_port;
int first_contact;
struct bsc_msc_connection *msc_con;
char *token;
/* timeouts */
int auth_timeout;
@@ -226,8 +229,6 @@ struct bsc_nat {
struct bsc_endpoint *bsc_endpoints;
/* filter */
char *imsi_allow;
regex_t imsi_allow_re;
char *imsi_deny;
regex_t imsi_deny_re;
@@ -257,6 +258,11 @@ int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *p
int bsc_nat_vty_init(struct bsc_nat *nat);
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *_lac);
/**
* Content filtering.
*/
int bsc_nat_filter_sccp_cr(struct bsc_connection *, struct msgb *msg, struct bsc_nat_parsed *);
/**
* SCCP patching and handling
*/
@@ -287,4 +293,7 @@ int bsc_mgcp_extract_ci(const char *resp);
int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
/* regexp handling */
void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv);
#endif

View File

@@ -45,7 +45,8 @@ int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
int h_len);
int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv);
int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t *mi_type);
int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, u_int8_t *mi_type);
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr);
int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode);

View File

@@ -148,6 +148,8 @@ extern const struct sockaddr_sccp sccp_ssn_bssap;
u_int32_t sccp_src_ref_to_int(struct sccp_source_reference *ref);
struct sccp_source_reference sccp_src_ref_from_int(u_int32_t);
struct msgb *sccp_create_refuse(struct sccp_source_reference *src_ref, int cause, uint8_t *data, int length);
/**
* Below this are helper functions and structs for parsing SCCP messages
*/

View File

@@ -22,6 +22,7 @@
#include <openbsc/bsc_msc.h>
#include <openbsc/debug.h>
#include <openbsc/ipaccess.h>
#include <osmocore/write_queue.h>
#include <osmocore/talloc.h>
@@ -239,3 +240,24 @@ void bsc_msc_schedule_connect(struct bsc_msc_connection *con)
con->reconnect_timer.data = con;
bsc_schedule_timer(&con->reconnect_timer, 5, 0);
}
struct msgb *bsc_msc_id_get_resp(const char *token)
{
struct msgb *msg;
if (!token) {
LOGP(DMSC, LOGL_ERROR, "No token specified.\n");
return NULL;
}
msg = msgb_alloc_headroom(4096, 128, "id resp");
if (!msg) {
LOGP(DMSC, LOGL_ERROR, "Failed to create the message.\n");
return NULL;
}
msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP);
msgb_l16tv_put(msg, strlen(token) + 1,
IPAC_IDTAG_UNITNAME, (u_int8_t *) token);
return msg;
}

View File

@@ -365,7 +365,14 @@ static int handle_paging_response(struct msgb *msg)
char mi_string[GSM48_MI_SIZE];
u_int8_t mi_type;
gsm48_paging_extract_mi(msg, mi_string, &mi_type);
struct gsm48_hdr *hdr;
struct gsm48_pag_resp *resp;
hdr = msgb_l3(msg);
resp = (struct gsm48_pag_resp *) &hdr->data[0];
gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*hdr),
mi_string, &mi_type);
LOGP(DMSC, LOGL_DEBUG, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
mi_type, mi_string);
@@ -869,16 +876,9 @@ static void send_id_get_response(int fd)
return;
}
if (!bsc_gsmnet->bsc_token) {
LOGP(DMSC, LOGL_ERROR, "The bsc token is not set.\n");
msg = bsc_msc_id_get_resp(bsc_gsmnet->bsc_token);
if (!msg)
return;
}
msg = msgb_alloc_headroom(4096, 128, "id resp");
msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP);
msgb_l16tv_put(msg, strlen(bsc_gsmnet->bsc_token) + 1,
IPAC_IDTAG_UNITNAME, (u_int8_t *) bsc_gsmnet->bsc_token);
msc_queue_write(msg, IPAC_PROTO_IPACCESS);
}

View File

@@ -609,7 +609,7 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg)
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_service_request *req =
(struct gsm48_service_request *)gh->data;
/* unfortunately in Phase1 the classmar2 length is variable */
/* unfortunately in Phase1 the classmark2 length is variable */
u_int8_t classmark2_len = gh->data[1];
u_int8_t *classmark2 = gh->data+2;
u_int8_t mi_len = *(classmark2 + classmark2_len);
@@ -779,13 +779,16 @@ static int gsm48_rx_rr_pag_resp(struct msgb *msg)
{
struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_pag_resp *resp;
u_int8_t *classmark2_lv = gh->data + 1;
u_int8_t mi_type;
char mi_string[GSM48_MI_SIZE];
struct gsm_subscriber *subscr = NULL;
int rc = 0;
gsm48_paging_extract_mi(msg, mi_string, &mi_type);
resp = (struct gsm48_pag_resp *) &gh->data[0];
gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
mi_string, &mi_type);
DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
mi_type, mi_string);

View File

@@ -285,16 +285,30 @@ int send_siemens_mrpci(struct gsm_lchan *lchan,
return rsl_siemens_mrpci(lchan, &mrpci);
}
int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type)
int gsm48_extract_mi(uint8_t *classmark2_lv, int length, char *mi_string, uint8_t *mi_type)
{
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t *classmark2_lv = gh->data + 1;
u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
*mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
/* Check the size for the classmark */
if (length < 1 + *classmark2_lv)
return -1;
u_int8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
if (length < 2 + *classmark2_lv + mi_lv[0])
return -2;
*mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
}
int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
char *mi_string, u_int8_t *mi_type)
{
static const uint32_t classmark_offset =
offsetof(struct gsm48_pag_resp, classmark2);
u_int8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
mi_string, mi_type);
}
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr)
{
struct gsm_bts *bts = msg->lchan->ts->trx->bts;

View File

@@ -23,6 +23,7 @@
*/
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>
#include <errno.h>
@@ -176,7 +177,7 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
}
}
/* throw away dummy message */
/* throw away the dummy message */
if (rc == 1 && buf[0] == DUMMY_LOAD) {
LOGP(DMGCP, LOGL_NOTICE, "Filtered dummy on 0x%x\n",
ENDPOINT_NUMBER(endp));
@@ -189,7 +190,7 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
else
++endp->in_remote;
/* dispatch */
/* For loop toggle the destination and then dispatch. */
if (cfg->audio_loop)
dest = !dest;

View File

@@ -103,7 +103,7 @@ DEFUN(cfg_mgcp,
DEFUN(cfg_mgcp_local_ip,
cfg_mgcp_local_ip_cmd,
"local ip IP",
"local ip A.B.C.D",
"Set the IP to be used in SDP records")
{
if (g_cfg->local_ip)
@@ -114,7 +114,7 @@ DEFUN(cfg_mgcp_local_ip,
DEFUN(cfg_mgcp_bts_ip,
cfg_mgcp_bts_ip_cmd,
"bts ip IP",
"bts ip A.B.C.D",
"Set the IP of the BTS for RTP forwarding")
{
if (g_cfg->bts_ip)
@@ -126,7 +126,7 @@ DEFUN(cfg_mgcp_bts_ip,
DEFUN(cfg_mgcp_bind_ip,
cfg_mgcp_bind_ip_cmd,
"bind ip IP",
"bind ip A.B.C.D",
"Bind the MGCP to this local addr")
{
if (g_cfg->source_addr)
@@ -141,11 +141,6 @@ DEFUN(cfg_mgcp_bind_port,
"Bind the MGCP to this port")
{
unsigned int port = atoi(argv[0]);
if (port > 65534) {
vty_out(vty, "%% wrong bind port '%s'%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->source_port = port;
return CMD_SUCCESS;
}
@@ -156,11 +151,6 @@ DEFUN(cfg_mgcp_bind_early,
"Bind all RTP ports early")
{
unsigned int bind = atoi(argv[0]);
if (bind != 0 && bind != 1) {
vty_out(vty, "%% param must be 0 or 1.%s", VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->early_bind = bind == 1;
return CMD_SUCCESS;
}
@@ -171,11 +161,6 @@ DEFUN(cfg_mgcp_rtp_base_port,
"Base port to use")
{
unsigned int port = atoi(argv[0]);
if (port > 65534) {
vty_out(vty, "%% wrong base port '%s'%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->rtp_base_port = port;
return CMD_SUCCESS;
}
@@ -186,11 +171,6 @@ DEFUN(cfg_mgcp_sdp_payload_number,
"Set the audio codec to use")
{
unsigned int payload = atoi(argv[0]);
if (payload > 255) {
vty_out(vty, "%% wrong payload number '%s'%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->audio_payload = payload;
return CMD_SUCCESS;
}
@@ -227,7 +207,7 @@ DEFUN(cfg_mgcp_number_endp,
DEFUN(cfg_mgcp_forward_ip,
cfg_mgcp_forward_ip_cmd,
"forward audio ip IP",
"forward audio ip A.B.C.D",
"Forward packets from and to the IP. This disables most of the MGCP feature.")
{
if (g_cfg->forward_ip)

View File

@@ -260,6 +260,16 @@ static void initialize_msc_if_needed()
msc_send_reset(nat->msc_con);
}
static void send_id_get_response()
{
struct msgb *msg = bsc_msc_id_get_resp(nat->token);
if (!msg)
return;
ipaccess_prepend_header(msg, IPAC_PROTO_IPACCESS);
queue_for_msc(nat->msc_con, msg);
}
/*
* Currently we are lacking refcounting so we need to copy each message.
*/
@@ -346,7 +356,7 @@ static int forward_sccp_to_bts(struct msgb *msg)
/* Exchange src/dest for the reply */
nat_send_rlc(parsed->dest_local_ref, parsed->src_local_ref);
} else if (!con)
LOGP(DNAT, LOGL_ERROR, "Unknown connection for msg type: 0x%x.\n", parsed->sccp_type);
LOGP(DNAT, LOGL_ERROR, "Unknown connection for msg type: 0x%x from the MSC.\n", parsed->sccp_type);
}
talloc_free(parsed);
@@ -455,9 +465,12 @@ static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
ipaccess_rcvmsg_base(msg, bfd);
/* initialize the networking. This includes sending a GSM08.08 message */
if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_ID_ACK)
initialize_msc_if_needed();
else if (hh->proto == IPAC_PROTO_SCCP)
if (hh->proto == IPAC_PROTO_IPACCESS) {
if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
initialize_msc_if_needed();
else if (msg->l2h[0] == IPAC_MSGT_ID_GET)
send_id_get_response();
} else if (hh->proto == IPAC_PROTO_SCCP)
forward_sccp_to_bts(msg);
msgb_free(msg);
@@ -561,6 +574,7 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
{
struct msgb *refuse;
struct sccp_connections *con;
struct bsc_nat_parsed *parsed;
@@ -591,6 +605,8 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
switch (parsed->sccp_type) {
case SCCP_MSG_TYPE_CR:
if (bsc_nat_filter_sccp_cr(bsc, msg, parsed) != 0)
goto exit3;
if (create_sccp_src_ref(bsc, msg, parsed) != 0)
goto exit2;
con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
@@ -658,6 +674,18 @@ exit2:
talloc_free(parsed);
msgb_free(msg);
return -1;
exit3:
/* send a SCCP Connection Refused */
refuse = sccp_create_refuse(parsed->src_local_ref, SCCP_REFUSAL_SCCP_FAILURE, NULL, 0);
if (refuse) {
bsc_send_data(bsc, refuse->l2h, msgb_l2len(refuse), IPAC_PROTO_SCCP);
msgb_free(refuse);
}
talloc_free(parsed);
msgb_free(msg);
return -1;
}
static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)

View File

@@ -193,3 +193,194 @@ int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int proto)
return 0;
}
/* apply white/black list */
static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
{
/*
* Now apply blacklist/whitelist of the BSC and the NAT.
* 1.) Reject if the IMSI is not allowed at the BSC
* 2.) Allow directly if the IMSI is allowed at the BSC
* 3.) Reject if the IMSI not allowed at the global level.
* 4.) Allow directly if the IMSI is allowed at the global level
*/
/* 1. BSC deny */
if (bsc->cfg->imsi_deny) {
if (regexec(&bsc->cfg->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
LOGP(DNAT, LOGL_ERROR,
"Filtering %s by imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
return -2;
}
}
/* 2. BSC allow */
if (bsc->cfg->imsi_allow) {
if (regexec(&bsc->cfg->imsi_allow_re, mi_string, 0, NULL, 0) == 0)
return 0;
}
/* 3. NAT deny */
if (bsc->nat->imsi_deny) {
if (regexec(&bsc->nat->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
LOGP(DNAT, LOGL_ERROR,
"Filtering %s by nat imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
return -3;
}
}
return 0;
}
static int _cr_check_loc_upd(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
{
u_int8_t mi_type;
struct gsm48_loc_upd_req *lu;
char mi_string[GSM48_MI_SIZE];
if (length < sizeof(*lu)) {
LOGP(DNAT, LOGL_ERROR,
"LU does not fit. Length is %d \n", length);
return -1;
}
lu = (struct gsm48_loc_upd_req *) data;
mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
/*
* We can only deal with the IMSI. This will fail for a phone that
* will send the TMSI of a previous network to us.
*/
if (mi_type != GSM_MI_TYPE_IMSI)
return 0;
gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
return auth_imsi(bsc, mi_string);
}
static int _cr_check_cm_serv_req(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
{
static const uint32_t classmark_offset =
offsetof(struct gsm48_service_request, classmark);
char mi_string[GSM48_MI_SIZE];
uint8_t mi_type;
int rc;
struct gsm48_service_request *req;
/* unfortunately in Phase1 the classmark2 length is variable */
if (length < sizeof(*req)) {
LOGP(DNAT, LOGL_ERROR,
"CM Serv Req does not fit. Length is %d\n", length);
return -1;
}
req = (struct gsm48_service_request *) data;
rc = gsm48_extract_mi((uint8_t *) &req->classmark,
length - classmark_offset, mi_string, &mi_type);
if (rc < 0) {
LOGP(DNAT, LOGL_ERROR, "Failed to parse the classmark2/mi. error: %d\n", rc);
return -1;
}
/* we have to let the TMSI or such pass */
if (mi_type != GSM_MI_TYPE_IMSI)
return 0;
return auth_imsi(bsc, mi_string);
}
static int _cr_check_pag_resp(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
{
struct gsm48_pag_resp *resp;
char mi_string[GSM48_MI_SIZE];
u_int8_t mi_type;
if (length < sizeof(*resp)) {
LOGP(DNAT, LOGL_ERROR, "PAG RESP does not fit. Length was %d.\n", length);
return -1;
}
resp = (struct gsm48_pag_resp *) data;
if (gsm48_paging_extract_mi(resp, length, mi_string, &mi_type) < 0) {
LOGP(DNAT, LOGL_ERROR, "Failed to extract the MI.\n");
return -1;
}
/* we need to let it pass for now */
if (mi_type != GSM_MI_TYPE_IMSI)
return 0;
return auth_imsi(bsc, mi_string);
}
/* Filter out CR data... */
int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed)
{
struct tlv_parsed tp;
struct gsm48_hdr *hdr48;
int hdr48_len;
int len;
if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
LOGP(DNAT, LOGL_ERROR,
"Rejecting CR message due wrong GSM Type %d\n", parsed->gsm_type);
return -1;
}
/* the parsed has had some basic l3 length check */
len = msg->l3h[1];
if (msgb_l3len(msg) - 3 < len) {
LOGP(DNAT, LOGL_ERROR,
"The CR Data has not enough space...\n");
return -1;
}
msg->l4h = &msg->l3h[3];
len -= 1;
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h, len, 0, 0);
if (!TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_INFORMATION)) {
LOGP(DNAT, LOGL_ERROR, "CR Data does not contain layer3 information.\n");
return -1;
}
hdr48_len = TLVP_LEN(&tp, GSM0808_IE_LAYER_3_INFORMATION);
if (hdr48_len < sizeof(*hdr48)) {
LOGP(DNAT, LOGL_ERROR, "GSM48 header does not fit.\n");
return -1;
}
hdr48 = (struct gsm48_hdr *) TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION);
if (hdr48->proto_discr == GSM48_PDISC_MM &&
hdr48->msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) {
return _cr_check_loc_upd(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
} else if (hdr48->proto_discr == GSM48_PDISC_MM &&
hdr48->msg_type == GSM48_MT_MM_CM_SERV_REQ) {
return _cr_check_cm_serv_req(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
} else if (hdr48->proto_discr == GSM48_PDISC_RR &&
hdr48->msg_type == GSM48_MT_RR_PAG_RESP) {
return _cr_check_pag_resp(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
} else {
/* We only want to filter the above, let other things pass */
return 0;
}
}
void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
{
if (*imsi) {
talloc_free(*imsi);
*imsi = NULL;
}
regfree(reg);
if (argc > 0) {
*imsi = talloc_strdup(ctx, argv[0]);
regcomp(reg, argv[0], 0);
}
}

View File

@@ -52,15 +52,15 @@ static struct cmd_node bsc_node = {
static int config_write_nat(struct vty *vty)
{
vty_out(vty, "nat%s", VTY_NEWLINE);
if (_nat->imsi_allow)
vty_out(vty, " imsi allow %s%s", _nat->imsi_allow, VTY_NEWLINE);
if (_nat->imsi_deny)
vty_out(vty, " insi deny %s%s", _nat->imsi_deny, VTY_NEWLINE);
vty_out(vty, " imsi deny %s%s", _nat->imsi_deny, VTY_NEWLINE);
vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
vty_out(vty, " msc port %d%s", _nat->msc_port, VTY_NEWLINE);
vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE);
vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE);
if (_nat->token)
vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -74,6 +74,8 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
if (bsc->imsi_deny)
vty_out(vty, " imsi deny %s%s", bsc->imsi_deny, VTY_NEWLINE);
vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
if (bsc->description)
vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
}
static int config_write_bsc(struct vty *vty)
@@ -139,6 +141,11 @@ DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
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;
@@ -224,43 +231,19 @@ DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
return CMD_SUCCESS;
}
static void parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
{
if (*imsi) {
talloc_free(*imsi);
*imsi = NULL;
}
regfree(reg);
if (argc > 0) {
*imsi = talloc_strdup(ctx, argv[0]);
regcomp(reg, argv[0], 0);
}
}
DEFUN(cfg_nat_imsi_allow,
cfg_nat_imsi_allow_cmd,
"imsi allow [REGEXP]",
"Allow matching IMSIs to talk to the MSC. "
"The defualt is to allow everyone.")
{
parse_reg(_nat, &_nat->imsi_allow_re, &_nat->imsi_allow, argc, argv);
return CMD_SUCCESS;
}
DEFUN(cfg_nat_imsi_deny,
cfg_nat_imsi_deny_cmd,
"imsi deny [REGEXP]",
"Deny matching IMSIs to talk to the MSC. "
"The defualt is to not deny.")
{
parse_reg(_nat, &_nat->imsi_deny_re, &_nat->imsi_deny, argc, argv);
bsc_parse_reg(_nat, &_nat->imsi_deny_re, &_nat->imsi_deny, argc, argv);
return CMD_SUCCESS;
}
DEFUN(cfg_nat_msc_ip,
cfg_nat_msc_ip_cmd,
"msc ip IP",
"msc ip A.B.C.D",
"Set the IP address of the MSC.")
{
bsc_nat_set_msc_ip(_nat, argv[0]);
@@ -303,6 +286,16 @@ DEFUN(cfg_nat_pong_time,
return CMD_SUCCESS;
}
DEFUN(cfg_nat_token, cfg_nat_token_cmd,
"token TOKEN",
"Set a token for the NAT")
{
if (_nat->token)
talloc_free(_nat->token);
_nat->token = talloc_strdup(_nat, argv[0]);
return CMD_SUCCESS;
}
/* per BSC configuration */
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure")
{
@@ -346,12 +339,6 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
int lac = atoi(argv[0]);
if (lac < 0 || lac > 0xffff) {
vty_out(vty, "%% LAC %d is not in the valid range (0-65535)%s",
lac, VTY_NEWLINE);
return CMD_WARNING;
}
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);
@@ -379,7 +366,7 @@ DEFUN(cfg_bsc_imsi_allow,
{
struct bsc_config *conf = vty->index;
parse_reg(conf, &conf->imsi_allow_re, &conf->imsi_allow, argc, argv);
bsc_parse_reg(conf, &conf->imsi_allow_re, &conf->imsi_allow, argc, argv);
return CMD_SUCCESS;
}
@@ -391,7 +378,7 @@ DEFUN(cfg_bsc_imsi_deny,
{
struct bsc_config *conf = vty->index;
parse_reg(conf, &conf->imsi_deny_re, &conf->imsi_deny, argc, argv);
bsc_parse_reg(conf, &conf->imsi_deny_re, &conf->imsi_deny, argc, argv);
return CMD_SUCCESS;
}
@@ -410,6 +397,37 @@ DEFUN(cfg_bsc_paging,
return CMD_SUCCESS;
}
DEFUN(cfg_bsc_desc,
cfg_bsc_desc_cmd,
"description DESC",
"Provide a description for the given BSC.")
{
struct bsc_config *conf = vty->index;
if (conf->description)
talloc_free(conf->description);
conf->description = talloc_strdup(conf, argv[0]);
return CMD_SUCCESS;
}
DEFUN(test_regex, test_regex_cmd,
"test regex PATTERN STRING",
"Check if the string is matching the current pattern.")
{
regex_t reg;
char *str = NULL;
memset(&reg, 0, sizeof(reg));
bsc_parse_reg(_nat, &reg, &str, 1, argv);
vty_out(vty, "String matches allow pattern: %d%s",
regexec(&reg, argv[1], 0, NULL, 0) == 0, VTY_NEWLINE);
talloc_free(str);
regfree(&reg);
return CMD_SUCCESS;
}
int bsc_nat_vty_init(struct bsc_nat *nat)
{
_nat = nat;
@@ -424,6 +442,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(VIEW_NODE, &show_stats_cmd);
install_element(VIEW_NODE, &close_bsc_cmd);
install_element(VIEW_NODE, &show_msc_cmd);
install_element(VIEW_NODE, &test_regex_cmd);
openbsc_vty_add_cmds();
@@ -431,13 +450,13 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(CONFIG_NODE, &cfg_nat_cmd);
install_node(&nat_node, config_write_nat);
install_default(NAT_NODE);
install_element(NAT_NODE, &cfg_nat_imsi_allow_cmd);
install_element(NAT_NODE, &cfg_nat_imsi_deny_cmd);
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);
/* BSC subgroups */
install_element(NAT_NODE, &cfg_bsc_cmd);
@@ -448,6 +467,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(BSC_NODE, &cfg_bsc_imsi_allow_cmd);
install_element(BSC_NODE, &cfg_bsc_imsi_deny_cmd);
install_element(BSC_NODE, &cfg_bsc_paging_cmd);
install_element(BSC_NODE, &cfg_bsc_desc_cmd);
mgcp_vty_init();

View File

@@ -638,7 +638,7 @@ static void _sccp_set_connection_state(struct sccp_connection *connection, int n
connection->state_cb(connection, old_state);
}
static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
struct msgb *sccp_create_refuse(struct sccp_source_reference *src_ref, int cause, uint8_t *inp, int length)
{
struct msgb *msgb;
struct sccp_connection_refused *ref;
@@ -646,6 +646,11 @@ static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
msgb = msgb_alloc_headroom(SCCP_MSG_SIZE,
SCCP_MSG_HEADROOM, "sccp ref");
if (!msgb) {
LOGP(DSCCP, LOGL_ERROR, "Failed to allocate refusal msg.\n");
return NULL;
}
msgb->l2h = &msgb->data[0];
ref = (struct sccp_connection_refused *) msgb_put(msgb, sizeof(*ref));
@@ -655,8 +660,23 @@ static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
ref->cause = cause;
ref->optional_start = 1;
if (inp) {
data = msgb_put(msgb, 1 + 1 + length);
data[0] = SCCP_PNC_DATA;
data[1] = length;
memcpy(&data[2], inp, length);
}
data = msgb_put(msgb, 1);
data[0] = SCCP_PNC_END_OF_OPTIONAL;
return msgb;
}
static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
{
struct msgb *msgb = sccp_create_refuse(src_ref, cause, NULL, 0);
if (!msgb)
return -1;
_send_msg(msgb);
return 0;

View File

@@ -681,7 +681,7 @@ static void meas_rep_dump_vty(struct vty *vty, struct gsm_meas_rep *mr,
meas_rep_dump_uni_vty(vty, &mr->ul, prefix, "ul");
}
static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan)
static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan)
{
int idx;
@@ -716,37 +716,28 @@ static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan)
meas_rep_dump_vty(vty, &lchan->meas_rep[idx], " ");
}
#if 0
TODO: callref and remote callref of call must be resolved to get gsm_trans object
static void call_dump_vty(struct vty *vty, struct gsm_call *call)
static void lchan_dump_short_vty(struct vty *vty, struct gsm_lchan *lchan)
{
vty_out(vty, "Call Type %u, State %u, Transaction ID %u%s",
call->type, call->state, call->transaction_id, VTY_NEWLINE);
struct gsm_meas_rep *mr;
int idx;
if (call->local_lchan) {
vty_out(vty, "Call Local Channel:%s", VTY_NEWLINE);
lchan_dump_vty(vty, call->local_lchan);
} else
vty_out(vty, "Call has no Local Channel%s", VTY_NEWLINE);
/* we want to report the last measurement report */
idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
lchan->meas_rep_idx, 1);
mr = &lchan->meas_rep[idx];
if (call->remote_lchan) {
vty_out(vty, "Call Remote Channel:%s", VTY_NEWLINE);
lchan_dump_vty(vty, call->remote_lchan);
} else
vty_out(vty, "Call has no Remote Channel%s", VTY_NEWLINE);
if (call->called_subscr) {
vty_out(vty, "Called Subscriber:%s", VTY_NEWLINE);
subscr_dump_vty(vty, call->called_subscr);
} else
vty_out(vty, "Call has no Called Subscriber%s", VTY_NEWLINE);
vty_out(vty, "Lchan: %u Timeslot: %u TRX: %u BTS: %u Type: %s - L1 MS Power: %u dBm "
"RXL-FULL-dl: %4d dBm RXL-FULL-ul: %4d dBm%s",
lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
mr->ms_l1.pwr,
rxlev2dbm(mr->dl.full.rx_lev),
rxlev2dbm(mr->ul.full.rx_lev),
VTY_NEWLINE);
}
#endif
DEFUN(show_lchan,
show_lchan_cmd,
"show lchan [bts_nr] [trx_nr] [ts_nr] [lchan_nr]",
SHOW_STR "Display information about a logical channel\n")
static int lchan_summary(struct vty *vty, int argc, const char **argv,
void (*dump_cb)(struct vty *, struct gsm_lchan *))
{
struct gsm_network *net = gsmnet;
struct gsm_bts *bts;
@@ -791,7 +782,7 @@ DEFUN(show_lchan,
return CMD_WARNING;
}
lchan = &ts->lchan[lchan_nr];
lchan_dump_vty(vty, lchan);
dump_cb(vty, lchan);
return CMD_SUCCESS;
}
for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
@@ -805,7 +796,7 @@ DEFUN(show_lchan,
lchan = &ts->lchan[lchan_nr];
if (lchan->type == GSM_LCHAN_NONE)
continue;
lchan_dump_vty(vty, lchan);
dump_cb(vty, lchan);
}
}
}
@@ -814,6 +805,23 @@ DEFUN(show_lchan,
return CMD_SUCCESS;
}
DEFUN(show_lchan,
show_lchan_cmd,
"show lchan [bts_nr] [trx_nr] [ts_nr] [lchan_nr]",
SHOW_STR "Display information about a logical channel\n")
{
return lchan_summary(vty, argc, argv, lchan_dump_full_vty);
}
DEFUN(show_lchan_summary,
show_lchan_summary_cmd,
"show lchan summary [bts_nr] [trx_nr] [ts_nr] [lchan_nr]",
SHOW_STR "Display a short summary about a logical channel\n")
{
return lchan_summary(vty, argc, argv, lchan_dump_short_vty);
}
static void e1drv_dump_vty(struct vty *vty, struct e1inp_driver *drv)
{
vty_out(vty, "E1 Input Driver %s%s", drv->name, VTY_NEWLINE);
@@ -1321,7 +1329,7 @@ DEFUN(cfg_net_pag_any_tch,
DEFUN(cfg_net_msc_ip,
cfg_net_msc_ip_cmd,
"msc ip IP",
"msc ip A.B.C.D",
"Set the MSC/MUX IP address.")
{
if (gsmnet->msc_ip)
@@ -2053,6 +2061,7 @@ int bsc_vty_init(struct gsm_network *net)
install_element(VIEW_NODE, &show_trx_cmd);
install_element(VIEW_NODE, &show_ts_cmd);
install_element(VIEW_NODE, &show_lchan_cmd);
install_element(VIEW_NODE, &show_lchan_summary_cmd);
install_element(VIEW_NODE, &show_e1drv_cmd);
install_element(VIEW_NODE, &show_e1line_cmd);

View File

@@ -108,6 +108,28 @@ static const u_int8_t mgcp_msg[] = {
0x20, 0x20, 0x20,
};
/* location updating request */
static const u_int8_t bss_lu[] = {
0x00, 0x2e, 0xfd,
0x01, 0x91, 0x45, 0x14, 0x02, 0x02, 0x04, 0x02,
0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x14, 0xc3,
0x50, 0x17, 0x12, 0x05, 0x08, 0x70, 0x72, 0xf4,
0x80, 0xff, 0xfe, 0x30, 0x08, 0x29, 0x44, 0x50,
0x12, 0x03, 0x24, 0x01, 0x95, 0x00
};
/* paging response */
static const uint8_t pag_resp[] = {
0x00, 0x2c, 0xfd, 0x01, 0xe5, 0x68,
0x14, 0x02, 0x02, 0x04, 0x02, 0x42, 0xfe, 0x0f,
0x1f, 0x00, 0x1d, 0x57, 0x05, 0x08, 0x00, 0x72,
0xf4, 0x80, 0x20, 0x16, 0xc3, 0x50, 0x17, 0x10,
0x06, 0x27, 0x01, 0x03, 0x30, 0x18, 0x96, 0x08,
0x29, 0x26, 0x30, 0x32, 0x11, 0x42, 0x01, 0x19,
0x00
};
struct filter_result {
const u_int8_t *data;
const u_int16_t length;
@@ -540,6 +562,109 @@ static void test_mgcp_parse(void)
}
}
struct cr_filter {
const u_int8_t *data;
int length;
int result;
const char *bsc_imsi_allow;
const char *bsc_imsi_deny;
const char *nat_imsi_deny;
};
static struct cr_filter cr_filter[] = {
{
.data = bssmap_cr,
.length = sizeof(bssmap_cr),
.result = 0,
},
{
.data = bss_lu,
.length = sizeof(bss_lu),
.result = 0,
},
{
.data = pag_resp,
.length = sizeof(pag_resp),
.result = 0,
},
{
/* nat deny is before blank/null BSC */
.data = bss_lu,
.length = sizeof(bss_lu),
.result = -3,
.nat_imsi_deny = "[0-9]*",
},
{
/* BSC allow is before NAT deny */
.data = bss_lu,
.length = sizeof(bss_lu),
.result = 0,
.nat_imsi_deny = "[0-9]*",
.bsc_imsi_allow = "2440[0-9]*",
},
{
/* BSC allow is before NAT deny */
.data = bss_lu,
.length = sizeof(bss_lu),
.result = 0,
.bsc_imsi_allow = "[0-9]*",
.nat_imsi_deny = "[0-9]*",
},
{
/* filter as deny is first */
.data = bss_lu,
.length = sizeof(bss_lu),
.result = -2,
.bsc_imsi_deny = "[0-9]*",
.bsc_imsi_allow = "[0-9]*",
.nat_imsi_deny = "[0-9]*",
},
};
static void test_cr_filter()
{
int i, res;
struct msgb *msg = msgb_alloc(4096, "test_cr_filter");
struct bsc_nat_parsed *parsed;
struct bsc_nat *nat = bsc_nat_alloc();
struct bsc_connection *bsc = bsc_connection_alloc(nat);
bsc->cfg = bsc_config_alloc(nat, "foo", 1234);
for (i = 0; i < ARRAY_SIZE(cr_filter); ++i) {
msgb_reset(msg);
copy_to_msg(msg, cr_filter[i].data, cr_filter[i].length);
bsc_parse_reg(nat, &nat->imsi_deny_re, &nat->imsi_deny,
cr_filter[i].nat_imsi_deny ? 1 : 0,
&cr_filter[i].nat_imsi_deny);
bsc_parse_reg(bsc->cfg, &bsc->cfg->imsi_allow_re, &bsc->cfg->imsi_allow,
cr_filter[i].bsc_imsi_allow ? 1 : 0,
&cr_filter[i].bsc_imsi_allow);
bsc_parse_reg(bsc->cfg, &bsc->cfg->imsi_deny_re, &bsc->cfg->imsi_deny,
cr_filter[i].bsc_imsi_deny ? 1 : 0,
&cr_filter[i].bsc_imsi_deny);
parsed = bsc_nat_parse(msg);
if (!parsed) {
fprintf(stderr, "FAIL: Failed to parse the message\n");
abort();
}
res = bsc_nat_filter_sccp_cr(bsc, msg, parsed);
if (res != cr_filter[i].result) {
fprintf(stderr, "FAIL: Wrong result %d for test %d.\n", res, i);
abort();
}
talloc_free(parsed);
}
msgb_free(msg);
}
int main(int argc, char **argv)
{
struct log_target *stderr_target;
@@ -556,6 +681,7 @@ int main(int argc, char **argv)
test_mgcp_find();
test_mgcp_rewrite();
test_mgcp_parse();
test_cr_filter();
return 0;
}