aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_nat.h2
-rw-r--r--openbsc/src/nat/bsc_nat.c10
-rw-r--r--openbsc/src/nat/bsc_nat_utils.c26
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c4
4 files changed, 32 insertions, 10 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 2792f002c..6fc0e6501 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -265,7 +265,7 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, i
* Content filtering.
*/
int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
- struct bsc_nat_parsed *, int *con_type);
+ struct bsc_nat_parsed *, int *con_type, char **imsi);
int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
struct sccp_connections *con, struct bsc_nat_parsed *parsed);
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index b8a6cfc7b..b82c4ef25 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -784,6 +784,7 @@ static void handle_con_stats(struct sccp_connections *con)
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;
@@ -818,7 +819,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
struct sccp_connections *con;
switch (parsed->sccp_type) {
case SCCP_MSG_TYPE_CR:
- filter = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &con_type);
+ filter = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &con_type, &imsi);
if (filter < 0) {
bsc_stat_reject(filter, bsc, 0);
goto exit3;
@@ -831,6 +832,9 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
con_msc = con->msc_con;
con->con_type = con_type;
con->imsi_checked = filter;
+ if (imsi)
+ con->imsi = talloc_steal(con, imsi);
+ imsi = NULL;
con_bsc = con->bsc;
handle_con_stats(con);
break;
@@ -927,12 +931,16 @@ exit:
}
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);
talloc_free(parsed);
msgb_free(msg);
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index 9e4ccc6e2..674de4184 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -360,7 +360,9 @@ static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
return 1;
}
-static int _cr_check_loc_upd(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
+static int _cr_check_loc_upd(struct bsc_connection *bsc,
+ uint8_t *data, unsigned int length,
+ char **imsi)
{
uint8_t mi_type;
struct gsm48_loc_upd_req *lu;
@@ -383,10 +385,13 @@ static int _cr_check_loc_upd(struct bsc_connection *bsc, uint8_t *data, unsigned
return 0;
gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
+ *imsi = talloc_strdup(bsc, mi_string);
return auth_imsi(bsc, mi_string);
}
-static int _cr_check_cm_serv_req(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
+static int _cr_check_cm_serv_req(struct bsc_connection *bsc,
+ uint8_t *data, unsigned int length,
+ char **imsi)
{
static const uint32_t classmark_offset =
offsetof(struct gsm48_service_request, classmark);
@@ -416,10 +421,13 @@ static int _cr_check_cm_serv_req(struct bsc_connection *bsc, uint8_t *data, unsi
if (mi_type != GSM_MI_TYPE_IMSI)
return 0;
+ *imsi = talloc_strdup(bsc, mi_string);
return auth_imsi(bsc, mi_string);
}
-static int _cr_check_pag_resp(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
+static int _cr_check_pag_resp(struct bsc_connection *bsc,
+ uint8_t *data, unsigned int length,
+ char **imsi)
{
struct gsm48_pag_resp *resp;
char mi_string[GSM48_MI_SIZE];
@@ -440,6 +448,7 @@ static int _cr_check_pag_resp(struct bsc_connection *bsc, uint8_t *data, unsigne
if (mi_type != GSM_MI_TYPE_IMSI)
return 0;
+ *imsi = talloc_strdup(bsc, mi_string);
return auth_imsi(bsc, mi_string);
}
@@ -474,7 +483,9 @@ static int _dt_check_id_resp(struct bsc_connection *bsc,
}
/* 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)
+int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
+ struct bsc_nat_parsed *parsed, int *con_type,
+ char **imsi)
{
struct tlv_parsed tp;
struct gsm48_hdr *hdr48;
@@ -483,6 +494,7 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct
uint8_t msg_type;
*con_type = NAT_CON_TYPE_NONE;
+ *imsi = NULL;
if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
LOGP(DNAT, LOGL_ERROR,
@@ -521,15 +533,15 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct
if (hdr48->proto_discr == GSM48_PDISC_MM &&
msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) {
*con_type = NAT_CON_TYPE_LU;
- return _cr_check_loc_upd(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
+ return _cr_check_loc_upd(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi);
} else if (hdr48->proto_discr == GSM48_PDISC_MM &&
msg_type == GSM48_MT_MM_CM_SERV_REQ) {
*con_type = NAT_CON_TYPE_CM_SERV_REQ;
- return _cr_check_cm_serv_req(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
+ return _cr_check_cm_serv_req(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi);
} else if (hdr48->proto_discr == GSM48_PDISC_RR &&
msg_type == GSM48_MT_RR_PAG_RESP) {
*con_type = NAT_CON_TYPE_PAG_RESP;
- return _cr_check_pag_resp(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
+ return _cr_check_pag_resp(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi);
} else {
/* We only want to filter the above, let other things pass */
*con_type = NAT_CON_TYPE_OTHER;
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 75bd80384..141775c7a 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -705,6 +705,7 @@ static void test_cr_filter()
nat_entry = bsc_nat_acc_lst_entry_create(nat_lst);
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);
@@ -727,7 +728,7 @@ static void test_cr_filter()
abort();
}
- res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype);
+ res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype, &imsi);
if (res != cr_filter[i].result) {
fprintf(stderr, "FAIL: Wrong result %d for test %d.\n", res, i);
abort();
@@ -738,6 +739,7 @@ static void test_cr_filter()
abort();
}
+ talloc_steal(parsed, imsi);
talloc_free(parsed);
}