diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 152b0de62..0a2c4c025 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "nas/nas-message.h" #include "fd/fd-lib.h" #include "fd/s6a/s6a-message.h" @@ -62,183 +81,151 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) mme_ue_t *mme_ue = NULL; enb_ue_t *enb_ue = NULL; + nas_message_t *message = NULL; + S1AP_ProcedureCode_t procedureCode; ogs_assert(e); mme_ue = e->mme_ue; ogs_assert(mme_ue); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - return; - } - case OGS_FSM_EXIT_SIG: - { - return; - } - case MME_EVT_EMM_MESSAGE: - { - nas_message_t *message = e->nas_message; - ogs_assert(message); + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + return; + case OGS_FSM_EXIT_SIG: + return; + case MME_EVT_EMM_MESSAGE: + message = e->nas_message; + ogs_assert(message); - enb_ue = mme_ue->enb_ue; - ogs_assert(enb_ue); + enb_ue = mme_ue->enb_ue; + ogs_assert(enb_ue); - if (message->emm.h.security_header_type - == NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) - { - ogs_debug("[EMM] Service request"); - rv = emm_handle_service_request( - mme_ue, &message->emm.service_request); - if (rv != OGS_OK) - { - ogs_error("emm_handle_service_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } + if (message->emm.h.security_header_type + == NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { + ogs_debug("[EMM] Service request"); + rv = emm_handle_service_request( + mme_ue, &message->emm.service_request); + if (rv != OGS_OK) { + ogs_error("emm_handle_service_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } - if (!MME_UE_HAVE_IMSI(mme_ue)) - { - ogs_warn("[EMM] Service request : Unknown UE"); - rv = nas_send_service_reject(mme_ue, - EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); - ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(s, &emm_state_exception); - return; - } + if (!MME_UE_HAVE_IMSI(mme_ue)) { + ogs_warn("[EMM] Service request : Unknown UE"); + rv = nas_send_service_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, &emm_state_exception); + return; + } - if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) - { - ogs_warn("No Security Context : IMSI[%s]", mme_ue->imsi_bcd); - rv = nas_send_service_reject(mme_ue, - EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); - ogs_assert(rv == OGS_OK); + if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) { + ogs_warn("No Security Context : IMSI[%s]", mme_ue->imsi_bcd); + rv = nas_send_service_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + ogs_assert(rv == OGS_OK); - rv = s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0); - ogs_assert(rv == OGS_OK); - return; - } - - rv = s1ap_send_initial_context_setup_request(mme_ue); + rv = s1ap_send_ue_context_release_command(enb_ue, + S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, + S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0); ogs_assert(rv == OGS_OK); return; } - switch(message->emm.h.message_type) - { - case NAS_IDENTITY_RESPONSE: - { - ogs_debug("[EMM] Identity response"); - rv = emm_handle_identity_response(mme_ue, - &message->emm.identity_response); - if (rv != OGS_OK) - { - ogs_error("emm_handle_identity_response() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - if (!MME_UE_HAVE_IMSI(mme_ue)) - { - ogs_error("No IMSI"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - break; - } - case NAS_ATTACH_REQUEST: - { - ogs_debug("[EMM] Attach request[%s]", mme_ue->imsi_bcd); - rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - break; - } - case NAS_TRACKING_AREA_UPDATE_REQUEST: - { - ogs_debug("[EMM] Tracking area update request"); - rv = emm_handle_tau_request( - mme_ue, &message->emm.tracking_area_update_request); - if (rv != OGS_OK) - { - ogs_error("emm_handle_tau_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - if (!MME_UE_HAVE_IMSI(mme_ue)) - { - ogs_warn("[EMM] TAU request : Unknown UE"); - rv = nas_send_tau_reject(mme_ue, - EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); - ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(s, &emm_state_exception); - return; - } - - break; - } - case NAS_TRACKING_AREA_UPDATE_COMPLETE: - { - ogs_debug("[EMM] Tracking area update complete"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - return; - } - case NAS_EMM_STATUS: - { - ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", - mme_ue->imsi_bcd, - message->emm.emm_status.emm_cause); - OGS_FSM_TRAN(s, &emm_state_exception); - return; - } - case NAS_DETACH_REQUEST: - { - ogs_debug("[EMM] Detach request"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - rv = emm_handle_detach_request( - mme_ue, &message->emm.detach_request_from_ue); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); - - OGS_FSM_TRAN(s, &emm_state_de_registered); - return; - } - default: - { - ogs_warn("Unknown message[%d]", message->emm.h.message_type); - return; - } - } - break; - } - default: - { - ogs_error("Unknown event[%s]", mme_event_get_name(e)); + rv = s1ap_send_initial_context_setup_request(mme_ue); + ogs_assert(rv == OGS_OK); return; } + + switch (message->emm.h.message_type) { + case NAS_IDENTITY_RESPONSE: + ogs_debug("[EMM] Identity response"); + rv = emm_handle_identity_response(mme_ue, + &message->emm.identity_response); + if (rv != OGS_OK) { + ogs_error("emm_handle_identity_response() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + if (!MME_UE_HAVE_IMSI(mme_ue)) { + ogs_error("No IMSI"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + break; + case NAS_ATTACH_REQUEST: + ogs_debug("[EMM] Attach request[%s]", mme_ue->imsi_bcd); + rv = emm_handle_attach_request( + mme_ue, &message->emm.attach_request); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + break; + case NAS_TRACKING_AREA_UPDATE_REQUEST: + ogs_debug("[EMM] Tracking area update request"); + rv = emm_handle_tau_request( + mme_ue, &message->emm.tracking_area_update_request); + if (rv != OGS_OK) { + ogs_error("emm_handle_tau_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + if (!MME_UE_HAVE_IMSI(mme_ue)) { + ogs_warn("[EMM] TAU request : Unknown UE"); + rv = nas_send_tau_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, &emm_state_exception); + return; + } + + break; + case NAS_TRACKING_AREA_UPDATE_COMPLETE: + ogs_debug("[EMM] Tracking area update complete"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + return; + case NAS_EMM_STATUS: + ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", + mme_ue->imsi_bcd, + message->emm.emm_status.emm_cause); + OGS_FSM_TRAN(s, &emm_state_exception); + return; + case NAS_DETACH_REQUEST: + ogs_debug("[EMM] Detach request"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + rv = emm_handle_detach_request( + mme_ue, &message->emm.detach_request_from_ue); + if (rv != OGS_OK) + { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + rv = mme_send_delete_session_or_detach(mme_ue); + ogs_assert(rv == OGS_OK); + + OGS_FSM_TRAN(s, &emm_state_de_registered); + return; + default: + ogs_warn("Unknown message[%d]", message->emm.h.message_type); + return; + } + break; + default: + ogs_error("Unknown event[%s]", mme_event_get_name(e)); + return; } - if (!MME_UE_HAVE_IMSI(mme_ue)) - { + if (!MME_UE_HAVE_IMSI(mme_ue)) { rv = nas_send_identity_request(mme_ue); ogs_assert(rv == OGS_OK); return; @@ -247,91 +234,70 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) enb_ue = mme_ue->enb_ue; ogs_assert(enb_ue); - switch(mme_ue->nas_eps.type) - { - case MME_EPS_TYPE_ATTACH_REQUEST: - { - if (SECURITY_CONTEXT_IS_VALID(mme_ue)) - { - rv = nas_send_emm_to_esm(mme_ue, - &mme_ue->pdn_connectivity_request); + switch (mme_ue->nas_eps.type) { + case MME_EPS_TYPE_ATTACH_REQUEST: + if (SECURITY_CONTEXT_IS_VALID(mme_ue)) { + rv = nas_send_emm_to_esm(mme_ue, + &mme_ue->pdn_connectivity_request); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, &emm_state_initial_context_setup); + } else { + if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + rv = mme_gtp_send_delete_all_sessions(mme_ue); ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(s, &emm_state_initial_context_setup); - } - else - { - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) - { - rv = mme_gtp_send_delete_all_sessions(mme_ue); - ogs_assert(rv == OGS_OK); - } - else - { - mme_s6a_send_air(mme_ue, NULL); - } - OGS_FSM_TRAN(s, &emm_state_authentication); + } else { + mme_s6a_send_air(mme_ue, NULL); } + OGS_FSM_TRAN(s, &emm_state_authentication); + } + break; + case MME_EPS_TYPE_TAU_REQUEST: + procedureCode = e->s1ap_code; + + if (!SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + ogs_warn("No PDN Connection : UE[%s]", mme_ue->imsi_bcd); + rv = nas_send_tau_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, emm_state_exception); break; } - case MME_EPS_TYPE_TAU_REQUEST: - { - S1AP_ProcedureCode_t procedureCode = e->s1ap_code; - if (!SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) - { - ogs_warn("No PDN Connection : UE[%s]", mme_ue->imsi_bcd); - rv = nas_send_tau_reject(mme_ue, - EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) { + mme_s6a_send_air(mme_ue, NULL); + OGS_FSM_TRAN(&mme_ue->sm, &emm_state_authentication); + break; + } + + if (procedureCode == S1AP_ProcedureCode_id_initialUEMessage) { + ogs_debug(" Iniital UE Message"); + if (mme_ue->nas_eps.update.active_flag) { + rv = nas_send_tau_accept(mme_ue, + S1AP_ProcedureCode_id_InitialContextSetup); ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(s, emm_state_exception); - break; - } - - if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) - { - mme_s6a_send_air(mme_ue, NULL); - OGS_FSM_TRAN(&mme_ue->sm, &emm_state_authentication); - break; - } - - if (procedureCode == S1AP_ProcedureCode_id_initialUEMessage) - { - ogs_debug(" Iniital UE Message"); - if (mme_ue->nas_eps.update.active_flag) - { - rv = nas_send_tau_accept(mme_ue, - S1AP_ProcedureCode_id_InitialContextSetup); - ogs_assert(rv == OGS_OK); - } - else - { - rv = nas_send_tau_accept(mme_ue, - S1AP_ProcedureCode_id_downlinkNASTransport); - ogs_assert(rv == OGS_OK); - - rv = mme_send_release_access_bearer_or_ue_context_release( - mme_ue, enb_ue); - ogs_assert(rv == OGS_OK); - } - } - else if (procedureCode == S1AP_ProcedureCode_id_uplinkNASTransport) - { - ogs_debug(" Uplink NAS Transport"); + } else { rv = nas_send_tau_accept(mme_ue, S1AP_ProcedureCode_id_downlinkNASTransport); ogs_assert(rv == OGS_OK); + + rv = mme_send_release_access_bearer_or_ue_context_release( + mme_ue, enb_ue); + ogs_assert(rv == OGS_OK); } - else - { - ogs_fatal("Invalid Procedure Code[%d]", (int)procedureCode); - ogs_assert_if_reached(); - } - break; - } - default: - ogs_fatal("Invalid NAS-EPS[%d]", mme_ue->nas_eps.type); + } else if (procedureCode == S1AP_ProcedureCode_id_uplinkNASTransport) { + ogs_debug(" Uplink NAS Transport"); + rv = nas_send_tau_accept(mme_ue, + S1AP_ProcedureCode_id_downlinkNASTransport); + ogs_assert(rv == OGS_OK); + } else { + ogs_fatal("Invalid Procedure Code[%d]", (int)procedureCode); ogs_assert_if_reached(); - break; + } + break; + default: + ogs_fatal("Invalid NAS-EPS[%d]", mme_ue->nas_eps.type); + ogs_assert_if_reached(); + break; } } @@ -339,6 +305,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e) { int rv; mme_ue_t *mme_ue = NULL; + nas_message_t *message = NULL; ogs_assert(s); ogs_assert(e); @@ -348,149 +315,125 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e) mme_ue = e->mme_ue; ogs_assert(mme_ue); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_EMM_MESSAGE: + message = e->nas_message; + ogs_assert(message); + + switch (message->emm.h.message_type) { + case NAS_AUTHENTICATION_RESPONSE: { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - case MME_EVT_EMM_MESSAGE: - { - nas_message_t *message = e->nas_message; - ogs_assert(message); + nas_authentication_response_t *authentication_response = + &message->emm.authentication_response; + nas_authentication_response_parameter_t + *authentication_response_parameter = + &authentication_response-> + authentication_response_parameter; - switch(message->emm.h.message_type) - { - case NAS_AUTHENTICATION_RESPONSE: - { - nas_authentication_response_t *authentication_response = - &message->emm.authentication_response; - nas_authentication_response_parameter_t - *authentication_response_parameter = - &authentication_response-> - authentication_response_parameter; + ogs_debug("[EMM] Authentication response"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - ogs_debug("[EMM] Authentication response"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - - if (memcmp(authentication_response_parameter->res, - mme_ue->xres, - authentication_response_parameter->length) != 0) - { - ogs_log_hexdump(OGS_LOG_WARN, - authentication_response_parameter->res, - authentication_response_parameter->length); - ogs_log_hexdump(OGS_LOG_WARN, - mme_ue->xres, MAX_RES_LEN); - rv = nas_send_authentication_reject(mme_ue); - ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception); - } - else - { - OGS_FSM_TRAN(&mme_ue->sm, &emm_state_security_mode); - } - break; - } - case NAS_AUTHENTICATION_FAILURE: - { - nas_authentication_failure_t *authentication_failure = - &message->emm.authentication_failure; - nas_authentication_failure_parameter_t - *authentication_failure_parameter = - &authentication_failure-> - authentication_failure_parameter; - - ogs_debug("[EMM] Authentication failure"); - ogs_debug(" IMSI[%s] EMM_CAUSE[%d]", mme_ue->imsi_bcd, - authentication_failure->emm_cause); - - switch(authentication_failure->emm_cause) - { - case EMM_CAUSE_MAC_FAILURE: - ogs_warn("Authentication failure(MAC failure)"); - break; - case EMM_CAUSE_NON_EPS_AUTHENTICATION_UNACCEPTABLE: - ogs_error("Authentication failure" - "(Non-EPS authentication unacceptable)"); - break; - case EMM_CAUSE_SYNCH_FAILURE: - ogs_warn("Authentication failure(Synch failure)"); - mme_s6a_send_air(mme_ue, - authentication_failure_parameter); - return; - default: - ogs_error("Unknown EMM_CAUSE{%d] in Authentication" - " failure", - authentication_failure->emm_cause); - break; - } - - rv = nas_send_authentication_reject(mme_ue); - ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception); - break; - } - case NAS_ATTACH_REQUEST: - { - ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); - rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - mme_s6a_send_air(mme_ue, NULL); - OGS_FSM_TRAN(s, &emm_state_authentication); - break; - } - case NAS_EMM_STATUS: - { - ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", - mme_ue->imsi_bcd, - message->emm.emm_status.emm_cause); - OGS_FSM_TRAN(s, &emm_state_exception); - break; - } - case NAS_DETACH_REQUEST: - { - ogs_debug("[EMM] Detach request"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - rv = emm_handle_detach_request( - mme_ue, &message->emm.detach_request_from_ue); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); - - OGS_FSM_TRAN(s, &emm_state_de_registered); - break; - } - default: - { - ogs_warn("Unknown message[%d]", message->emm.h.message_type); - break; - } + if (memcmp(authentication_response_parameter->res, + mme_ue->xres, + authentication_response_parameter->length) != 0) { + ogs_log_hexdump(OGS_LOG_WARN, + authentication_response_parameter->res, + authentication_response_parameter->length); + ogs_log_hexdump(OGS_LOG_WARN, + mme_ue->xres, MAX_RES_LEN); + rv = nas_send_authentication_reject(mme_ue); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception); + } else { + OGS_FSM_TRAN(&mme_ue->sm, &emm_state_security_mode); } break; } - default: + case NAS_AUTHENTICATION_FAILURE: { - ogs_error("Unknown event[%s]", mme_event_get_name(e)); + nas_authentication_failure_t *authentication_failure = + &message->emm.authentication_failure; + nas_authentication_failure_parameter_t + *authentication_failure_parameter = + &authentication_failure-> + authentication_failure_parameter; + + ogs_debug("[EMM] Authentication failure"); + ogs_debug(" IMSI[%s] EMM_CAUSE[%d]", mme_ue->imsi_bcd, + authentication_failure->emm_cause); + + switch (authentication_failure->emm_cause) { + case EMM_CAUSE_MAC_FAILURE: + ogs_warn("Authentication failure(MAC failure)"); + break; + case EMM_CAUSE_NON_EPS_AUTHENTICATION_UNACCEPTABLE: + ogs_error("Authentication failure" + "(Non-EPS authentication unacceptable)"); + break; + case EMM_CAUSE_SYNCH_FAILURE: + ogs_warn("Authentication failure(Synch failure)"); + mme_s6a_send_air(mme_ue, + authentication_failure_parameter); + return; + default: + ogs_error("Unknown EMM_CAUSE{%d] in Authentication" + " failure", + authentication_failure->emm_cause); + break; + } + + rv = nas_send_authentication_reject(mme_ue); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception); break; } + case NAS_ATTACH_REQUEST: + ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); + rv = emm_handle_attach_request( + mme_ue, &message->emm.attach_request); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + mme_s6a_send_air(mme_ue, NULL); + OGS_FSM_TRAN(s, &emm_state_authentication); + break; + case NAS_EMM_STATUS: + ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", + mme_ue->imsi_bcd, + message->emm.emm_status.emm_cause); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + case NAS_DETACH_REQUEST: + ogs_debug("[EMM] Detach request"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + rv = emm_handle_detach_request( + mme_ue, &message->emm.detach_request_from_ue); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + rv = mme_send_delete_session_or_detach(mme_ue); + ogs_assert(rv == OGS_OK); + + OGS_FSM_TRAN(s, &emm_state_de_registered); + break; + default: + ogs_warn("Unknown message[%d]", message->emm.h.message_type); + break; + } + break; + default: + ogs_error("Unknown event[%s]", mme_event_get_name(e)); + break; } } @@ -498,6 +441,8 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e) { int rv; mme_ue_t *mme_ue = NULL; + ogs_pkbuf_t *emmbuf = NULL; + nas_message_t *message = NULL; ogs_assert(s); ogs_assert(e); @@ -507,127 +452,95 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e) mme_ue = e->mme_ue; ogs_assert(mme_ue); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - ogs_pkbuf_t *emmbuf = NULL; + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + rv = emm_build_security_mode_command(&emmbuf, mme_ue); + ogs_assert(rv == OGS_OK && emmbuf); - rv = emm_build_security_mode_command(&emmbuf, mme_ue); - ogs_assert(rv == OGS_OK && emmbuf); + rv = nas_send_to_downlink_nas_transport(mme_ue, emmbuf); + ogs_assert(rv == OGS_OK && emmbuf); - rv = nas_send_to_downlink_nas_transport(mme_ue, emmbuf); - ogs_assert(rv == OGS_OK && emmbuf); + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_EMM_MESSAGE: + message = e->nas_message; + ogs_assert(message); - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - case MME_EVT_EMM_MESSAGE: - { - nas_message_t *message = e->nas_message; - ogs_assert(message); + switch (message->emm.h.message_type) { + case NAS_SECURITY_MODE_COMPLETE: + ogs_debug("[EMM] Security mode complete"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - switch(message->emm.h.message_type) - { - case NAS_SECURITY_MODE_COMPLETE: - { - ogs_debug("[EMM] Security mode complete"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + /* Update Kenb */ + if (SECURITY_CONTEXT_IS_VALID(mme_ue)) { + mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32, + mme_ue->kenb); + mme_kdf_nh(mme_ue->kasme, mme_ue->kenb, mme_ue->nh); + mme_ue->nhcc = 1; + } - /* Update Kenb */ - if (SECURITY_CONTEXT_IS_VALID(mme_ue)) - { - mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32, - mme_ue->kenb); - mme_kdf_nh(mme_ue->kasme, mme_ue->kenb, mme_ue->nh); - mme_ue->nhcc = 1; - } - - mme_s6a_send_ulr(mme_ue); - if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) - { - OGS_FSM_TRAN(s, &emm_state_initial_context_setup); - } - else if (mme_ue->nas_eps.type == - MME_EPS_TYPE_SERVICE_REQUEST || - mme_ue->nas_eps.type == MME_EPS_TYPE_TAU_REQUEST) - { - OGS_FSM_TRAN(s, &emm_state_registered); - } - else - { - ogs_fatal("Invalid NAS_EPS[%d]", mme_ue->nas_eps.type); - ogs_assert_if_reached(); - } - break; - } - case NAS_SECURITY_MODE_REJECT: - { - ogs_warn("[EMM] Security mode reject : IMSI[%s] Cause[%d]", - mme_ue->imsi_bcd, - message->emm.security_mode_reject.emm_cause); - OGS_FSM_TRAN(s, &emm_state_exception); - break; - } - case NAS_ATTACH_REQUEST: - { - ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); - rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - mme_s6a_send_air(mme_ue, NULL); - OGS_FSM_TRAN(s, &emm_state_authentication); - break; - } - case NAS_EMM_STATUS: - { - ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", - mme_ue->imsi_bcd, - message->emm.emm_status.emm_cause); - OGS_FSM_TRAN(s, &emm_state_exception); - break; - } - case NAS_DETACH_REQUEST: - { - ogs_debug("[EMM] Detach request"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - rv = emm_handle_detach_request( - mme_ue, &message->emm.detach_request_from_ue); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); - - OGS_FSM_TRAN(s, &emm_state_de_registered); - break; - } - default: - { - ogs_warn("Unknown message[%d]", message->emm.h.message_type); - break; - } + mme_s6a_send_ulr(mme_ue); + if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) { + OGS_FSM_TRAN(s, &emm_state_initial_context_setup); + } else if (mme_ue->nas_eps.type == + MME_EPS_TYPE_SERVICE_REQUEST || + mme_ue->nas_eps.type == MME_EPS_TYPE_TAU_REQUEST) { + OGS_FSM_TRAN(s, &emm_state_registered); + } else { + ogs_fatal("Invalid NAS_EPS[%d]", mme_ue->nas_eps.type); + ogs_assert_if_reached(); } break; - } + case NAS_SECURITY_MODE_REJECT: + ogs_warn("[EMM] Security mode reject : IMSI[%s] Cause[%d]", + mme_ue->imsi_bcd, + message->emm.security_mode_reject.emm_cause); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + case NAS_ATTACH_REQUEST: + ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); + rv = emm_handle_attach_request( + mme_ue, &message->emm.attach_request); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + mme_s6a_send_air(mme_ue, NULL); + OGS_FSM_TRAN(s, &emm_state_authentication); + break; + case NAS_EMM_STATUS: + ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", + mme_ue->imsi_bcd, + message->emm.emm_status.emm_cause); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + case NAS_DETACH_REQUEST: + ogs_debug("[EMM] Detach request"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + rv = emm_handle_detach_request( + mme_ue, &message->emm.detach_request_from_ue); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + rv = mme_send_delete_session_or_detach(mme_ue); + ogs_assert(rv == OGS_OK); + + OGS_FSM_TRAN(s, &emm_state_de_registered); + break; default: - { - ogs_error("Unknown event[%s]", mme_event_get_name(e)); + ogs_warn("Unknown message[%d]", message->emm.h.message_type); break; } + break; + default: + ogs_error("Unknown event[%s]", mme_event_get_name(e)); + break; } } @@ -635,6 +548,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) { int rv; mme_ue_t *mme_ue = NULL; + nas_message_t *message = NULL; ogs_assert(s); ogs_assert(e); @@ -644,97 +558,74 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) mme_ue = e->mme_ue; ogs_assert(mme_ue); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - case MME_EVT_EMM_MESSAGE: - { - nas_message_t *message = e->nas_message; - ogs_assert(message); + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_EMM_MESSAGE: + message = e->nas_message; + ogs_assert(message); - switch(message->emm.h.message_type) - { - case NAS_ATTACH_COMPLETE: - { - ogs_debug("[EMM] Attach complete"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - rv = emm_handle_attach_complete( - mme_ue, &message->emm.attach_complete); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_complete() failed " - "in emm_state_initial_context_setup"); - OGS_FSM_TRAN(s, emm_state_exception); - break; - } - OGS_FSM_TRAN(s, &emm_state_registered); - break; - } - case NAS_ATTACH_REQUEST: - { - ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); - rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - rv = mme_gtp_send_delete_all_sessions(mme_ue); - ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(s, &emm_state_authentication); - break; - } - case NAS_EMM_STATUS: - { - ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", - mme_ue->imsi_bcd, - message->emm.emm_status.emm_cause); - OGS_FSM_TRAN(s, &emm_state_exception); - break; - } - case NAS_DETACH_REQUEST: - { - ogs_debug("[EMM] Detach request"); - ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - rv = emm_handle_detach_request( - mme_ue, &message->emm.detach_request_from_ue); - if (rv != OGS_OK) - { - ogs_error("emm_handle_attach_request() failed"); - OGS_FSM_TRAN(s, emm_state_exception); - return; - } - - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); - - OGS_FSM_TRAN(s, &emm_state_de_registered); - break; - } - default: - { - ogs_warn("Unknown message[%d]", - message->emm.h.message_type); - break; - } + switch (message->emm.h.message_type) { + case NAS_ATTACH_COMPLETE: + ogs_debug("[EMM] Attach complete"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + rv = emm_handle_attach_complete( + mme_ue, &message->emm.attach_complete); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_complete() failed " + "in emm_state_initial_context_setup"); + OGS_FSM_TRAN(s, emm_state_exception); + break; } + OGS_FSM_TRAN(s, &emm_state_registered); + break; + case NAS_ATTACH_REQUEST: + ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); + rv = emm_handle_attach_request( + mme_ue, &message->emm.attach_request); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + rv = mme_gtp_send_delete_all_sessions(mme_ue); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, &emm_state_authentication); + break; + case NAS_EMM_STATUS: + ogs_warn("[EMM] EMM STATUS : IMSI[%s] Cause[%d]", + mme_ue->imsi_bcd, + message->emm.emm_status.emm_cause); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + case NAS_DETACH_REQUEST: + ogs_debug("[EMM] Detach request"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + rv = emm_handle_detach_request( + mme_ue, &message->emm.detach_request_from_ue); + if (rv != OGS_OK) { + ogs_error("emm_handle_attach_request() failed"); + OGS_FSM_TRAN(s, emm_state_exception); + return; + } + + rv = mme_send_delete_session_or_detach(mme_ue); + ogs_assert(rv == OGS_OK); + + OGS_FSM_TRAN(s, &emm_state_de_registered); break; - } default: - { - ogs_error("Unknown event[%s]", mme_event_get_name(e)); + ogs_warn("Unknown message[%d]", + message->emm.h.message_type); break; } + break; + default: + ogs_error("Unknown event[%s]", mme_event_get_name(e)); + break; } } @@ -743,20 +634,13 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) ogs_assert(e); mme_sm_debug(e); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - default: - { - ogs_error("Unknown event[%s]", mme_event_get_name(e)); - break; - } + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + default: + ogs_error("Unknown event[%s]", mme_event_get_name(e)); + break; } } diff --git a/src/mme/esm-build.c b/src/mme/esm-build.c index 042f0cb25..946e3a801 100644 --- a/src/mme/esm-build.c +++ b/src/mme/esm-build.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "nas/nas-message.h" #include "nas-security.h" @@ -24,8 +43,7 @@ int esm_build_pdn_connectivity_reject( mme_ue->imsi_bcd, sess->pti, esm_cause); memset(&message, 0, sizeof(message)); - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) - { + if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { message.h.security_header_type = NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; @@ -37,13 +55,10 @@ int esm_build_pdn_connectivity_reject( pdn_connectivity_reject->esm_cause = esm_cause; - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) - { + if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { ogs_assert(nas_security_encode(pkbuf, mme_ue, &message) == OGS_OK && *pkbuf); - } - else - { + } else { ogs_assert(nas_plain_encode(pkbuf, &message) == OGS_OK && *pkbuf); } @@ -118,8 +133,7 @@ int esm_build_activate_default_bearer_context_request( mme_ue->imsi_bcd, sess->pti, bearer->ebi); memset(&message, 0, sizeof(message)); - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) - { + if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { message.h.security_header_type = NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; @@ -142,38 +156,30 @@ int esm_build_activate_default_bearer_context_request( ogs_debug(" APN[%s]", pdn->apn); pdn_address->pdn_type = pdn->paa.pdn_type; - if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV4) - { + if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV4) { pdn_address->addr = pdn->paa.addr; pdn_address->length = NAS_PDN_ADDRESS_IPV4_LEN; ogs_debug(" IPv4"); - } - else if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV6) - { + } else if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV6) { memcpy(pdn_address->addr6, pdn->paa.addr6+(IPV6_LEN>>1), IPV6_LEN>>1); pdn_address->length = NAS_PDN_ADDRESS_IPV6_LEN; ogs_debug(" IPv6"); - } - else if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV4V6) - { + } else if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV4V6) { pdn_address->both.addr = pdn->paa.both.addr; memcpy(pdn_address->both.addr6, pdn->paa.both.addr6+(IPV6_LEN>>1), IPV6_LEN>>1); pdn_address->length = NAS_PDN_ADDRESS_IPV4V6_LEN; ogs_debug(" IPv4v6"); - } - else + } else ogs_assert_if_reached(); - if (pdn->ambr.downlink || pdn->ambr.uplink) - { + if (pdn->ambr.downlink || pdn->ambr.uplink) { activate_default_eps_bearer_context_request->presencemask |= NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT; apn_ambr_build(apn_ambr, pdn->ambr.downlink, pdn->ambr.uplink); } - if (sess->pgw_pco.presence && sess->pgw_pco.len && sess->pgw_pco.data) - { + if (sess->pgw_pco.presence && sess->pgw_pco.len && sess->pgw_pco.data) { activate_default_eps_bearer_context_request->presencemask |= NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; protocol_configuration_options->length = sess->pgw_pco.len; @@ -181,13 +187,10 @@ int esm_build_activate_default_bearer_context_request( sess->pgw_pco.data, protocol_configuration_options->length); } - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) - { + if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { ogs_assert(nas_security_encode(pkbuf, mme_ue, &message) == OGS_OK && *pkbuf); - } - else - { + } else { ogs_assert(nas_plain_encode(pkbuf, &message) == OGS_OK && *pkbuf); } @@ -282,8 +285,7 @@ int esm_build_modify_bearer_context_request( message.esm.h.procedure_transaction_identity = sess->pti; message.esm.h.message_type = NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST; - if (qos_presence == 1) - { + if (qos_presence == 1) { modify_eps_bearer_context_request->presencemask |= NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_PRESENT; eps_qos_build(new_eps_qos, bearer->qos.qci, @@ -291,8 +293,7 @@ int esm_build_modify_bearer_context_request( bearer->qos.gbr.downlink, bearer->qos.gbr.uplink); } - if (tft_presence == 1) - { + if (tft_presence == 1) { modify_eps_bearer_context_request->presencemask |= NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_PRESENT; tft->length = bearer->tft.len; diff --git a/src/mme/esm-build.h b/src/mme/esm-build.h index 0e175182f..1398c88f3 100644 --- a/src/mme/esm-build.h +++ b/src/mme/esm-build.h @@ -1,11 +1,30 @@ -#ifndef __ESM_BUILD_H__ -#define __ESM_BUILD_H__ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ESM_BUILD_H +#define ESM_BUILD_H #include "mme-context.h" #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif int esm_build_pdn_connectivity_reject(ogs_pkbuf_t **pkbuf, mme_sess_t *sess, nas_esm_cause_t esm_cause); @@ -22,6 +41,6 @@ int esm_build_deactivate_bearer_context_request( #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif -#endif /* __ESM_BUILD_H__ */ +#endif /* ESM_BUILD_H */ diff --git a/src/mme/esm-handler.c b/src/mme/esm-handler.c index b33e6ebd0..585ed6e26 100644 --- a/src/mme/esm-handler.c +++ b/src/mme/esm-handler.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "nas/nas-message.h" #include "mme-context.h" @@ -34,8 +53,7 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer, security_protected_required = 0; if (pdn_connectivity_request->presencemask & - NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT) - { + NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT) { nas_esm_information_transfer_flag_t *esm_information_transfer_flag = &pdn_connectivity_request->esm_information_transfer_flag; security_protected_required = @@ -45,12 +63,10 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer, } if (pdn_connectivity_request->presencemask & - NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT) - { + NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT) { sess->pdn = mme_pdn_find_by_apn(mme_ue, pdn_connectivity_request->access_point_name.apn); - if (!sess->pdn) - { + if (!sess->pdn) { /* Invalid APN */ rv = nas_send_pdn_connectivity_reject( sess, ESM_CAUSE_MISSING_OR_UNKNOWN_APN); @@ -61,36 +77,30 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer, } if (pdn_connectivity_request->presencemask & - NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { nas_protocol_configuration_options_t *protocol_configuration_options = &pdn_connectivity_request->protocol_configuration_options; NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options); } - if (security_protected_required) - { + if (security_protected_required) { rv = nas_send_esm_information_request(bearer); ogs_assert(rv == OGS_OK); return OGS_OK; } - if (!sess->pdn) - { + if (!sess->pdn) { /* Default APN */ sess->pdn = mme_default_pdn(mme_ue); } - if (sess->pdn) - { + if (sess->pdn) { ogs_debug(" APN[%s]", sess->pdn->apn); rv = mme_gtp_send_create_session_request(sess); ogs_assert(rv == OGS_OK); - } - else - { + } else { rv = nas_send_pdn_connectivity_reject( sess, ESM_CAUSE_MISSING_OR_UNKNOWN_APN); ogs_assert(rv == OGS_OK); @@ -112,25 +122,21 @@ int esm_handle_information_response(mme_sess_t *sess, ogs_assert(mme_ue); if (esm_information_response->presencemask & - NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT) - { + NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT) { sess->pdn = mme_pdn_find_by_apn(mme_ue, esm_information_response->access_point_name.apn); } if (esm_information_response->presencemask & - NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { nas_protocol_configuration_options_t *protocol_configuration_options = &esm_information_response->protocol_configuration_options; NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options); } - if (sess->pdn) - { + if (sess->pdn) { ogs_debug(" APN[%s]", sess->pdn->apn); - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) - { + if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { mme_vlr_t *vlr = mme_vlr_find_by_tai(&mme_ue->tai); mme_ue->vlr = vlr; @@ -138,15 +144,11 @@ int esm_handle_information_response(mme_sess_t *sess, sgsap_send_location_update_request(mme_ue); else nas_send_attach_accept(mme_ue); - } - else - { + } else { rv = mme_gtp_send_create_session_request(sess); ogs_assert(rv == OGS_OK); } - } - else - { + } else { rv = nas_send_pdn_connectivity_reject( sess, ESM_CAUSE_MISSING_OR_UNKNOWN_APN); ogs_assert(rv == OGS_OK); diff --git a/src/mme/esm-handler.h b/src/mme/esm-handler.h index 2ac590d72..8b3ed1a87 100644 --- a/src/mme/esm-handler.h +++ b/src/mme/esm-handler.h @@ -1,5 +1,24 @@ -#ifndef __ESM_HANDLER_H__ -#define __ESM_HANDLER_H__ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ESM_HANDLER_H +#define ESM_HANDLER_H #include "nas/nas-message.h" @@ -7,7 +26,7 @@ #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer, nas_pdn_connectivity_request_t *pdn_connectivity_request); @@ -16,6 +35,6 @@ int esm_handle_information_response(mme_sess_t *sess, #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif -#endif /* __ESM_HANDLER_H__ */ +#endif /* ESM_HANDLER_H */ diff --git a/src/mme/esm-sm.c b/src/mme/esm-sm.c index 63d13b124..fff7acb34 100644 --- a/src/mme/esm-sm.c +++ b/src/mme/esm-sm.c @@ -1,5 +1,23 @@ -#include "nas/nas-message.h" +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "nas/nas-message.h" #include "mme-event.h" #include "mme-sm.h" #include "mme-fd-path.h" @@ -35,6 +53,7 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) mme_ue_t *mme_ue = NULL; mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + nas_message_t *message = NULL; ogs_assert(s); ogs_assert(e); @@ -48,103 +67,78 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) mme_ue = sess->mme_ue; ogs_assert(mme_ue); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - case MME_EVT_ESM_MESSAGE: - { - nas_message_t *message = e->nas_message; - ogs_assert(message); + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_ESM_MESSAGE: + message = e->nas_message; + ogs_assert(message); - switch(message->esm.h.message_type) - { - case NAS_PDN_CONNECTIVITY_REQUEST: - { - ogs_debug("[ESM] PDN Connectivity request"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - rv = esm_handle_pdn_connectivity_request( - bearer, &message->esm.pdn_connectivity_request); - if (rv != OGS_OK) - { - OGS_FSM_TRAN(s, esm_state_exception); - break; - } - break; - } - case NAS_ESM_INFORMATION_RESPONSE: - { - ogs_debug("[ESM] ESM information response"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - rv = esm_handle_information_response( - sess, &message->esm.esm_information_response); - if (rv != OGS_OK) - { - OGS_FSM_TRAN(s, esm_state_exception); - break; - } - break; - } - case NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: - { - ogs_debug("[ESM] Activate default EPS bearer " - "context accept"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - /* Check if Initial Context Setup Response or - * E-RAB Setup Response is received */ - if (MME_HAVE_ENB_S1U_PATH(bearer)) - { - rv = mme_gtp_send_modify_bearer_request(bearer, 0); - ogs_assert(rv == OGS_OK); - } - - rv = nas_send_activate_all_dedicated_bearers(bearer); - ogs_assert(rv == OGS_OK); - - OGS_FSM_TRAN(s, esm_state_active); - break; - } - case NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: - { - ogs_debug("[ESM] Activate dedicated EPS bearer " - "context accept"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - /* Check if Initial Context Setup Response or - * E-RAB Setup Response is received */ - if (MME_HAVE_ENB_S1U_PATH(bearer)) - { - rv = mme_gtp_send_create_bearer_response(bearer); - ogs_assert(rv == OGS_OK); - } - - OGS_FSM_TRAN(s, esm_state_active); - break; - } - default: - { - ogs_error("Unknown message(type:%d)", - message->esm.h.message_type); - break; - } + switch (message->esm.h.message_type) { + case NAS_PDN_CONNECTIVITY_REQUEST: + ogs_debug("[ESM] PDN Connectivity request"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + rv = esm_handle_pdn_connectivity_request( + bearer, &message->esm.pdn_connectivity_request); + if (rv != OGS_OK) { + OGS_FSM_TRAN(s, esm_state_exception); + break; } break; - } + case NAS_ESM_INFORMATION_RESPONSE: + ogs_debug("[ESM] ESM information response"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + rv = esm_handle_information_response( + sess, &message->esm.esm_information_response); + if (rv != OGS_OK) { + OGS_FSM_TRAN(s, esm_state_exception); + break; + } + break; + case NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: + ogs_debug("[ESM] Activate default EPS bearer " + "context accept"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + /* Check if Initial Context Setup Response or + * E-RAB Setup Response is received */ + if (MME_HAVE_ENB_S1U_PATH(bearer)) { + rv = mme_gtp_send_modify_bearer_request(bearer, 0); + ogs_assert(rv == OGS_OK); + } + rv = nas_send_activate_all_dedicated_bearers(bearer); + ogs_assert(rv == OGS_OK); + + OGS_FSM_TRAN(s, esm_state_active); + break; + case NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: + ogs_debug("[ESM] Activate dedicated EPS bearer " + "context accept"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + /* Check if Initial Context Setup Response or + * E-RAB Setup Response is received */ + if (MME_HAVE_ENB_S1U_PATH(bearer)) { + rv = mme_gtp_send_create_bearer_response(bearer); + ogs_assert(rv == OGS_OK); + } + + OGS_FSM_TRAN(s, esm_state_active); + break; default: - { - ogs_error("Unknown event %s", mme_event_get_name(e)); + ogs_error("Unknown message(type:%d)", + message->esm.h.message_type); break; } + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; } } @@ -154,6 +148,7 @@ void esm_state_active(ogs_fsm_t *s, mme_event_t *e) mme_ue_t *mme_ue = NULL; mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + nas_message_t *message = NULL; ogs_assert(s); ogs_assert(e); @@ -167,93 +162,68 @@ void esm_state_active(ogs_fsm_t *s, mme_event_t *e) mme_ue = sess->mme_ue; ogs_assert(mme_ue); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - case MME_EVT_ESM_MESSAGE: - { - nas_message_t *message = e->nas_message; - ogs_assert(message); + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_ESM_MESSAGE: + message = e->nas_message; + ogs_assert(message); - switch(message->esm.h.message_type) - { - case NAS_PDN_CONNECTIVITY_REQUEST: - { - ogs_debug("[ESM] PDN Connectivity request"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - rv = esm_handle_pdn_connectivity_request( - bearer, &message->esm.pdn_connectivity_request); - if (rv != OGS_OK) - { - OGS_FSM_TRAN(s, esm_state_exception); - break; - } - - OGS_FSM_TRAN(s, esm_state_inactive); - break; - } - case NAS_PDN_DISCONNECT_REQUEST: - { - ogs_debug("[ESM] PDN disconnect request"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - if (MME_HAVE_SGW_S1U_PATH(sess)) - { - rv = mme_gtp_send_delete_session_request(sess); - ogs_assert(rv == OGS_OK); - } - else - { - rv = nas_send_deactivate_bearer_context_request(bearer); - ogs_assert(rv == OGS_OK); - } - OGS_FSM_TRAN(s, esm_state_pdn_will_disconnect); - break; - } - case NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: - { - ogs_debug("[ESM] Modify EPS bearer context accept"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - - rv = mme_gtp_send_update_bearer_response(bearer); - ogs_assert(rv == OGS_OK); - break; - } - case NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: - { - ogs_debug("[ESM] [A] Deactivate EPS bearer " - "context accept"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - rv = mme_gtp_send_delete_bearer_response(bearer); - ogs_assert(rv == OGS_OK); - OGS_FSM_TRAN(s, esm_state_bearer_deactivated); - break; - } - default: - { - ogs_error("Unknown message(type:%d)", - message->esm.h.message_type); - break; - } + switch (message->esm.h.message_type) { + case NAS_PDN_CONNECTIVITY_REQUEST: + ogs_debug("[ESM] PDN Connectivity request"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + rv = esm_handle_pdn_connectivity_request( + bearer, &message->esm.pdn_connectivity_request); + if (rv != OGS_OK) { + OGS_FSM_TRAN(s, esm_state_exception); + break; } - break; - } + OGS_FSM_TRAN(s, esm_state_inactive); + break; + case NAS_PDN_DISCONNECT_REQUEST: + ogs_debug("[ESM] PDN disconnect request"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + if (MME_HAVE_SGW_S1U_PATH(sess)) { + rv = mme_gtp_send_delete_session_request(sess); + ogs_assert(rv == OGS_OK); + } else { + rv = nas_send_deactivate_bearer_context_request(bearer); + ogs_assert(rv == OGS_OK); + } + OGS_FSM_TRAN(s, esm_state_pdn_will_disconnect); + break; + case NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: + ogs_debug("[ESM] Modify EPS bearer context accept"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + + rv = mme_gtp_send_update_bearer_response(bearer); + ogs_assert(rv == OGS_OK); + break; + case NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: + ogs_debug("[ESM] [A] Deactivate EPS bearer " + "context accept"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + rv = mme_gtp_send_delete_bearer_response(bearer); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, esm_state_bearer_deactivated); + break; default: - { - ogs_error("Unknown event %s", mme_event_get_name(e)); + ogs_error("Unknown message(type:%d)", + message->esm.h.message_type); break; } + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; } } @@ -262,6 +232,7 @@ void esm_state_pdn_will_disconnect(ogs_fsm_t *s, mme_event_t *e) mme_ue_t *mme_ue = NULL; mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + nas_message_t *message = NULL; ogs_assert(s); ogs_assert(e); @@ -275,47 +246,33 @@ void esm_state_pdn_will_disconnect(ogs_fsm_t *s, mme_event_t *e) mme_ue = sess->mme_ue; ogs_assert(mme_ue); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - case MME_EVT_ESM_MESSAGE: - { - nas_message_t *message = e->nas_message; - ogs_assert(message); + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + case MME_EVT_ESM_MESSAGE: + message = e->nas_message; + ogs_assert(message); - switch(message->esm.h.message_type) - { - case NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: - { - ogs_debug("[ESM] [D] Deactivate EPS bearer " - "context accept"); - ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", - mme_ue->imsi_bcd, sess->pti, bearer->ebi); - OGS_FSM_TRAN(s, esm_state_pdn_did_disconnect); - break; - } - default: - { - ogs_error("Unknown message(type:%d)", - message->esm.h.message_type); - break; - } - } + switch (message->esm.h.message_type) { + case NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: + ogs_debug("[ESM] [D] Deactivate EPS bearer " + "context accept"); + ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + OGS_FSM_TRAN(s, esm_state_pdn_did_disconnect); break; - } - default: - { - ogs_error("Unknown event %s", mme_event_get_name(e)); + ogs_error("Unknown message(type:%d)", + message->esm.h.message_type); break; } + break; + + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; } } @@ -324,21 +281,14 @@ void esm_state_pdn_did_disconnect(ogs_fsm_t *s, mme_event_t *e) ogs_assert(e); mme_sm_debug(e); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - default: - { - ogs_error("Unknown event %s", mme_event_get_name(e)); - break; - } + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; } } @@ -347,21 +297,14 @@ void esm_state_bearer_deactivated(ogs_fsm_t *s, mme_event_t *e) ogs_assert(e); mme_sm_debug(e); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - default: - { - ogs_error("Unknown event %s", mme_event_get_name(e)); - break; - } + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; } } @@ -370,20 +313,13 @@ void esm_state_exception(ogs_fsm_t *s, mme_event_t *e) ogs_assert(e); mme_sm_debug(e); - switch (e->id) - { - case OGS_FSM_ENTRY_SIG: - { - break; - } - case OGS_FSM_EXIT_SIG: - { - break; - } - default: - { - ogs_error("Unknown event %s", mme_event_get_name(e)); - break; - } + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + case OGS_FSM_EXIT_SIG: + break; + default: + ogs_error("Unknown event %s", mme_event_get_name(e)); + break; } }