diff options
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/bsc_nat.h | 2 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat.c | 10 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat_utils.c | 26 | ||||
-rw-r--r-- | openbsc/tests/bsc-nat/bsc_nat_test.c | 4 |
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); } |