aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-09-29 01:19:42 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-10-21 12:22:50 +0200
commit749497eeb3cae13fa2252abcf93468ecd415f063 (patch)
tree02d6719db109aaf697e28f74a0c2d4ee3b40606d /openbsc
parent8c78b480f9d1dbb0461f9294891687d43080abf5 (diff)
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.
Diffstat (limited to 'openbsc')
-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);
}