diff --git a/srsepc/hdr/mme/nas.h b/srsepc/hdr/mme/nas.h index 320a78b99..602001094 100644 --- a/srsepc/hdr/mme/nas.h +++ b/srsepc/hdr/mme/nas.h @@ -247,6 +247,7 @@ public: bool pack_identity_request(srslte::byte_buffer_t* nas_buffer); bool pack_emm_information(srslte::byte_buffer_t* nas_buffer); bool pack_service_reject(srslte::byte_buffer_t* nas_buffer, uint8_t emm_cause); + bool pack_tracking_area_update_reject(srslte::byte_buffer_t* nas_buffer, uint8_t emm_cause); bool pack_attach_accept(srslte::byte_buffer_t* nas_buffer); /* Security functions */ diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index 0b30583fc..fed81c0ee 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -776,6 +776,8 @@ bool nas::handle_tracking_area_update_request(uint32_t m_tmsi, nas_if_t itf, srslte::log* nas_log) { + srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); + nas_log->info("Tracking Area Update Request -- S-TMSI 0x%x\n", m_tmsi); nas_log->console("Tracking Area Update Request -- S-TMSI 0x%x\n", m_tmsi); nas_log->info("Tracking Area Update Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); @@ -789,20 +791,17 @@ bool nas::handle_tracking_area_update_request(uint32_t m_tmsi, hss_interface_nas* hss = itf.hss; gtpc_interface_nas* gtpc = itf.gtpc; - uint64_t imsi = s1ap->find_imsi_from_m_tmsi(m_tmsi); - if (imsi == 0) { - nas_log->console("Could not find IMSI from M-TMSI. M-TMSI 0x%x\n", m_tmsi); - nas_log->error("Could not find IMSI from M-TMSI. M-TMSI 0x%x\n", m_tmsi); - return true; - } - - nas* nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); - emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; + // TODO don't search for NAS ctxt, just send that reject + // with context we could enable integrity protection - sec_ctx_t* sec_ctx = &nas_ctx->m_sec_ctx; + nas nas_tmp(args, itf, nas_log); + nas_tmp.m_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; + nas_tmp.m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); - sec_ctx->ul_nas_count++; // Increment the NAS count, not to break the security ctx + srslte::byte_buffer_t* nas_tx = pool->allocate(); + nas_tmp.pack_tracking_area_update_reject(nas_tx, LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); + s1ap->send_downlink_nas_transport(enb_ue_s1ap_id, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id, nas_tx, *enb_sri); + pool->deallocate(nas_tx); return true; } @@ -1150,6 +1149,18 @@ bool nas::handle_tracking_area_update_request(srslte::byte_buffer_t* nas_rx) m_nas_log->console("Warning: Tracking Area Update Request messages not handled yet.\n"); m_nas_log->warning("Warning: Tracking Area Update Request messages not handled yet.\n"); + srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); + srslte::byte_buffer_t* nas_tx; + + /* TAU handling unsupported, therefore send TAU reject with cause IMPLICITLY DETACHED. + * this will trigger full re-attach by the UE, instead of going to a TAU request loop */ + nas_tx = pool->allocate(); + // TODO we could enable integrity protection in some cases, but UE should comply anyway + pack_tracking_area_update_reject(nas_tx, LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED); + // Send reply + m_s1ap->send_downlink_nas_transport(m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx, m_ecm_ctx.enb_sri); + pool->deallocate(nas_tx); + return true; } @@ -1561,6 +1572,28 @@ bool nas::pack_service_reject(srslte::byte_buffer_t* nas_buffer, uint8_t emm_cau return true; } +bool nas::pack_tracking_area_update_reject(srslte::byte_buffer_t* nas_buffer, uint8_t emm_cause) +{ + LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT tau_rej; + tau_rej.t3446_present = false; + tau_rej.t3446 = 0; + tau_rej.emm_cause = emm_cause; + + if (emm_cause == LIBLTE_MME_EMM_CAUSE_CONGESTION) { + // Standard would want T3446 set in this case + m_nas_log->error("Tracking Area Update Reject EMM Cause set to \"CONGESTION\", but back-off timer not set.\n"); + } + + LIBLTE_ERROR_ENUM err = liblte_mme_pack_tracking_area_update_reject_msg(&tau_rej, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, 0, + (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); + if (err != LIBLTE_SUCCESS) { + m_nas_log->error("Error packing Tracking Area Update Reject\n"); + m_nas_log->console("Error packing Tracking Area Update Reject\n"); + return false; + } + return true; +} + /************************ * * Security Functions