aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2013-04-16 13:23:43 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2013-04-16 14:14:17 +0200
commitb2b291d3efea54a60c2e5c50f8ac34a2f12125cd (patch)
tree13a9793755108f044ebaf31d6e914986eb06ecf7 /openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
parentc279e39c128615286a50e440179b6957158ceadb (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/bsc_nat_utils.c')
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_utils.c62
1 files changed, 62 insertions, 0 deletions
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;
+}