nat: Copy the IMSI, then free it or move the context to the connection

Extract the IMSI from the first message as well and safe it
in the connection structure. The problem is that we do not
have this structure at this point, so we will allocate the
imsi as child of the bsc_connection and then move/steal it.
This commit is contained in:
Holger Hans Peter Freyther 2010-09-29 01:19:42 +08:00
parent 8c78b480f9
commit 749497eeb3
4 changed files with 32 additions and 10 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);
}