diff options
author | Stefan Sperling <ssperling@sysmocom.de> | 2018-01-05 17:22:11 +0100 |
---|---|---|
committer | Stefan Sperling <ssperling@sysmocom.de> | 2018-01-11 12:50:07 +0000 |
commit | 33e900900307ec7268d642c84943d624b3f83568 (patch) | |
tree | 13f0063dc100c269b465db101311b2be1bda6bb3 | |
parent | f56a28d1c24e7ab40402939676edd8d5f50bc94e (diff) |
Implement support for paging by LAI.
Also, parse the complete cell identifier list for both LAC and LAI.
Change-Id: Ic3c62ff0fccea586794ea4b3c275a0685cc9326e
Related: OS#2751
-rw-r--r-- | src/osmo-bsc/osmo_bsc_bssap.c | 124 | ||||
-rw-r--r-- | tests/bssap/bssap_test.c | 5 | ||||
-rw-r--r-- | tests/bssap/bssap_test.err | 11 |
3 files changed, 105 insertions, 35 deletions
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c index 0ecc11c6b..54e020563 100644 --- a/src/osmo-bsc/osmo_bsc_bssap.c +++ b/src/osmo-bsc/osmo_bsc_bssap.c @@ -228,21 +228,52 @@ static int bssmap_handle_reset(struct bsc_msc_data *msc, return 0; } +/* Page a subscriber based on TMSI and LAC. + * A non-zero return value indicates a fatal out of memory condition. */ +static int +page_subscriber(struct bsc_msc_data *msc, uint32_t tmsi, uint32_t lac, + const char *mi_string, uint8_t chan_needed) +{ + struct bsc_subscr *subscr; + + subscr = bsc_subscr_find_or_create_by_imsi(msc->network->bsc_subscribers, + mi_string); + if (!subscr) { + LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string); + return -1; + } + + subscr->lac = lac; + subscr->tmsi = tmsi; + + LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac); + bsc_grace_paging_request(msc->network->bsc_data->rf_ctrl->policy, + subscr, chan_needed, msc); + + /* the paging code has grabbed its own references */ + bsc_subscr_put(subscr); + + return 0; +} + /* GSM 08.08 ยง 3.2.1.19 */ static int bssmap_handle_paging(struct bsc_msc_data *msc, struct msgb *msg, unsigned int payload_length) { - struct bsc_subscr *subscr; struct tlv_parsed tp; char mi_string[GSM48_MI_SIZE]; uint32_t tmsi = GSM_RESERVED_TMSI; - unsigned int lac; + uint16_t lac, *lacp_be; + uint16_t mcc; + uint16_t mnc; uint8_t data_length; + int remain; const uint8_t *data; uint8_t chan_needed = RSL_CHANNEED_ANY; uint8_t cell_ident; tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0); + remain = payload_length - 1; if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) { LOGP(DMSC, LOGL_ERROR, "Mandatory IMSI not present.\n"); @@ -251,6 +282,7 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc, LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n"); return -1; } + remain -= TLVP_LEN(&tp, GSM0808_IE_IMSI); if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) { LOGP(DMSC, LOGL_ERROR, "Mandatory CELL IDENTIFIER LIST not present.\n"); @@ -260,6 +292,12 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc, if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI) && TLVP_LEN(&tp, GSM0808_IE_TMSI) == 4) { tmsi = ntohl(tlvp_val32_unal(&tp, GSM0808_IE_TMSI)); + remain -= TLVP_LEN(&tp, GSM0808_IE_TMSI); + } + + if (remain <= 0) { + LOGP(DMSC, LOGL_ERROR, "Payload too short.\n"); + return -1; } /* @@ -280,22 +318,64 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc, LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Zero length Cell Identifier List\n", mi_string); return -1; + } else if (data_length > remain) { + LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Bogus Cell Identifier List length\n", + mi_string); + return -1; + } + remain = data_length; /* ignore payload padding data beyond data_length */ + + if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1) + chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03; + + if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) { + LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n"); } cell_ident = data[0] & 0xf; + remain -= 1; /* cell ident consumed */ /* Default fallback: page entire BSS */ lac = GSM_LAC_RESERVED_ALL_BTS; switch (cell_ident) { + case CELL_IDENT_LAI_AND_LAC: { + struct gsm48_loc_area_id lai; + int i = 0; + while (remain >= sizeof(lai)) { + /* Parse and decode 5-byte LAI list element (see TS 08.08 3.2.2.27). + * Copy data to stack to prevent unaligned access in gsm48_decode_lai(). */ + memcpy(&lai, &data[1 + i * sizeof(lai)], sizeof(lai)); /* don't byte swap yet */ + if (gsm48_decode_lai(&lai, &mcc, &mnc, &lac) != 0) { + LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Invalid LAI in Cell Identifier List " + "for BSS (0x%x), paging entire BSS anyway (%s)\n", + mi_string, CELL_IDENT_BSS, osmo_hexdump(data, data_length)); + lac = GSM_LAC_RESERVED_ALL_BTS; + break; + } + if (mcc == msc->network->country_code && mnc == msc->network->network_code) { + if (page_subscriber(msc, tmsi, lac, mi_string, chan_needed) != 0) + break; + } else + LOGP(DMSC, LOGL_DEBUG, "Not paging IMSI %s: MCC/MNC in Cell Identifier List " + "(%d/%d) do not match our network (%d/%d)\n", mi_string, mcc, mnc, + msc->network->country_code, msc->network->network_code); + + remain -= sizeof(lai); + i++; + } + break; + } + case CELL_IDENT_LAC: - if (data_length != 3) { - LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Cell Identifier List for LAC (0x%x)" - " has invalid length: %u, paging entire BSS instead (%s)\n", - mi_string, CELL_IDENT_LAC, data_length, osmo_hexdump(data, data_length)); - break; + lacp_be = (uint16_t *)(&data[1]); + while (remain >= sizeof(*lacp_be)) { + lac = osmo_load16be(lacp_be); + if (page_subscriber(msc, tmsi, lac, mi_string, chan_needed) != 0) + break; + remain -= sizeof(*lacp_be); + lacp_be++; } - lac = osmo_load16be(&data[1]); break; case CELL_IDENT_BSS: @@ -304,39 +384,19 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc, " has invalid length: %u, paging entire BSS anyway (%s)\n", mi_string, CELL_IDENT_BSS, data_length, osmo_hexdump(data, data_length)); } + if (page_subscriber(msc, tmsi, GSM_LAC_RESERVED_ALL_BTS, mi_string, chan_needed) != 0) + break; break; default: LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: unimplemented Cell Identifier List (0x%x)," " paging entire BSS instead (%s)\n", mi_string, cell_ident, osmo_hexdump(data, data_length)); + if (page_subscriber(msc, tmsi, GSM_LAC_RESERVED_ALL_BTS, mi_string, chan_needed) != 0) + break; break; } - if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1) - chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03; - - if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) { - LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n"); - } - - subscr = bsc_subscr_find_or_create_by_imsi(msc->network->bsc_subscribers, - mi_string); - if (!subscr) { - LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string); - return -1; - } - - subscr->lac = lac; - subscr->tmsi = tmsi; - - LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac); - bsc_grace_paging_request(msc->network->bsc_data->rf_ctrl->policy, - subscr, chan_needed, msc); - - /* the paging code has grabbed its own references */ - bsc_subscr_put(subscr); - return 0; } diff --git a/tests/bssap/bssap_test.c b/tests/bssap/bssap_test.c index 579cae237..c97393d5e 100644 --- a/tests/bssap/bssap_test.c +++ b/tests/bssap/bssap_test.c @@ -73,6 +73,11 @@ struct { /* ^^^^^^^^^^^^ Cell Identifier List: LAI */ GSM_LAC_RESERVED_ALL_BTS, 0 }, + { + "001952080859512069000743940904010844601a060400f1100065", + /* ^^^^^^^^^^^^ Cell Identifier List: LAI */ + 0x65, 0 + }, }; void test_cell_identifier() diff --git a/tests/bssap/bssap_test.err b/tests/bssap/bssap_test.err index 1c432eb08..f24ff7c8c 100644 --- a/tests/bssap/bssap_test.err +++ b/tests/bssap/bssap_test.err @@ -16,7 +16,12 @@ bsc_handle_udt() returned 0 2: DMSC Rx MSC UDT: 00 19 52 08 08 59 51 20 69 00 07 43 94 09 04 01 08 44 60 1a 06 04 15 f5 49 00 65 DMSC Rx MSC UDT BSSMAP PAGING -DMSC Paging IMSI 515029600703449: unimplemented Cell Identifier List (0x4), paging entire BSS instead (04 15 f5 49 00 65 ) -DMSC Paging request from MSC IMSI: '515029600703449' TMSI: '0x1084460/17319008' LAC: 0xfffe -BSC paging started on entire BSS (65534) +DMSC Not paging IMSI 515029600703449: MCC/MNC in Cell Identifier List (515/94) do not match our network (1/1) +bsc_handle_udt() returned 0 + +3: +DMSC Rx MSC UDT: 00 19 52 08 08 59 51 20 69 00 07 43 94 09 04 01 08 44 60 1a 06 04 00 f1 10 00 65 +DMSC Rx MSC UDT BSSMAP PAGING +DMSC Paging request from MSC IMSI: '515029600703449' TMSI: '0x1084460/17319008' LAC: 0x65 +BSC paging started with LAC 101 bsc_handle_udt() returned 0 |