diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2013-04-16 13:23:43 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2013-04-16 14:14:17 +0200 |
commit | b2b291d3efea54a60c2e5c50f8ac34a2f12125cd (patch) | |
tree | 13a9793755108f044ebaf31d6e914986eb06ecf7 /openbsc/src/osmo-bsc_nat | |
parent | c279e39c128615286a50e440179b6957158ceadb (diff) |
nat: Extract the LAC/CI from the Complete Layer3 Information
Find the Cell Identifier from the Complete Layer3 Information and
store it for future reference. We could begin to verify that the
LAC/CI used really belongs to the BSC.
Diffstat (limited to 'openbsc/src/osmo-bsc_nat')
-rw-r--r-- | openbsc/src/osmo-bsc_nat/bsc_nat.c | 5 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc_nat/bsc_nat_utils.c | 62 |
2 files changed, 65 insertions, 2 deletions
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index 21f52871e..049680295 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -1,8 +1,8 @@ /* BSC Multiplexer/NAT */ /* - * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org> - * (C) 2010-2012 by On-Waves + * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2010-2013 by On-Waves * (C) 2009 by Harald Welte <laforge@gnumonks.org> * All Rights Reserved * @@ -1056,6 +1056,7 @@ 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; + bsc_nat_extract_lac(bsc, con, parsed, msg); if (imsi) con->imsi = talloc_steal(con, imsi); imsi = NULL; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c index b4c87d093..45c224ce8 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c @@ -502,3 +502,65 @@ int bsc_write_cb(struct osmo_fd *bfd, struct msgb *msg) return rc; } +static void extract_lac(const uint8_t *data, uint16_t *lac, uint16_t *ci) +{ + memcpy(lac, &data[0], sizeof(*lac)); + memcpy(ci, &data[2], sizeof(*ci)); + + *lac = ntohs(*lac); + *ci = ntohs(*ci); +} + +int bsc_nat_extract_lac(struct bsc_connection *bsc, + struct nat_sccp_connection *con, + struct bsc_nat_parsed *parsed, struct msgb *msg) +{ + int data_length; + const uint8_t *data; + struct tlv_parsed tp; + uint16_t lac, ci; + + if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) { + LOGP(DNAT, LOGL_ERROR, "Can only extract LAC from Complete Layer3\n"); + return -1; + } + + if (!msg->l3h || msgb_l3len(msg) < 3) { + LOGP(DNAT, LOGL_ERROR, "Complete Layer3 mssage is too short.\n"); + return -1; + } + + tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0); + if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER)) { + LOGP(DNAT, LOGL_ERROR, "No CellIdentifier List inside paging msg.\n"); + return -2; + } + + data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER); + data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER); + + /* Attemt to get the LAC/CI from it */ + if (data[0] == CELL_IDENT_WHOLE_GLOBAL) { + if (data_length != 8) { + LOGP(DNAT, LOGL_ERROR, + "Ident too short: %d\n", data_length); + return -3; + } + extract_lac(&data[1 + 3], &lac, &ci); + } else if (data[0] == CELL_IDENT_LAC_AND_CI) { + if (data_length != 5) { + LOGP(DNAT, LOGL_ERROR, + "Ident too short: %d\n", data_length); + return -3; + } + extract_lac(&data[1], &lac, &ci); + } else { + LOGP(DNAT, LOGL_ERROR, + "Unhandled cell identifier: %d\n", data[0]); + return -1; + } + + con->lac = lac; + con->ci = ci; + return 0; +} |