From d2fd394e4dccb979698760df98de3437e7383316 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Fri, 26 May 2023 17:14:26 +0200 Subject: [PATCH] gmm: Implement rx RAU Reject Change-Id: I0d4d8288b78cfd3140c786a52a3906eaf37ebe6b --- include/osmocom/gprs/gmm/gmm_ms_fsm.h | 2 +- src/gmm/gmm.c | 46 +++++++++++++++++++++++++++ src/gmm/gmm_ms_fsm.c | 18 ++++++++--- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/include/osmocom/gprs/gmm/gmm_ms_fsm.h b/include/osmocom/gprs/gmm/gmm_ms_fsm.h index 1ebc53c..772444f 100644 --- a/include/osmocom/gprs/gmm/gmm_ms_fsm.h +++ b/include/osmocom/gprs/gmm/gmm_ms_fsm.h @@ -51,7 +51,7 @@ enum gprs_gmm_ms_fsm_events { GPRS_GMM_MS_EV_SR_REJECTED, /* (Iu only) */ GPRS_GMM_MS_EV_SR_ACCEPTED, /* (Iu only) */ GPRS_GMM_MS_EV_RAU_REQUESTED, - GPRS_GMM_MS_EV_RAU_REJECTED, + GPRS_GMM_MS_EV_RAU_REJECTED, /* data: ptr to "uint8_t cause" */ GPRS_GMM_MS_EV_RAU_ACCEPTED, GPRS_GMM_MS_EV_LOW_LVL_FAIL, }; diff --git a/src/gmm/gmm.c b/src/gmm/gmm.c index c96917b..4836d58 100644 --- a/src/gmm/gmm.c +++ b/src/gmm/gmm.c @@ -1137,6 +1137,49 @@ rejected: return -EINVAL; /* TODO: what to do on error? */ } +/* Rx GMM Routing area update reject, 9.4.17 */ +static int gprs_gmm_rx_rau_rej(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + uint8_t *buf = &gh->data[0]; + struct tlv_parsed tp; + uint8_t cause = GMM_CAUSE_SEM_INCORR_MSG; + bool force_standby_indicated; + int rc; + + if (len < sizeof(*gh) + 2) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM ROUTING AREA UPDATE REJECT with wrong size %u\n", len); + goto rejected; + } + + cause = buf[0]; + force_standby_indicated = (buf[1] >> 4) == 0x01; + buf += 2; + + LOGGMME(gmme, LOGL_NOTICE, "Rx GMM ROUTING AREA UPDATE REJECT cause='%s' (%u) force_stdby=%u\n", + get_value_string(gsm48_gmm_cause_names, cause), cause, force_standby_indicated); + + if (force_standby_indicated) + gprs_gmm_gmme_ready_timer_stop(gmme); + + if (len > (buf - (uint8_t *)gh)) { + rc = gprs_gmm_tlv_parse(&tp, buf, len - (buf - (uint8_t *)gh)); + if (rc < 0) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM ROUTING AREA UPDATE REJECT: failed to parse TLVs %d\n", rc); + goto rejected; + } + + if (TLVP_PRES_LEN(&tp, GSM48_IE_GMM_TIMER_T3302, 1)) + gmme->t3302 = *TLVP_VAL(&tp, GSM48_IE_GMM_TIMER_T3302); + + if (TLVP_PRES_LEN(&tp, GSM48_IE_GMM_TIMER_T3346, 1)) + gmme->t3346 = *TLVP_VAL(&tp, GSM48_IE_GMM_TIMER_T3346); + } + +rejected: + rc = osmo_fsm_inst_dispatch(gmme->ms_fsm.fi, GPRS_GMM_MS_EV_RAU_REJECTED, &cause); + return -EINVAL; +} + /* Rx GMM Identity Request, 9.2.10 */ static int gprs_gmm_rx_id_req(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) { @@ -1380,6 +1423,9 @@ int gprs_gmm_rx(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int case GSM48_MT_GMM_RA_UPD_ACK: rc = gprs_gmm_rx_rau_acc(gmme, gh, len); break; + case GSM48_MT_GMM_RA_UPD_REJ: + rc = gprs_gmm_rx_rau_rej(gmme, gh, len); + break; case GSM48_MT_GMM_ID_REQ: rc = gprs_gmm_rx_id_req(gmme, gh, len); break; diff --git a/src/gmm/gmm_ms_fsm.c b/src/gmm/gmm_ms_fsm.c index e5a7002..ff26dfa 100644 --- a/src/gmm/gmm_ms_fsm.c +++ b/src/gmm/gmm_ms_fsm.c @@ -239,13 +239,22 @@ static void st_gmm_ms_rau_initiated(struct osmo_fsm_inst *fi, uint32_t event, vo { struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv; struct osmo_gprs_llc_prim *llc_prim_tx; + enum gsm48_gmm_cause cause; switch (event) { case GPRS_GMM_MS_EV_RAU_REJECTED: - // causes #13, #15, #25 - gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); - // else - //mm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED_INITIATED); + cause = *(uint8_t *)data; + /* 3GPP TS 24.008 Figure 4.1b */ + switch (cause) { + case GMM_CAUSE_ROAMING_NOTALLOWED: + case GMM_CAUSE_NO_SUIT_CELL_IN_LA: + case GMM_CAUSE_NOT_AUTH_FOR_CSG: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + break; + default: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + } break; case GPRS_GMM_MS_EV_RAU_ACCEPTED: gprs_gmm_gmme_t3316_stop(ctx->gmme); @@ -351,7 +360,6 @@ static struct osmo_fsm_state gmm_ms_fsm_states[] = { X(GPRS_GMM_MS_EV_RAU_ACCEPTED), .out_state_mask = X(GPRS_GMM_MS_ST_REGISTERED) | - X(GPRS_GMM_MS_ST_DEREGISTERED_INITIATED) | X(GPRS_GMM_MS_ST_DEREGISTERED), .name = "RAUInitidated", .action = st_gmm_ms_rau_initiated,