From 66ac860f6213a18ee18e135e2367d09f59539339 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 15 May 2010 21:58:33 +0800 Subject: [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. --- openbsc/src/nat/bsc_nat_utils.c | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c index d5537f796..2e0c5a45a 100644 --- a/openbsc/src/nat/bsc_nat_utils.c +++ b/openbsc/src/nat/bsc_nat_utils.c @@ -257,6 +257,52 @@ static int _cr_check_loc_upd(struct bsc_connection *bsc, uint8_t *data, unsigned return auth_imsi(bsc, mi_string); } +static int _cr_check_cm_serv_req(struct bsc_connection *bsc, uint8_t *data, unsigned int length) +{ + char mi_string[GSM48_MI_SIZE]; + struct gsm48_service_request *req; + + /* unfortunately in Phase1 the classmark2 length is variable */ + uint8_t classmark2_len; + uint8_t *classmark2; + uint8_t mi_len; + uint8_t *mi; + uint8_t mi_type; + + 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; + classmark2_len = ((uint8_t *) &req->classmark)[0]; + if (length < 2 + classmark2_len) { + LOGP(DNAT, LOGL_ERROR, + "Classmark2 does not fit. cml: %d\n", classmark2_len); + return -1; + } + + classmark2 = ((uint8_t *) &req->classmark) + 1; + mi_len = *(classmark2 + classmark2_len); + if (length < 3 + classmark2_len + mi_len) { + LOGP(DNAT, LOGL_ERROR, + "MI does not fit length: %d vs. %d\n", + length, 3 + classmark2_len + mi_len); + return -1; + } + + mi = (classmark2 + classmark2_len + 1); + mi_type = mi[0] & GSM_MI_TYPE_MASK; + + /* we have to let the TMSI or such pass */ + if (mi_type != GSM_MI_TYPE_IMSI) + return 0; + + gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len); + 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) @@ -301,6 +347,8 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct if (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->msg_type == GSM48_MT_MM_CM_SERV_REQ) { + return _cr_check_cm_serv_req(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48)); } else { return 0; } -- cgit v1.2.3