lynxis lazus has uploaded this change for review.

View Change

gprs_gmm_util: add parsing of GMM Attach Requests

Change-Id: I4a82e0c4070da982efd6c2f15fd145393423772b
---
M include/osmocom/sgsn/gprs_gmm_util.h
M src/sgsn/gprs_gmm_util.c
2 files changed, 133 insertions(+), 0 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/46/39246/1
diff --git a/include/osmocom/sgsn/gprs_gmm_util.h b/include/osmocom/sgsn/gprs_gmm_util.h
index c136cce..c844caf 100644
--- a/include/osmocom/sgsn/gprs_gmm_util.h
+++ b/include/osmocom/sgsn/gprs_gmm_util.h
@@ -4,6 +4,7 @@
#include <stdint.h>

#include <osmocom/gsm/gsm23003.h>
+#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/tlv.h>

struct msgb;
@@ -22,4 +23,20 @@
struct tlv_parsed tlv;
};

+struct gprs_gmm_att_req {
+ uint8_t skip_ind; /* 10.3.1 */
+ uint8_t attach_type; /* 10.5.5.2 */
+ bool follow_up_req; /* 10.5.5.2 */
+ uint8_t cksq; /* 10.5.1.2 */
+ uint16_t drx_parms; /* 10.5.5.6 */
+ struct osmo_mobile_identity mi; /* 10.5.1.4 */
+ struct osmo_routing_area_id old_rai; /* 10.5.5.15 */
+ uint8_t *ms_network_cap; /* 10.5.5.12 */
+ uint8_t ms_network_cap_len;
+ uint8_t *ms_radio_cap; /* 10.5.5.12a */
+ uint8_t ms_radio_cap_len;
+ struct tlv_parsed tlv;
+};
+
int gprs_gmm_parse_ra_upd_req(struct msgb *msg, struct gprs_gmm_ra_upd_req *rau_req);
+int gprs_gmm_parse_att_req(struct msgb *msg, struct gprs_gmm_att_req *att_req);
diff --git a/src/sgsn/gprs_gmm_util.c b/src/sgsn/gprs_gmm_util.c
index ee51ceb..549e0b1 100644
--- a/src/sgsn/gprs_gmm_util.c
+++ b/src/sgsn/gprs_gmm_util.c
@@ -29,6 +29,7 @@
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/tlv.h>

+#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_gmm_util.h>

const struct tlv_definition gsm48_gmm_ie_tlvdef = {
@@ -63,6 +64,121 @@
},
};

+const struct tlv_definition gsm48_gmm_att_ie_tlvdef = {
+ .def = {
+ [GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 },
+ [GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
+ [GSM48_IE_GMM_TMSI_STATUS] = { TLV_TYPE_SINGLE_TV, 1 },
+ [GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_MS_CLASSMARK2] = { TLV_TYPE_TLV, 3 },
+ [GSM48_IE_GMM_MS_CLASSMARK3] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_SUPP_CODEC_LIST] = { TLV_TYPE_TLV, 3 },
+ [GSM48_IE_GMM_UE_NET_CAP] = { TLV_TYPE_TLV, 2 },
+ [GSM48_IE_GMM_ADD_IDENTITY] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_RAI2] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_VD_PREF_UE_USAGE] = { TLV_TYPE_TLV, 1 },
+ [GSM48_IE_GMM_DEVICE_PROP] = { TLV_TYPE_SINGLE_TV, 1 },
+ [GSM48_IE_GMM_PTMSI_TYPE] = { TLV_TYPE_SINGLE_TV, 1 },
+ [GSM48_IE_GMM_MS_NET_FEAT_SUP] = { TLV_TYPE_SINGLE_TV, 1 },
+ [GSM48_IE_GMM_ADD_UPDATE_TYPE] = { TLV_TYPE_SINGLE_TV, 1 },
+ [GSM48_IE_GMM_TMSI_BASED_NRI_C] = { TLV_TYPE_TLV, 4 },
+ [GMM48_IE_GMM_TIMER_T3324] = { TLV_TYPE_TLV, 3 },
+ [GSM48_IE_GMM_TIMER_T3312_EXT] = { TLV_TYPE_TLV, 3 },
+ [GSM48_IE_GMM_EXT_DRX_PARAMS] = { TLV_TYPE_TLV, 3 },
+ }
+};
+
+
+/*! Parse 24.008 9.4.1 Attach Request
+ * \param[in] msg l3 pointers must point to gmm.
+ * \param[out] rau_req parsed RA update request
+ * \returns 0 on success or GMM cause
+ */
+int gprs_gmm_parse_att_req(struct msgb *msg, struct gprs_gmm_att_req *att_req)
+{
+ uint8_t *cur, len;
+ size_t mandatory_fields_len;
+ struct gsm48_hdr *gh;
+ int ret;
+
+ OSMO_ASSERT(msg);
+ OSMO_ASSERT(att_req);
+
+ memset(att_req, 0, sizeof(struct gprs_gmm_att_req));
+ /* all mandatory fields */
+ if (msgb_l3len(msg) < 25)
+ return GMM_CAUSE_PROTO_ERR_UNSPEC;
+
+ gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ cur = gh->data;
+
+ att_req->skip_ind = gh->proto_discr >> 4;
+
+ /* LV: MS network cap 10.5.5.12 */
+ len = *cur++;
+ if (msgb_l3len(msg) < (len + 21 + (cur - msgb_gmmh(msg))))
+ return GMM_CAUSE_PROTO_ERR_UNSPEC;
+ /* MS network cap must be at least 2 bytes long */
+ if (len == 0)
+ return GMM_CAUSE_INV_MAND_INFO;
+
+ att_req->ms_network_cap = cur;
+ att_req->ms_network_cap_len = len;
+ cur += len;
+
+ /* V: Update Type 10.5.5.18 */
+ att_req->attach_type = *cur & 0x07;
+ att_req->follow_up_req = !!(*cur & 0x08);
+
+ /* V: GPRS Ciphering Key Sequence 10.5.1.2 */
+ att_req->cksq = *cur >> 4;
+ cur++;
+
+ /* V: DRX parameter 10.5.5.6 */
+ att_req->drx_parms = osmo_load16le(cur);
+ cur += 2;
+
+ /* LV: Mobile identity 10.5.1.4 */
+ len = *cur++;
+ if (msgb_l3len(msg) < (len + 12 + (cur - msgb_gmmh(msg))))
+ return GMM_CAUSE_PROTO_ERR_UNSPEC;
+ ret = osmo_mobile_identity_decode(&att_req->mi, cur, len, false);
+ if (ret)
+ return GMM_CAUSE_PROTO_ERR_UNSPEC;
+ cur += len;
+
+ /* V: Old routing area identification 10.5.5.15 */
+ osmo_routing_area_id_decode(&att_req->old_rai, cur, 6);
+ cur += 6;
+
+ /* LV: MS radio cap 10.5.5.12a */
+ len = *cur++;
+ if (msgb_l3len(msg) < (len + (cur - msgb_gmmh(msg))))
+ return GMM_CAUSE_PROTO_ERR_UNSPEC;
+ /* 24.008 Rel 17 specifies min 5, but SGSN will still work with 4 */
+ if (len < 4)
+ return GMM_CAUSE_INV_MAND_INFO;
+
+ att_req->ms_radio_cap = cur;
+ att_req->ms_radio_cap_len = len;
+ cur += len;
+
+ mandatory_fields_len = (cur - msgb_gmmh(msg));
+ if (msgb_l3len(msg) == mandatory_fields_len)
+ return 0;
+
+ ret = tlv_parse(&att_req->tlv, &gsm48_gmm_att_ie_tlvdef,
+ cur, msgb_l3len(msg) - mandatory_fields_len, 0, 0);
+
+ /* gracefully handle unknown IEs (partial parsing) */
+ if (ret < 0 && ret != OSMO_TLVP_ERR_UNKNOWN_TLV_TYPE) {
+ LOGP(DMM, LOGL_NOTICE, "%s(): tlv_parse() failed (%d)\n", __func__, ret);
+ return GMM_CAUSE_COND_IE_ERR;
+ }
+
+ return 0;
+}
+
/*! Parse 24.008 9.4.14 RAU Request
* \param[in] msg l3 pointers must point to gmm.
* \param[out] rau_req parsed RA update request

To view, visit change 39246. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: I4a82e0c4070da982efd6c2f15fd145393423772b
Gerrit-Change-Number: 39246
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <lynxis@fe80.eu>