mirror of
https://github.com/open5gs/open5gs.git
synced 2026-04-28 03:19:31 +00:00
[AMF] Follow-up on Context transfer (#3052)
This commit is contained in:
parent
2a4d8db72e
commit
7062b9c0d6
18 changed files with 1216 additions and 613 deletions
|
|
@ -1082,21 +1082,3 @@ cleanup:
|
|||
|
||||
return (int)(rule-first);
|
||||
}
|
||||
|
||||
bool ogs_nas_5gs_guti_is_valid(ogs_nas_5gs_guti_t *guti)
|
||||
{
|
||||
if ((guti->amf_id.region !=0) &&
|
||||
(guti->amf_id.set2 !=0) &&
|
||||
(guti->m_tmsi != 0) &&
|
||||
((guti->nas_plmn_id.mcc1) !=0 ||
|
||||
(guti->nas_plmn_id.mcc2) !=0 ||
|
||||
(guti->nas_plmn_id.mcc3) !=0) &&
|
||||
((guti->nas_plmn_id.mnc1) !=0 ||
|
||||
(guti->nas_plmn_id.mnc2) !=0 ||
|
||||
(guti->nas_plmn_id.mnc3) !=0)) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1192,8 +1192,6 @@ typedef struct ogs_nas_rsn_s {
|
|||
uint8_t value;
|
||||
} __attribute__ ((packed)) ogs_nas_rsn_t;
|
||||
|
||||
bool ogs_nas_5gs_guti_is_valid(ogs_nas_5gs_guti_t *guti);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1983,9 +1983,9 @@ bool ogs_sbi_discovery_option_is_matched(
|
|||
switch (nf_info->nf_type) {
|
||||
case OpenAPI_nf_type_AMF:
|
||||
if (requester_nf_type == OpenAPI_nf_type_AMF &&
|
||||
discovery_option->target_guami &&
|
||||
discovery_option->guami_presence &&
|
||||
ogs_sbi_check_amf_info_guami(&nf_info->amf,
|
||||
discovery_option->target_guami) == false)
|
||||
&discovery_option->guami) == false)
|
||||
return false;
|
||||
break;
|
||||
case OpenAPI_nf_type_SMF:
|
||||
|
|
|
|||
|
|
@ -394,16 +394,18 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message)
|
|||
OGS_SBI_PARAM_REQUESTER_NF_INSTANCE_ID,
|
||||
discovery_option->requester_nf_instance_id);
|
||||
}
|
||||
if (discovery_option->target_guami) {
|
||||
if (discovery_option->guami_presence) {
|
||||
char *v = ogs_sbi_discovery_option_build_guami(discovery_option);
|
||||
if (v) {
|
||||
ogs_sbi_header_set(request->http.params,
|
||||
OGS_SBI_PARAM_GUAMI, v);
|
||||
ogs_free(v);
|
||||
} else {
|
||||
ogs_warn("build failed: service-names[%d:%s]",
|
||||
discovery_option->num_of_service_names,
|
||||
discovery_option->service_names[0]);
|
||||
ogs_error("build failed: guami[PLMN_ID:%06x,AMF_ID:%d]",
|
||||
ogs_plmn_id_hexdump(
|
||||
&discovery_option->guami.plmn_id),
|
||||
ogs_amf_id_hexdump(
|
||||
&discovery_option->guami.amf_id));
|
||||
}
|
||||
}
|
||||
if (ogs_sbi_self()->discovery_config.no_service_names == false &&
|
||||
|
|
@ -2940,8 +2942,6 @@ void ogs_sbi_discovery_option_free(
|
|||
ogs_free(discovery_option->requester_nf_instance_id);
|
||||
if (discovery_option->dnn)
|
||||
ogs_free(discovery_option->dnn);
|
||||
if (discovery_option->target_guami)
|
||||
ogs_free(discovery_option->target_guami);
|
||||
|
||||
for (i = 0; i < discovery_option->num_of_service_names; i++)
|
||||
ogs_free(discovery_option->service_names[i]);
|
||||
|
|
@ -3182,6 +3182,18 @@ void ogs_sbi_discovery_option_parse_snssais(
|
|||
ogs_free(v);
|
||||
}
|
||||
|
||||
void ogs_sbi_discovery_option_set_guami(
|
||||
ogs_sbi_discovery_option_t *discovery_option, ogs_guami_t *guami)
|
||||
{
|
||||
ogs_assert(discovery_option);
|
||||
ogs_assert(guami);
|
||||
|
||||
ogs_assert(discovery_option->guami_presence == false);
|
||||
|
||||
memcpy(&discovery_option->guami, guami, sizeof(ogs_guami_t));
|
||||
discovery_option->guami_presence = true;
|
||||
}
|
||||
|
||||
char *ogs_sbi_discovery_option_build_guami(
|
||||
ogs_sbi_discovery_option_t *discovery_option)
|
||||
{
|
||||
|
|
@ -3190,9 +3202,9 @@ char *ogs_sbi_discovery_option_build_guami(
|
|||
char *v = NULL;
|
||||
|
||||
ogs_assert(discovery_option);
|
||||
ogs_assert(discovery_option->target_guami);
|
||||
ogs_assert(discovery_option->guami_presence);
|
||||
|
||||
Guami = ogs_sbi_build_guami(discovery_option->target_guami);
|
||||
Guami = ogs_sbi_build_guami(&discovery_option->guami);
|
||||
ogs_assert(Guami);
|
||||
guamiItem = OpenAPI_guami_convertToJSON(Guami);
|
||||
ogs_assert(guamiItem);
|
||||
|
|
@ -3231,12 +3243,9 @@ void ogs_sbi_discovery_option_parse_guami(
|
|||
Guami = OpenAPI_guami_parseFromJSON(guamItem);
|
||||
|
||||
if (Guami) {
|
||||
ogs_guami_t *ogs_guami = NULL;
|
||||
|
||||
discovery_option->target_guami = ogs_malloc(sizeof(*ogs_guami));
|
||||
ogs_assert(discovery_option->target_guami);
|
||||
|
||||
ogs_sbi_parse_guami(discovery_option->target_guami, Guami);
|
||||
ogs_guami_t guami;
|
||||
ogs_sbi_parse_guami(&guami, Guami);
|
||||
ogs_sbi_discovery_option_set_guami(discovery_option, &guami);
|
||||
OpenAPI_guami_free(Guami);
|
||||
} else {
|
||||
ogs_error("OpenAPI_guami_parseFromJSON() failed : guami[%s]",
|
||||
|
|
|
|||
|
|
@ -435,7 +435,8 @@ typedef struct ogs_sbi_discovery_option_s {
|
|||
bool tai_presence;
|
||||
ogs_5gs_tai_t tai;
|
||||
|
||||
ogs_guami_t *target_guami;
|
||||
bool guami_presence;
|
||||
ogs_guami_t guami;
|
||||
|
||||
int num_of_target_plmn_list;
|
||||
ogs_plmn_id_t target_plmn_list[OGS_MAX_NUM_OF_PLMN];
|
||||
|
|
@ -649,6 +650,8 @@ char *ogs_sbi_discovery_option_build_snssais(
|
|||
void ogs_sbi_discovery_option_parse_snssais(
|
||||
ogs_sbi_discovery_option_t *discovery_option, char *snssais);
|
||||
|
||||
void ogs_sbi_discovery_option_set_guami(
|
||||
ogs_sbi_discovery_option_t *discovery_option, ogs_guami_t *guami);
|
||||
char *ogs_sbi_discovery_option_build_guami(
|
||||
ogs_sbi_discovery_option_t *discovery_option);
|
||||
void ogs_sbi_discovery_option_parse_guami(
|
||||
|
|
|
|||
|
|
@ -284,9 +284,14 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
/* Target NF-Instance */
|
||||
nf_instance = OGS_SBI_GET_NF_INSTANCE(
|
||||
sbi_object->service_type_array[service_type]);
|
||||
ogs_debug("OGS_SBI_GET_NF_INSTANCE [nf_instance:%p,service_name:%s]",
|
||||
nf_instance, ogs_sbi_service_type_to_name(service_type));
|
||||
if (!nf_instance) {
|
||||
nf_instance = ogs_sbi_nf_instance_find_by_discovery_param(
|
||||
target_nf_type, requester_nf_type, discovery_option);
|
||||
ogs_debug("ogs_sbi_nf_instance_find_by_discovery_param() "
|
||||
"[nf_instance:%p,service_name:%s]",
|
||||
nf_instance, ogs_sbi_service_type_to_name(service_type));
|
||||
if (nf_instance)
|
||||
OGS_SBI_SETUP_NF_INSTANCE(
|
||||
sbi_object->service_type_array[service_type], nf_instance);
|
||||
|
|
@ -337,6 +342,7 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
apiroot = ogs_sbi_client_apiroot(client);
|
||||
ogs_assert(apiroot);
|
||||
|
||||
ogs_debug("apiroot [%s]", apiroot);
|
||||
ogs_sbi_header_set(request->http.headers,
|
||||
OGS_SBI_CUSTOM_TARGET_APIROOT, apiroot);
|
||||
|
||||
|
|
@ -355,6 +361,8 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
*/
|
||||
if (discovery_option &&
|
||||
discovery_option->target_nf_instance_id) {
|
||||
ogs_debug("target_nf_instance_id [%s]",
|
||||
discovery_option->target_nf_instance_id);
|
||||
ogs_sbi_header_set(request->http.headers,
|
||||
OGS_SBI_CUSTOM_DISCOVERY_TARGET_NF_INSTANCE_ID,
|
||||
discovery_option->target_nf_instance_id);
|
||||
|
|
@ -362,6 +370,7 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
ogs_sbi_header_set(request->http.headers,
|
||||
OGS_SBI_CUSTOM_DISCOVERY_TARGET_NF_INSTANCE_ID,
|
||||
nf_instance->id);
|
||||
ogs_debug("nf_instance->id [%s]", nf_instance->id);
|
||||
}
|
||||
|
||||
if (discovery_option && discovery_option->num_of_snssais) {
|
||||
|
|
@ -373,6 +382,7 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
if (v) {
|
||||
char *encoded = ogs_sbi_url_encode(v);
|
||||
ogs_expect(encoded);
|
||||
ogs_debug("snssai [%s]", v);
|
||||
|
||||
if (encoded) {
|
||||
/*
|
||||
|
|
@ -399,6 +409,7 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
}
|
||||
|
||||
if (discovery_option && discovery_option->dnn) {
|
||||
ogs_debug("dnn [%s]", discovery_option->dnn);
|
||||
ogs_sbi_header_set(request->http.headers,
|
||||
OGS_SBI_CUSTOM_DISCOVERY_DNN, discovery_option->dnn);
|
||||
}
|
||||
|
|
@ -408,9 +419,11 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
char *v = ogs_sbi_discovery_option_build_tai(discovery_option);
|
||||
ogs_expect(v);
|
||||
|
||||
|
||||
if (v) {
|
||||
char *encoded = ogs_sbi_url_encode(v);
|
||||
ogs_expect(encoded);
|
||||
ogs_debug("tai [%s]", v);
|
||||
|
||||
if (encoded) {
|
||||
ogs_sbi_header_set(request->http.headers,
|
||||
|
|
@ -429,7 +442,7 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
discovery_option->tai.tac.v);
|
||||
}
|
||||
|
||||
if (discovery_option && discovery_option->target_guami) {
|
||||
if (discovery_option && discovery_option->guami_presence) {
|
||||
bool rc = false;
|
||||
char *v = ogs_sbi_discovery_option_build_guami(discovery_option);
|
||||
ogs_expect(v);
|
||||
|
|
@ -437,6 +450,7 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
if (v) {
|
||||
char *encoded = ogs_sbi_url_encode(v);
|
||||
ogs_expect(encoded);
|
||||
ogs_debug("guami [%s]", v);
|
||||
|
||||
if (encoded) {
|
||||
ogs_sbi_header_set(request->http.headers,
|
||||
|
|
@ -451,9 +465,9 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
|
|||
if (rc == false)
|
||||
ogs_error("build failed: guami[PLMN_ID:%06x,AMF_ID:%x]",
|
||||
ogs_plmn_id_hexdump(
|
||||
&discovery_option->target_guami->plmn_id),
|
||||
&discovery_option->guami.plmn_id),
|
||||
ogs_amf_id_hexdump(
|
||||
&discovery_option->target_guami->amf_id));
|
||||
&discovery_option->guami.amf_id));
|
||||
}
|
||||
|
||||
if (discovery_option &&
|
||||
|
|
|
|||
|
|
@ -1980,31 +1980,26 @@ static bool amf_namf_comm_parse_guti(ogs_nas_5gs_guti_t *guti, char *ue_context_
|
|||
|
||||
short index = 8; /* start parsing guti after "5g-guti-" */
|
||||
|
||||
strncpy(mcc_string, &ue_context_id[index], LENGTH_OF_MCC);
|
||||
mcc_string[LENGTH_OF_MCC] = '\0';
|
||||
ogs_cpystrn(mcc_string, &ue_context_id[index], LENGTH_OF_MCC+1);
|
||||
index += LENGTH_OF_MCC;
|
||||
|
||||
if (strlen(ue_context_id) == OGS_MAX_5G_GUTI_LEN - 1) {
|
||||
/* mnc is 2 characters long */
|
||||
mnc_string[MIN_LENGTH_OF_MNC] = '\0';
|
||||
strncpy(mnc_string, &ue_context_id[index], MIN_LENGTH_OF_MNC);
|
||||
ogs_cpystrn(mnc_string, &ue_context_id[index], MIN_LENGTH_OF_MNC+1);
|
||||
index += MIN_LENGTH_OF_MNC;
|
||||
} else if (strlen(ue_context_id) == OGS_MAX_5G_GUTI_LEN) {
|
||||
/* mnc is 3 characters long */
|
||||
mnc_string[MAX_LENGTH_OF_MNC] = '\0';
|
||||
strncpy(mnc_string, &ue_context_id[index], MAX_LENGTH_OF_MNC);
|
||||
ogs_cpystrn(mnc_string, &ue_context_id[index], MAX_LENGTH_OF_MNC+1);
|
||||
index += MAX_LENGTH_OF_MNC;
|
||||
} else {
|
||||
ogs_error("Invalid Ue context id");
|
||||
return false;
|
||||
}
|
||||
|
||||
strncpy(amf_id_string, &ue_context_id[index], LENGTH_OF_AMF_ID);
|
||||
amf_id_string[LENGTH_OF_AMF_ID] = '\0';
|
||||
ogs_cpystrn(amf_id_string, &ue_context_id[index], LENGTH_OF_AMF_ID+1);
|
||||
index += LENGTH_OF_AMF_ID;
|
||||
|
||||
strncpy(tmsi_string, &ue_context_id[index], LENGTH_OF_TMSI);
|
||||
tmsi_string[LENGTH_OF_TMSI] = '\0';
|
||||
ogs_cpystrn(tmsi_string, &ue_context_id[index], LENGTH_OF_TMSI+1);
|
||||
|
||||
memset(&Plmn_id, 0, sizeof(Plmn_id));
|
||||
Plmn_id.mcc = mcc_string;
|
||||
|
|
|
|||
|
|
@ -268,6 +268,8 @@ struct amf_ue_s {
|
|||
ogs_nas_5gs_guti_t guti;
|
||||
} current, next;
|
||||
|
||||
ogs_nas_5gs_guti_t old_guti;
|
||||
|
||||
/* UE Info */
|
||||
ogs_guami_t *guami;
|
||||
uint16_t gnb_ostream_id;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_request(amf_ue_t *amf_ue,
|
|||
ogs_nas_5gs_mobile_identity_suci_t *mobile_identity_suci = NULL;
|
||||
ogs_nas_5gs_mobile_identity_guti_t *mobile_identity_guti = NULL;
|
||||
ogs_nas_ue_security_capability_t *ue_security_capability = NULL;
|
||||
ogs_nas_5gs_guti_t nas_guti;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
||||
|
|
@ -139,6 +138,8 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_request(amf_ue_t *amf_ue,
|
|||
mobile_identity_header =
|
||||
(ogs_nas_5gs_mobile_identity_header_t *)mobile_identity->buffer;
|
||||
|
||||
memset(&amf_ue->old_guti, 0, sizeof(ogs_nas_5gs_guti_t));
|
||||
|
||||
switch (mobile_identity_header->type) {
|
||||
case OGS_NAS_5GS_MOBILE_IDENTITY_SUCI:
|
||||
mobile_identity_suci =
|
||||
|
|
@ -180,11 +181,12 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_request(amf_ue_t *amf_ue,
|
|||
}
|
||||
|
||||
ogs_nas_5gs_mobile_identity_guti_to_nas_guti(
|
||||
mobile_identity_guti, &nas_guti);
|
||||
mobile_identity_guti, &amf_ue->old_guti);
|
||||
|
||||
ogs_info("[%s] 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]",
|
||||
AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID",
|
||||
ogs_amf_id_hexdump(&nas_guti.amf_id), nas_guti.m_tmsi);
|
||||
ogs_amf_id_hexdump(&amf_ue->old_guti.amf_id),
|
||||
amf_ue->old_guti.m_tmsi);
|
||||
break;
|
||||
default:
|
||||
ogs_error("Unknown SUCI type [%d]", mobile_identity_header->type);
|
||||
|
|
@ -540,6 +542,86 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_update(
|
|||
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
|
||||
bool gmm_registration_request_from_old_amf(amf_ue_t *amf_ue,
|
||||
ogs_nas_5gs_registration_request_t *registration_request)
|
||||
{
|
||||
ogs_nas_5gs_mobile_identity_t *mobile_identity = NULL;
|
||||
ogs_nas_5gs_mobile_identity_header_t *mobile_identity_header = NULL;
|
||||
|
||||
int i;
|
||||
ogs_plmn_id_t plmn_id;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
ogs_assert(registration_request);
|
||||
mobile_identity = ®istration_request->mobile_identity;
|
||||
mobile_identity_header =
|
||||
(ogs_nas_5gs_mobile_identity_header_t *)mobile_identity->buffer;
|
||||
|
||||
if (mobile_identity_header->type != OGS_NAS_5GS_MOBILE_IDENTITY_GUTI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO : FIXME
|
||||
*
|
||||
* Typically, UEs send 5G-GUTIs with all 0. In such cases,
|
||||
* we need to prevent context transfer betwen AMFs by the N14 interface
|
||||
* because they are not included in served_guami.
|
||||
*
|
||||
* We don't yet know how to check for 5G GUTI conformance,
|
||||
* so we've implemented the following as a temporary solution.
|
||||
*/
|
||||
if ((amf_ue->old_guti.amf_id.region == 0 &&
|
||||
amf_ue->old_guti.amf_id.set2 == 0) &&
|
||||
(amf_ue->old_guti.nas_plmn_id.mcc1 == 0 &&
|
||||
amf_ue->old_guti.nas_plmn_id.mcc2 == 0 &&
|
||||
amf_ue->old_guti.nas_plmn_id.mcc3 == 0) &&
|
||||
(amf_ue->old_guti.nas_plmn_id.mnc1 == 0 &&
|
||||
amf_ue->old_guti.nas_plmn_id.mnc2 == 0 &&
|
||||
amf_ue->old_guti.nas_plmn_id.mnc3 == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* TS 23.502
|
||||
* 4.2.2.2.2 General Registration
|
||||
* (Without UDSF Deployment): If the UE's 5G-GUTI was included in the
|
||||
* Registration Request and the serving AMF has changed since last
|
||||
* Registration procedure, the new AMF may invoke the
|
||||
* Namf_Communication_UEContextTransfer service operation on the
|
||||
* old AMF including the complete Registration Request NAS message,
|
||||
* which may be integrity protected, as well as the Access Type,
|
||||
* to request the UE's SUPI and UE Context. See clause 5.2.2.2.2
|
||||
* for details of this service operation.
|
||||
*/
|
||||
ogs_nas_to_plmn_id(&plmn_id, &amf_ue->old_guti.nas_plmn_id);
|
||||
|
||||
ogs_info("[%s] 5G-S_GUTI[PLMN_ID:0x%x,AMF_ID:0x%x,M_TMSI:0x%x]",
|
||||
AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID",
|
||||
ogs_plmn_id_hexdump(&plmn_id),
|
||||
ogs_amf_id_hexdump(&amf_ue->old_guti.amf_id),
|
||||
amf_ue->old_guti.m_tmsi);
|
||||
|
||||
for (i = 0; i < amf_self()->num_of_served_guami; i++) {
|
||||
if (memcmp(&amf_self()->served_guami[i].plmn_id,
|
||||
&plmn_id, OGS_PLMN_ID_LEN) == 0 &&
|
||||
memcmp(&amf_self()->served_guami[i].amf_id,
|
||||
&amf_ue->old_guti.amf_id, sizeof(ogs_amf_id_t)) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_info("Serving AMF Changed [NumberOfServedGuami:%d]",
|
||||
amf_self()->num_of_served_guami);
|
||||
for (i = 0; i < amf_self()->num_of_served_guami; i++) {
|
||||
ogs_info("Served Guami[PLMN_ID:0x%x,AMF_ID:0x%x]",
|
||||
ogs_plmn_id_hexdump(&amf_self()->served_guami[i].plmn_id),
|
||||
ogs_amf_id_hexdump(&amf_self()->served_guami[i].amf_id));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ogs_nas_5gmm_cause_t gmm_handle_service_request(amf_ue_t *amf_ue,
|
||||
ogs_nas_security_header_type_t h, NGAP_ProcedureCode_t ngap_code,
|
||||
ogs_nas_5gs_service_request_t *service_request)
|
||||
|
|
@ -1540,243 +1622,6 @@ static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
|
|||
return gmm_cause;
|
||||
}
|
||||
|
||||
static ogs_nas_5gmm_capability_t
|
||||
amf_namf_comm_base64_decode_5gmm_capability(char *encoded)
|
||||
{
|
||||
ogs_nas_5gmm_capability_t gmm_capability;
|
||||
char *gmm_capability_octets_string = NULL;
|
||||
uint8_t gmm_capability_iei = 0;
|
||||
|
||||
memset(&gmm_capability, 0, sizeof(gmm_capability));
|
||||
gmm_capability_octets_string =
|
||||
(char*) ogs_calloc(sizeof(gmm_capability) + 1, sizeof(char));
|
||||
ogs_assert(gmm_capability_octets_string);
|
||||
|
||||
int len = ogs_base64_decode(gmm_capability_octets_string, encoded);
|
||||
|
||||
if (len == 0)
|
||||
ogs_error("Gmm capability not decoded");
|
||||
|
||||
ogs_assert(sizeof(gmm_capability_octets_string) <=
|
||||
sizeof(gmm_capability) + 1);
|
||||
|
||||
gmm_capability_iei = // not copied anywhere for now
|
||||
gmm_capability_octets_string[0];
|
||||
if (gmm_capability_iei !=
|
||||
OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE) {
|
||||
ogs_error("Type of 5GMM capability IEI is incorrect");
|
||||
}
|
||||
memcpy(&gmm_capability,
|
||||
gmm_capability_octets_string + 1,
|
||||
sizeof(gmm_capability));
|
||||
if (gmm_capability_octets_string) {
|
||||
ogs_free(gmm_capability_octets_string);
|
||||
}
|
||||
|
||||
return gmm_capability;
|
||||
}
|
||||
|
||||
static ogs_nas_ue_security_capability_t
|
||||
amf_namf_comm_base64_decode_ue_security_capability(char *encoded)
|
||||
{
|
||||
ogs_nas_ue_security_capability_t ue_security_capability;
|
||||
char *ue_security_capability_octets_string = NULL;
|
||||
uint8_t ue_security_capability_iei = 0;
|
||||
|
||||
memset(&ue_security_capability, 0, sizeof(ue_security_capability));
|
||||
ue_security_capability_octets_string =
|
||||
(char*) ogs_calloc(sizeof(ue_security_capability), sizeof(char));
|
||||
ogs_assert(ue_security_capability_octets_string);
|
||||
|
||||
ogs_base64_decode(ue_security_capability_octets_string, encoded);
|
||||
|
||||
ogs_assert(sizeof(ue_security_capability_octets_string) <=
|
||||
sizeof(ogs_nas_ue_security_capability_t) + 1);
|
||||
|
||||
ue_security_capability_iei = // not copied anywhere for now
|
||||
ue_security_capability_octets_string[0];
|
||||
if (ue_security_capability_iei !=
|
||||
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE) {
|
||||
ogs_error("UE security capability IEI is incorrect");
|
||||
}
|
||||
|
||||
memcpy(&ue_security_capability, ue_security_capability_octets_string + 1,
|
||||
sizeof(ue_security_capability));
|
||||
|
||||
if (ue_security_capability_octets_string) {
|
||||
ogs_free(ue_security_capability_octets_string);
|
||||
}
|
||||
|
||||
return ue_security_capability;
|
||||
}
|
||||
|
||||
static void amf_namf_comm_decode_ue_mm_context_list(
|
||||
amf_ue_t *amf_ue, OpenAPI_list_t *MmContextList) {
|
||||
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
|
||||
OpenAPI_list_for_each(MmContextList, node) {
|
||||
|
||||
OpenAPI_mm_context_t *MmContext = NULL;
|
||||
OpenAPI_list_t *AllowedNssaiList = NULL;
|
||||
OpenAPI_lnode_t *node1 = NULL;
|
||||
OpenAPI_list_t *NssaiMappingList = NULL;
|
||||
int num_of_s_nssai = 0;
|
||||
int num_of_nssai_mapping = 0;
|
||||
|
||||
MmContext = node->data;
|
||||
|
||||
AllowedNssaiList = MmContext->allowed_nssai;
|
||||
NssaiMappingList = MmContext->nssai_mapping_list;
|
||||
|
||||
OpenAPI_list_for_each(AllowedNssaiList, node1) {
|
||||
OpenAPI_snssai_t *AllowedNssai = node1->data;
|
||||
|
||||
ogs_assert(num_of_s_nssai < OGS_MAX_NUM_OF_SLICE);
|
||||
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_s_nssai].sst =
|
||||
(uint8_t)AllowedNssai->sst;
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_s_nssai].sd =
|
||||
ogs_s_nssai_sd_from_string(AllowedNssai->sd);
|
||||
|
||||
num_of_s_nssai++;
|
||||
amf_ue->allowed_nssai.num_of_s_nssai = num_of_s_nssai;
|
||||
}
|
||||
|
||||
OpenAPI_list_for_each(NssaiMappingList, node1) {
|
||||
OpenAPI_nssai_mapping_t *NssaiMapping = node1->data;
|
||||
OpenAPI_snssai_t *HSnssai = NssaiMapping->h_snssai;
|
||||
|
||||
ogs_assert(num_of_nssai_mapping < OGS_MAX_NUM_OF_SLICE);
|
||||
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_nssai_mapping].
|
||||
mapped_hplmn_sst = HSnssai->sst;
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_nssai_mapping].
|
||||
mapped_hplmn_sd = ogs_s_nssai_sd_from_string(HSnssai->sd);
|
||||
|
||||
num_of_nssai_mapping++;
|
||||
}
|
||||
|
||||
if (MmContext->ue_security_capability) {
|
||||
amf_ue->ue_security_capability =
|
||||
amf_namf_comm_base64_decode_ue_security_capability(
|
||||
MmContext->ue_security_capability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void amf_namf_comm_decode_ue_session_context_list(
|
||||
amf_ue_t *amf_ue, OpenAPI_list_t *SessionContextList)
|
||||
{
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
|
||||
OpenAPI_list_for_each(SessionContextList, node) {
|
||||
OpenAPI_pdu_session_context_t *PduSessionContext;
|
||||
PduSessionContext = node->data;
|
||||
amf_sess_t *sess = NULL;
|
||||
|
||||
sess = amf_sess_add(amf_ue, PduSessionContext->pdu_session_id);
|
||||
ogs_assert(sess);
|
||||
|
||||
sess->sm_context.ref = PduSessionContext->sm_context_ref;
|
||||
|
||||
if (PduSessionContext->s_nssai) {
|
||||
memset(&sess->s_nssai, 0, sizeof(sess->s_nssai));
|
||||
|
||||
sess->s_nssai.sst = PduSessionContext->s_nssai->sst;
|
||||
sess->s_nssai.sd = ogs_s_nssai_sd_from_string(
|
||||
PduSessionContext->s_nssai->sd);
|
||||
}
|
||||
|
||||
if (PduSessionContext->dnn)
|
||||
sess->dnn = ogs_strdup(PduSessionContext->dnn);
|
||||
if (PduSessionContext->access_type)
|
||||
amf_ue->nas.access_type = (int)PduSessionContext->access_type;
|
||||
}
|
||||
}
|
||||
|
||||
int amf_namf_comm_handle_ue_context_transfer_response(
|
||||
ogs_sbi_message_t *recvmsg, amf_ue_t *amf_ue)
|
||||
{
|
||||
OpenAPI_ue_context_t *UeContext = NULL;
|
||||
|
||||
ogs_error("V funkciji amf_namf_comm_handle_ue_context_transfer_response");
|
||||
|
||||
if (!recvmsg->UeContextTransferRspData) {
|
||||
ogs_error("No UeContextTransferRspData");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
if (!recvmsg->UeContextTransferRspData->ue_context) {
|
||||
ogs_error("No UE context");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
UeContext = recvmsg->UeContextTransferRspData->ue_context;
|
||||
|
||||
if (UeContext->supi) {
|
||||
amf_ue_set_supi(amf_ue, UeContext->supi);
|
||||
if (!UeContext->supi_unauth_ind){
|
||||
amf_ue->auth_result = OpenAPI_auth_result_AUTHENTICATION_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (UeContext->pei) {
|
||||
if (amf_ue->pei)
|
||||
ogs_free(amf_ue->pei);
|
||||
amf_ue->pei = ogs_strdup(UeContext->pei);
|
||||
}
|
||||
|
||||
if (UeContext->sub_ue_ambr) {
|
||||
amf_ue->ue_ambr.downlink =
|
||||
ogs_sbi_bitrate_from_string(UeContext->sub_ue_ambr->downlink);
|
||||
amf_ue->ue_ambr.uplink =
|
||||
ogs_sbi_bitrate_from_string(UeContext->sub_ue_ambr->uplink);
|
||||
}
|
||||
|
||||
if (UeContext->seaf_data) {
|
||||
if (UeContext->seaf_data->ng_ksi->tsc != OpenAPI_sc_type_NULL) {
|
||||
amf_ue->nas.ue.tsc =
|
||||
(UeContext->seaf_data->ng_ksi->tsc == OpenAPI_sc_type_NATIVE) ? 0 : 1;
|
||||
amf_ue->nas.ue.ksi = (uint8_t)UeContext->seaf_data->ng_ksi->ksi;
|
||||
|
||||
ogs_ascii_to_hex(
|
||||
UeContext->seaf_data->key_amf->key_val,
|
||||
strlen(UeContext->seaf_data->key_amf->key_val),
|
||||
amf_ue->kamf,
|
||||
sizeof(amf_ue->kamf));
|
||||
}
|
||||
}
|
||||
|
||||
if (UeContext->_5g_mm_capability) {
|
||||
ogs_nas_5gmm_capability_t gmm_capability;
|
||||
|
||||
gmm_capability = amf_namf_comm_base64_decode_5gmm_capability(
|
||||
UeContext->_5g_mm_capability);
|
||||
amf_ue->gmm_capability.lte_positioning_protocol_capability =
|
||||
(bool)gmm_capability.lte_positioning_protocol_capability;
|
||||
amf_ue->gmm_capability.ho_attach = (bool)gmm_capability.ho_attach;
|
||||
amf_ue->gmm_capability.s1_mode = (bool)gmm_capability.s1_mode;
|
||||
}
|
||||
|
||||
if (UeContext->pcf_id) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
/* TODO UeContext->pcfAmPolicyUri */
|
||||
/* TODO UeContext->pcfUePolicyUri */
|
||||
|
||||
if (UeContext->mm_context_list)
|
||||
amf_namf_comm_decode_ue_mm_context_list(amf_ue, UeContext->mm_context_list);
|
||||
|
||||
if (UeContext->session_context_list)
|
||||
amf_namf_comm_decode_ue_session_context_list(amf_ue, UeContext->session_context_list);
|
||||
|
||||
/* TODO ueRadioCapability */
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
static uint8_t gmm_cause_from_access_control(ogs_plmn_id_t *plmn_id)
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_request(amf_ue_t *amf_ue,
|
|||
ogs_nas_5gmm_cause_t gmm_handle_registration_update(
|
||||
ran_ue_t *ran_ue, amf_ue_t *amf_ue,
|
||||
ogs_nas_5gs_registration_request_t *registration_request);
|
||||
bool gmm_registration_request_from_old_amf(amf_ue_t *amf_ue,
|
||||
ogs_nas_5gs_registration_request_t *registration_request);
|
||||
|
||||
ogs_nas_5gmm_cause_t gmm_handle_service_request(amf_ue_t *amf_ue,
|
||||
ogs_nas_security_header_type_t h, NGAP_ProcedureCode_t ngap_code,
|
||||
|
|
|
|||
112
src/amf/gmm-sm.c
112
src/amf/gmm-sm.c
|
|
@ -67,7 +67,7 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e)
|
|||
|
||||
ogs_sbi_message_t *sbi_message = NULL;
|
||||
|
||||
int r, state = 0;
|
||||
int r, state = 0, xact_count;
|
||||
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
|
@ -298,7 +298,7 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e)
|
|||
state ==
|
||||
AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) {
|
||||
|
||||
int xact_count = amf_sess_xact_count(amf_ue);
|
||||
xact_count = amf_sess_xact_count(amf_ue);
|
||||
amf_sbi_send_release_all_sessions(NULL, amf_ue, state);
|
||||
|
||||
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
|
||||
|
|
@ -549,21 +549,31 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e)
|
|||
SWITCH(sbi_message->h.resource.component[2])
|
||||
CASE(OGS_SBI_RESOURCE_NAME_TRANSFER)
|
||||
|
||||
r = OGS_ERROR;
|
||||
|
||||
if (sbi_message->res_status == OGS_SBI_HTTP_STATUS_OK) {
|
||||
r = amf_namf_comm_handle_ue_context_transfer_response(sbi_message, amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
r = amf_namf_comm_handle_ue_context_transfer_response(
|
||||
sbi_message, amf_ue);
|
||||
if (r != OGS_OK) {
|
||||
ogs_error("failed to handle "
|
||||
"UE_CONTEXT_TRANSFER response");
|
||||
}
|
||||
} else {
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
amf_ue->suci, sbi_message->res_status);
|
||||
}
|
||||
|
||||
int xact_count = amf_sess_xact_count(amf_ue);
|
||||
|
||||
if (!AMF_UE_HAVE_SUCI(amf_ue)) {
|
||||
CLEAR_AMF_UE_TIMER(amf_ue->t3570);
|
||||
r = nas_5gs_send_identity_request(amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
break;
|
||||
if (r != OGS_OK) {
|
||||
if (!AMF_UE_HAVE_SUCI(amf_ue)) {
|
||||
CLEAR_AMF_UE_TIMER(amf_ue->t3570);
|
||||
r = nas_5gs_send_identity_request(amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xact_count = amf_sess_xact_count(amf_ue);
|
||||
amf_sbi_send_release_all_sessions(
|
||||
amf_ue->ran_ue, amf_ue,
|
||||
AMF_RELEASE_SM_CONTEXT_NO_STATE);
|
||||
|
|
@ -579,7 +589,6 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e)
|
|||
}
|
||||
|
||||
OGS_FSM_TRAN(s, &gmm_state_authentication);
|
||||
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
@ -1182,9 +1191,6 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
|
|||
amf_sess_t *sess = NULL;
|
||||
ogs_nas_5gs_message_t *nas_message = NULL;
|
||||
ogs_nas_security_header_type_t h;
|
||||
ogs_nas_5gs_registration_request_t *registration_request = NULL;
|
||||
ogs_nas_5gs_mobile_identity_header_t *mobile_identity_header = NULL;
|
||||
ogs_nas_5gs_mobile_identity_t *mobile_identity = NULL;
|
||||
|
||||
ogs_assert(e);
|
||||
|
||||
|
|
@ -1243,64 +1249,32 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
|
|||
break;
|
||||
}
|
||||
|
||||
registration_request = &nas_message->gmm.registration_request;
|
||||
mobile_identity = ®istration_request->mobile_identity;
|
||||
mobile_identity_header =
|
||||
(ogs_nas_5gs_mobile_identity_header_t *)mobile_identity->buffer;
|
||||
if (gmm_registration_request_from_old_amf(amf_ue,
|
||||
&nas_message->gmm.registration_request) == true) {
|
||||
ogs_sbi_discovery_option_t *discovery_option = NULL;
|
||||
ogs_guami_t guami;
|
||||
|
||||
/* Check if registration is done with GUTI */
|
||||
if (mobile_identity_header && mobile_identity_header->type ==
|
||||
OGS_NAS_5GS_MOBILE_IDENTITY_GUTI &&
|
||||
ogs_nas_5gs_guti_is_valid(&amf_ue->current.guti)) {
|
||||
discovery_option = ogs_sbi_discovery_option_new();
|
||||
ogs_assert(discovery_option);
|
||||
|
||||
/*
|
||||
* TS 23.502
|
||||
* 4.2.2.2.2 General Registration
|
||||
* (Without UDSF Deployment): If the UE's 5G-GUTI was included in the
|
||||
* Registration Request and the serving AMF has changed since last
|
||||
* Registration procedure, the new AMF may invoke the
|
||||
* Namf_Communication_UEContextTransfer service operation on the
|
||||
* old AMF including the complete Registration Request NAS message,
|
||||
* which may be integrity protected, as well as the Access Type,
|
||||
* to request the UE's SUPI and UE Context. See clause 5.2.2.2.2
|
||||
* for details of this service operation.
|
||||
*/
|
||||
/* Configure Home PLMN ID */
|
||||
ogs_nas_to_plmn_id(
|
||||
&amf_ue->home_plmn_id, &amf_ue->old_guti.nas_plmn_id);
|
||||
|
||||
int state = e->h.sbi.state;
|
||||
bool serving_guami = false;
|
||||
int i;
|
||||
memcpy(&guami.plmn_id, &amf_ue->home_plmn_id,
|
||||
sizeof(ogs_plmn_id_t));
|
||||
memcpy(&guami.amf_id, &amf_ue->old_guti.amf_id,
|
||||
sizeof(ogs_amf_id_t));
|
||||
|
||||
/* Compare all serving guamis with guami from UE's GUTI */
|
||||
for (i = 0; i < amf_self()->num_of_served_guami; i++) {
|
||||
if ((memcmp(&amf_self()->served_guami[i].amf_id,
|
||||
&amf_ue->current.guti.amf_id,
|
||||
sizeof(ogs_amf_id_t)) == 0) &&
|
||||
(memcmp(&amf_self()->served_guami[i].plmn_id,
|
||||
&amf_ue->current.guti.nas_plmn_id,
|
||||
OGS_PLMN_ID_LEN) == 0)) {
|
||||
ogs_sbi_discovery_option_set_guami(discovery_option, &guami);
|
||||
|
||||
serving_guami = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!serving_guami) {
|
||||
/* Guami from UE is not this AMF's serving guami - send UEContextTransfer */
|
||||
ogs_sbi_discovery_option_t *discovery_option = NULL;
|
||||
|
||||
discovery_option = ogs_sbi_discovery_option_new();
|
||||
ogs_assert(discovery_option);
|
||||
|
||||
memcpy(discovery_option->target_guami,
|
||||
amf_ue->guami, sizeof(ogs_guami_t));
|
||||
|
||||
int r = amf_ue_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NAMF_COMM, discovery_option,
|
||||
amf_namf_comm_build_ue_context_transfer,
|
||||
amf_ue, state, nas_message);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
break;
|
||||
}
|
||||
r = amf_ue_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NAMF_COMM, discovery_option,
|
||||
amf_namf_comm_build_ue_context_transfer,
|
||||
amf_ue, state, nas_message);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!AMF_UE_HAVE_SUCI(amf_ue)) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "namf-build.h"
|
||||
|
||||
static char* ogs_guti_to_string(amf_ue_t *amf_ue)
|
||||
static char* ogs_guti_to_string(ogs_nas_5gs_guti_t *nas_guti)
|
||||
{
|
||||
ogs_plmn_id_t plmn_id;
|
||||
char plmn_id_buff[OGS_PLMNIDSTRLEN];
|
||||
|
|
@ -27,11 +27,13 @@ static char* ogs_guti_to_string(amf_ue_t *amf_ue)
|
|||
char *tmsi = NULL;
|
||||
char *guti = NULL;
|
||||
|
||||
memset(&plmn_id, 0, sizeof(plmn_id));
|
||||
ogs_nas_to_plmn_id(&plmn_id, &amf_ue->current.guti.nas_plmn_id);
|
||||
ogs_assert(nas_guti);
|
||||
|
||||
amf_id = ogs_amf_id_to_string(&amf_ue->current.guti.amf_id);
|
||||
tmsi = ogs_uint32_to_0string(*(amf_ue->current.m_tmsi));
|
||||
memset(&plmn_id, 0, sizeof(plmn_id));
|
||||
ogs_nas_to_plmn_id(&plmn_id, &nas_guti->nas_plmn_id);
|
||||
|
||||
amf_id = ogs_amf_id_to_string(&nas_guti->amf_id);
|
||||
tmsi = ogs_uint32_to_0string(nas_guti->m_tmsi);
|
||||
|
||||
guti = ogs_msprintf("5g-guti-%s%s%s",
|
||||
ogs_plmn_id_to_string(&plmn_id, plmn_id_buff),
|
||||
|
|
@ -56,7 +58,7 @@ static char* amf_ue_to_context_id(amf_ue_t *amf_ue)
|
|||
if (amf_ue->supi) {
|
||||
ue_context_id = ogs_strdup(amf_ue->supi);
|
||||
} else {
|
||||
ue_context_id = ogs_guti_to_string(amf_ue);
|
||||
ue_context_id = ogs_guti_to_string(&amf_ue->old_guti);
|
||||
}
|
||||
|
||||
return ue_context_id;
|
||||
|
|
@ -83,11 +85,9 @@ ogs_sbi_request_t *amf_namf_comm_build_ue_context_transfer(
|
|||
message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST;
|
||||
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NAMF_COMM;
|
||||
message.h.api.version = (char *)OGS_SBI_API_V1;
|
||||
message.h.resource.component[0] =
|
||||
(char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXTS;
|
||||
message.h.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXTS;
|
||||
message.h.resource.component[1] = ue_context_id;
|
||||
message.h.resource.component[2] =
|
||||
(char *)OGS_SBI_RESOURCE_NAME_TRANSFER;
|
||||
message.h.resource.component[2] = (char *)OGS_SBI_RESOURCE_NAME_TRANSFER;
|
||||
message.UeContextTransferReqData = &UeContextTransferReqData;
|
||||
|
||||
request = ogs_sbi_build_request(&message);
|
||||
|
|
|
|||
|
|
@ -1079,238 +1079,12 @@ cleanup:
|
|||
}
|
||||
|
||||
static char *amf_namf_comm_base64_encode_ue_security_capability(
|
||||
ogs_nas_ue_security_capability_t ue_security_capability)
|
||||
{
|
||||
char *enc = NULL;
|
||||
int enc_len = 0;
|
||||
|
||||
char num_of_octets =
|
||||
ue_security_capability.length +
|
||||
sizeof(ue_security_capability.length) +
|
||||
sizeof((uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE);
|
||||
/* Security guarantee */
|
||||
num_of_octets = ogs_min(
|
||||
num_of_octets, sizeof(ue_security_capability) + 1);
|
||||
/*
|
||||
* size [sizeof(ue_security_capability) + 1] is a sum of lengths:
|
||||
* ue_security_capability (9 octets) +
|
||||
* type (1 octet)
|
||||
*/
|
||||
char security_octets_string[sizeof(ue_security_capability) + 1];
|
||||
|
||||
enc_len = ogs_base64_encode_len(num_of_octets);
|
||||
|
||||
enc = ogs_malloc(enc_len);
|
||||
ogs_assert(enc);
|
||||
memset(enc, 0, sizeof(*enc));
|
||||
|
||||
security_octets_string[0] =
|
||||
(uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE;
|
||||
memcpy(security_octets_string + 1, &ue_security_capability, num_of_octets);
|
||||
ogs_base64_encode(enc , security_octets_string, num_of_octets);
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
static char *amf_namf_comm_base64_encode_5gmm_capability(amf_ue_t *amf_ue)
|
||||
{
|
||||
ogs_nas_5gmm_capability_t nas_gmm_capability;
|
||||
int enc_len = 0;
|
||||
char *enc = NULL;
|
||||
|
||||
memset(&nas_gmm_capability, 0, sizeof(nas_gmm_capability));
|
||||
|
||||
/* 1 octet is mandatory, n.3 from TS 24.501 V16.12.0, 9.11.3.1 */
|
||||
nas_gmm_capability.length = 1;
|
||||
nas_gmm_capability.lte_positioning_protocol_capability =
|
||||
amf_ue->gmm_capability.lte_positioning_protocol_capability;
|
||||
nas_gmm_capability.ho_attach = amf_ue->gmm_capability.ho_attach;
|
||||
nas_gmm_capability.s1_mode = amf_ue->gmm_capability.s1_mode;
|
||||
|
||||
uint8_t num_of_octets =
|
||||
nas_gmm_capability.length +
|
||||
sizeof(nas_gmm_capability.length) +
|
||||
sizeof((uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE);
|
||||
|
||||
/* Security guarantee. + 1 stands for 5GMM capability IEI */
|
||||
num_of_octets = ogs_min(
|
||||
num_of_octets, sizeof(ogs_nas_5gmm_capability_t) + 1);
|
||||
|
||||
char gmm_capability_octets_string[sizeof(ogs_nas_5gmm_capability_t) + 1];
|
||||
|
||||
enc_len = ogs_base64_encode_len(num_of_octets);
|
||||
enc = ogs_malloc(enc_len);
|
||||
ogs_assert(enc);
|
||||
memset(enc, 0, sizeof(*enc));
|
||||
|
||||
/* Fill the bytes of data */
|
||||
gmm_capability_octets_string[0] =
|
||||
(uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE;
|
||||
memcpy(gmm_capability_octets_string + 1, &nas_gmm_capability, num_of_octets);
|
||||
ogs_base64_encode(enc, gmm_capability_octets_string, num_of_octets);
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
static OpenAPI_list_t *amf_namf_comm_encode_ue_session_context_list(amf_ue_t *amf_ue)
|
||||
{
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
amf_sess_t *sess = NULL;
|
||||
OpenAPI_list_t *PduSessionList = NULL;
|
||||
OpenAPI_pdu_session_context_t *PduSessionContext = NULL;
|
||||
OpenAPI_snssai_t *sNSSAI = NULL;
|
||||
|
||||
PduSessionList = OpenAPI_list_create();
|
||||
ogs_assert(PduSessionList);
|
||||
|
||||
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
||||
PduSessionContext = ogs_calloc(1, sizeof(*PduSessionContext));
|
||||
ogs_assert(PduSessionContext);
|
||||
|
||||
sNSSAI = ogs_calloc(1, sizeof(*sNSSAI));
|
||||
ogs_assert(sNSSAI);
|
||||
|
||||
PduSessionContext->pdu_session_id = sess->psi;
|
||||
PduSessionContext->sm_context_ref = sess->sm_context.ref;
|
||||
|
||||
sNSSAI->sst = sess->s_nssai.sst;
|
||||
sNSSAI->sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd);
|
||||
PduSessionContext->s_nssai = sNSSAI;
|
||||
|
||||
PduSessionContext->dnn = sess->dnn;
|
||||
PduSessionContext->access_type = (OpenAPI_access_type_e)amf_ue->nas.access_type;
|
||||
|
||||
OpenAPI_list_add(PduSessionList, PduSessionContext);
|
||||
}
|
||||
|
||||
return PduSessionList;
|
||||
}
|
||||
|
||||
static OpenAPI_list_t *amf_namf_comm_encode_ue_mm_context_list(amf_ue_t *amf_ue)
|
||||
{
|
||||
OpenAPI_list_t *MmContextList = NULL;
|
||||
OpenAPI_mm_context_t *MmContext = NULL;
|
||||
|
||||
int i;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
|
||||
MmContextList = OpenAPI_list_create();
|
||||
ogs_assert(MmContextList);
|
||||
|
||||
MmContext = ogs_malloc(sizeof(*MmContext));
|
||||
ogs_assert(MmContext);
|
||||
memset(MmContext, 0, sizeof(*MmContext));
|
||||
|
||||
MmContext->access_type = (OpenAPI_access_type_e)amf_ue->nas.access_type;
|
||||
|
||||
if ((OpenAPI_ciphering_algorithm_e)amf_ue->selected_enc_algorithm &&
|
||||
(OpenAPI_integrity_algorithm_e)amf_ue->selected_int_algorithm) {
|
||||
|
||||
OpenAPI_nas_security_mode_t *NasSecurityMode;
|
||||
|
||||
NasSecurityMode = ogs_calloc(1, sizeof(*NasSecurityMode));
|
||||
ogs_assert(NasSecurityMode);
|
||||
|
||||
NasSecurityMode->ciphering_algorithm =
|
||||
(OpenAPI_ciphering_algorithm_e)amf_ue->selected_enc_algorithm;
|
||||
NasSecurityMode->integrity_algorithm =
|
||||
(OpenAPI_integrity_algorithm_e)amf_ue->selected_int_algorithm;
|
||||
|
||||
MmContext->nas_security_mode = NasSecurityMode;
|
||||
}
|
||||
|
||||
if (amf_ue->dl_count > 0) {
|
||||
MmContext->is_nas_downlink_count = true;
|
||||
MmContext->nas_downlink_count = amf_ue->dl_count;
|
||||
}
|
||||
|
||||
if (amf_ue->ul_count.i32 > 0) {
|
||||
MmContext->is_nas_uplink_count = true;
|
||||
MmContext->nas_uplink_count = amf_ue->ul_count.i32;
|
||||
}
|
||||
|
||||
if (amf_ue->ue_security_capability.length > 0) {
|
||||
MmContext->ue_security_capability =
|
||||
amf_namf_comm_base64_encode_ue_security_capability(
|
||||
amf_ue->ue_security_capability);
|
||||
}
|
||||
|
||||
if (amf_ue->allowed_nssai.num_of_s_nssai) {
|
||||
|
||||
OpenAPI_list_t *AllowedNssaiList;
|
||||
OpenAPI_list_t *NssaiMappingList;
|
||||
|
||||
/* This IE shall be present if the source AMF and the target AMF are
|
||||
* in the same PLMN and if available. When present, this IE shall
|
||||
* contain the allowed NSSAI for the access type.
|
||||
*/
|
||||
AllowedNssaiList = OpenAPI_list_create();
|
||||
|
||||
/* This IE shall be present if the source AMF and the target AMF are
|
||||
* in the same PLMN and if available. When present, this IE shall
|
||||
* contain the mapping of the allowed NSSAI for the UE.
|
||||
*/
|
||||
NssaiMappingList = OpenAPI_list_create();
|
||||
|
||||
ogs_assert(AllowedNssaiList);
|
||||
ogs_assert(NssaiMappingList);
|
||||
|
||||
for (i = 0; i < amf_ue->allowed_nssai.num_of_s_nssai; i++) {
|
||||
OpenAPI_snssai_t *AllowedNssai;
|
||||
|
||||
AllowedNssai = ogs_calloc(1, sizeof(*AllowedNssai));
|
||||
ogs_assert(AllowedNssai);
|
||||
|
||||
AllowedNssai->sst = amf_ue->allowed_nssai.s_nssai[i].sst;
|
||||
AllowedNssai->sd = ogs_s_nssai_sd_to_string(
|
||||
amf_ue->allowed_nssai.s_nssai[i].sd);
|
||||
|
||||
OpenAPI_list_add(AllowedNssaiList, AllowedNssai);
|
||||
}
|
||||
|
||||
for (i = 0; i < amf_ue->allowed_nssai.num_of_s_nssai; i++) {
|
||||
OpenAPI_nssai_mapping_t *NssaiMapping;
|
||||
OpenAPI_snssai_t *HSnssai;
|
||||
OpenAPI_snssai_t *MappedSnssai;
|
||||
|
||||
NssaiMapping = ogs_calloc(1, sizeof(*NssaiMapping));
|
||||
ogs_assert(NssaiMapping);
|
||||
|
||||
/* Indicates the S-NSSAI in home PLMN */
|
||||
HSnssai = ogs_calloc(1, sizeof(*HSnssai));
|
||||
ogs_assert(HSnssai);
|
||||
|
||||
HSnssai->sst =
|
||||
amf_ue->allowed_nssai.s_nssai[i].mapped_hplmn_sst;
|
||||
HSnssai->sd =
|
||||
ogs_s_nssai_sd_to_string(
|
||||
amf_ue->allowed_nssai.s_nssai[i].mapped_hplmn_sd);
|
||||
NssaiMapping->h_snssai = HSnssai;
|
||||
|
||||
/* Indicates the mapped S-NSSAI in the serving PLMN */
|
||||
MappedSnssai = ogs_calloc(1, sizeof(*MappedSnssai));
|
||||
ogs_assert(MappedSnssai);
|
||||
|
||||
/* MappedSnssai must be defined, else
|
||||
"nssaiMappingList" will not convert to json*/
|
||||
MappedSnssai->sst = 0;
|
||||
MappedSnssai->sd = ogs_strdup("");
|
||||
NssaiMapping->mapped_snssai = MappedSnssai;
|
||||
|
||||
OpenAPI_list_add(NssaiMappingList, NssaiMapping);
|
||||
}
|
||||
|
||||
MmContext->allowed_nssai = AllowedNssaiList;
|
||||
MmContext->nssai_mapping_list = NssaiMappingList;
|
||||
}
|
||||
|
||||
OpenAPI_list_add(MmContextList, MmContext);
|
||||
|
||||
return MmContextList;
|
||||
}
|
||||
ogs_nas_ue_security_capability_t ue_security_capability);
|
||||
static char *amf_namf_comm_base64_encode_5gmm_capability(amf_ue_t *amf_ue);
|
||||
static OpenAPI_list_t *amf_namf_comm_encode_ue_session_context_list(
|
||||
amf_ue_t *amf_ue);
|
||||
static OpenAPI_list_t *amf_namf_comm_encode_ue_mm_context_list(
|
||||
amf_ue_t *amf_ue);
|
||||
|
||||
int amf_namf_comm_handle_ue_context_transfer_request(
|
||||
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg)
|
||||
|
|
@ -1381,9 +1155,8 @@ int amf_namf_comm_handle_ue_context_transfer_request(
|
|||
}
|
||||
|
||||
if ((amf_ue->ue_ambr.uplink > 0) || (amf_ue->ue_ambr.downlink > 0)) {
|
||||
UeAmbr = ogs_malloc(sizeof(*UeAmbr));
|
||||
UeAmbr = ogs_calloc(1, sizeof(*UeAmbr));
|
||||
ogs_assert(UeAmbr);
|
||||
memset(UeAmbr, 0, sizeof(*UeAmbr));
|
||||
|
||||
if (amf_ue->ue_ambr.uplink > 0)
|
||||
UeAmbr->uplink = ogs_sbi_bitrate_to_string(
|
||||
|
|
@ -1415,7 +1188,8 @@ int amf_namf_comm_handle_ue_context_transfer_request(
|
|||
UeContext.seaf_data = &SeafData;
|
||||
}
|
||||
|
||||
encoded_gmm_capability = amf_namf_comm_base64_encode_5gmm_capability(amf_ue);
|
||||
encoded_gmm_capability =
|
||||
amf_namf_comm_base64_encode_5gmm_capability(amf_ue);
|
||||
UeContext._5g_mm_capability = encoded_gmm_capability;
|
||||
|
||||
pcf_nf_instance = OGS_SBI_GET_NF_INSTANCE(
|
||||
|
|
@ -1435,7 +1209,8 @@ int amf_namf_comm_handle_ue_context_transfer_request(
|
|||
|
||||
if (recvmsg->UeContextTransferReqData->reason ==
|
||||
OpenAPI_transfer_reason_MOBI_REG) {
|
||||
SessionContextList = amf_namf_comm_encode_ue_session_context_list(amf_ue);
|
||||
SessionContextList =
|
||||
amf_namf_comm_encode_ue_session_context_list(amf_ue);
|
||||
UeContext.session_context_list = SessionContextList;
|
||||
}
|
||||
|
||||
|
|
@ -1447,6 +1222,7 @@ int amf_namf_comm_handle_ue_context_transfer_request(
|
|||
|
||||
if (encoded_gmm_capability)
|
||||
ogs_free(encoded_gmm_capability);
|
||||
|
||||
if (UeAmbr)
|
||||
OpenAPI_ambr_free(UeAmbr);
|
||||
|
||||
|
|
@ -1466,6 +1242,14 @@ int amf_namf_comm_handle_ue_context_transfer_request(
|
|||
OpenAPI_list_free(MmContextList);
|
||||
}
|
||||
|
||||
/*
|
||||
* Context TRANSFERRED !!!
|
||||
* So, we removed UE context.
|
||||
*/
|
||||
if (amf_ue->ran_ue)
|
||||
ran_ue_remove(amf_ue->ran_ue);
|
||||
amf_ue_remove(amf_ue);
|
||||
|
||||
return OGS_OK;
|
||||
|
||||
cleanup:
|
||||
|
|
@ -1478,3 +1262,500 @@ cleanup:
|
|||
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
static ogs_nas_5gmm_capability_t
|
||||
amf_namf_comm_base64_decode_5gmm_capability(char *encoded);
|
||||
static ogs_nas_ue_security_capability_t
|
||||
amf_namf_comm_base64_decode_ue_security_capability(char *encoded);
|
||||
static void amf_namf_comm_decode_ue_mm_context_list(
|
||||
amf_ue_t *amf_ue, OpenAPI_list_t *MmContextList);
|
||||
static void amf_namf_comm_decode_ue_session_context_list(
|
||||
amf_ue_t *amf_ue, OpenAPI_list_t *SessionContextList);
|
||||
|
||||
int amf_namf_comm_handle_ue_context_transfer_response(
|
||||
ogs_sbi_message_t *recvmsg, amf_ue_t *amf_ue)
|
||||
{
|
||||
OpenAPI_ue_context_t *UeContext = NULL;
|
||||
|
||||
if (!recvmsg->UeContextTransferRspData) {
|
||||
ogs_error("No UeContextTransferRspData");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
if (!recvmsg->UeContextTransferRspData->ue_context) {
|
||||
ogs_error("No UE context");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
UeContext = recvmsg->UeContextTransferRspData->ue_context;
|
||||
|
||||
if (!UeContext->supi) {
|
||||
ogs_error("No SUPI");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
amf_ue_set_supi(amf_ue, UeContext->supi);
|
||||
if (!UeContext->supi_unauth_ind){
|
||||
amf_ue->auth_result = OpenAPI_auth_result_AUTHENTICATION_SUCCESS;
|
||||
}
|
||||
|
||||
if (UeContext->pei) {
|
||||
if (amf_ue->pei)
|
||||
ogs_free(amf_ue->pei);
|
||||
amf_ue->pei = ogs_strdup(UeContext->pei);
|
||||
}
|
||||
|
||||
if (UeContext->sub_ue_ambr) {
|
||||
amf_ue->ue_ambr.downlink =
|
||||
ogs_sbi_bitrate_from_string(UeContext->sub_ue_ambr->downlink);
|
||||
amf_ue->ue_ambr.uplink =
|
||||
ogs_sbi_bitrate_from_string(UeContext->sub_ue_ambr->uplink);
|
||||
}
|
||||
|
||||
if (UeContext->seaf_data) {
|
||||
if (UeContext->seaf_data->ng_ksi->tsc != OpenAPI_sc_type_NULL) {
|
||||
amf_ue->nas.ue.tsc =
|
||||
(UeContext->seaf_data->ng_ksi->tsc ==
|
||||
OpenAPI_sc_type_NATIVE) ? 0 : 1;
|
||||
amf_ue->nas.ue.ksi = (uint8_t)UeContext->seaf_data->ng_ksi->ksi;
|
||||
|
||||
ogs_ascii_to_hex(
|
||||
UeContext->seaf_data->key_amf->key_val,
|
||||
strlen(UeContext->seaf_data->key_amf->key_val),
|
||||
amf_ue->kamf,
|
||||
sizeof(amf_ue->kamf));
|
||||
}
|
||||
}
|
||||
|
||||
if (UeContext->_5g_mm_capability) {
|
||||
ogs_nas_5gmm_capability_t gmm_capability;
|
||||
|
||||
gmm_capability = amf_namf_comm_base64_decode_5gmm_capability(
|
||||
UeContext->_5g_mm_capability);
|
||||
amf_ue->gmm_capability.lte_positioning_protocol_capability =
|
||||
(bool)gmm_capability.lte_positioning_protocol_capability;
|
||||
amf_ue->gmm_capability.ho_attach = (bool)gmm_capability.ho_attach;
|
||||
amf_ue->gmm_capability.s1_mode = (bool)gmm_capability.s1_mode;
|
||||
}
|
||||
|
||||
if (UeContext->pcf_id) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
/* TODO UeContext->pcfAmPolicyUri */
|
||||
/* TODO UeContext->pcfUePolicyUri */
|
||||
|
||||
if (UeContext->mm_context_list)
|
||||
amf_namf_comm_decode_ue_mm_context_list(
|
||||
amf_ue, UeContext->mm_context_list);
|
||||
|
||||
if (UeContext->session_context_list)
|
||||
amf_namf_comm_decode_ue_session_context_list(
|
||||
amf_ue, UeContext->session_context_list);
|
||||
|
||||
/* TODO ueRadioCapability */
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
static char *amf_namf_comm_base64_encode_ue_security_capability(
|
||||
ogs_nas_ue_security_capability_t ue_security_capability)
|
||||
{
|
||||
char *enc = NULL;
|
||||
int enc_len = 0;
|
||||
|
||||
char num_of_octets =
|
||||
ue_security_capability.length +
|
||||
sizeof(ue_security_capability.length) +
|
||||
sizeof((uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE);
|
||||
/*
|
||||
* size [sizeof(ue_security_capability) + 1] is a sum of lengths:
|
||||
* ue_security_capability (9 octets) +
|
||||
* type (1 octet)
|
||||
*/
|
||||
char security_octets_string[sizeof(ue_security_capability) + 1];
|
||||
|
||||
/* Security guarantee */
|
||||
num_of_octets = ogs_min(
|
||||
num_of_octets, sizeof(ue_security_capability) + 1);
|
||||
enc_len = ogs_base64_encode_len(num_of_octets);
|
||||
|
||||
enc = ogs_calloc(1, enc_len);
|
||||
ogs_assert(enc);
|
||||
|
||||
security_octets_string[0] = (uint8_t)
|
||||
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE;
|
||||
memcpy(security_octets_string + 1, &ue_security_capability, num_of_octets);
|
||||
ogs_base64_encode(enc , security_octets_string, num_of_octets);
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
static char *amf_namf_comm_base64_encode_5gmm_capability(amf_ue_t *amf_ue)
|
||||
{
|
||||
ogs_nas_5gmm_capability_t nas_gmm_capability;
|
||||
int enc_len = 0;
|
||||
char *enc = NULL;
|
||||
|
||||
memset(&nas_gmm_capability, 0, sizeof(nas_gmm_capability));
|
||||
|
||||
/* 1 octet is mandatory, n.3 from TS 24.501 V16.12.0, 9.11.3.1 */
|
||||
nas_gmm_capability.length = 1;
|
||||
nas_gmm_capability.lte_positioning_protocol_capability =
|
||||
amf_ue->gmm_capability.lte_positioning_protocol_capability;
|
||||
nas_gmm_capability.ho_attach = amf_ue->gmm_capability.ho_attach;
|
||||
nas_gmm_capability.s1_mode = amf_ue->gmm_capability.s1_mode;
|
||||
|
||||
uint8_t num_of_octets;
|
||||
|
||||
char gmm_capability_octets_string[sizeof(ogs_nas_5gmm_capability_t) + 1];
|
||||
|
||||
num_of_octets =
|
||||
nas_gmm_capability.length +
|
||||
sizeof(nas_gmm_capability.length) +
|
||||
sizeof((uint8_t)
|
||||
OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE);
|
||||
|
||||
/* Security guarantee. + 1 stands for 5GMM capability IEI */
|
||||
num_of_octets = ogs_min(
|
||||
num_of_octets, sizeof(ogs_nas_5gmm_capability_t) + 1);
|
||||
|
||||
enc_len = ogs_base64_encode_len(num_of_octets);
|
||||
enc = ogs_calloc(1, enc_len);
|
||||
ogs_assert(enc);
|
||||
|
||||
/* Fill the bytes of data */
|
||||
gmm_capability_octets_string[0] =
|
||||
(uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE;
|
||||
memcpy(gmm_capability_octets_string + 1,
|
||||
&nas_gmm_capability, num_of_octets);
|
||||
ogs_base64_encode(enc, gmm_capability_octets_string, num_of_octets);
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
static OpenAPI_list_t *amf_namf_comm_encode_ue_session_context_list(
|
||||
amf_ue_t *amf_ue)
|
||||
{
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
amf_sess_t *sess = NULL;
|
||||
OpenAPI_list_t *PduSessionList = NULL;
|
||||
OpenAPI_pdu_session_context_t *PduSessionContext = NULL;
|
||||
OpenAPI_snssai_t *sNSSAI = NULL;
|
||||
|
||||
PduSessionList = OpenAPI_list_create();
|
||||
ogs_assert(PduSessionList);
|
||||
|
||||
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
||||
PduSessionContext = ogs_calloc(1, sizeof(*PduSessionContext));
|
||||
ogs_assert(PduSessionContext);
|
||||
|
||||
sNSSAI = ogs_calloc(1, sizeof(*sNSSAI));
|
||||
ogs_assert(sNSSAI);
|
||||
|
||||
PduSessionContext->pdu_session_id = sess->psi;
|
||||
ogs_assert(sess->sm_context.resource_uri);
|
||||
PduSessionContext->sm_context_ref =
|
||||
ogs_strdup(sess->sm_context.resource_uri);
|
||||
|
||||
sNSSAI->sst = sess->s_nssai.sst;
|
||||
sNSSAI->sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd);
|
||||
PduSessionContext->s_nssai = sNSSAI;
|
||||
|
||||
ogs_assert(sess->dnn);
|
||||
PduSessionContext->dnn = ogs_strdup(sess->dnn);
|
||||
PduSessionContext->access_type =
|
||||
(OpenAPI_access_type_e)amf_ue->nas.access_type;
|
||||
|
||||
OpenAPI_list_add(PduSessionList, PduSessionContext);
|
||||
}
|
||||
|
||||
return PduSessionList;
|
||||
}
|
||||
|
||||
static OpenAPI_list_t *amf_namf_comm_encode_ue_mm_context_list(amf_ue_t *amf_ue)
|
||||
{
|
||||
OpenAPI_list_t *MmContextList = NULL;
|
||||
OpenAPI_mm_context_t *MmContext = NULL;
|
||||
|
||||
int i;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
MmContextList = OpenAPI_list_create();
|
||||
ogs_assert(MmContextList);
|
||||
|
||||
MmContext = ogs_malloc(sizeof(*MmContext));
|
||||
ogs_assert(MmContext);
|
||||
memset(MmContext, 0, sizeof(*MmContext));
|
||||
|
||||
MmContext->access_type = (OpenAPI_access_type_e)amf_ue->nas.access_type;
|
||||
|
||||
if ((OpenAPI_ciphering_algorithm_e)amf_ue->selected_enc_algorithm &&
|
||||
(OpenAPI_integrity_algorithm_e)amf_ue->selected_int_algorithm) {
|
||||
|
||||
OpenAPI_nas_security_mode_t *NasSecurityMode;
|
||||
|
||||
NasSecurityMode = ogs_calloc(1, sizeof(*NasSecurityMode));
|
||||
ogs_assert(NasSecurityMode);
|
||||
|
||||
NasSecurityMode->ciphering_algorithm =
|
||||
(OpenAPI_ciphering_algorithm_e)amf_ue->selected_enc_algorithm;
|
||||
NasSecurityMode->integrity_algorithm =
|
||||
(OpenAPI_integrity_algorithm_e)amf_ue->selected_int_algorithm;
|
||||
|
||||
MmContext->nas_security_mode = NasSecurityMode;
|
||||
}
|
||||
|
||||
if (amf_ue->dl_count > 0) {
|
||||
MmContext->is_nas_downlink_count = true;
|
||||
MmContext->nas_downlink_count = amf_ue->dl_count;
|
||||
}
|
||||
|
||||
if (amf_ue->ul_count.i32 > 0) {
|
||||
MmContext->is_nas_uplink_count = true;
|
||||
MmContext->nas_uplink_count = amf_ue->ul_count.i32;
|
||||
}
|
||||
|
||||
if (amf_ue->ue_security_capability.length > 0) {
|
||||
MmContext->ue_security_capability =
|
||||
amf_namf_comm_base64_encode_ue_security_capability(
|
||||
amf_ue->ue_security_capability);
|
||||
}
|
||||
|
||||
if (amf_ue->allowed_nssai.num_of_s_nssai) {
|
||||
|
||||
OpenAPI_list_t *AllowedNssaiList;
|
||||
|
||||
/* This IE shall be present if the source AMF and the target AMF are
|
||||
* in the same PLMN and if available. When present, this IE shall
|
||||
* contain the allowed NSSAI for the access type.
|
||||
*/
|
||||
AllowedNssaiList = OpenAPI_list_create();
|
||||
|
||||
ogs_assert(AllowedNssaiList);
|
||||
|
||||
for (i = 0; i < amf_ue->allowed_nssai.num_of_s_nssai; i++) {
|
||||
OpenAPI_snssai_t *AllowedNssai;
|
||||
|
||||
AllowedNssai = ogs_calloc(1, sizeof(*AllowedNssai));
|
||||
ogs_assert(AllowedNssai);
|
||||
|
||||
AllowedNssai->sst = amf_ue->allowed_nssai.s_nssai[i].sst;
|
||||
AllowedNssai->sd = ogs_s_nssai_sd_to_string(
|
||||
amf_ue->allowed_nssai.s_nssai[i].sd);
|
||||
|
||||
OpenAPI_list_add(AllowedNssaiList, AllowedNssai);
|
||||
}
|
||||
|
||||
MmContext->allowed_nssai = AllowedNssaiList;
|
||||
}
|
||||
|
||||
OpenAPI_list_add(MmContextList, MmContext);
|
||||
|
||||
return MmContextList;
|
||||
}
|
||||
|
||||
static ogs_nas_5gmm_capability_t
|
||||
amf_namf_comm_base64_decode_5gmm_capability(char *encoded)
|
||||
{
|
||||
ogs_nas_5gmm_capability_t gmm_capability;
|
||||
char *gmm_capability_octets_string = NULL;
|
||||
uint8_t gmm_capability_iei = 0;
|
||||
int len;
|
||||
|
||||
memset(&gmm_capability, 0, sizeof(gmm_capability));
|
||||
gmm_capability_octets_string =
|
||||
(char*) ogs_calloc(sizeof(gmm_capability) + 1, sizeof(char));
|
||||
ogs_assert(gmm_capability_octets_string);
|
||||
|
||||
len = ogs_base64_decode(gmm_capability_octets_string, encoded);
|
||||
|
||||
if (len == 0)
|
||||
ogs_error("Gmm capability not decoded");
|
||||
|
||||
ogs_assert(sizeof(gmm_capability_octets_string) <=
|
||||
sizeof(gmm_capability) + 1);
|
||||
|
||||
gmm_capability_iei = // not copied anywhere for now
|
||||
gmm_capability_octets_string[0];
|
||||
if (gmm_capability_iei !=
|
||||
OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE) {
|
||||
ogs_error("Type of 5GMM capability IEI is incorrect");
|
||||
}
|
||||
memcpy(&gmm_capability,
|
||||
gmm_capability_octets_string + 1,
|
||||
sizeof(gmm_capability));
|
||||
if (gmm_capability_octets_string) {
|
||||
ogs_free(gmm_capability_octets_string);
|
||||
}
|
||||
|
||||
return gmm_capability;
|
||||
}
|
||||
|
||||
static ogs_nas_ue_security_capability_t
|
||||
amf_namf_comm_base64_decode_ue_security_capability(char *encoded)
|
||||
{
|
||||
ogs_nas_ue_security_capability_t ue_security_capability;
|
||||
char *ue_security_capability_octets_string = NULL;
|
||||
uint8_t ue_security_capability_iei = 0;
|
||||
|
||||
memset(&ue_security_capability, 0, sizeof(ue_security_capability));
|
||||
ue_security_capability_octets_string =
|
||||
(char*) ogs_calloc(sizeof(ue_security_capability), sizeof(char));
|
||||
ogs_assert(ue_security_capability_octets_string);
|
||||
|
||||
ogs_base64_decode(ue_security_capability_octets_string, encoded);
|
||||
|
||||
ogs_assert(sizeof(ue_security_capability_octets_string) <=
|
||||
sizeof(ogs_nas_ue_security_capability_t) + 1);
|
||||
|
||||
ue_security_capability_iei = // not copied anywhere for now
|
||||
ue_security_capability_octets_string[0];
|
||||
if (ue_security_capability_iei !=
|
||||
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE) {
|
||||
ogs_error("UE security capability IEI is incorrect");
|
||||
}
|
||||
|
||||
memcpy(&ue_security_capability, ue_security_capability_octets_string + 1,
|
||||
sizeof(ue_security_capability));
|
||||
|
||||
if (ue_security_capability_octets_string) {
|
||||
ogs_free(ue_security_capability_octets_string);
|
||||
}
|
||||
|
||||
return ue_security_capability;
|
||||
}
|
||||
|
||||
static void amf_namf_comm_decode_ue_mm_context_list(
|
||||
amf_ue_t *amf_ue, OpenAPI_list_t *MmContextList) {
|
||||
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
|
||||
OpenAPI_list_for_each(MmContextList, node) {
|
||||
|
||||
OpenAPI_mm_context_t *MmContext = NULL;
|
||||
OpenAPI_list_t *AllowedNssaiList = NULL;
|
||||
OpenAPI_lnode_t *node1 = NULL;
|
||||
OpenAPI_list_t *NssaiMappingList = NULL;
|
||||
int num_of_s_nssai = 0;
|
||||
int num_of_nssai_mapping = 0;
|
||||
|
||||
MmContext = node->data;
|
||||
|
||||
AllowedNssaiList = MmContext->allowed_nssai;
|
||||
NssaiMappingList = MmContext->nssai_mapping_list;
|
||||
|
||||
OpenAPI_list_for_each(AllowedNssaiList, node1) {
|
||||
OpenAPI_snssai_t *AllowedNssai = node1->data;
|
||||
|
||||
ogs_assert(num_of_s_nssai < OGS_MAX_NUM_OF_SLICE);
|
||||
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_s_nssai].sst =
|
||||
(uint8_t)AllowedNssai->sst;
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_s_nssai].sd =
|
||||
ogs_s_nssai_sd_from_string(AllowedNssai->sd);
|
||||
|
||||
num_of_s_nssai++;
|
||||
amf_ue->allowed_nssai.num_of_s_nssai = num_of_s_nssai;
|
||||
}
|
||||
|
||||
OpenAPI_list_for_each(NssaiMappingList, node1) {
|
||||
OpenAPI_nssai_mapping_t *NssaiMapping = node1->data;
|
||||
OpenAPI_snssai_t *HSnssai = NssaiMapping->h_snssai;
|
||||
|
||||
ogs_assert(num_of_nssai_mapping < OGS_MAX_NUM_OF_SLICE);
|
||||
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_nssai_mapping].
|
||||
mapped_hplmn_sst = HSnssai->sst;
|
||||
amf_ue->allowed_nssai.s_nssai[num_of_nssai_mapping].
|
||||
mapped_hplmn_sd = ogs_s_nssai_sd_from_string(HSnssai->sd);
|
||||
|
||||
num_of_nssai_mapping++;
|
||||
}
|
||||
|
||||
if (MmContext->ue_security_capability) {
|
||||
amf_ue->ue_security_capability =
|
||||
amf_namf_comm_base64_decode_ue_security_capability(
|
||||
MmContext->ue_security_capability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void amf_namf_comm_decode_ue_session_context_list(
|
||||
amf_ue_t *amf_ue, OpenAPI_list_t *SessionContextList)
|
||||
{
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
|
||||
OpenAPI_list_for_each(SessionContextList, node) {
|
||||
OpenAPI_pdu_session_context_t *PduSessionContext;
|
||||
PduSessionContext = node->data;
|
||||
amf_sess_t *sess = NULL;
|
||||
|
||||
int rv;
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_header_t header;
|
||||
|
||||
if (!PduSessionContext->sm_context_ref) {
|
||||
ogs_error("No smContextRef [PSI:%d]",
|
||||
PduSessionContext->pdu_session_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PduSessionContext->s_nssai) {
|
||||
ogs_error("No sNSSI [PSI:%d]", PduSessionContext->pdu_session_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PduSessionContext->dnn) {
|
||||
ogs_error("No DNN [PSI:%d]", PduSessionContext->pdu_session_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PduSessionContext->access_type) {
|
||||
ogs_error("No accessType [PSI:%d]",
|
||||
PduSessionContext->pdu_session_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
header.uri = PduSessionContext->sm_context_ref;
|
||||
|
||||
rv = ogs_sbi_parse_header(&message, &header);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%d] Cannot parse sm_context_ref [%s]",
|
||||
PduSessionContext->pdu_session_id,
|
||||
PduSessionContext->sm_context_ref);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!message.h.resource.component[1]) {
|
||||
ogs_error("[%d] No SmContextRef [%s]",
|
||||
PduSessionContext->pdu_session_id,
|
||||
PduSessionContext->sm_context_ref);
|
||||
|
||||
ogs_sbi_header_free(&header);
|
||||
continue;
|
||||
}
|
||||
|
||||
sess = amf_sess_add(amf_ue, PduSessionContext->pdu_session_id);
|
||||
ogs_assert(sess);
|
||||
|
||||
sess->sm_context.resource_uri =
|
||||
ogs_strdup(PduSessionContext->sm_context_ref);
|
||||
sess->sm_context.ref =
|
||||
ogs_strdup(message.h.resource.component[1]);
|
||||
|
||||
memset(&sess->s_nssai, 0, sizeof(sess->s_nssai));
|
||||
|
||||
sess->s_nssai.sst = PduSessionContext->s_nssai->sst;
|
||||
sess->s_nssai.sd = ogs_s_nssai_sd_from_string(
|
||||
PduSessionContext->s_nssai->sd);
|
||||
|
||||
sess->dnn = ogs_strdup(PduSessionContext->dnn);
|
||||
amf_ue->nas.access_type = (int)PduSessionContext->access_type;
|
||||
|
||||
ogs_sbi_header_free(&header);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,8 +46,18 @@ ogs_sbi_request_t *amf_nausf_auth_build_authenticate(
|
|||
|
||||
memset(&AuthenticationInfo, 0, sizeof(AuthenticationInfo));
|
||||
|
||||
ogs_assert(amf_ue->suci);
|
||||
AuthenticationInfo.supi_or_suci = amf_ue->suci;
|
||||
if (amf_ue->suci)
|
||||
AuthenticationInfo.supi_or_suci = amf_ue->suci;
|
||||
else
|
||||
AuthenticationInfo.supi_or_suci = amf_ue->supi;
|
||||
|
||||
if (!AuthenticationInfo.supi_or_suci) {
|
||||
ogs_error("No SUPI[%s] or SUCI[%s]",
|
||||
amf_ue->supi ? amf_ue->supi : "NULL",
|
||||
amf_ue->suci ? amf_ue->suci : "NULL");
|
||||
goto end;
|
||||
}
|
||||
|
||||
AuthenticationInfo.serving_network_name =
|
||||
ogs_serving_network_name_from_plmn_id(&amf_ue->nr_tai.plmn_id);
|
||||
if (!AuthenticationInfo.serving_network_name) {
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
|
|||
CASE(OGS_SBI_HTTP_METHOD_POST)
|
||||
if (message.AuthenticationInfo &&
|
||||
message.AuthenticationInfo->supi_or_suci) {
|
||||
ausf_ue = ausf_ue_find_by_suci(
|
||||
ausf_ue = ausf_ue_find_by_suci_or_supi(
|
||||
message.AuthenticationInfo->supi_or_suci);
|
||||
if (!ausf_ue) {
|
||||
ausf_ue = ausf_ue_add(
|
||||
|
|
|
|||
|
|
@ -835,12 +835,12 @@ bool nrf_nnrf_handle_nf_discover(
|
|||
&discovery_option->tai.plmn_id),
|
||||
discovery_option->tai.tac.v);
|
||||
}
|
||||
if (discovery_option->target_guami) {
|
||||
if (discovery_option->guami_presence) {
|
||||
ogs_debug("guami[PLMN_ID:%06x,AMF_ID:%x]",
|
||||
ogs_plmn_id_hexdump(
|
||||
&discovery_option->target_guami->plmn_id),
|
||||
&discovery_option->guami.plmn_id),
|
||||
ogs_amf_id_hexdump(
|
||||
&discovery_option->target_guami->amf_id));
|
||||
&discovery_option->guami.amf_id));
|
||||
}
|
||||
if (discovery_option->num_of_target_plmn_list) {
|
||||
for (i = 0; i < discovery_option->num_of_target_plmn_list; i++)
|
||||
|
|
|
|||
|
|
@ -233,6 +233,9 @@ static int request_handler(ogs_sbi_request_t *request, void *data)
|
|||
} else if (!strcasecmp(key, OGS_SBI_CUSTOM_DISCOVERY_TAI)) {
|
||||
if (val)
|
||||
ogs_sbi_discovery_option_parse_tai(discovery_option, val);
|
||||
} else if (!strcasecmp(key, OGS_SBI_CUSTOM_DISCOVERY_GUAMI)) {
|
||||
if (val)
|
||||
ogs_sbi_discovery_option_parse_guami(discovery_option, val);
|
||||
} else if (!strcasecmp(key, OGS_SBI_CUSTOM_DISCOVERY_TARGET_PLMN_LIST)) {
|
||||
if (val)
|
||||
discovery_option->num_of_target_plmn_list =
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ static void test1_func(abts_case *tc, void *data)
|
|||
static void test2_func(abts_case *tc, void *data)
|
||||
{
|
||||
int rv;
|
||||
ogs_socknode_t *ngap;
|
||||
ogs_socknode_t *ngap, *ngap2;
|
||||
ogs_socknode_t *gtpu;
|
||||
ogs_pkbuf_t *gmmbuf;
|
||||
ogs_pkbuf_t *gsmbuf;
|
||||
|
|
@ -539,7 +539,7 @@ static void test2_func(abts_case *tc, void *data)
|
|||
test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
|
||||
test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca";
|
||||
|
||||
/* gNB connects to AMF */
|
||||
/* gNB connects to AMF(default configuration) */
|
||||
ngap = testngap_client(AF_INET);
|
||||
ABTS_PTR_NOTNULL(tc, ngap);
|
||||
|
||||
|
|
@ -1517,14 +1517,499 @@ static void test4_issues2839_func(abts_case *tc, void *data)
|
|||
test_ue_remove(test_ue);
|
||||
}
|
||||
|
||||
#define CONTEXT_TRANSFER_TEST 0
|
||||
#define OLD_AMF_NOT_FOUND 0
|
||||
|
||||
#if CONTEXT_TRANSFER_TEST
|
||||
static void context_transfer_func(abts_case *tc, void *data)
|
||||
{
|
||||
int rv;
|
||||
ogs_socknode_t *ngap, *ngap2;
|
||||
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;
|
||||
|
||||
bson_t *doc = NULL;
|
||||
|
||||
/* 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_PROTECTION_SCHEME_NULL;
|
||||
mobile_identity_suci.home_network_pki_value = 0;
|
||||
|
||||
test_ue = test_ue_add_by_suci(&mobile_identity_suci, "0000203190");
|
||||
ogs_assert(test_ue);
|
||||
|
||||
test_ue->nr_cgi.cell_id = 0x40001;
|
||||
|
||||
test_ue->nas.registration.tsc = 0;
|
||||
test_ue->nas.registration.ksi = 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;
|
||||
|
||||
test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
|
||||
test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca";
|
||||
|
||||
/* gNB connects to AMF(default configuration) */
|
||||
ngap = testngap_client(AF_INET);
|
||||
ABTS_PTR_NOTNULL(tc, ngap);
|
||||
|
||||
/* gNB connects to AMF(127.0.1.5) */
|
||||
ngap2 = testsctp_client("127.0.1.5", OGS_NGAP_SCTP_PORT);
|
||||
ABTS_PTR_NOTNULL(tc, ngap2);
|
||||
|
||||
/* 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, 22);
|
||||
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);
|
||||
|
||||
/* Send NG-Setup Reqeust */
|
||||
sendbuf = testngap_build_ng_setup_request(0x4000, 22);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive NG-Setup Response */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/********** Insert Subscriber in Database */
|
||||
doc = test_db_new_simple(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, doc);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc));
|
||||
|
||||
/* Send Registration request */
|
||||
test_ue->registration_request_param.guti = 1;
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
|
||||
test_ue->registration_request_param.gmm_capability = 1;
|
||||
test_ue->registration_request_param.s1_ue_network_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, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, nasbuf);
|
||||
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Identity request */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Identity response */
|
||||
gmmbuf = testgmm_build_identity_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 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 InitialContextSetupRequest +
|
||||
* Registration accept */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_InitialContextSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UERadioCapabilityInfoIndication */
|
||||
sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send InitialContextSetupResponse */
|
||||
sendbuf = testngap_build_initial_context_setup_response(test_ue, false);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Registration complete */
|
||||
gmmbuf = testgmm_build_registration_complete(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 Configuration update command */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send PDU session establishment request */
|
||||
sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5);
|
||||
ogs_assert(sess);
|
||||
|
||||
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;
|
||||
|
||||
sess->pdu_session_establishment_param.ssc_mode = 1;
|
||||
sess->pdu_session_establishment_param.epco = 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 PDUSessionResourceSetupRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session establishment accept */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
qos_flow = test_qos_flow_find_by_qfi(sess, 1);
|
||||
ogs_assert(qos_flow);
|
||||
rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send PDUSessionResourceSetupResponse */
|
||||
sendbuf = testngap_sess_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);
|
||||
|
||||
/* Receive GTP-U ICMP Packet */
|
||||
recvbuf = testgnb_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
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);
|
||||
|
||||
/* Send GTP-U Router Solicitation */
|
||||
rv = test_gtpu_send_slacc_rs(gtpu, qos_flow);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive GTP-U Router Advertisement */
|
||||
recvbuf = test_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testgtpu_recv(test_ue, recvbuf);
|
||||
|
||||
#if !defined(__FreeBSD__)
|
||||
/* Send GTP-U ICMP Packet */
|
||||
rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV6);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive GTP-U ICMP Packet */
|
||||
recvbuf = test_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
#endif
|
||||
|
||||
ogs_msleep(300);
|
||||
|
||||
/* Send Registration request
|
||||
* - Update Registration request type
|
||||
* - Uplink Data Status */
|
||||
test_ue->nas.registration.value =
|
||||
OGS_NAS_5GS_REGISTRATION_TYPE_MOBILITY_UPDATING;
|
||||
|
||||
test_ue->registration_request_param.uplink_data_status = 1;
|
||||
test_ue->registration_request_param.psimask.uplink_data_status =
|
||||
1 << sess->psi;
|
||||
nasbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, nasbuf);
|
||||
|
||||
memset(&test_ue->registration_request_param, 0,
|
||||
sizeof(test_ue->registration_request_param));
|
||||
test_ue->registration_request_param.guti = 1;
|
||||
#if OLD_AMF_NOT_FOUND
|
||||
test_ue->nas_5gs_guti.amf_id.pointer = 2;
|
||||
#endif
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, true, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
NGAP_RRCEstablishmentCause_mo_Signalling, true, true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
#if OLD_AMF_NOT_FOUND
|
||||
/* Receive Identity request */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Identity response */
|
||||
gmmbuf = testgmm_build_identity_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(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
#endif
|
||||
|
||||
/* Receive Authentication request */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
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(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Security mode command */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
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(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive InitialContextSetupRequest +
|
||||
* Registration accept */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_InitialContextSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UERadioCapabilityInfoIndication */
|
||||
sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send InitialContextSetupResponse */
|
||||
sendbuf = testngap_build_initial_context_setup_response(test_ue, false);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Registration complete */
|
||||
gmmbuf = testgmm_build_registration_complete(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(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Configuration update command */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send PDU session establishment request */
|
||||
sess = test_sess_find_by_psi(test_ue, 5);
|
||||
ogs_assert(sess);
|
||||
|
||||
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 = 0;
|
||||
|
||||
sess->pdu_session_establishment_param.ssc_mode = 1;
|
||||
sess->pdu_session_establishment_param.epco = 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(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive PDUSessionResourceSetupRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session establishment accept */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
qos_flow = test_qos_flow_find_by_qfi(sess, 1);
|
||||
ogs_assert(qos_flow);
|
||||
rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send PDUSessionResourceSetupResponse */
|
||||
sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
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);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
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);
|
||||
|
||||
/* Send GTP-U Router Solicitation */
|
||||
rv = test_gtpu_send_slacc_rs(gtpu, qos_flow);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive GTP-U Router Advertisement */
|
||||
recvbuf = test_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testgtpu_recv(test_ue, recvbuf);
|
||||
|
||||
#if !defined(__FreeBSD__)
|
||||
/* Send GTP-U ICMP Packet */
|
||||
rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV6);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive GTP-U ICMP Packet */
|
||||
recvbuf = test_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
#endif
|
||||
|
||||
/* Send UEContextReleaseRequest */
|
||||
sendbuf = testngap_build_ue_context_release_request(test_ue,
|
||||
NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity,
|
||||
true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive UEContextReleaseCommand */
|
||||
recvbuf = testgnb_ngap_read(ngap2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_UEContextRelease,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UEContextReleaseComplete */
|
||||
sendbuf = testngap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
ogs_msleep(300);
|
||||
|
||||
/********** Remove Subscriber in Database */
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
|
||||
|
||||
/* gNB disonncect from UPF */
|
||||
testgnb_gtpu_close(gtpu);
|
||||
|
||||
/* gNB disonncect from AMF(127.0.1.5) */
|
||||
testgnb_ngap_close(ngap2);
|
||||
|
||||
/* gNB disonncect from AMF */
|
||||
testgnb_ngap_close(ngap);
|
||||
|
||||
/* Clear Test UE Context */
|
||||
test_ue_remove(test_ue);
|
||||
}
|
||||
#endif
|
||||
|
||||
abts_suite *test_guti(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
#if !CONTEXT_TRANSFER_TEST
|
||||
abts_run_test(suite, test1_func, NULL);
|
||||
abts_run_test(suite, test2_func, NULL);
|
||||
abts_run_test(suite, test3_func, NULL);
|
||||
abts_run_test(suite, test4_issues2839_func, NULL);
|
||||
#else
|
||||
abts_run_test(suite, context_transfer_func, NULL);
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue