diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index 450c027889..68550f5304 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -847,7 +847,6 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) SWITCH(sbi_message->h.resource.component[1]) CASE(OGS_SBI_RESOURCE_NAME_AM_DATA) CASE(OGS_SBI_RESOURCE_NAME_SMF_SELECT_DATA) - CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXT_IN_SMF_DATA) if (sbi_message->res_status != OGS_SBI_HTTP_STATUS_OK) { ogs_error("[%s] HTTP response error [%d]", amf_ue->supi, sbi_message->res_status); @@ -859,6 +858,29 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) amf_nudm_sdm_handle_provisioned(amf_ue, sbi_message); break; + CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXT_IN_SMF_DATA) + /* + * Issues #553 + * + * o Tester + * 1. UE registered to 5GS and can connect to internet. + * 2. Turn off the UE and turn on the UE immediately + * 3. UE send PDU session request message + * without sending registration complete + * + * o Analysis Result + * 1. UE sends registration request with unknown GUTI + * 2. AMF send registration accept without GUTI + * 3. UE skips the registration complete + * + * So, if GUTI is not present, + * we need to move REGISTERED state. + */ + if (amf_ue->guti_present == 0) + OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_registered); + + nas_5gs_send_registration_accept(amf_ue); + break; DEFAULT ogs_error("Invalid resource name [%s]", @@ -913,28 +935,6 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) OGS_FSM_TRAN(s, &gmm_state_registered); break; - case OGS_NAS_5GS_UL_NAS_TRANSPORT: - /* - * Issues #553 - * - * o Tester - * 1. UE registered to 5GS and can connect to internet. - * 2. Turn off the UE and turn on the UE immediately - * 3. UE send PDU session request message - * without sending registration complete - * - * o Analysis Result - * 1. UE sends registration request with unknown GUTI - * 2. AMF send registration accept without GUTI - * 3. UE skips the registration complete - * - * So, we need the handler UL NAS Transport in this state. - */ - gmm_handle_ul_nas_transport( - amf_ue, &nas_message->gmm.ul_nas_transport); - OGS_FSM_TRAN(s, &gmm_state_registered); - break; - case OGS_NAS_5GS_REGISTRATION_REQUEST: ogs_warn("Registration request"); rv = gmm_handle_registration_request( diff --git a/src/amf/nudm-handler.c b/src/amf/nudm-handler.c index 234b4c4b9a..0591bc68e3 100644 --- a/src/amf/nudm-handler.c +++ b/src/amf/nudm-handler.c @@ -85,10 +85,6 @@ int amf_nudm_sdm_handle_provisioned( amf_nudm_sdm_build_get); break; - CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXT_IN_SMF_DATA) - nas_5gs_send_registration_accept(amf_ue); - break; - DEFAULT END diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index e0c5b9ff08..c13df16fd1 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -721,7 +721,10 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e) 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); + if (mme_ue->guti_present) + OGS_FSM_TRAN(s, &emm_state_initial_context_setup); + else + OGS_FSM_TRAN(s, &emm_state_registered); } else if (mme_ue->nas_eps.type == MME_EPS_TYPE_SERVICE_REQUEST || mme_ue->nas_eps.type == MME_EPS_TYPE_TAU_REQUEST) { diff --git a/src/mme/esm-build.c b/src/mme/esm-build.c index 03c900e7de..5e22adae22 100644 --- a/src/mme/esm-build.c +++ b/src/mme/esm-build.c @@ -41,7 +41,7 @@ ogs_pkbuf_t *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 (!SESSION_CONTEXT_IN_ATTACH(sess)) { message.h.security_header_type = OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM; @@ -53,11 +53,10 @@ ogs_pkbuf_t *esm_build_pdn_connectivity_reject( pdn_connectivity_reject->esm_cause = esm_cause; - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { - return nas_eps_security_encode(mme_ue, &message); - } else { + if (SESSION_CONTEXT_IN_ATTACH(sess)) return ogs_nas_eps_plain_encode(&message); - } + else + return nas_eps_security_encode(mme_ue, &message); } ogs_pkbuf_t *esm_build_information_request(mme_bearer_t *bearer) @@ -133,7 +132,7 @@ ogs_pkbuf_t *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 (!SESSION_CONTEXT_IN_ATTACH(sess)) { message.h.security_header_type = OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM; @@ -245,11 +244,10 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request( } } - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { - return nas_eps_security_encode(mme_ue, &message); - } else { + if (SESSION_CONTEXT_IN_ATTACH(sess)) return ogs_nas_eps_plain_encode(&message); - } + else + return nas_eps_security_encode(mme_ue, &message); } ogs_pkbuf_t *esm_build_activate_dedicated_bearer_context_request( @@ -416,7 +414,7 @@ ogs_pkbuf_t *esm_build_bearer_resource_allocation_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 (!SESSION_CONTEXT_IN_ATTACH(sess)) { message.h.security_header_type = OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM; @@ -429,11 +427,10 @@ ogs_pkbuf_t *esm_build_bearer_resource_allocation_reject( bearer_resource_allocation_reject->esm_cause = esm_cause; - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { - return nas_eps_security_encode(mme_ue, &message); - } else { + if (SESSION_CONTEXT_IN_ATTACH(sess)) return ogs_nas_eps_plain_encode(&message); - } + else + return nas_eps_security_encode(mme_ue, &message); } ogs_pkbuf_t *esm_build_bearer_resource_modification_reject( @@ -458,7 +455,7 @@ ogs_pkbuf_t *esm_build_bearer_resource_modification_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 (!SESSION_CONTEXT_IN_ATTACH(sess)) { message.h.security_header_type = OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM; @@ -472,9 +469,8 @@ ogs_pkbuf_t *esm_build_bearer_resource_modification_reject( bearer_resource_modification_reject->esm_cause = esm_cause; - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { - return nas_eps_security_encode(mme_ue, &message); - } else { + if (SESSION_CONTEXT_IN_ATTACH(sess)) return ogs_nas_eps_plain_encode(&message); - } + else + return nas_eps_security_encode(mme_ue, &message); } diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index c848ae1601..6ce897f8e8 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -2743,6 +2743,17 @@ mme_sess_t *mme_sess_next(mme_sess_t *sess) return ogs_list_next(sess); } +bool mme_sess_in_attach(mme_sess_t *sess) +{ + mme_ue_t *mme_ue = NULL; + + ogs_assert(sess); + mme_ue = sess->mme_ue; + ogs_assert(mme_ue); + + return ogs_list_first(&mme_ue->sess_list) == sess; +} + unsigned int mme_sess_count(mme_ue_t *mme_ue) { unsigned int count = 0; diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 87c8df5826..5f0c51d6d3 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -761,10 +761,14 @@ void mme_sess_remove_all(mme_ue_t *mme_ue); mme_sess_t *mme_sess_find_by_pti(mme_ue_t *mme_ue, uint8_t pti); mme_sess_t *mme_sess_find_by_ebi(mme_ue_t *mme_ue, uint8_t ebi); mme_sess_t *mme_sess_find_by_apn(mme_ue_t *mme_ue, char *apn); + mme_sess_t *mme_sess_first(mme_ue_t *mme_ue); mme_sess_t *mme_sess_next(mme_sess_t *sess); unsigned int mme_sess_count(mme_ue_t *mme_ue); +#define SESSION_CONTEXT_IN_ATTACH(__sESS) mme_sess_in_attach(__sESS) +bool mme_sess_in_attach(mme_sess_t *sess); + mme_bearer_t *mme_bearer_add(mme_sess_t *sess); void mme_bearer_remove(mme_bearer_t *bearer); void mme_bearer_remove_all(mme_sess_t *sess); diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index 1b72e7a635..824276aab5 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -187,7 +187,7 @@ void mme_s11_handle_create_session_response( rv = ogs_gtp_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip); ogs_assert(rv == OGS_OK); - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_initial_context_setup)) { + if (SESSION_CONTEXT_IN_ATTACH(sess)) { mme_csmap_t *csmap = mme_csmap_find_by_tai(&mme_ue->tai); mme_ue->csmap = csmap; @@ -197,10 +197,9 @@ void mme_s11_handle_create_session_response( nas_eps_send_attach_accept(mme_ue); } - } else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { + } else { nas_eps_send_activate_default_bearer_context_request(bearer); - } else - ogs_assert_if_reached(); + } } void mme_s11_handle_modify_bearer_response( diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 86ce52914d..2d5f800f3d 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -471,34 +471,24 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) case OGS_DIAM_S6A_CMD_CODE_UPDATE_LOCATION: mme_s6a_handle_ula(mme_ue, &s6a_message->ula_message); - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_initial_context_setup)) { - if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) { - rv = nas_eps_send_emm_to_esm(mme_ue, - &mme_ue->pdn_connectivity_request); - if (rv != OGS_OK) { - ogs_error("nas_eps_send_emm_to_esm() failed"); - nas_eps_send_attach_reject(mme_ue, - EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, - ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); - } - } else { - ogs_fatal("Invalid Type[%d]", mme_ue->nas_eps.type); - ogs_assert_if_reached(); + if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) { + rv = nas_eps_send_emm_to_esm(mme_ue, + &mme_ue->pdn_connectivity_request); + if (rv != OGS_OK) { + ogs_error("nas_eps_send_emm_to_esm() failed"); + nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, + ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); } - } - else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { - if (mme_ue->nas_eps.type == MME_EPS_TYPE_TAU_REQUEST) { - nas_eps_send_tau_accept(mme_ue, - S1AP_ProcedureCode_id_InitialContextSetup); - } else if (mme_ue->nas_eps.type == - MME_EPS_TYPE_SERVICE_REQUEST) { - s1ap_send_initial_context_setup_request(mme_ue); - } else { - ogs_fatal("Invalid Type[%d]", mme_ue->nas_eps.type); - ogs_assert_if_reached(); - } - } else + } else if (mme_ue->nas_eps.type == MME_EPS_TYPE_TAU_REQUEST) { + nas_eps_send_tau_accept(mme_ue, + S1AP_ProcedureCode_id_InitialContextSetup); + } else if (mme_ue->nas_eps.type == MME_EPS_TYPE_SERVICE_REQUEST) { + s1ap_send_initial_context_setup_request(mme_ue); + } else { + ogs_fatal("Invalid Type[%d]", mme_ue->nas_eps.type); ogs_assert_if_reached(); + } break; default: ogs_error("Invalid Type[%d]", s6a_message->cmd_code); diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index ab063f0d73..2841befd25 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -277,17 +277,17 @@ void nas_eps_send_pdn_connectivity_reject( mme_ue = sess->mme_ue; ogs_assert(mme_ue); - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { + if (SESSION_CONTEXT_IN_ATTACH(sess)) { + /* During the UE-attach process, we'll send Attach-Reject + * with pyggybacking PDN-connectivity-Reject */ + nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, esm_cause); + } else { esmbuf = esm_build_pdn_connectivity_reject(sess, esm_cause); ogs_expect_or_return(esmbuf); rv = nas_eps_send_to_downlink_nas_transport(mme_ue, esmbuf); ogs_expect(rv == OGS_OK); - } else { - /* During the UE-attach process, we'll send Attach-Reject - * with pyggybacking PDN-connectivity-Reject */ - nas_eps_send_attach_reject(mme_ue, - EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, esm_cause); } } diff --git a/tests/attach/ue-context-test.c b/tests/attach/ue-context-test.c index 8be7fc9b0a..7848f7e311 100644 --- a/tests/attach/ue-context-test.c +++ b/tests/attach/ue-context-test.c @@ -594,24 +594,9 @@ static void test2_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Send Attach Complete + Activate default EPS bearer cotext accept */ - test_ue->nr_cgi.cell_id = 0x1234502; - bearer = test_bearer_find_by_ue_ebi(test_ue, 5); - ogs_assert(bearer); - esmbuf = testesm_build_activate_default_eps_bearer_context_accept( - bearer, false); - ABTS_PTR_NOTNULL(tc, esmbuf); - emmbuf = testemm_build_attach_complete(test_ue, esmbuf); - ABTS_PTR_NOTNULL(tc, emmbuf); - sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); - ABTS_PTR_NOTNULL(tc, sendbuf); - 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); - tests1ap_recv(test_ue, recvbuf); + /* GUTI Not Present + * SKIP Send Attach Complete + Activate default EPS bearer cotext accept + * SKIP Receive EMM information */ /* Send Initial context setup failure */ sendbuf = test_s1ap_build_initial_context_setup_failure(test_ue, @@ -974,24 +959,9 @@ static void test3_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Send Attach Complete + Activate default EPS bearer cotext accept */ - test_ue->nr_cgi.cell_id = 0x1234502; - bearer = test_bearer_find_by_ue_ebi(test_ue, 5); - ogs_assert(bearer); - esmbuf = testesm_build_activate_default_eps_bearer_context_accept( - bearer, false); - ABTS_PTR_NOTNULL(tc, esmbuf); - emmbuf = testemm_build_attach_complete(test_ue, esmbuf); - ABTS_PTR_NOTNULL(tc, emmbuf); - sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); - ABTS_PTR_NOTNULL(tc, sendbuf); - 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); - tests1ap_recv(test_ue, recvbuf); + /* GUTI Not Present + * SKIP Send Attach Complete + Activate default EPS bearer cotext accept + * SKIP Receive EMM information */ /* Send UE Context Release Request */ sendbuf = test_s1ap_build_ue_context_release_request(test_ue, @@ -1084,7 +1054,7 @@ static void test3_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - ogs_msleep(100); + ogs_msleep(300); /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); diff --git a/tests/common/esm-build.c b/tests/common/esm-build.c index 28c210b797..5bc9af177b 100644 --- a/tests/common/esm-build.c +++ b/tests/common/esm-build.c @@ -213,7 +213,6 @@ ogs_pkbuf_t *testesm_build_activate_default_eps_bearer_context_accept( message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM; } - message.esm.h.eps_bearer_identity = bearer->ebi; message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM; message.esm.h.message_type = diff --git a/tests/registration/ue-context-test.c b/tests/registration/ue-context-test.c index f23c3f532c..d7786bb43c 100644 --- a/tests/registration/ue-context-test.c +++ b/tests/registration/ue-context-test.c @@ -250,11 +250,352 @@ static void test1_func(abts_case *tc, void *data) test_ue_remove(test_ue); } +static void test2_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + const char *_k_string = "70d49a71dd1a2b806a25abe0ef749f1e"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "6f1bf53d624b3a43af6592854e2444c7"; + 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\" : \"597223158b8861d7605378c6\" }, " + "\"imsi\" : \"901700000021309\"," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1024000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1024000\" } " + "}," + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"597223158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1024000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1024000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"security\" : { " + "\"k\" : \"70d49a71dd1a2b806a25abe0ef749f1e\", " + "\"opc\" : \"6f1bf53d624b3a43af6592854e2444c7\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"25235952177090\" } " + "}, " + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"__v\" : 0 " + "}"; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.type = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + OGS_HEX(_k_string, strlen(_k_string), test_ue->k); + OGS_HEX(_opc_string, strlen(_opc_string), test_ue->opc); + + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 30); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, 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); + + /* Send Registration request */ + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial context setup request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* OLD Receive UE context release command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send OLD UE Context Release Complete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial context setup request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Initial context setup response */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* GUTI Not Present + * SKIP Send Registration complete */ + /* SKIP Receive Configuration update command */ + + /* Send PDU session establishment request */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session resource setup response */ + sendbuf = testngap_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_ue_qfi(test_ue, 1); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + ogs_msleep(300); + + /* Send Initial context setup failure */ + sendbuf = testngap_build_initial_context_setup_failure(test_ue, + NGAP_Cause_PR_radioNetwork, + NGAP_CauseRadioNetwork_radio_connection_with_ue_lost); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + + /* Receive UE context release command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send UE context release complete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /********** 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); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + abts_suite *test_ue_context(abts_suite *suite) { suite = ADD_SUITE(suite) abts_run_test(suite, test1_func, NULL); + abts_run_test(suite, test2_func, NULL); return suite; }