diff --git a/lib/core/ogs-3gpp-types.h b/lib/core/ogs-3gpp-types.h index f1af7720a..0b6b1c0cf 100644 --- a/lib/core/ogs-3gpp-types.h +++ b/lib/core/ogs-3gpp-types.h @@ -211,6 +211,8 @@ typedef struct ogs_nr_cgi_s { typedef struct ogs_s_nssai_s { uint8_t sst; ogs_uint24_t sd; + uint8_t mapped_hplmn_sst; + ogs_uint24_t mapped_hplmn_sd; } __attribute__ ((packed)) ogs_s_nssai_t; char *ogs_s_nssai_sd_to_string(ogs_uint24_t sd); diff --git a/lib/crypt/ogs-crypt.h b/lib/crypt/ogs-crypt.h index 09f88713c..e39e25d4d 100644 --- a/lib/crypt/ogs-crypt.h +++ b/lib/crypt/ogs-crypt.h @@ -58,6 +58,8 @@ extern "C" { #define OGS_SQN_LEN 6 #define OGS_MAX_SQN 0xffffffffffff +#define OGS_HASH_MME_LEN 8 + #define OGS_KEYSTRLEN(x) ((x*2)+1) #ifdef __cplusplus diff --git a/lib/crypt/ogs-kdf.c b/lib/crypt/ogs-kdf.c index a35700e6d..bbbcfeead 100644 --- a/lib/crypt/ogs-kdf.c +++ b/lib/crypt/ogs-kdf.c @@ -306,6 +306,26 @@ void ogs_kdf_nas_eps(uint8_t algorithm_type_distinguishers, memcpy(knas, output+16, 16); } +/* + * TS33.401 Annex I Hash Functions + * Use the KDF given in TS33.220 + */ +void ogs_kdf_hash_mme(uint8_t *message, uint8_t message_len, uint8_t *hash_mme) +{ + uint8_t key[32]; + uint8_t output[OGS_SHA256_DIGEST_SIZE]; + + ogs_assert(message); + ogs_assert(message_len); + ogs_assert(hash_mme); + + memset(key, 0, 32); + ogs_hmac_sha256(key, 32, message, message_len, + output, OGS_SHA256_DIGEST_SIZE); + + memcpy(hash_mme, output+24, OGS_HASH_MME_LEN); +} + /* * TS33.102 * 6.3.3 Authentication and key agreement diff --git a/lib/crypt/ogs-kdf.h b/lib/crypt/ogs-kdf.h index 257fe7cb6..8b6f6e344 100644 --- a/lib/crypt/ogs-kdf.h +++ b/lib/crypt/ogs-kdf.h @@ -87,6 +87,11 @@ void ogs_kdf_nh_enb(uint8_t *kasme, uint8_t *sync_input, uint8_t *kenb); void ogs_kdf_nas_eps(uint8_t algorithm_type_distinguishers, uint8_t algorithm_identity, uint8_t *kasme, uint8_t *knas); +/* + * TS33.401 Annex I Hash Functions + * Use the KDF given in TS33.220 + */ +void ogs_kdf_hash_mme(uint8_t *message, uint8_t message_len, uint8_t *hash_mme); /* * TS33.102 diff --git a/lib/nas/5gs/types.c b/lib/nas/5gs/types.c index 039c7dcee..1177ff875 100644 --- a/lib/nas/5gs/types.c +++ b/lib/nas/5gs/types.c @@ -91,11 +91,114 @@ void ogs_nas_5gs_tai_list_build( } } +void ogs_nas_build_s_nssai( + ogs_nas_s_nssai_t *nas_s_nssai, ogs_s_nssai_t *s_nssai) +{ + int pos; + ogs_uint24_t v; + + ogs_assert(nas_s_nssai); + ogs_assert(s_nssai); + + pos = 0; + + if (s_nssai->sst) + nas_s_nssai->buffer[pos++] = s_nssai->sst; + + if (s_nssai->sd.v != OGS_S_NSSAI_NO_SD_VALUE) { + v = ogs_htobe24(s_nssai->sd); + memcpy(nas_s_nssai->buffer+pos, &v, 3); + pos += 3; + } + + if (s_nssai->mapped_hplmn_sst) + nas_s_nssai->buffer[pos++] = s_nssai->mapped_hplmn_sst; + + if (s_nssai->mapped_hplmn_sd.v != OGS_S_NSSAI_NO_SD_VALUE) { + v = ogs_htobe24(s_nssai->mapped_hplmn_sd); + memcpy(nas_s_nssai->buffer+pos, &v, 3); + pos += 3; + } + + nas_s_nssai->length = pos; +} + +int ogs_nas_parse_s_nssai( + ogs_s_nssai_t *s_nssai, ogs_nas_s_nssai_t *nas_s_nssai) +{ + ogs_uint24_t v; + int pos = 0; + bool sst, sd, mapped_hplmn_sst, mapped_hplmn_sd; + + ogs_assert(nas_s_nssai); + ogs_assert(s_nssai); + + memset(s_nssai, 0, sizeof(*s_nssai)); + s_nssai->sd.v = OGS_S_NSSAI_NO_SD_VALUE; + s_nssai->mapped_hplmn_sd.v = OGS_S_NSSAI_NO_SD_VALUE; + + if (nas_s_nssai->length == OGS_NAS_S_NSSAI_SST_LEN) { + sst = true; + sd = false; + mapped_hplmn_sst = false; + mapped_hplmn_sd = false; + } else if (nas_s_nssai->length == + OGS_NAS_S_NSSAI_SST_AND_MAPPED_HPLMN_SST_LEN) { + sst = true; + sd = false; + mapped_hplmn_sst = true; + mapped_hplmn_sd = false; + } else if (nas_s_nssai->length == OGS_NAS_S_NSSAI_SST_AND_SD) { + sst = true; + sd = true; + mapped_hplmn_sst = false; + mapped_hplmn_sd = false; + } else if (nas_s_nssai->length == + OGS_NAS_S_NSSAI_SST_SD_AND_MAPPED_HPLMN_SST_LEN) { + sst = true; + sd = true; + mapped_hplmn_sst = true; + mapped_hplmn_sd = false; + } else if (nas_s_nssai->length == + OGS_NAS_S_NSSAI_SST_SD_AND_MAPPED_HPLMN_SST_SD_LEN) { + sst = true; + sd = true; + mapped_hplmn_sst = true; + mapped_hplmn_sd = true; + } else { + ogs_error("Cannot parse S-NSSAI [%d]", nas_s_nssai->length); + ogs_log_hexdump(OGS_ERROR, nas_s_nssai->buffer, nas_s_nssai->length); + return 0; + } + + pos = 0; + + if (sst) + s_nssai->sst = nas_s_nssai->buffer[pos++]; + + if (sd) { + memcpy(&v, nas_s_nssai->buffer+pos, 3); + s_nssai->sd = ogs_htobe24(v); + pos += 3; + } + + if (mapped_hplmn_sst) + s_nssai->mapped_hplmn_sst = nas_s_nssai->buffer[pos++]; + + if (mapped_hplmn_sd) { + memcpy(&v, nas_s_nssai->buffer+pos, 3); + s_nssai->mapped_hplmn_sd = ogs_htobe24(v); + pos += 3; + } + + return nas_s_nssai->length + 1; +} + void ogs_nas_build_nssai(ogs_nas_nssai_t *nas_nssai, ogs_s_nssai_t *s_nssai, int num_of_s_nssai) { int i; - ogs_s_nssai_t target; + ogs_nas_s_nssai_t nas_s_nssai; ogs_assert(nas_nssai); ogs_assert(s_nssai); @@ -103,23 +206,11 @@ void ogs_nas_build_nssai(ogs_nas_nssai_t *nas_nssai, for (i = 0; i < num_of_s_nssai; i++) { if (nas_nssai->length < OGS_NAS_MAX_NSSAI_LEN) { - memcpy(&target, s_nssai + i, sizeof(ogs_s_nssai_t)); - - nas_nssai->buffer[nas_nssai->length] = 1; - nas_nssai->length++; - - nas_nssai->buffer[nas_nssai->length] = target.sst; - nas_nssai->length++; - - if (target.sd.v != OGS_S_NSSAI_NO_SD_VALUE) { - ogs_uint24_t v; - - v = ogs_htobe24(target.sd); - memcpy(nas_nssai->buffer+nas_nssai->length, &v, 3); - - nas_nssai->length += 3; - nas_nssai->buffer[nas_nssai->length-5] += 3; - } + ogs_nas_build_s_nssai(&nas_s_nssai, s_nssai + i); + memcpy(nas_nssai->buffer + nas_nssai->length, &nas_s_nssai, + sizeof(nas_s_nssai.length) + nas_s_nssai.length); + nas_nssai->length += + (sizeof(nas_s_nssai.length) + nas_s_nssai.length); } } } @@ -127,7 +218,6 @@ void ogs_nas_build_nssai(ogs_nas_nssai_t *nas_nssai, int ogs_nas_parse_nssai(ogs_s_nssai_t *s_nssai, ogs_nas_nssai_t *nas_nssai) { int num_of_s_nssai = 0; - ogs_s_nssai_t *iter = NULL; int pos = 0, len; ogs_assert(nas_nssai); @@ -141,26 +231,15 @@ int ogs_nas_parse_nssai(ogs_s_nssai_t *s_nssai, ogs_nas_nssai_t *nas_nssai) while (pos < nas_nssai->length && num_of_s_nssai < OGS_MAX_NUM_OF_S_NSSAI) { - iter = s_nssai + num_of_s_nssai; - ogs_assert(iter); - - len = nas_nssai->buffer[pos++]; - if (len == 1) { - iter->sst = nas_nssai->buffer[pos++]; - iter->sd.v = OGS_S_NSSAI_NO_SD_VALUE; - } else if (len == 4) { - ogs_uint24_t v; - iter->sst = nas_nssai->buffer[pos++]; - memcpy(&v, nas_nssai->buffer+pos, 3); - pos += 3; - iter->sd = ogs_htobe24(v); - } else { + len = ogs_nas_parse_s_nssai(s_nssai + num_of_s_nssai, + (ogs_nas_s_nssai_t *)(nas_nssai->buffer + pos)); + if (len == 0) { ogs_error("Cannot parse NSSAI [%d]", nas_nssai->length); - ogs_log_hexdump(OGS_LOG_ERROR, - (uint8_t *)nas_nssai->buffer, nas_nssai->length); - return 0; + ogs_log_hexdump(OGS_ERROR, nas_nssai->buffer, nas_nssai->length); } + pos += len; + num_of_s_nssai++; } diff --git a/lib/nas/5gs/types.h b/lib/nas/5gs/types.h index 595a61863..b532d9ac5 100644 --- a/lib/nas/5gs/types.h +++ b/lib/nas/5gs/types.h @@ -56,12 +56,16 @@ typedef struct ogs_nas_eap_message_s { #define OGS_NAS_S_NSSAI_SST_AND_MAPPED_HPLMN_SST_LEN 2 #define OGS_NAS_S_NSSAI_SST_AND_SD 4 #define OGS_NAS_S_NSSAI_SST_SD_AND_MAPPED_HPLMN_SST_LEN 5 +#define OGS_NAS_S_NSSAI_SST_SD_AND_MAPPED_HPLMN_SST_SD_LEN 8 typedef struct ogs_nas_s_nssai_s { uint8_t length; - uint8_t sst; - ogs_uint24_t sd; + uint8_t buffer[OGS_NAS_S_NSSAI_SST_SD_AND_MAPPED_HPLMN_SST_SD_LEN]; } __attribute__ ((packed)) ogs_nas_s_nssai_t; +void ogs_nas_build_s_nssai( + ogs_nas_s_nssai_t *nas_s_nssai, ogs_s_nssai_t *s_nssai); +int ogs_nas_parse_s_nssai( + ogs_s_nssai_t *s_nssai, ogs_nas_s_nssai_t *nas_s_nssai); /* 9.11.3.1 5GMM capability * O TLV 3-15 */ typedef struct ogs_nas_5gmm_capability_s { @@ -434,7 +438,7 @@ ED4(uint8_t type:4;, #define OGS_NAS_MAX_NSSAI_LEN 70 typedef struct ogs_nas_nssai_s { uint8_t length; - char buffer[OGS_NAS_MAX_NSSAI_LEN]; + uint8_t buffer[OGS_NAS_MAX_NSSAI_LEN]; } __attribute__ ((packed)) ogs_nas_nssai_t; void ogs_nas_build_nssai(ogs_nas_nssai_t *nas_nssai, diff --git a/lib/nas/eps/types.h b/lib/nas/eps/types.h index e1a67054a..1b417561d 100644 --- a/lib/nas/eps/types.h +++ b/lib/nas/eps/types.h @@ -324,18 +324,21 @@ typedef struct ogs_nas_eps_mobile_identity_s { * O TLV 3 */ typedef struct ogs_nas_eps_network_feature_support_s { uint8_t length; -ED7(uint8_t cp_ciot:1;, - uint8_t erw_opdn:1;, - uint8_t esr_ps:1;, - uint8_t cs_lcs:2;, - uint8_t epc_lcs:1;, - uint8_t emc_bs:1;, - uint8_t ims_vops:1;) -ED5(uint8_t spare:4;, - uint8_t e_pco:1;, - uint8_t hc_cp_ciot:1;, - uint8_t s1_u_data:1;, - uint8_t up_ciot :1;) +ED7(uint8_t control_plane_ciot_eps_optimization:1;, + uint8_t emm_registered_without_pdn_connectivity:1;, + uint8_t support_of_extended_service_request_for_packet_services:1;, + uint8_t cs_lcs_no_information_about_support_of_location_service_via_cs_domain_is_avaiable:2;, + uint8_t location_service_via_epc:1;, + uint8_t emergency_bearer_services_in_s1_mode:1;, + uint8_t ims_voice_over_ps_session_in_s1_mode:1;) +ED8(uint8_t signalling_for_a_maximum_number_of_16_eps_bearer_contexts:1;, + uint8_t interworking_without_n26_interface:1;, + uint8_t restriction_on_the_use_of_dual_connectivity_with_nr:1;, + uint8_t restriction_on_enhanced_coverage:1;, + uint8_t extended_protocol_configuration_options:1;, + uint8_t header_compression_for_control_plan_ciot_eps_optimization:1;, + uint8_t s1_u_data_transfer:1;, + uint8_t user_plane_ciot_eps_optimization :1;) } __attribute__ ((packed)) ogs_nas_eps_network_feature_support_t; /* 9.9.3.13 EPS update result @@ -645,10 +648,9 @@ ED3(uint8_t type:4;, /* 9.9.3.50 HashMME * O TLV 10 */ -#define OGS_NAS_HASHMME_LEN 8 typedef struct ogs_nas_hashmme_s { uint8_t length; - uint8_t value[OGS_NAS_HASHMME_LEN]; + uint8_t value[OGS_HASH_MME_LEN]; } ogs_nas_hashmme_t; /* 9.9.3.51 Replayed NAS message container diff --git a/src/amf/context.c b/src/amf/context.c index 7a1839430..b3f4782a5 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -634,6 +634,10 @@ int amf_context_parse_config(void) s_nssai->sd.v = OGS_S_NSSAI_NO_SD_VALUE; + s_nssai->mapped_hplmn_sst = 0; + s_nssai->mapped_hplmn_sd.v = + OGS_S_NSSAI_NO_SD_VALUE; + self.plmn_support[ self.num_of_plmn_support]. num_of_s_nssai++; @@ -1467,6 +1471,11 @@ amf_sess_t *amf_sess_add(amf_ue_t *amf_ue, uint8_t psi) sess->amf_ue = amf_ue; sess->psi = psi; + sess->s_nssai.sst = 0; + sess->s_nssai.sd.v = OGS_S_NSSAI_NO_SD_VALUE; + sess->s_nssai.mapped_hplmn_sst = 0; + sess->s_nssai.mapped_hplmn_sd.v = OGS_S_NSSAI_NO_SD_VALUE; + sess->sbi.client_wait.timer = ogs_timer_add( self.timer_mgr, amf_timer_sbi_client_wait_expire, sess); diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index fdda0214d..61497f7ff 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -228,6 +228,12 @@ int gmm_handle_registration_update(amf_ue_t *amf_ue, amf_ue, ®istration_request->nas_message_container); } + if (registration_request->presencemask & + OGS_NAS_5GS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT) { + + amf_ue->num_of_requested_nssai = ogs_nas_parse_nssai( + amf_ue->requested_nssai, ®istration_request->requested_nssai); + } if (registration_request->presencemask & OGS_NAS_5GS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) { @@ -236,13 +242,6 @@ int gmm_handle_registration_update(amf_ue_t *amf_ue, &last_visited_registered_tai->nas_plmn_id); } - if (registration_request->presencemask & - OGS_NAS_5GS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT) { - - amf_ue->num_of_requested_nssai = ogs_nas_parse_nssai( - amf_ue->requested_nssai, ®istration_request->requested_nssai); - } - if (registration_request->presencemask & OGS_NAS_5GS_REGISTRATION_REQUEST_UE_USAGE_SETTING_PRESENT) { memcpy(&amf_ue->ue_usage_setting, @@ -861,13 +860,10 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue, if (ul_nas_transport->presencemask & OGS_NAS_5GS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT) { ogs_s_nssai_t s_nssai; - s_nssai.sst = nas_s_nssai->sst; - if (nas_s_nssai->length > 1) - s_nssai.sd = ogs_be24toh(nas_s_nssai->sd); - else - s_nssai.sd.v = OGS_S_NSSAI_NO_SD_VALUE; - selected_s_nssai = - amf_find_s_nssai(&amf_ue->tai.plmn_id, &s_nssai); + if (ogs_nas_parse_s_nssai(&s_nssai, nas_s_nssai) != 0) { + selected_s_nssai = + amf_find_s_nssai(&amf_ue->tai.plmn_id, &s_nssai); + } } if (!selected_s_nssai) { diff --git a/src/amf/ngap-build.c b/src/amf/ngap-build.c index 6e7b26c9f..9262dcf10 100644 --- a/src/amf/ngap-build.c +++ b/src/amf/ngap-build.c @@ -132,7 +132,7 @@ ogs_pkbuf_t *ngap_build_ng_setup_response(void) ogs_asn_buffer_to_OCTET_STRING( &amf_self()->plmn_support[i].plmn_id, OGS_PLMN_ID_LEN, pLMNIdentity); - for (j = 0; j < amf_self()->plmn_support[j].num_of_s_nssai; j++) { + for (j = 0; j < amf_self()->plmn_support[i].num_of_s_nssai; j++) { NGAP_SliceSupportItem_t *NGAP_SliceSupportItem = NULL; NGAP_S_NSSAI_t *s_NSSAI = NULL; NGAP_SST_t *sST = NULL; diff --git a/src/amf/nsmf-build.c b/src/amf/nsmf-build.c index adb728b71..92f7ff852 100644 --- a/src/amf/nsmf-build.c +++ b/src/amf/nsmf-build.c @@ -34,6 +34,7 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context( OpenAPI_sm_context_create_data_t SmContextCreateData; OpenAPI_plmn_id_nid_t plmn_id_nid; OpenAPI_snssai_t s_nssai; + OpenAPI_snssai_t hplmn_snssai; OpenAPI_ref_to_binary_data_t n1SmMsg; OpenAPI_guami_t guami; @@ -74,6 +75,14 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context( s_nssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd); SmContextCreateData.s_nssai = &s_nssai; + memset(&hplmn_snssai, 0, sizeof(hplmn_snssai)); + if (sess->s_nssai.mapped_hplmn_sst) { + hplmn_snssai.sst = sess->s_nssai.mapped_hplmn_sst; + hplmn_snssai.sd = ogs_s_nssai_sd_to_string( + sess->s_nssai.mapped_hplmn_sd); + SmContextCreateData.hplmn_snssai = &hplmn_snssai; + } + ogs_assert(amf_ue->guami); guami.amf_id = ogs_amf_id_to_string(&amf_ue->guami->amf_id, buf); guami.plmn_id = (OpenAPI_plmn_id_t *)&plmn_id_nid; @@ -120,6 +129,8 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context( ogs_free(header.resource.component[2]); if (s_nssai.sd) ogs_free(s_nssai.sd); + if (hplmn_snssai.sd) + ogs_free(hplmn_snssai.sd); if (SmContextCreateData.gpsi) ogs_free(SmContextCreateData.gpsi); diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index ca5c1cc37..eecbc6b5d 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -108,7 +108,8 @@ ogs_pkbuf_t *emm_build_attach_accept( attach_accept->presencemask |= OGS_NAS_EPS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; eps_network_feature_support->length = 2; - eps_network_feature_support->ims_vops = 1; + eps_network_feature_support->ims_voice_over_ps_session_in_s1_mode = 1; + eps_network_feature_support->extended_protocol_configuration_options = 1; if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { ogs_assert(mme_ue->csmap); @@ -234,6 +235,7 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue) &security_mode_command->replayed_ue_security_capabilities; ogs_nas_imeisv_request_t *imeisv_request = &security_mode_command->imeisv_request; + ogs_nas_hashmme_t *hashmme = &security_mode_command->hashmme; ogs_nas_ue_additional_security_capability_t *replayed_ue_additional_security_capability = &security_mode_command->replayed_ue_additional_security_capability; @@ -251,18 +253,14 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue) OGS_HEX(_reg, strlen(_reg), tmp); + memcpy(s, tmp, 94); + len = htobe16(94); memcpy(&s[94], &len, sizeof(len)); memset(key, 0, 32); - ogs_log_hexdump(OGS_LOG_FATAL, s, 96); - ogs_log_hexdump(OGS_LOG_FATAL, key, 32); - ogs_hmac_sha256(key, 32, s, 94, output, OGS_SHA256_DIGEST_SIZE); - ogs_log_hexdump(OGS_LOG_FATAL, output, 32); - memcpy(s, key, 32); - memcpy(s+32, tmp, 94); - ogs_sha256(s, 32+94, output); + ogs_fatal("output"); ogs_log_hexdump(OGS_LOG_FATAL, output, 32); #endif @@ -329,6 +327,11 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue) imeisv_request->type = OGS_NAS_IMEISV_TYPE; imeisv_request->value = OGS_NAS_IMEISV_REQUESTED; + security_mode_command->presencemask |= + OGS_NAS_EPS_SECURITY_MODE_COMMAND_HASHMME_PRESENT; + hashmme->length = OGS_HASH_MME_LEN; + memcpy(hashmme->value, mme_ue->hash_mme, hashmme->length); + if (mme_ue->ue_additional_security_capability.length) { security_mode_command->presencemask |= OGS_NAS_EPS_SECURITY_MODE_COMMAND_REPLAYED_UE_ADDITIONAL_SECURITY_CAPABILITY_PRESENT; @@ -463,7 +466,10 @@ ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue) tau_accept->presencemask |= OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; tau_accept->eps_network_feature_support.length = 1; - tau_accept->eps_network_feature_support.ims_vops = 1; + tau_accept->eps_network_feature_support. + ims_voice_over_ps_session_in_s1_mode = 1; + tau_accept->eps_network_feature_support. + extended_protocol_configuration_options = 1; return nas_eps_security_encode(mme_ue, &message); } diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index f4e4b9c79..70b8f87e9 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -32,8 +32,8 @@ #undef OGS_LOG_DOMAIN #define OGS_LOG_DOMAIN __emm_log_domain -int emm_handle_attach_request( - mme_ue_t *mme_ue, ogs_nas_eps_attach_request_t *attach_request) +int emm_handle_attach_request(mme_ue_t *mme_ue, + ogs_nas_eps_attach_request_t *attach_request, ogs_pkbuf_t *pkbuf) { int served_tai_index = 0; @@ -57,6 +57,13 @@ int emm_handle_attach_request( ogs_assert(esm_message_container); ogs_assert(esm_message_container->length); + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + /* HashMME */ + ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme); + /* Set EPS Attach Type */ memcpy(&mme_ue->nas_eps.attach, eps_attach_type, sizeof(ogs_nas_eps_attach_type_t)); @@ -426,7 +433,7 @@ int emm_handle_service_request( } int emm_handle_tau_request(mme_ue_t *mme_ue, - ogs_nas_eps_tracking_area_update_request_t *tau_request) + ogs_nas_eps_tracking_area_update_request_t *tau_request, ogs_pkbuf_t *pkbuf) { int served_tai_index = 0; @@ -443,6 +450,13 @@ int emm_handle_tau_request(mme_ue_t *mme_ue, enb_ue = mme_ue->enb_ue; ogs_assert(enb_ue); + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + /* HashMME */ + ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme); + /* Set EPS Update Type */ memcpy(&mme_ue->nas_eps.update, eps_update_type, sizeof(ogs_nas_eps_update_type_t)); diff --git a/src/mme/emm-handler.h b/src/mme/emm-handler.h index 990f20e7e..9ea14b93a 100644 --- a/src/mme/emm-handler.h +++ b/src/mme/emm-handler.h @@ -26,8 +26,8 @@ extern "C" { #endif -int emm_handle_attach_request( - mme_ue_t *mme_ue, ogs_nas_eps_attach_request_t *attach_request); +int emm_handle_attach_request(mme_ue_t *mme_ue, + ogs_nas_eps_attach_request_t *attach_request, ogs_pkbuf_t *pkbuf); int emm_handle_attach_complete( mme_ue_t *mme_ue, ogs_nas_eps_attach_complete_t *attach_complete); @@ -40,8 +40,9 @@ int emm_handle_detach_request( int emm_handle_service_request( mme_ue_t *mme_ue, ogs_nas_eps_service_request_t *service_request); -int emm_handle_tau_request( - mme_ue_t *mme_ue, ogs_nas_eps_tracking_area_update_request_t *tau_request); +int emm_handle_tau_request(mme_ue_t *mme_ue, + ogs_nas_eps_tracking_area_update_request_t *tau_request, + ogs_pkbuf_t *pkbuf); int emm_handle_extended_service_request(mme_ue_t *mme_ue, ogs_nas_eps_extended_service_request_t *extended_service_request); diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 11d2d0c36..8ba14e75e 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -185,7 +185,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) case OGS_NAS_EPS_ATTACH_REQUEST: ogs_debug("[EMM] Attach request[%s]", mme_ue->imsi_bcd); rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); + mme_ue, &message->emm.attach_request, e->pkbuf); if (rv != OGS_OK) { ogs_error("emm_handle_attach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); @@ -222,8 +222,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) case OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST: ogs_debug("[EMM] Tracking area update request"); - rv = emm_handle_tau_request( - mme_ue, &message->emm.tracking_area_update_request); + rv = emm_handle_tau_request(mme_ue, + &message->emm.tracking_area_update_request, e->pkbuf); if (rv != OGS_OK) { ogs_error("emm_handle_tau_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); @@ -390,7 +390,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) 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_error("emm_handle_detach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); break; } @@ -581,7 +581,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e) case OGS_NAS_EPS_ATTACH_REQUEST: ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); + mme_ue, &message->emm.attach_request, e->pkbuf); if (rv != OGS_OK) { ogs_error("emm_handle_attach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); @@ -603,7 +603,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e) 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_error("emm_handle_detach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); return; } @@ -737,7 +737,7 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e) case OGS_NAS_EPS_ATTACH_REQUEST: ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); + mme_ue, &message->emm.attach_request, e->pkbuf); if (rv != OGS_OK) { ogs_error("emm_handle_attach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); @@ -765,7 +765,7 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e) 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_error("emm_handle_detach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); break; } @@ -852,7 +852,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) case OGS_NAS_EPS_ATTACH_REQUEST: ogs_warn("[EMM] Attach request[%s]", mme_ue->imsi_bcd); rv = emm_handle_attach_request( - mme_ue, &message->emm.attach_request); + mme_ue, &message->emm.attach_request, e->pkbuf); if (rv != OGS_OK) { ogs_error("emm_handle_attach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); @@ -874,7 +874,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) 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_error("emm_handle_detach_request() failed"); OGS_FSM_TRAN(s, emm_state_exception); return; } diff --git a/src/mme/esm-build.c b/src/mme/esm-build.c index 2dc14cd84..03c900e7d 100644 --- a/src/mme/esm-build.c +++ b/src/mme/esm-build.c @@ -106,6 +106,10 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request( ogs_nas_protocol_configuration_options_t *protocol_configuration_options = &activate_default_eps_bearer_context_request ->protocol_configuration_options; + ogs_nas_extended_protocol_configuration_options_t + *extended_protocol_configuration_options = + &activate_default_eps_bearer_context_request + ->extended_protocol_configuration_options; mme_ue_t *mme_ue = NULL; mme_bearer_t *bearer = NULL; @@ -225,11 +229,20 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request( } if (sess->pgw_pco.presence && sess->pgw_pco.len && sess->pgw_pco.data) { - activate_default_eps_bearer_context_request->presencemask |= - OGS_NAS_EPS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - protocol_configuration_options->length = sess->pgw_pco.len; - memcpy(protocol_configuration_options->buffer, - sess->pgw_pco.data, protocol_configuration_options->length); + if (mme_ue->ue_network_capability. + extended_protocol_configuration_options) { + activate_default_eps_bearer_context_request->presencemask |= + OGS_NAS_EPS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + extended_protocol_configuration_options->length = sess->pgw_pco.len; + extended_protocol_configuration_options->buffer = + sess->pgw_pco.data; + } else { + activate_default_eps_bearer_context_request->presencemask |= + OGS_NAS_EPS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + protocol_configuration_options->length = sess->pgw_pco.len; + memcpy(protocol_configuration_options->buffer, + sess->pgw_pco.data, protocol_configuration_options->length); + } } if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 499ee999f..4548b6ae0 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -358,7 +358,8 @@ struct mme_ue_s { /* Security Context */ ogs_nas_ue_network_capability_t ue_network_capability; ogs_nas_ms_network_capability_t ms_network_capability; - ogs_nas_ue_additional_security_capability_t ue_additional_security_capability; + ogs_nas_ue_additional_security_capability_t + ue_additional_security_capability; uint8_t xres[OGS_MAX_RES_LEN]; uint8_t xres_len; uint8_t kasme[OGS_SHA256_DIGEST_SIZE]; @@ -375,6 +376,7 @@ struct mme_ue_s { uint32_t i32; } ul_count; uint8_t kenb[OGS_SHA256_DIGEST_SIZE]; + uint8_t hash_mme[OGS_HASH_MME_LEN]; struct { ED2(uint8_t nhcc_spare:5;, diff --git a/src/smf/context.c b/src/smf/context.c index 3740a15d1..5a017fc8a 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1207,6 +1207,12 @@ smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi) /* Set PSI */ sess->psi = psi; + /* Set S-NSSAI */ + sess->s_nssai.sst = 0; + sess->s_nssai.sd.v = OGS_S_NSSAI_NO_SD_VALUE; + sess->s_nssai.mapped_hplmn_sst = 0; + sess->s_nssai.mapped_hplmn_sd.v = OGS_S_NSSAI_NO_SD_VALUE; + /* Set TEID & SEID */ sess->smf_n4_teid = sess->index; sess->smf_n4_seid = sess->index; diff --git a/src/smf/gsm-build.c b/src/smf/gsm-build.c index c84b3f407..fea4cc5fd 100644 --- a/src/smf/gsm-build.c +++ b/src/smf/gsm-build.c @@ -145,14 +145,7 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess) /* S-NSSAI */ pdu_session_establishment_accept->presencemask |= OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_ACCEPT_S_NSSAI_PRESENT; - if (sess->s_nssai.sd.v == OGS_S_NSSAI_NO_SD_VALUE) { - nas_s_nssai->length = 1; - nas_s_nssai->sst = sess->s_nssai.sst; - } else { - nas_s_nssai->length = 4; - nas_s_nssai->sst = sess->s_nssai.sst; - nas_s_nssai->sd.v = sess->s_nssai.sd.v; - } + ogs_nas_build_s_nssai(nas_s_nssai, &sess->s_nssai); /* QoS flow descriptions */ memset(&qos_flow_description, 0, sizeof(qos_flow_description)); diff --git a/src/smf/nsmf-handler.c b/src/smf/nsmf-handler.c index b8f9b9fca..f34f39b1b 100644 --- a/src/smf/nsmf-handler.c +++ b/src/smf/nsmf-handler.c @@ -136,6 +136,13 @@ bool smf_nsmf_handle_create_sm_context( sess->s_nssai.sst = sNssai->sst; sess->s_nssai.sd = ogs_s_nssai_sd_from_string(sNssai->sd); + if (SmContextCreateData->hplmn_snssai) { + sess->s_nssai.mapped_hplmn_sst = + SmContextCreateData->hplmn_snssai->sst; + sess->s_nssai.mapped_hplmn_sd = + ogs_s_nssai_sd_from_string( + SmContextCreateData->hplmn_snssai->sd); + } if (sess->sm_context_status_uri) ogs_free(sess->sm_context_status_uri); diff --git a/tests/23504/r16-test.c b/tests/23504/r16-test.c index c223bcad0..3ea3fce30 100644 --- a/tests/23504/r16-test.c +++ b/tests/23504/r16-test.c @@ -35,6 +35,11 @@ static void test1_func(abts_case *tc, void *data) test_ue_t test_ue; + const char *_k_string = "4d060eab0a7743bc8eede608a94b63de"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "7c0f7d5a427048a86fb429cc003c117c"; + uint8_t opc[OGS_KEY_LEN]; + mongoc_collection_t *collection = NULL; bson_t *doc = NULL; int64_t count = 0; @@ -55,7 +60,7 @@ static void test1_func(abts_case *tc, void *data) "\"qci\" : 9, " "\"arp\" : { " "\"priority_level\" : 15," - "\"pre_emption_vulnerability\" : 0, " + "\"pre_emption_vulnerability\" : 1, " "\"pre_emption_capability\" : 1" "} " "}, " @@ -71,10 +76,10 @@ static void test1_func(abts_case *tc, void *data) "\"subscriber_status\" : 0, " "\"access_restriction_data\" : 32, " "\"security\" : { " - "\"k\" : \"465B5CE8 B199B49F AA5F0A2E E238A6BC\", " - "\"opc\" : \"E8ED289D EBA952E4 283B54E8 8E6183CA\", " - "\"amf\" : \"8000\", " - "\"sqn\" : { \"$numberLong\" : \"64\" }, " + "\"k\" : \"4d060eab0a7743bc8eede608a94b63de\", " + "\"opc\" : \"7c0f7d5a427048a86fb429cc003c117c\", " + "\"amf\" : \"9001\", " + "\"sqn\" : { \"$numberLong\" : \"7085\" }, " "\"rand\" : \"198e06800ea7a4c61e9e424f2558a774\" " "}, " "\"__v\" : 0 " @@ -179,13 +184,429 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Receive Initial Context Setup Request + - * Attach Accept + + /* Receive Initial Context Setup Request + + * Attach Accept + * Activate Default Bearer Context Request */ recvbuf = testenb_s1ap_read(s1ap); ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); + /* Send Initial Context Setup Response */ + rv = tests1ap_build_initial_context_setup_response(&sendbuf, + 16777373, 1, 5, 1, "127.0.0.5"); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + rv = tests1ap_build_attach_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi)); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + testenb_s1ap_close(s1ap); + + /* eNB disonncect from SGW */ + testenb_gtpu_close(gtpu); +} + +static void test2_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_s1ap_message_t message; + int i; + int msgindex = 25; + enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; + uint32_t m_tmsi = 0; + + test_ue_t test_ue; + + const char *_k_string = "4d060eab0a7743bc8eede608a94b63de"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "7c0f7d5a427048a86fb429cc003c117c"; + uint8_t opc[OGS_KEY_LEN]; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"235047364000060\", " + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 15," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"security\" : { " + "\"k\" : \"4d060eab0a7743bc8eede608a94b63de\", " + "\"opc\" : \"7c0f7d5a427048a86fb429cc003c117c\", " + "\"amf\" : \"9001\", " + "\"sqn\" : { \"$numberLong\" : \"9034\" }, " + "\"rand\" : \"bb17c5f251e2ff6a528a9e9f70248ed9\" " + "}, " + "\"__v\" : 0 " + "}"; + + /* Setup Test UE & Session Context */ + memset(&test_ue, 0, sizeof(test_ue)); + test_ue.imsi = (char *)"235047364000060"; + + /* eNB connects to MME */ + s1ap = testenb_s1ap_client("127.0.0.1"); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* eNB connects to SGW */ + gtpu = testenb_gtpu_server("127.0.0.5"); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send S1-Setup Reqeust */ + rv = tests1ap_build_setup_req( + &sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x2000, 1, 235, 4, 2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + rv = ogs_s1ap_decode(&message, recvbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ogs_s1ap_free(&message); + ogs_pkbuf_free(recvbuf); + + /********** Insert Subscriber in Database */ + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi)); + ABTS_PTR_NOTNULL(tc, doc); + + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + if (count) { + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + } + bson_destroy(doc); + + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi)); + ABTS_PTR_NOTNULL(tc, doc); + do { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /* Send Attach Request */ + rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Authentication Response */ + rv = tests1ap_build_authentication_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Security mode Complete */ + rv = tests1ap_build_security_mode_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(50); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Initial Context Setup Response */ + rv = tests1ap_build_initial_context_setup_response(&sendbuf, + 1, 1, 5, 0x10783d92, "127.0.0.5"); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + +#if 0 + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + rv = tests1ap_build_attach_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); +#endif + + ogs_msleep(50); + +#if 0 + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); +#endif + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi)); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + testenb_s1ap_close(s1ap); + + /* eNB disonncect from SGW */ + testenb_gtpu_close(gtpu); +} + +static void test3_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_s1ap_message_t message; + int i; + int msgindex = 26; + enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; + uint32_t m_tmsi = 0; + + test_ue_t test_ue; + + const char *_k_string = "4d060eab0a7743bc8eede608a94b63de"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "7c0f7d5a427048a86fb429cc003c117c"; + uint8_t opc[OGS_KEY_LEN]; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"235047364000060\", " + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 15," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"security\" : { " + "\"k\" : \"4d060eab0a7743bc8eede608a94b63de\", " + "\"opc\" : \"7c0f7d5a427048a86fb429cc003c117c\", " + "\"amf\" : \"9001\", " + "\"sqn\" : { \"$numberLong\" : \"8968\" }, " + "\"rand\" : \"5616d4deb87e39be6259ef8e5c753c0b\" " + "}, " + "\"__v\" : 0 " + "}"; + + /* Setup Test UE & Session Context */ + memset(&test_ue, 0, sizeof(test_ue)); + test_ue.imsi = (char *)"235047364000060"; + + /* eNB connects to MME */ + s1ap = testenb_s1ap_client("127.0.0.1"); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* eNB connects to SGW */ + gtpu = testenb_gtpu_server("127.0.0.5"); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send S1-Setup Reqeust */ + rv = tests1ap_build_setup_req( + &sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x2000, 1, 235, 4, 2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + rv = ogs_s1ap_decode(&message, recvbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ogs_s1ap_free(&message); + ogs_pkbuf_free(recvbuf); + + /********** Insert Subscriber in Database */ + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi)); + ABTS_PTR_NOTNULL(tc, doc); + + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + if (count) { + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + } + bson_destroy(doc); + + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi)); + ABTS_PTR_NOTNULL(tc, doc); + do { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /* Send Attach Request */ + rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Authentication Response */ + rv = tests1ap_build_authentication_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Security mode Complete */ + rv = tests1ap_build_security_mode_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Initial Context Setup Response */ + rv = tests1ap_build_initial_context_setup_response(&sendbuf, + 1, 1, 5, 0x1654c84e, "127.0.0.5"); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + rv = tests1ap_build_attach_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi)); ABTS_PTR_NOTNULL(tc, doc); @@ -207,6 +628,8 @@ abts_suite *test_r16(abts_suite *suite) suite = ADD_SUITE(suite) abts_run_test(suite, test1_func, NULL); + abts_run_test(suite, test2_func, NULL); + abts_run_test(suite, test3_func, NULL); return suite; } diff --git a/tests/app/test-packet.c b/tests/app/test-packet.c index 9ddf2c739..91c1ec7f5 100644 --- a/tests/app/test-packet.c +++ b/tests/app/test-packet.c @@ -316,8 +316,17 @@ int tests1ap_build_initial_ue_msg(ogs_pkbuf_t **pkbuf, int i) "0000000000030000 0a00000d005232f5 4000015c20001332 f540000111034f18" "805d0105e010028d c06f04f000f00000 4300060032f54000 01006440080032f5" "4000200010008640 0130", - "", - "", + "000c" + "4074000005000800 020001001a004c4b 0741720829534037 4600000607f0f0c0" + "4001001000230201 d031271d80802110 0101001081060000 0000830600000000" + "000300000a00000d 005c20009011034f 18805d01056f04f0 00f0000043000600" + "32f5400001006440 080032f540002000 100086400130", + "000c" + "4080870000050008 00020001001a005f 5e07417208295340 374600000607f0f0" + "c040018030002702 01d0312721808021 1001010010810600 0000008306000000" + "00000300000a0000 0d00001a010f5232 f54000015c200013 32f540000111034f" + "18805d0105100245 c06f04f000f00000 4300060032f54000 01006440080032f5" + "4000200010008640 0130", }; uint16_t len[TESTS1AP_MAX_MESSAGE] = { 92, @@ -355,8 +364,8 @@ int tests1ap_build_initial_ue_msg(ogs_pkbuf_t **pkbuf, int i) /* 24 */ 140, - 0, - 0, + 120, + 140, }; char hexbuf[OGS_MAX_SDU_LEN]; @@ -537,10 +546,14 @@ int tests1ap_build_authentication_response(ogs_pkbuf_t **pkbuf, int i) /* 24 */ "000d" - "4035000005000000 0200640008000200 01001a000c0b0753 086fe8c7de55d0a2" - "74006440080032f5 4000200010004340 060032f5400001", - "", - "", + "4035000005000000 0200640008000200 01001a000c0b0753 08db8af07f4b815c" + "9a006440080032f5 4000200010004340 060032f5400001", + "000d" + "4035000005000000 0200640008000200 01001a000c0b0753 0886f726fd424fa5" + "ab006440080032f5 4000200010004340 060032f5400001", + "000d" + "4035000005000000 0200640008000200 01001a000c0b0753 08d4150f5e02472e" + "8f006440080032f5 4000200010004340 060032f5400001", }; uint16_t len[TESTS1AP_MAX_MESSAGE] = { @@ -575,12 +588,12 @@ int tests1ap_build_authentication_response(ogs_pkbuf_t **pkbuf, int i) /* 21 */ 63, 63, - 0, + 63, /* 24 */ 57, - 0, - 0, + 57, + 57, }; char hexbuf[OGS_MAX_SDU_LEN]; @@ -708,10 +721,14 @@ int tests1ap_build_security_mode_complete(ogs_pkbuf_t **pkbuf, int i) /* 24 */ "000d" - "403d000005000000 0200640008000200 01001a0014134713 a0e91700075e2309" + "403d000005000000 0200640008000200 01001a0014134725 f0f17d00075e2309" + "8306370004448009 f1006440080032f5 4000200010004340 060032f5400001", + "000d" + "403d000005000000 0200640008000200 01001a0014134716 baaf8800075e2309" + "8306370004448009 f1006440080032f5 4000200010004340 060032f5400001", + "000d" + "403d000005000000 0200640008000200 01001a0014134793 728e4000075e2309" "8306370004448009 f1006440080032f5 4000200010004340 060032f5400001", - "", - "", }; uint16_t len[TESTS1AP_MAX_MESSAGE] = { 57, @@ -749,8 +766,8 @@ int tests1ap_build_security_mode_complete(ogs_pkbuf_t **pkbuf, int i) /* 24 */ 65, - 0, - 0, + 65, + 65, }; char hexbuf[OGS_MAX_SDU_LEN]; @@ -1311,6 +1328,18 @@ int tests1ap_build_attach_complete(ogs_pkbuf_t **pkbuf, int i) "000d403700000500 00000200d1000800 0200d1001a000e0d 27f6962d51010743" "00035200c2006440 080064f013000640 10004340060064f0 130002", "", + + /* 24 */ + "000d" + "4037000005000000 0200640008000200 01001a000e0d277a 6f1f5b0107430003" + "5200c20064400800 32f5400020001000 4340060032f54000 01", + "000d" + "4044000006000000 0200640008000200 01001a000e0d2728 e58e6d0107430003" + "5200c20064400800 32f5400020001000 4340060032f54000 01012040090032f5" + "400012345020", + "000d" + "4037000005000000 0200640008000200 01001a000e0d27e3 11971d0107430003" + "5200c20064400800 32f5400020001000 4340060032f54000 01", }; uint16_t len[TESTS1AP_MAX_MESSAGE] = { 62, @@ -1345,6 +1374,11 @@ int tests1ap_build_attach_complete(ogs_pkbuf_t **pkbuf, int i) 0, 59, 0, + + /* 24 */ + 59, + 72, + 59, }; char hexbuf[OGS_MAX_SDU_LEN]; diff --git a/tests/common/context.c b/tests/common/context.c index 3ad786a6e..b65a891f9 100644 --- a/tests/common/context.c +++ b/tests/common/context.c @@ -423,6 +423,10 @@ int test_context_parse_config(void) s_nssai->sd.v = OGS_S_NSSAI_NO_SD_VALUE; + s_nssai->mapped_hplmn_sst = 0; + s_nssai->mapped_hplmn_sd.v = + OGS_S_NSSAI_NO_SD_VALUE; + self.plmn_support[ self.num_of_plmn_support]. num_of_s_nssai++; diff --git a/tests/common/gmm-build.c b/tests/common/gmm-build.c index 092ff28bc..b6a49e721 100644 --- a/tests/common/gmm-build.c +++ b/tests/common/gmm-build.c @@ -22,6 +22,7 @@ ogs_pkbuf_t *testgmm_build_registration_request( test_ue_t *test_ue, ogs_pkbuf_t *nasbuf) { + int i; test_sess_t *sess = NULL; uint16_t psimask = 0; ogs_s_nssai_t *s_nssai = NULL; @@ -147,11 +148,13 @@ ogs_pkbuf_t *testgmm_build_registration_request( /* Set Requested NSSAI */ registration_request->presencemask |= OGS_NAS_5GS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT; - requested_nssai->length = 0; - ogs_nas_build_nssai(requested_nssai, - &test_self()->plmn_support[0].s_nssai[0], 1); + for (i = 0; i < test_self()->num_of_plmn_support; i++) { + ogs_nas_build_nssai(requested_nssai, + test_self()->plmn_support[i].s_nssai, + test_self()->plmn_support[i].num_of_s_nssai); + } } if (test_ue->registration_request_type.last_visited_registered_tai) { @@ -573,7 +576,7 @@ ogs_pkbuf_t *testgmm_build_ul_nas_transport(test_sess_t *test_sess, ogs_nas_request_type_t *request_type = NULL; #define S_NSSAI_PRECENSE 0 #if S_NSSAI_PRECENSE - ogs_nas_s_nssai_t *s_nssai = NULL; + ogs_nas_s_nssai_t *nas_s_nssai = NULL; #endif ogs_assert(test_sess); @@ -587,7 +590,7 @@ ogs_pkbuf_t *testgmm_build_ul_nas_transport(test_sess_t *test_sess, pdu_session_id = &ul_nas_transport->pdu_session_id; request_type = &ul_nas_transport->request_type; #if S_NSSAI_PRECENSE - s_nssai = &ul_nas_transport->s_nssai; + nas_s_nssai = &ul_nas_transport->s_nssai; #endif memset(&message, 0, sizeof(message)); @@ -616,15 +619,8 @@ ogs_pkbuf_t *testgmm_build_ul_nas_transport(test_sess_t *test_sess, #if S_NSSAI_PRECENSE ul_nas_transport->presencemask |= OGS_NAS_5GS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT; - if (test_self()->plmn_support[0].s_nssai[0].sd.v == - OGS_S_NSSAI_NO_SD_VALUE) { - s_nssai->length = 1; - s_nssai->sst = test_self()->plmn_support[0].s_nssai[0].sst; - } else { - s_nssai->length = 4; - s_nssai->sst = test_self()->plmn_support[0].s_nssai[0].sst; - s_nssai->sd = ogs_htobe24(test_self()->plmn_support[0].s_nssai[0].sd); - } + ogs_nas_build_s_nssai( + nas_s_nssai, &test_self()->plmn_support[0].s_nssai[0]); #endif ul_nas_transport->presencemask |= diff --git a/tests/csfb/mo-idle-test.c b/tests/csfb/mo-idle-test.c index b6dd17adc..83dd3174e 100644 --- a/tests/csfb/mo-idle-test.c +++ b/tests/csfb/mo-idle-test.c @@ -41,9 +41,8 @@ static void test1_func(abts_case *tc, void *data) "000b403800000300 0000020001000800 020001001a002524 075200aa266700bc" "2887354e9f87368d 5d0ae710ab857af5 5f1a8000d71e5537 4ee176e9"; const char *_security_mode_command = - "000b4025" - "0000030000000200 0100080002000100 1a001211379be42b 4200075d010005f0" - "f0c04070c1"; + "000b402f00000300 0000020001000800 020001001a001c1b 37654673a700075d" + "010005f0f0c04070 c14f08e56478c08b 01fb65"; const char *_esm_information_request = "000b401d00000300 0000020001000800 020001001a000a09 27d1237969010234" "d9"; @@ -53,14 +52,13 @@ static void test1_func(abts_case *tc, void *data) "036f72670a010104 0509f1070926"; const char *_initial_context_setup_request = "00090080e9000007 0000000200010008 000200010042000a 183d090000603d09" - "0000001800808e00 0034008088450009 230f807f00000200 0000017927bd89db" - "c802074202490620 09f1070007004652 34c101090908696e 7465726e65740501" + "0000001800808e00 0034008088450009 230f807f00000200 00000179270104e1" + "7e02074202490620 09f1070007004652 34c101090908696e 7465726e65740501" "0a2d00025e06fefe e2e2030327278080 2110020000108106 0808080883060808" - "0404000d04080808 08000d0408080404 0010020578500bf6 09f107000201d900" - "73891309f1070926 2305f49ee88e6459 4964020100006b00 051c000e00000049" + "0404000d04080808 08000d0408080404 0010020578500bf6 09f107000201c100" + "c3ba1309f1070926 2305f49ee88e6459 4964020108006b00 051c000e00000049" "0020f9f4f80b206c 33ae286c6daff4c2 53585174c3a0a12a 661967f5e1ba0a68" "6c8c00c040083572 200924ffff14"; - const char *_emm_information = "000b403800000300 0000020001000800 020001001a002524 2751034124030761" "430f10004f007000 65006e0035004700 5347916051216124 63490100"; diff --git a/tests/epc-simple/attach-test.c b/tests/epc-simple/attach-test.c index 77dbf49ad..23f0343a7 100644 --- a/tests/epc-simple/attach-test.c +++ b/tests/epc-simple/attach-test.c @@ -42,9 +42,8 @@ static void attach_test1(abts_case *tc, void *data) "000b403b00000300 000005c00100009d 000800020001001a 0025240752002008" "0c3818183b522614 162c07601d0d10f1 1b89a2a8de8000ad 0ccf7f55e8b20d"; const char *_security_mode_command = - "000b4028" - "00000300000005c0 0100009d00080002 0001001a00121137 f497722900075d01" - "0005e060c04070c1"; + "000b403200000300 000005c00100009d 000800020001001a 001c1b3708deab59" + "00075d010005e060 c04070c14f08116b f77412f7d151"; const char *_esm_information_request = "000b402000000300 000005c00100009d 000800020001001a 000a092779012320" "010221d9"; @@ -763,15 +762,12 @@ static void attach_test3(abts_case *tc, void *data) "403b000003000000 05c0020000c80008 00020002001a0025 2407520042200639" "1c0021554d444928 4a1a062e10e543cb 257f1f800021f4f9 2d522a5b87"; const char *_security_mode_command = - "000b4025" - "00000300000005c0 020000c800080002 0002001a000f0e37 c48c93b000075d01" - "0002f0f0c1"; - + "000b402f00000300 000005c0020000c8 000800020002001a 001918371fb7de55" + "00075d010002f0f0 c14f088f4677974b faed1e"; const char *_esm_information_request = "000b" "4020000003000000 05c0020000c80008 00020002001a000a 09277330e06c0102" "01d9"; - const char *_initial_context_setup_request = "00090080c8000006 00000005c0020000 c800080002000200 42000a183e800000" "603e800000001800 7700003400724540 0920000000000000 00000f800a0123d8" diff --git a/tests/mnc3/mnc3-test.c b/tests/mnc3/mnc3-test.c index 1a2be73a5..02709d793 100644 --- a/tests/mnc3/mnc3-test.c +++ b/tests/mnc3/mnc3-test.c @@ -38,21 +38,19 @@ static void test1_func(abts_case *tc, void *data) "000b403b00000300 000005c001a00102 000800020018001a 002524075200906d" "231ff57ef278c719 1d170303deb610d0 7c4defa47480001f 2b5350926bdb3a"; const char *_security_mode_command = - "000b4025" - "00000300000005c0 01a0010200080002 0018001a000f0e37 62522c0900075d01" - "0002e0e0c1"; + "000b402f00000300 000005c001a00102 000800020018001a 00191837b4fe6e27" + "00075d010002e0e0 c14f08d14b7a88d1 d1d02e"; const char *_esm_information_request = "000b402000000300 000005c001a00102 000800020018001a 000a0927846a01a8" "010201d9"; const char *_initial_context_setup_request = "00090080c2000006 00000005c001a001 0200080002001800 42000a183d090000" - "603d090000001800 71000034006c4500 093d0f807f000002 000000015d2729ff" - "32a202074201490c 0313401000320033 0034003500315201 c101090c07737461" + "603d090000001800 71000034006c4500 093d0f807f000002 000000015d279cc9" + "988102074201490c 0313401000320033 0034003500315201 c101090c07737461" "72656e7403636f6d 05010a2d00025e06 fefee2e20303270f 80000d0408080808" - "000d040808040450 0bf6134010801e64 ff0077e359496402 0100006b00051800" + "000d040808040450 0bf6134010801e64 ee00502459496402 0108006b00051800" "0c00000049002046 c789cba93e9b9775 8335c097e6c386c8 72e4b82434a48037" "c30601590edd8e"; - const char *_emm_information = "000b403b00000300 000005c001a00102 000800020018001a 0025242729f8b0bb" "030761430f10004f 00700065006e0035 0047005347914032 80113463490100"; diff --git a/tests/unit/nas-message-test.c b/tests/unit/nas-message-test.c index ee6c33e9b..180ff7176 100644 --- a/tests/unit/nas-message-test.c +++ b/tests/unit/nas-message-test.c @@ -121,9 +121,12 @@ static void ogs_nas_eps_message_test2(abts_case *tc, void *data) attach_accept->presencemask |= OGS_NAS_EPS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; attach_accept->eps_network_feature_support.length = 1; - attach_accept->eps_network_feature_support.esr_ps = 1; - attach_accept->eps_network_feature_support.emc_bs = 1; - attach_accept->eps_network_feature_support.ims_vops = 1; + attach_accept->eps_network_feature_support. + support_of_extended_service_request_for_packet_services = 1; + attach_accept->eps_network_feature_support. + emergency_bearer_services_in_s1_mode = 1; + attach_accept->eps_network_feature_support. + ims_voice_over_ps_session_in_s1_mode = 1; pkbuf = ogs_nas_eps_plain_encode(&message); ABTS_INT_EQUAL(tc, sizeof(buffer), pkbuf->len);