diff --git a/lib/base/types.c b/lib/base/types.c index 377b1552d..d2a84a347 100644 --- a/lib/base/types.c +++ b/lib/base/types.c @@ -23,11 +23,11 @@ #define PLMN_ID_DIGIT2(x) (((x) / 10) % 10) #define PLMN_ID_DIGIT3(x) ((x) % 10) -uint32_t plmn_id_hexdump(plmn_id_t *plmn_id) +uint32_t plmn_id_hexdump(void *plmn_id) { uint32_t hex; ogs_assert(plmn_id); - memcpy(&hex, plmn_id, sizeof *plmn_id); + memcpy(&hex, plmn_id, sizeof(plmn_id_t)); hex = ntohl(hex) >> 8; return hex; } diff --git a/lib/base/types.h b/lib/base/types.h index 6f97bd2b7..09cccaa87 100644 --- a/lib/base/types.h +++ b/lib/base/types.h @@ -81,7 +81,7 @@ ED2(uint8_t mnc3:4;, uint8_t mnc2:4;) } __attribute__ ((packed)) plmn_id_t; -uint32_t plmn_id_hexdump(plmn_id_t *plmn_id); +uint32_t plmn_id_hexdump(void *plmn_id); uint16_t plmn_id_mcc(plmn_id_t *plmn_id); uint16_t plmn_id_mnc(plmn_id_t *plmn_id); diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index 8f875dc96..5461f7a06 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-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" @@ -64,8 +83,7 @@ int emm_build_attach_accept( mme_ue->guti_present ? "[V]" : "[N]", mme_ue->guti.mme_gid, mme_ue->guti.mme_code, mme_ue->guti.m_tmsi, mme_ue->imsi_bcd); - if (mme_ue->guti_present) - { + if (mme_ue->guti_present) { attach_accept->presencemask |= NAS_ATTACH_ACCEPT_GUTI_PRESENT; nas_guti->length = sizeof(nas_eps_mobile_identity_guti_t); nas_guti->guti.odd_even = NAS_EPS_MOBILE_IDENTITY_EVEN; @@ -98,23 +116,8 @@ int emm_build_attach_accept( NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT; lai->nas_plmn_id = mme_ue->vlr->lai.nas_plmn_id; lai->lac = mme_ue->vlr->lai.lac; - if (lai->nas_plmn_id.mnc3 == 0xf) - ogs_debug(" LAI[MCC:%d%d%d,MNC:%d%d,LAC:%d]", - lai->nas_plmn_id.mcc1, - lai->nas_plmn_id.mcc2, - lai->nas_plmn_id.mcc3, - lai->nas_plmn_id.mnc1, - lai->nas_plmn_id.mnc2, - lai->lac); - else - ogs_debug(" LAI[MCC:%d%d%d,MNC:%d%d%d,LAC:%d]", - lai->nas_plmn_id.mcc1, - lai->nas_plmn_id.mcc2, - lai->nas_plmn_id.mcc3, - lai->nas_plmn_id.mnc1, - lai->nas_plmn_id.mnc2, - lai->nas_plmn_id.mnc3, - lai->lac); + ogs_debug(" LAI[PLMN_ID:%06x,LAC:%d]", + plmn_id_hexdump(&lai->nas_plmn_id), lai->lac); } if (mme_ue->p_tmsi) { @@ -147,8 +150,7 @@ int emm_build_attach_reject( attach_reject->emm_cause = emm_cause; - if (esmbuf) - { + if (esmbuf) { attach_reject->presencemask |= NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT; attach_reject->esm_message_container.buffer = esmbuf->data; @@ -158,8 +160,7 @@ int emm_build_attach_reject( rv = nas_plain_encode(emmbuf, &message); ogs_assert(rv == OGS_OK && *emmbuf); - if (esmbuf) - { + if (esmbuf) { ogs_pkbuf_free(esmbuf); } @@ -263,20 +264,16 @@ int emm_build_security_mode_command( message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; message.emm.h.message_type = NAS_SECURITY_MODE_COMMAND; - for (i = 0; i < mme_self()->num_of_integrity_order; i++) - { + for (i = 0; i < mme_self()->num_of_integrity_order; i++) { if (mme_ue->ue_network_capability.eia & - (0x80 >> mme_self()->integrity_order[i])) - { + (0x80 >> mme_self()->integrity_order[i])) { mme_ue->selected_int_algorithm = mme_self()->integrity_order[i]; break; } } - for (i = 0; i < mme_self()->num_of_ciphering_order; i++) - { + for (i = 0; i < mme_self()->num_of_ciphering_order; i++) { if (mme_ue->ue_network_capability.eea & - (0x80 >> mme_self()->ciphering_order[i])) - { + (0x80 >> mme_self()->ciphering_order[i])) { mme_ue->selected_enc_algorithm = mme_self()->ciphering_order[i]; break; } @@ -325,8 +322,7 @@ int emm_build_security_mode_command( replayed_ue_security_capabilities->gea); ogs_debug(" Selected[Integrity:0x%x Encrypt:0x%x]", mme_ue->selected_int_algorithm, mme_ue->selected_enc_algorithm); - if (mme_ue->selected_int_algorithm == NAS_SECURITY_ALGORITHMS_EIA0) - { + if (mme_ue->selected_int_algorithm == NAS_SECURITY_ALGORITHMS_EIA0) { ogs_fatal("Encrypt[0x%x] can be skipped with EEA0, " "but Integrity[0x%x] cannot be bypassed with EIA0", mme_ue->selected_enc_algorithm, mme_ue->selected_int_algorithm); @@ -420,25 +416,22 @@ int emm_build_tau_accept(ogs_pkbuf_t **emmbuf, mme_ue_t *mme_ue) NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT; tau_accept->eps_bearer_context_status.length = 2; sess = mme_sess_first(mme_ue); - while(sess) - { + while (sess) { mme_bearer_t *bearer = mme_bearer_first(sess); - while(bearer) - { - switch(bearer->ebi) - { - case 5: tau_accept->eps_bearer_context_status.ebi5 = 1; break; - case 6: tau_accept->eps_bearer_context_status.ebi6 = 1; break; - case 7: tau_accept->eps_bearer_context_status.ebi7 = 1; break; - case 8: tau_accept->eps_bearer_context_status.ebi8 = 1; break; - case 9: tau_accept->eps_bearer_context_status.ebi9 = 1; break; - case 10: tau_accept->eps_bearer_context_status.ebi10 = 1; break; - case 11: tau_accept->eps_bearer_context_status.ebi11 = 1; break; - case 12: tau_accept->eps_bearer_context_status.ebi12 = 1; break; - case 13: tau_accept->eps_bearer_context_status.ebi13 = 1; break; - case 14: tau_accept->eps_bearer_context_status.ebi14 = 1; break; - case 15: tau_accept->eps_bearer_context_status.ebi15 = 1; break; - default: break; + while (bearer) { + switch (bearer->ebi) { + case 5: tau_accept->eps_bearer_context_status.ebi5 = 1; break; + case 6: tau_accept->eps_bearer_context_status.ebi6 = 1; break; + case 7: tau_accept->eps_bearer_context_status.ebi7 = 1; break; + case 8: tau_accept->eps_bearer_context_status.ebi8 = 1; break; + case 9: tau_accept->eps_bearer_context_status.ebi9 = 1; break; + case 10: tau_accept->eps_bearer_context_status.ebi10 = 1; break; + case 11: tau_accept->eps_bearer_context_status.ebi11 = 1; break; + case 12: tau_accept->eps_bearer_context_status.ebi12 = 1; break; + case 13: tau_accept->eps_bearer_context_status.ebi13 = 1; break; + case 14: tau_accept->eps_bearer_context_status.ebi14 = 1; break; + case 15: tau_accept->eps_bearer_context_status.ebi15 = 1; break; + default: break; } bearer = mme_bearer_next(bearer); diff --git a/src/mme/emm-build.h b/src/mme/emm-build.h index e7024a71e..33cc42953 100644 --- a/src/mme/emm-build.h +++ b/src/mme/emm-build.h @@ -1,11 +1,30 @@ -#ifndef __EMM_BUILD_H__ -#define __EMM_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 EMM_BUILD_H +#define EMM_BUILD_H #include "mme-context.h" #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif int emm_build_attach_accept( ogs_pkbuf_t **emmbuf, mme_ue_t *mme_ue, ogs_pkbuf_t *esmbuf); @@ -33,6 +52,6 @@ int emm_build_service_reject(ogs_pkbuf_t **emmbuf, #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif -#endif /* __EMM_BUILD_H__ */ +#endif /* EMM_BUILD_H */ diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index 4eea89f51..c54f29669 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.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-kdf.h" @@ -10,6 +28,7 @@ #include "nas-path.h" #include "mme-fd-path.h" #include "mme-gtp-path.h" +#include "sgsap-path.h" #include "emm-handler.h" @@ -58,8 +77,7 @@ int emm_handle_attach_request( */ CLEAR_EPS_BEARER_ID(mme_ue); CLEAR_PAGING_INFO(mme_ue); - if (SECURITY_CONTEXT_IS_VALID(mme_ue)) - { + 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; @@ -81,8 +99,7 @@ int emm_handle_attach_request( /* Check TAI */ served_tai_index = mme_find_served_tai(&mme_ue->tai); - if (served_tai_index < 0) - { + if (served_tai_index < 0) { /* Send Attach Reject */ ogs_warn("Cannot find Served TAI[PLMN_ID:%06x,TAC:%d]", plmn_id_hexdump(&mme_ue->tai.plmn_id), mme_ue->tai.tac); @@ -95,8 +112,7 @@ int emm_handle_attach_request( /* Store UE specific information */ if (attach_request->presencemask & - NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) - { + NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) { nas_tracking_area_identity_t *last_visited_registered_tai = &attach_request->last_visited_registered_tai; @@ -104,9 +120,7 @@ int emm_handle_attach_request( &last_visited_registered_tai->nas_plmn_id); ogs_debug(" Visited_PLMN_ID:%06x", plmn_id_hexdump(&mme_ue->visited_plmn_id)); - } - else - { + } else { memcpy(&mme_ue->visited_plmn_id, &mme_ue->tai.plmn_id, PLMN_ID_LEN); } @@ -115,54 +129,50 @@ int emm_handle_attach_request( sizeof(attach_request->ue_network_capability)); if (attach_request->presencemask & - NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) - { + NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) { memcpy(&mme_ue->ms_network_capability, &attach_request->ms_network_capability, sizeof(attach_request->ms_network_capability)); } - switch(eps_mobile_identity->imsi.type) + switch (eps_mobile_identity->imsi.type) { + case NAS_EPS_MOBILE_IDENTITY_IMSI: { - case NAS_EPS_MOBILE_IDENTITY_IMSI: - { - char imsi_bcd[MAX_IMSI_BCD_LEN+1]; + char imsi_bcd[MAX_IMSI_BCD_LEN+1]; - memcpy(&mme_ue->nas_mobile_identity_imsi, - &eps_mobile_identity->imsi, sizeof(nas_mobile_identity_imsi_t)); - nas_imsi_to_bcd( - &eps_mobile_identity->imsi, eps_mobile_identity->length, - imsi_bcd); - mme_ue_set_imsi(mme_ue, imsi_bcd); + memcpy(&mme_ue->nas_mobile_identity_imsi, + &eps_mobile_identity->imsi, sizeof(nas_mobile_identity_imsi_t)); + nas_imsi_to_bcd( + &eps_mobile_identity->imsi, eps_mobile_identity->length, + imsi_bcd); + mme_ue_set_imsi(mme_ue, imsi_bcd); - ogs_debug(" IMSI[%s]", imsi_bcd); + ogs_debug(" IMSI[%s]", imsi_bcd); - break; - } - case NAS_EPS_MOBILE_IDENTITY_GUTI: - { - nas_eps_mobile_identity_guti_t *nas_eps_mobile_identity_guti = - &eps_mobile_identity->guti; - nas_guti_t nas_guti; + break; + } + case NAS_EPS_MOBILE_IDENTITY_GUTI: + { + nas_eps_mobile_identity_guti_t *nas_eps_mobile_identity_guti = + &eps_mobile_identity->guti; + nas_guti_t nas_guti; - nas_guti.nas_plmn_id = nas_eps_mobile_identity_guti->nas_plmn_id; - nas_guti.mme_gid = nas_eps_mobile_identity_guti->mme_gid; - nas_guti.mme_code = nas_eps_mobile_identity_guti->mme_code; - nas_guti.m_tmsi = nas_eps_mobile_identity_guti->m_tmsi; + nas_guti.nas_plmn_id = nas_eps_mobile_identity_guti->nas_plmn_id; + nas_guti.mme_gid = nas_eps_mobile_identity_guti->mme_gid; + nas_guti.mme_code = nas_eps_mobile_identity_guti->mme_code; + nas_guti.m_tmsi = nas_eps_mobile_identity_guti->m_tmsi; - ogs_debug(" GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI[%s]", - nas_guti.mme_gid, - nas_guti.mme_code, - nas_guti.m_tmsi, - MME_UE_HAVE_IMSI(mme_ue) - ? mme_ue->imsi_bcd : "Unknown"); - break; - } - default: - { - ogs_warn("Not implemented[%d]", eps_mobile_identity->imsi.type); - break; - } + ogs_debug(" GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI[%s]", + nas_guti.mme_gid, + nas_guti.mme_code, + nas_guti.m_tmsi, + MME_UE_HAVE_IMSI(mme_ue) + ? mme_ue->imsi_bcd : "Unknown"); + break; + } + default: + ogs_warn("Not implemented[%d]", eps_mobile_identity->imsi.type); + break; } NAS_STORE_DATA(&mme_ue->pdn_connectivity_request, esm_message_container); @@ -224,13 +234,10 @@ int emm_handle_attach_complete( NAS_TIME_TO_BCD(gmt.tm_hour); universal_time_and_local_time_zone->min = NAS_TIME_TO_BCD(gmt.tm_min); universal_time_and_local_time_zone->sec = NAS_TIME_TO_BCD(gmt.tm_sec); - if (local.tm_gmtoff >= 0) - { + if (local.tm_gmtoff >= 0) { universal_time_and_local_time_zone->timezone = NAS_TIME_TO_BCD(local.tm_gmtoff / 900); - } - else - { + } else { universal_time_and_local_time_zone->timezone = NAS_TIME_TO_BCD((-local.tm_gmtoff) / 900); universal_time_and_local_time_zone->timezone |= 0x08; @@ -242,16 +249,14 @@ int emm_handle_attach_complete( NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT; network_daylight_saving_time->length = 1; - if(mme_self()->full_name.length) - { + if (mme_self()->full_name.length) { emm_information->presencemask |= NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_PRESENT; memcpy(&emm_information->full_name_for_network, &mme_self()->full_name, sizeof(nas_network_name_t)); } - if(mme_self()->short_name.length) - { + if (mme_self()->short_name.length) { emm_information->presencemask |= NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_PRESENT; memcpy(&emm_information->short_name_for_network, @@ -265,6 +270,9 @@ int emm_handle_attach_complete( ogs_debug("[EMM] EMM information"); ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + if (mme_ue->vlr) + sgsap_send_tmsi_reallocation_complete(mme_ue); + return OGS_OK; } @@ -282,8 +290,7 @@ int emm_handle_identity_response( mobile_identity = &identity_response->mobile_identity; - if (mobile_identity->imsi.type == NAS_IDENTITY_TYPE_2_IMSI) - { + if (mobile_identity->imsi.type == NAS_IDENTITY_TYPE_2_IMSI) { char imsi_bcd[MAX_IMSI_BCD_LEN+1]; memcpy(&mme_ue->nas_mobile_identity_imsi, @@ -293,9 +300,7 @@ int emm_handle_identity_response( mme_ue_set_imsi(mme_ue, imsi_bcd); ogs_assert(mme_ue->imsi_len); - } - else - { + } else { ogs_warn("Not supported Identity type[%d]", mobile_identity->imsi.type); } @@ -319,26 +324,25 @@ int emm_handle_detach_request( ogs_debug(" NAS_EPS TYPE[%d] KSI[%d] DETACH[0x%x]", mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, mme_ue->nas_eps.data); - switch (detach_request->detach_type.detach_type) - { - /* 0 0 1 : EPS detach */ - case NAS_DETACH_TYPE_FROM_UE_EPS_DETACH: - ogs_debug(" EPS Detach"); - break; - /* 0 1 0 : IMSI detach */ - case NAS_DETACH_TYPE_FROM_UE_IMSI_DETACH: - ogs_debug(" IMSI Detach"); - break; - case 6: /* 1 1 0 : reserved */ - case 7: /* 1 1 1 : reserved */ - ogs_warn("Unknown Detach type[%d]", - detach_request->detach_type.detach_type); - break; - /* 0 1 1 : combined EPS/IMSI detach */ - case NAS_DETACH_TYPE_FROM_UE_COMBINED_EPS_IMSI_DETACH: - ogs_debug(" Combined EPS/IMSI Detach"); - default: /* all other values */ - break; + switch (detach_request->detach_type.detach_type) { + /* 0 0 1 : EPS detach */ + case NAS_DETACH_TYPE_FROM_UE_EPS_DETACH: + ogs_debug(" EPS Detach"); + break; + /* 0 1 0 : IMSI detach */ + case NAS_DETACH_TYPE_FROM_UE_IMSI_DETACH: + ogs_debug(" IMSI Detach"); + break; + case 6: /* 1 1 0 : reserved */ + case 7: /* 1 1 1 : reserved */ + ogs_warn("Unknown Detach type[%d]", + detach_request->detach_type.detach_type); + break; + /* 0 1 1 : combined EPS/IMSI detach */ + case NAS_DETACH_TYPE_FROM_UE_COMBINED_EPS_IMSI_DETACH: + ogs_debug(" Combined EPS/IMSI Detach"); + default: /* all other values */ + break; } if (detach_request->detach_type.switch_off) ogs_debug(" Switch-Off"); @@ -374,8 +378,7 @@ int emm_handle_service_request( * Update KeNB */ CLEAR_PAGING_INFO(mme_ue); - if (SECURITY_CONTEXT_IS_VALID(mme_ue)) - { + 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; @@ -455,8 +458,7 @@ int emm_handle_tau_request( /* Check TAI */ served_tai_index = mme_find_served_tai(&mme_ue->tai); - if (served_tai_index < 0) - { + if (served_tai_index < 0) { /* Send TAU reject */ ogs_warn("Cannot find Served TAI[PLMN_ID:%06x,TAC:%d]", plmn_id_hexdump(&mme_ue->tai.plmn_id), mme_ue->tai.tac); @@ -467,8 +469,7 @@ int emm_handle_tau_request( /* Store UE specific information */ if (tau_request->presencemask & - NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) - { + NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) { nas_tracking_area_identity_t *last_visited_registered_tai = &tau_request->last_visited_registered_tai; @@ -476,23 +477,19 @@ int emm_handle_tau_request( &last_visited_registered_tai->nas_plmn_id); ogs_debug(" Visited_PLMN_ID:%06x", plmn_id_hexdump(&mme_ue->visited_plmn_id)); - } - else - { + } else { memcpy(&mme_ue->visited_plmn_id, &mme_ue->tai.plmn_id, PLMN_ID_LEN); } if (tau_request->presencemask & - NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_PRESENT) - { + NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_PRESENT) { memcpy(&mme_ue->ue_network_capability, &tau_request->ue_network_capability, sizeof(tau_request->ue_network_capability)); } if (tau_request->presencemask & - NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) - { + NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) { memcpy(&mme_ue->ms_network_capability, &tau_request->ms_network_capability, sizeof(tau_request->ms_network_capability)); @@ -502,34 +499,31 @@ int emm_handle_tau_request( * 1) Consider if MME is changed or not. * 2) Consider if SGW is changed or not. */ - switch(eps_mobile_identity->imsi.type) + switch (eps_mobile_identity->imsi.type) { + case NAS_EPS_MOBILE_IDENTITY_GUTI: { - case NAS_EPS_MOBILE_IDENTITY_GUTI: - { - nas_eps_mobile_identity_guti_t *nas_eps_mobile_identity_guti = - &eps_mobile_identity->guti; - nas_guti_t nas_guti; + nas_eps_mobile_identity_guti_t *nas_eps_mobile_identity_guti = + &eps_mobile_identity->guti; + nas_guti_t nas_guti; - nas_guti.nas_plmn_id = nas_eps_mobile_identity_guti->nas_plmn_id; - nas_guti.mme_gid = nas_eps_mobile_identity_guti->mme_gid; - nas_guti.mme_code = nas_eps_mobile_identity_guti->mme_code; - nas_guti.m_tmsi = nas_eps_mobile_identity_guti->m_tmsi; + nas_guti.nas_plmn_id = nas_eps_mobile_identity_guti->nas_plmn_id; + nas_guti.mme_gid = nas_eps_mobile_identity_guti->mme_gid; + nas_guti.mme_code = nas_eps_mobile_identity_guti->mme_code; + nas_guti.m_tmsi = nas_eps_mobile_identity_guti->m_tmsi; - ogs_debug(" GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI:[%s]", - nas_guti.mme_gid, - nas_guti.mme_code, - nas_guti.m_tmsi, - MME_UE_HAVE_IMSI(mme_ue) - ? mme_ue->imsi_bcd : "Unknown"); - break; - } - default: - { - ogs_warn("Not implemented[%d]", - eps_mobile_identity->imsi.type); - - return OGS_OK; - } + ogs_debug(" GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI:[%s]", + nas_guti.mme_gid, + nas_guti.mme_code, + nas_guti.m_tmsi, + MME_UE_HAVE_IMSI(mme_ue) + ? mme_ue->imsi_bcd : "Unknown"); + break; + } + default: + ogs_warn("Not implemented[%d]", + eps_mobile_identity->imsi.type); + + return OGS_OK; } return OGS_OK; diff --git a/src/mme/emm-handler.h b/src/mme/emm-handler.h index 04135e7d5..563282fb4 100644 --- a/src/mme/emm-handler.h +++ b/src/mme/emm-handler.h @@ -1,5 +1,24 @@ -#ifndef __EMM_HANDLER_H__ -#define __EMM_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 EMM_HANDLER_H +#define EMM_HANDLER_H #include "nas/nas-message.h" @@ -7,7 +26,7 @@ #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif int emm_handle_attach_request( mme_ue_t *mme_ue, nas_attach_request_t *attach_request); @@ -28,6 +47,6 @@ int emm_handle_tau_request( #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif -#endif /* __EMM_HANDLER_H__ */ +#endif /* EMM_HANDLER_H */ diff --git a/src/mme/sgsap-build.c b/src/mme/sgsap-build.c index 885e90240..2d13e9d70 100644 --- a/src/mme/sgsap-build.c +++ b/src/mme/sgsap-build.c @@ -67,12 +67,34 @@ ogs_pkbuf_t *sgsap_build_location_update_request(mme_ue_t *mme_ue) } ogs_pkbuf_t *sgsap_build_tmsi_reallocation_complete(mme_ue_t *mme_ue) { - return NULL; + mme_vlr_t *vlr = NULL; + ogs_tlv_t *root = NULL; + ogs_pkbuf_t *pkbuf = NULL; + + ogs_assert(mme_ue); + vlr = mme_ue->vlr; + ogs_assert(vlr); + + root = ogs_tlv_add(NULL, SGSAP_IE_IMSI_TYPE, SGSAP_IE_IMSI_LEN, 0, + &mme_ue->nas_mobile_identity_imsi); + + pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); + ogs_pkbuf_put_u8(pkbuf, SGSAP_TMSI_REALLOCATION_COMPLETE); + ogs_pkbuf_put(pkbuf, MAX_SDU_LEN-1); + + ogs_pkbuf_trim(pkbuf, 1+ogs_tlv_render(root, + pkbuf->data+1, MAX_SDU_LEN-1, OGS_TLV_MODE_T1_L1)); + + ogs_tlv_free_all(root); + + return pkbuf; } + ogs_pkbuf_t *sgsap_build_service_request(mme_ue_t *mme_ue) { return NULL; } + ogs_pkbuf_t *sgsap_build_mo_csfb_indication(mme_ue_t *mme_ue) { return NULL; diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index 0b2f72ce5..76a5e5560 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -38,6 +38,8 @@ void sgsap_handler_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_assert(vlr); ogs_assert(pkbuf); + ogs_debug("[SGSAP] LOCATION-UPDATE-ACCEPT"); + ogs_pkbuf_pull(pkbuf, 1); root = ogs_tlv_parse_block(pkbuf->len, pkbuf->data, OGS_TLV_MODE_T1_L1); @@ -87,6 +89,9 @@ void sgsap_handler_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) goto error; } + ogs_debug(" IMSI[%s] P-TMSI[0x%08x]", + mme_ue->imsi_bcd, mme_ue->p_tmsi); + nas_send_attach_accept(mme_ue); return; diff --git a/src/mme/sgsap-path.c b/src/mme/sgsap-path.c index 80ca78944..917e9e8da 100644 --- a/src/mme/sgsap-path.c +++ b/src/mme/sgsap-path.c @@ -87,23 +87,11 @@ int sgsap_send_to_vlr_with_sid( sock = node->sock; ogs_assert(sock); - ogs_debug(" IP[%s] TAI[MCC:%d%d%d,MNC:%d%d%d,TAC:%d]", - OGS_ADDR(node->addr, buf), - vlr->tai.nas_plmn_id.mcc1, - vlr->tai.nas_plmn_id.mcc2, - vlr->tai.nas_plmn_id.mcc3, - vlr->tai.nas_plmn_id.mnc1, - vlr->tai.nas_plmn_id.mnc2, - vlr->tai.nas_plmn_id.mnc3, - vlr->tai.tac); - ogs_debug(" LAI[MCC:%d%d%d,MNC:%d%d%d,TAC:%d]", - vlr->lai.nas_plmn_id.mcc1, - vlr->lai.nas_plmn_id.mcc2, - vlr->lai.nas_plmn_id.mcc3, - vlr->lai.nas_plmn_id.mnc1, - vlr->lai.nas_plmn_id.mnc2, - vlr->lai.nas_plmn_id.mnc3, - vlr->lai.lac); + ogs_debug(" VLR-IP[%s]", OGS_ADDR(node->addr, buf)); + ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]", + plmn_id_hexdump(&vlr->tai.nas_plmn_id), vlr->tai.tac); + ogs_debug(" LAI[PLMN_ID:%06x,LAC:%d]", + plmn_id_hexdump(&vlr->lai.nas_plmn_id), vlr->lai.lac); rv = sgsap_send(sock, pkbuf, node->addr, stream_no); if (rv != OGS_OK) { @@ -131,6 +119,8 @@ int sgsap_send_location_update_request(mme_ue_t *mme_ue) ogs_pkbuf_t *pkbuf = NULL; ogs_assert(mme_ue); + ogs_debug("[SGSAP] LOCATION-UPDATE-REQUEST"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); pkbuf = sgsap_build_location_update_request(mme_ue); rv = sgsap_send_to_vlr(mme_ue, pkbuf); @@ -138,3 +128,19 @@ int sgsap_send_location_update_request(mme_ue_t *mme_ue) return OGS_OK; } + +int sgsap_send_tmsi_reallocation_complete(mme_ue_t *mme_ue) +{ + int rv; + ogs_pkbuf_t *pkbuf = NULL; + ogs_assert(mme_ue); + + ogs_debug("[SGSAP] TMSI-REALLOCATION-COMPLETE"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + pkbuf = sgsap_build_tmsi_reallocation_complete(mme_ue); + + rv = sgsap_send_to_vlr(mme_ue, pkbuf); + ogs_assert(rv == OGS_OK); + + return OGS_OK; +} diff --git a/src/mme/sgsap-path.h b/src/mme/sgsap-path.h index c64210eb6..a3ec8d607 100644 --- a/src/mme/sgsap-path.h +++ b/src/mme/sgsap-path.h @@ -40,6 +40,7 @@ int sgsap_send_to_vlr_with_sid( int sgsap_send_to_vlr(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf); int sgsap_send_location_update_request(mme_ue_t *mme_ue); +int sgsap_send_tmsi_reallocation_complete(mme_ue_t *mme_ue); #ifdef __cplusplus } diff --git a/tests/csfb/csfb-test.c b/tests/csfb/csfb-test.c index 81885dca8..3cb3dd2d4 100644 --- a/tests/csfb/csfb-test.c +++ b/tests/csfb/csfb-test.c @@ -53,6 +53,8 @@ static void test1_func(abts_case *tc, void *data) char *_emm_information = "000b403800000300 0000020001000800 020001001a002524 2751034124030761" "430f10004e006500 7800740045005000 4347916051216124 63490100"; + char *_sgsap_tmsi_reallocation_complete = + "0c01082926240000 111893"; mongoc_collection_t *collection = NULL; bson_t *doc = NULL; @@ -253,6 +255,15 @@ static void test1_func(abts_case *tc, void *data) ABTS_TRUE(tc, memcmp(recvbuf->data+57, tmp+57, 3) == 0); ogs_pkbuf_free(recvbuf); + /* Receive SGsAP TMSI-REALLOCATION-COMPLETE */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ABTS_TRUE(tc, memcmp(recvbuf->data, + OGS_HEX(_sgsap_tmsi_reallocation_complete, + strlen(_sgsap_tmsi_reallocation_complete), tmp), + recvbuf->len) == 0); + ogs_pkbuf_free(recvbuf); + #if 0 /* Sometimes, it's not working. */ /* Send GTP-U ICMP Packet */ rv = testgtpu_build_ping(&sendbuf, "45.45.0.2", "45.45.0.1");