lynxis lazus has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-sgsn/+/37869?usp=email )

Change subject: GMM: split parsing of a RA Update Request in a separate file
......................................................................

GMM: split parsing of a RA Update Request in a separate file

gprs_gmm.c is huge. Further split the general validation
and parsing of the message into an own function.

Change-Id: I413da1b6b4b7c0c4781393acd8564661bc74ce2d
---
M include/osmocom/sgsn/gprs_gmm_util.h
M src/sgsn/gprs_gmm.c
M src/sgsn/gprs_gmm_util.c
3 files changed, 104 insertions(+), 44 deletions(-)

Approvals:
  pespin: Looks good to me, but someone else must approve
  daniel: Looks good to me, approved
  Jenkins Builder: Verified
  laforge: Looks good to me, but someone else must approve




diff --git a/include/osmocom/sgsn/gprs_gmm_util.h 
b/include/osmocom/sgsn/gprs_gmm_util.h
index be89c35..c136cce 100644
--- a/include/osmocom/sgsn/gprs_gmm_util.h
+++ b/include/osmocom/sgsn/gprs_gmm_util.h
@@ -1,5 +1,25 @@
 #pragma once

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

+struct msgb;
+
 extern const struct tlv_definition gsm48_gmm_ie_tlvdef;
+
+/* 9.4.14 RAU Request */
+struct gprs_gmm_ra_upd_req {
+       uint8_t skip_ind; /* 10.3.1 */
+       uint8_t update_type; /* 10.5.5.18 */
+       bool follow_up_req; /* 10.5.5.18 */
+       uint8_t cksq; /* 10.5.1.2 */
+       struct osmo_routing_area_id old_rai; /* 10.5.5.15 */
+       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);
diff --git a/src/sgsn/gprs_gmm.c b/src/sgsn/gprs_gmm.c
index 324c6bf..6122421 100644
--- a/src/sgsn/gprs_gmm.c
+++ b/src/sgsn/gprs_gmm.c
@@ -1594,52 +1594,30 @@
 #ifndef PTMSI_ALLOC
        struct sgsn_signal_data sig_data;
 #endif
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-       uint8_t *cur = gh->data;
-       uint8_t ms_ra_acc_cap_len;
-       struct osmo_routing_area_id old_ra_id;
-       struct tlv_parsed tp;
-       uint8_t upd_type;
        enum gsm48_gmm_cause reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
+       struct gprs_gmm_ra_upd_req req;
        int rc;

+       rc = gprs_gmm_parse_ra_upd_req(msg, &req);
+       if (rc) {
+               reject_cause = rc;
+               goto rejected;
+       }
+
        /* TODO: In iu mode - handle follow-on request.
         * The follow-on request can be signaled in an Attach Request on IuPS.
         * This means the MS/UE asks to keep the PS connection open for further 
requests
         * after the Attach Request succeed.
         * The SGSN can decide if it close the connection or not. Both are spec 
conform. */

-       /* Update Type 10.5.5.18 */
-       upd_type = *cur++ & 0x07;
-
        rate_ctr_inc(rate_ctr_group_get_ctr(sgsn->rate_ctrs, 
CTR_GPRS_ROUTING_AREA_REQUEST));
        LOGMMCTXP(LOGL_INFO, mmctx, "-> GMM RA UPDATE REQUEST type=\"%s\"\n",
-               get_value_string(gprs_upd_t_strs, upd_type));
+               get_value_string(gprs_upd_t_strs, req.update_type));

-       /* Old routing area identification 10.5.5.15 */
-       osmo_routing_area_id_decode(&old_ra_id, cur, msgb_l3len(msg) - (cur - 
msgb_gmmh(msg)));
-       cur += 6;
-
-       /* MS Radio Access Capability 10.5.5.12a */
-       ms_ra_acc_cap_len = *cur++;
-       if (ms_ra_acc_cap_len > 52) {
-               LOGMMCTXP(LOGL_ERROR, mmctx,
-                    "Rejecting GMM RA Update Request: MS Radio Access 
Capability too long"
-                    " (ms_ra_acc_cap_len = %u > 52)\n", ms_ra_acc_cap_len);
-               reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
-               goto rejected;
-       }
-       cur += ms_ra_acc_cap_len;
-
-       /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
-        * DRX parameter, MS network capability */
-       tlv_parse(&tp, &gsm48_gmm_ie_tlvdef, cur,
-                       (msg->data + msg->len) - cur, 0, 0);
-
-       switch (upd_type) {
+       switch (req.update_type) {
        case GPRS_UPD_T_RA_LA:
        case GPRS_UPD_T_RA_LA_IMSI_ATT:
-               LOGMMCTXP(LOGL_NOTICE, mmctx, "Update type %i unsupported in 
Mode III, is your SI13 corrupt?\n", upd_type);
+               LOGMMCTXP(LOGL_NOTICE, mmctx, "Update type %d unsupported in 
Mode III, is your SI13 corrupt?\n", req.update_type);
                reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
                goto rejected;
        case GPRS_UPD_T_RA:
@@ -1658,13 +1636,13 @@
                /* Look-up the MM context based on old RA-ID and TLLI */
                if (!MSG_IU_UE_CTX(msg)) {
                        /* Gb */
-                       mmctx = sgsn_mm_ctx_by_tlli_and_ptmsi(msgb_tlli(msg), 
&old_ra_id);
-               } else if (TLVP_PRESENT(&tp, GSM48_IE_GMM_ALLOC_PTMSI)) {
+                       mmctx = sgsn_mm_ctx_by_tlli_and_ptmsi(msgb_tlli(msg), 
&req.old_rai);
+               } else if (TLVP_PRESENT(&req.tlv, GSM48_IE_GMM_ALLOC_PTMSI)) {
 #ifdef BUILD_IU
                        /* In Iu mode search only for ptmsi */
                        struct osmo_mobile_identity mi;
-                       if (osmo_mobile_identity_decode(&mi, TLVP_VAL(&tp, 
GSM48_IE_GMM_ALLOC_PTMSI),
-                                                       TLVP_LEN(&tp, 
GSM48_IE_GMM_ALLOC_PTMSI), false)
+                       if (osmo_mobile_identity_decode(&mi, TLVP_VAL(&req.tlv, 
GSM48_IE_GMM_ALLOC_PTMSI),
+                                                       TLVP_LEN(&req.tlv, 
GSM48_IE_GMM_ALLOC_PTMSI), false)
                            || mi.type != GSM_MI_TYPE_TMSI) {
                                LOGIUP(MSG_IU_UE_CTX(msg), LOGL_ERROR, "Cannot 
decode P-TMSI\n");
                                goto rejected;
@@ -1692,7 +1670,7 @@
                                osmo_fsm_inst_dispatch(mmctx->gmm_fsm, 
E_GMM_COMMON_PROC_INIT_REQ, NULL);

                }
-       } else if (osmo_rai_cmp(&mmctx->ra, &old_ra_id) ||
+       } else if (osmo_rai_cmp(&mmctx->ra, &req.old_rai) ||
                mmctx->gmm_fsm->state == ST_GMM_DEREGISTERED)
        {
                /* We've received either a RAU for a MS which isn't registered
@@ -1707,11 +1685,11 @@
                if (mmctx->gmm_fsm->state == ST_GMM_DEREGISTERED)
                        LOGMMCTXP(LOGL_INFO, mmctx,
                                  "Rejecting RAU - GMM state is deregistered. 
Old RA: %s New RA: %s\n",
-                                 osmo_rai_name2(&old_ra_id), new_ra);
+                                 osmo_rai_name2(&req.old_rai), new_ra);
                else
                        LOGMMCTXP(LOGL_INFO, mmctx,
                                  "Rejecting RAU - Old RA doesn't match MM. Old 
RA: %s New RA: %s\n",
-                                 osmo_rai_name2(&old_ra_id), new_ra);
+                                 osmo_rai_name2(&req.old_rai), new_ra);

                reject_cause = GMM_CAUSE_IMPL_DETACHED;
                goto rejected;
@@ -1732,7 +1710,7 @@
                        mmctx = sgsn_mm_ctx_by_llme(llme);
                        if (mmctx) {
                                char old_ra_id_name[32];
-                               osmo_rai_name2_buf(old_ra_id_name, 
sizeof(old_ra_id_name), &old_ra_id);
+                               osmo_rai_name2_buf(old_ra_id_name, 
sizeof(old_ra_id_name), &req.old_rai);
                                LOGMMCTXP(LOGL_NOTICE, mmctx,
                                          "Rx RA Update Request with unexpected 
TLLI=%08x Old RA=%s (expected Old RA: %s)!\n",
                                          msgb_tlli(msg), old_ra_id_name, 
osmo_rai_name2(&mmctx->ra));
@@ -1764,8 +1742,8 @@
                mmctx->gb.tlli = msgb_tlli(msg);
        }
        /* Update the MM context with the new DRX params */
-       if (TLVP_PRESENT(&tp, GSM48_IE_GMM_DRX_PARAM))
-               memcpy(&mmctx->drx_parms, TLVP_VAL(&tp, 
GSM48_IE_GMM_DRX_PARAM), sizeof(mmctx->drx_parms));
+       if (TLVP_PRESENT(&req.tlv, GSM48_IE_GMM_DRX_PARAM))
+               memcpy(&mmctx->drx_parms, TLVP_VAL(&req.tlv, 
GSM48_IE_GMM_DRX_PARAM), sizeof(mmctx->drx_parms));

        /* FIXME: Update the MM context with the MS radio acc capabilities */
        /* FIXME: Update the MM context with the MS network capabilities */
@@ -1798,8 +1776,8 @@

        /* Look at PDP Context Status IE and see if MS's view of
         * activated/deactivated NSAPIs agrees with our view */
-       if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
-               const uint8_t *pdp_status = TLVP_VAL(&tp, 
GSM48_IE_GMM_PDP_CTX_STATUS);
+       if (TLVP_PRESENT(&req.tlv, GSM48_IE_GMM_PDP_CTX_STATUS)) {
+               const uint8_t *pdp_status = TLVP_VAL(&req.tlv, 
GSM48_IE_GMM_PDP_CTX_STATUS);
                process_ms_ctx_status(mmctx, pdp_status);
        }

diff --git a/src/sgsn/gprs_gmm_util.c b/src/sgsn/gprs_gmm_util.c
index 1248e93..0cf730f 100644
--- a/src/sgsn/gprs_gmm_util.c
+++ b/src/sgsn/gprs_gmm_util.c
@@ -23,10 +23,14 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */

+#include <osmocom/core/msgb.h>
+#include <osmocom/gprs/gprs_msgb.h>
 #include <osmocom/gsm/gsm48.h>
 #include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
 #include <osmocom/gsm/tlv.h>

+#include <osmocom/sgsn/gprs_gmm_util.h>
+
 const struct tlv_definition gsm48_gmm_ie_tlvdef = {
        .def = {
                [GSM48_IE_GMM_CIPH_CKSN]        = { TLV_TYPE_SINGLE_TV, 1 },
@@ -47,3 +51,61 @@
        },
 };

+/*! 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
+ * \returns 0 on success or GMM cause
+ */
+int gprs_gmm_parse_ra_upd_req(struct msgb *msg, struct gprs_gmm_ra_upd_req 
*rau_req)
+{
+       uint8_t *cur, len;
+       size_t mandatory_fields_len;
+       struct gsm48_hdr *gh;
+       int ret;
+
+       OSMO_ASSERT(msg);
+       OSMO_ASSERT(rau_req);
+
+       memset(rau_req, 0, sizeof(struct gprs_gmm_ra_upd_req));
+
+       /* all mandatory fields + variable length MS Radio Cap (min value) */
+       if (msgb_l3len(msg) < 16)
+               return GMM_CAUSE_PROTO_ERR_UNSPEC;
+
+       gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+       cur = gh->data;
+
+       rau_req->skip_ind = gh->proto_discr >> 4;
+
+       /* V: Update Type 10.5.5.18 */
+       rau_req->update_type = *cur & 0x07;
+       rau_req->follow_up_req = !!(*cur & 0x08);
+       /* V: GPRS Ciphering Key Sequence 10.5.1.2 */
+       rau_req->cksq = *cur >> 4;
+       cur++;
+
+       /* V: Old routing area identification 10.5.5.15 */
+       osmo_routing_area_id_decode(&rau_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;
+
+       rau_req->ms_radio_cap = cur;
+       rau_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(&rau_req->tlv, &gsm48_gmm_ie_tlvdef,
+                 cur, msgb_l3len(msg) - mandatory_fields_len, 0, 0);
+
+       if (ret < 0)
+               return GMM_CAUSE_COND_IE_ERR;
+
+       return 0;
+}

--
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/37869?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: I413da1b6b4b7c0c4781393acd8564661bc74ce2d
Gerrit-Change-Number: 37869
Gerrit-PatchSet: 23
Gerrit-Owner: lynxis lazus <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: lynxis lazus <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to