From 2cb1f27ddb812a111a3e6e582afe7524ee9ccf4a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 16 Feb 2018 17:47:55 +0000 Subject: [PATCH] Adding UE context release command. Fixing issue when identity response is integrity protected. --- srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h | 2 +- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 38 ++++++++++++++++----------- srsepc/src/mme/s1ap_mngmt_proc.cc | 6 +++-- srsepc/src/mme/s1ap_nas_transport.cc | 30 ++++++++++++++------- 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h index 2e448f110..9979b6594 100644 --- a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h +++ b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h @@ -50,7 +50,7 @@ public: bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); - bool pack_ue_context_release_request(uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t *reply_buffer); + bool send_ue_context_release_command(ue_ecm_ctx_t *ecm_ctx, srslte::byte_buffer_t *reply_buffer); private: s1ap_ctx_mngmt_proc(); diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 527f310b5..ba9d38577 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -309,36 +309,44 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON } bool -s1ap_ctx_mngmt_proc::pack_ue_context_release_request(uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t *reply_buffer) +s1ap_ctx_mngmt_proc::send_ue_context_release_command(ue_ecm_ctx_t *ecm_ctx, srslte::byte_buffer_t *reply_buffer) { + int s1mme = m_s1ap->get_s1_mme(); + //Prepare reply PDU LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &pdu.choice.initiatingMessage; - init->procedureCode = LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASEREQUEST; - init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST; + init->procedureCode = LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASE; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASECOMMAND; + + LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMAND_STRUCT *ctx_rel_cmd = &init->choice.UEContextReleaseCommand; + + ctx_rel_cmd->UE_S1AP_IDs.choice_type = LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR; + ctx_rel_cmd->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID.MME_UE_S1AP_ID = ecm_ctx->mme_ue_s1ap_id; + ctx_rel_cmd->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ecm_ctx->enb_ue_s1ap_id; + + ctx_rel_cmd->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_NAS; + ctx_rel_cmd->Cause.choice.nas.ext = false; + ctx_rel_cmd->Cause.choice.nas.e = LIBLTE_S1AP_CAUSENAS_NORMAL_RELEASE; - LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ctx_rel_req = &init->choice.UEContextReleaseRequest; - - /* - typedef struct{ - bool ext; - LIBLTE_S1AP_MME_UE_S1AP_ID_STRUCT MME_UE_S1AP_ID; - LIBLTE_S1AP_ENB_UE_S1AP_ID_STRUCT eNB_UE_S1AP_ID; - LIBLTE_S1AP_CAUSE_STRUCT Cause; - LIBLTE_S1AP_GWCONTEXTRELEASEINDICATION_ENUM_EXT GWContextReleaseIndication; - bool GWContextReleaseIndication_present; - }LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT; - */ LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); return false; } + //Send Reply to eNB + int n_sent = sctp_send(s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ecm_ctx->enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); + return false; + } + return true; } diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc index 8fa469ec3..43fa5d860 100644 --- a/srsepc/src/mme/s1ap_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -234,7 +234,7 @@ s1ap_mngmt_proc::pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buff LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT *serv_gummei = &s1_resp->ServedGUMMEIs.buffer[0]; serv_gummei->ext=false; - //serv_gummei->iE_Extensions=false; + serv_gummei->iE_Extensions_present = false; uint32_t plmn=0; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &plmn); @@ -257,7 +257,9 @@ s1ap_mngmt_proc::pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buff //Relay Unsupported s1_resp->MMERelaySupportIndicator_present=false; - + + s1_resp->CriticalityDiagnostics_present = false; + liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg); return true; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index af7d785cb..8dd6c6e68 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -158,15 +158,27 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); if(ue_emm_ctx == NULL) { - m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); - m_pool->deallocate(nas_msg); - return false; + //No EMM context found. + //Perhaps a temporary context is being created? + //This can happen with integrity protected identity reponse and authentication response messages + if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) && + !(msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) + { + m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + m_pool->deallocate(nas_msg); + return false; + } } } - if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) + if( sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS || + (msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) || + (msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) { - //Plain NAS, only identity response is valid. + //Only identity response and authentication response are valid as plain NAS. + //Sometimes authentication response and identity are sent as integrity protected, + //but these messages are sent when the securty context is not setup yet, so we cannot integrity check it. + //FIXME Double-check switch(msg_type) { case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: @@ -220,17 +232,17 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA //Integrity protected NAS message, possibly chiphered. ue_emm_ctx->security_ctxt.ul_nas_count++; mac_valid = integrity_check(ue_emm_ctx,nas_msg); - if(!mac_valid && msg_type != LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE){ + if(!mac_valid){ m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type); m_pool->deallocate(nas_msg); return false; } switch (msg_type) { - case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: + /*case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: m_s1ap_log->info("Uplink NAS: Received Authentication Response\n"); m_s1ap_log->console("Uplink NAS: Received Authentication Response\n"); handle_nas_authentication_response(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); - break; + break;*/ case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: m_s1ap_log->info("Uplink NAS: Received Attach Complete\n"); m_s1ap_log->console("Uplink NAS: Received Attach Complete\n"); @@ -599,7 +611,7 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, //Service request to Connected UE. //Delete ECM context and connect. m_mme_gtpc->send_delete_session_request(ecm_ctx); - //pack_context_release_request(); + //m_s1ap send_context_release_request(ecm_ctx, reply_buffer); } else {