2020-06-04 18:12:05 +00:00
|
|
|
/*
|
2023-03-25 00:18:20 +00:00
|
|
|
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
2020-06-04 18:12:05 +00:00
|
|
|
*
|
|
|
|
* This file is part of Open5GS.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nas-security.h"
|
|
|
|
|
|
|
|
#include "ngap-path.h"
|
|
|
|
#include "nas-path.h"
|
2020-06-22 03:07:14 +00:00
|
|
|
#include "sbi-path.h"
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
#include "gmm-handler.h"
|
|
|
|
|
|
|
|
#undef OGS_LOG_DOMAIN
|
|
|
|
#define OGS_LOG_DOMAIN __gmm_log_domain
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue_t *ran_ue, amf_ue_t *amf_ue, uint8_t message_type,
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_nas_message_container_t *nas_message_container);
|
|
|
|
|
2023-03-25 00:18:20 +00:00
|
|
|
static uint8_t gmm_cause_from_access_control(ogs_plmn_id_t *plmn_id);
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
ogs_nas_5gmm_cause_t gmm_handle_registration_request(amf_ue_t *amf_ue,
|
2021-05-19 04:27:31 +00:00
|
|
|
ogs_nas_security_header_type_t h, NGAP_ProcedureCode_t ngap_code,
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_5gs_registration_request_t *registration_request)
|
|
|
|
{
|
|
|
|
int served_tai_index = 0;
|
2023-03-25 00:18:20 +00:00
|
|
|
uint8_t gmm_cause;
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
ogs_nas_5gs_registration_type_t *registration_type = NULL;
|
|
|
|
ogs_nas_5gs_mobile_identity_t *mobile_identity = NULL;
|
|
|
|
ogs_nas_5gs_mobile_identity_header_t *mobile_identity_header = NULL;
|
2022-06-09 12:35:59 +00:00
|
|
|
ogs_nas_5gs_mobile_identity_suci_t *mobile_identity_suci = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_5gs_mobile_identity_guti_t *mobile_identity_guti = NULL;
|
2020-06-23 04:35:41 +00:00
|
|
|
ogs_nas_ue_security_capability_t *ue_security_capability = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_5gs_guti_t nas_guti;
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_assert(amf_ue);
|
2020-10-29 02:59:27 +00:00
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_assert(ran_ue);
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_assert(registration_request);
|
|
|
|
registration_type = ®istration_request->registration_type;
|
|
|
|
ogs_assert(registration_type);
|
|
|
|
mobile_identity = ®istration_request->mobile_identity;
|
|
|
|
ogs_assert(mobile_identity);
|
2020-06-23 04:35:41 +00:00
|
|
|
ue_security_capability = ®istration_request->ue_security_capability;
|
|
|
|
ogs_assert(ue_security_capability);
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-05-07 06:07:51 +00:00
|
|
|
/*
|
|
|
|
* TS33.501
|
|
|
|
* Ch 6.4.6. Protection of initial NAS message
|
|
|
|
*
|
|
|
|
* If non-cleartext IEs is received, Open5GS will send Registration reject.
|
|
|
|
*
|
|
|
|
* Step 1: The UE shall send the initial NAS message to the AMF.
|
|
|
|
* If the UE has no NAS security context, the initial NAS message
|
|
|
|
* shall only contain the cleartext IEs, i.e. subscription identifiers
|
|
|
|
* (e.g. SUCI or GUTIs), UE security capabilities, ngKSI, indication
|
|
|
|
* that the UE is moving from EPC, Additional GUTI, and IE containing
|
|
|
|
* the TAU Request in the case idle mobility from LTE.
|
|
|
|
*
|
|
|
|
* If the UE has a NAS security context, the message sent shall contain
|
|
|
|
* the information given above in cleartext and the complete initial
|
|
|
|
* NAS message ciphered in a NAS container which is ciphered.
|
|
|
|
* With a NAS security context, the sent message shall also be
|
|
|
|
* integrity protected. In the case that the initial NAS message
|
|
|
|
* was protected and the AMF has the same security context,
|
|
|
|
* then steps 2 to 4 may be omitted In this case the AMF shall
|
|
|
|
* use the complete initial NAS message that is in the NAS container
|
|
|
|
* as the message to respond to.
|
|
|
|
*
|
|
|
|
* TS24.501
|
|
|
|
* Ch 4.4.6 Protection of initial NAS signalling messages
|
|
|
|
*
|
|
|
|
* When the initial NAS message is a REGISTRATION REQUEST message,
|
|
|
|
* the cleartext IEs are:
|
|
|
|
*
|
|
|
|
* - Extended protocol discriminator;
|
|
|
|
* - Security header type;
|
|
|
|
* - Spare half octet;
|
|
|
|
* - Registration request message identity;
|
|
|
|
* - 5GS registration type;
|
|
|
|
* - ngKSI;
|
|
|
|
* - 5GS mobile identity;
|
|
|
|
* - UE security capability;
|
|
|
|
* - Additional GUTI;
|
|
|
|
* - UE status; and
|
|
|
|
* - EPS NAS message container.
|
|
|
|
*/
|
2021-05-08 04:24:17 +00:00
|
|
|
|
|
|
|
#define OGS_REGISTRATION_CLEARTEXT_PRESENT \
|
|
|
|
(OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT| \
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_STATUS_PRESENT| \
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_PRESENT| \
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT)
|
|
|
|
|
2021-05-19 04:27:31 +00:00
|
|
|
if (ngap_code == NGAP_ProcedureCode_id_InitialUEMessage &&
|
|
|
|
registration_request->presencemask &
|
2021-05-07 06:07:51 +00:00
|
|
|
~OGS_REGISTRATION_CLEARTEXT_PRESENT) {
|
|
|
|
ogs_error("Non cleartext IEs is included [0x%llx]",
|
|
|
|
(long long)registration_request->presencemask);
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2021-05-07 06:07:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!h.integrity_protected &&
|
|
|
|
(registration_request->presencemask &
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT)) {
|
|
|
|
ogs_error("NAS container present without Integrity-protected");
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2021-05-07 06:07:51 +00:00
|
|
|
}
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (!mobile_identity->length || !mobile_identity->buffer) {
|
|
|
|
ogs_error("No Mobile Identity");
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2020-06-22 03:07:14 +00:00
|
|
|
}
|
|
|
|
|
2024-03-05 22:19:28 +00:00
|
|
|
if (mobile_identity->length < OGS_NAS_5GS_MOBILE_IDENTITY_SUCI_MIN_SIZE) {
|
|
|
|
ogs_error("The length of Mobile Identity(%d) is less then the min(%d)",
|
|
|
|
mobile_identity->length, OGS_NAS_5GS_MOBILE_IDENTITY_SUCI_MIN_SIZE);
|
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
mobile_identity_header =
|
|
|
|
(ogs_nas_5gs_mobile_identity_header_t *)mobile_identity->buffer;
|
|
|
|
|
|
|
|
switch (mobile_identity_header->type) {
|
|
|
|
case OGS_NAS_5GS_MOBILE_IDENTITY_SUCI:
|
2022-06-09 12:35:59 +00:00
|
|
|
mobile_identity_suci =
|
|
|
|
(ogs_nas_5gs_mobile_identity_suci_t *)mobile_identity->buffer;
|
2023-09-03 08:56:50 +00:00
|
|
|
if (mobile_identity_suci->h.supi_format !=
|
|
|
|
OGS_NAS_5GS_SUPI_FORMAT_IMSI) {
|
|
|
|
ogs_error("Not implemented SUPI format [%d]",
|
|
|
|
mobile_identity_suci->h.supi_format);
|
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
|
|
|
}
|
2022-06-09 12:35:59 +00:00
|
|
|
if (mobile_identity_suci->protection_scheme_id !=
|
2022-12-24 11:22:45 +00:00
|
|
|
OGS_PROTECTION_SCHEME_NULL &&
|
2022-06-09 12:35:59 +00:00
|
|
|
mobile_identity_suci->protection_scheme_id !=
|
2022-12-24 11:22:45 +00:00
|
|
|
OGS_PROTECTION_SCHEME_PROFILE_A &&
|
2022-06-09 12:35:59 +00:00
|
|
|
mobile_identity_suci->protection_scheme_id !=
|
2022-12-24 11:22:45 +00:00
|
|
|
OGS_PROTECTION_SCHEME_PROFILE_B) {
|
2022-06-09 12:35:59 +00:00
|
|
|
ogs_error("Invalid ProtectionSchemeID(%d) in SUCI",
|
|
|
|
mobile_identity_suci->protection_scheme_id);
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2022-06-09 12:35:59 +00:00
|
|
|
}
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_nas_to_plmn_id(&amf_ue->home_plmn_id,
|
|
|
|
&mobile_identity_suci->nas_plmn_id);
|
|
|
|
|
|
|
|
gmm_cause = gmm_cause_from_access_control(&amf_ue->home_plmn_id);
|
|
|
|
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
ogs_error("Rejected by PLMN-ID access control");
|
|
|
|
return gmm_cause;
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
amf_ue_set_suci(amf_ue, mobile_identity);
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("[%s] SUCI", amf_ue->suci);
|
2020-06-04 18:12:05 +00:00
|
|
|
break;
|
|
|
|
case OGS_NAS_5GS_MOBILE_IDENTITY_GUTI:
|
|
|
|
mobile_identity_guti =
|
|
|
|
(ogs_nas_5gs_mobile_identity_guti_t *)mobile_identity->buffer;
|
2020-06-22 03:07:14 +00:00
|
|
|
if (!mobile_identity_guti) {
|
|
|
|
ogs_error("No mobile identity");
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2020-06-22 03:07:14 +00:00
|
|
|
}
|
2020-06-04 18:12:05 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_nas_5gs_mobile_identity_guti_to_nas_guti(
|
|
|
|
mobile_identity_guti, &nas_guti);
|
2020-06-04 18:12:05 +00:00
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("[%s] 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]",
|
2020-06-04 18:12:05 +00:00
|
|
|
AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID",
|
|
|
|
ogs_amf_id_hexdump(&nas_guti.amf_id), nas_guti.m_tmsi);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown SUCI type [%d]", mobile_identity_header->type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Set 5GS Registration Type */
|
|
|
|
memcpy(&amf_ue->nas.registration, registration_type,
|
|
|
|
sizeof(ogs_nas_5gs_registration_type_t));
|
2020-06-17 05:22:28 +00:00
|
|
|
amf_ue->nas.message_type = OGS_NAS_5GS_REGISTRATION_REQUEST;
|
2021-05-08 04:24:17 +00:00
|
|
|
|
2023-02-07 13:29:53 +00:00
|
|
|
if (registration_type->value == OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL) {
|
|
|
|
/*
|
|
|
|
* Issue #2040
|
|
|
|
*
|
|
|
|
* TS23.501
|
|
|
|
* 5.4.4 UE Radio Capability handling
|
|
|
|
* 5.4.4.1 UE radio capability information storage in the AMF
|
|
|
|
*
|
|
|
|
* The AMF deletes the UE radio capability when the UE RM state
|
|
|
|
* in the AMF transitions to RM-DEREGISTERED. When the AMF receives
|
|
|
|
* Registration Request with the Registration type set to Initial
|
|
|
|
* Registration or when it receives the first Registration Request
|
|
|
|
* after E-UTRA/EPC Attach with Registration type set to Mobility
|
|
|
|
* Registration Update, the AMF deletes the UE radio capability.
|
|
|
|
*
|
|
|
|
* TS24.501
|
|
|
|
* 5.5.2 De-registration procedure
|
|
|
|
* 5.5.2.1 General
|
|
|
|
*
|
|
|
|
* When the AMF enters the state 5GMM-DEREGISTERED for 3GPP access,
|
|
|
|
* the AMF shall delete the stored UE radio capability information
|
|
|
|
* or the UE radio capability ID, if any.
|
|
|
|
*
|
|
|
|
* (DEPRECATED) Issue #1917 (from Switch-Off to De-Registration)
|
|
|
|
*
|
|
|
|
* When the UE sends a De-registration Request with Switch-Off,
|
|
|
|
* AMF should remove the the stored UE Radio Capability.
|
|
|
|
*
|
|
|
|
* Otherwise, the Radio Capability will not match
|
|
|
|
* because the gNB will not query the Radio Capability
|
|
|
|
* when the UE changes USIM.
|
|
|
|
*/
|
|
|
|
OGS_ASN_CLEAR_DATA(&amf_ue->ueRadioCapability);
|
|
|
|
}
|
|
|
|
|
2021-05-08 04:24:17 +00:00
|
|
|
amf_ue->nas.ue.tsc = registration_type->tsc;
|
|
|
|
amf_ue->nas.ue.ksi = registration_type->ksi;
|
|
|
|
ogs_debug(" OLD TSC[UE:%d,AMF:%d] KSI[UE:%d,AMF:%d]",
|
|
|
|
amf_ue->nas.ue.tsc, amf_ue->nas.amf.tsc,
|
|
|
|
amf_ue->nas.ue.ksi, amf_ue->nas.amf.ksi);
|
|
|
|
if (amf_ue->nas.ue.ksi < OGS_NAS_KSI_NO_KEY_IS_AVAILABLE) {
|
|
|
|
amf_ue->nas.amf.tsc = amf_ue->nas.ue.tsc;
|
|
|
|
amf_ue->nas.amf.ksi = amf_ue->nas.ue.ksi;
|
|
|
|
}
|
|
|
|
ogs_debug(" NEW TSC[UE:%d,AMF:%d] KSI[UE:%d,AMF:%d]",
|
|
|
|
amf_ue->nas.ue.tsc, amf_ue->nas.amf.tsc,
|
|
|
|
amf_ue->nas.ue.ksi, amf_ue->nas.amf.ksi);
|
2020-06-04 18:12:05 +00:00
|
|
|
/*
|
|
|
|
* REGISTRATION_REQUEST
|
|
|
|
* SERVICE_REQUEST
|
2021-01-18 16:48:35 +00:00
|
|
|
* Clear N2 Transfer
|
2020-06-04 18:12:05 +00:00
|
|
|
* Clear Timer and Message
|
|
|
|
*/
|
2021-01-18 16:48:35 +00:00
|
|
|
AMF_UE_CLEAR_PAGING_INFO(amf_ue);
|
|
|
|
AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request);
|
2021-11-14 12:07:56 +00:00
|
|
|
AMF_UE_CLEAR_5GSM_MESSAGE(amf_ue);
|
2020-06-04 18:12:05 +00:00
|
|
|
CLEAR_AMF_UE_ALL_TIMERS(amf_ue);
|
|
|
|
|
|
|
|
if (SECURITY_CONTEXT_IS_VALID(amf_ue)) {
|
|
|
|
ogs_kdf_kgnb_and_kn3iwf(
|
|
|
|
amf_ue->kamf, amf_ue->ul_count.i32,
|
2020-06-17 05:22:28 +00:00
|
|
|
amf_ue->nas.access_type, amf_ue->kgnb);
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_kdf_nh_gnb(amf_ue->kamf, amf_ue->kgnb, amf_ue->nh);
|
|
|
|
amf_ue->nhcc = 1;
|
|
|
|
}
|
|
|
|
|
2021-07-01 07:23:27 +00:00
|
|
|
/*
|
|
|
|
* TS24.501
|
|
|
|
* 5.3.3 Temporary identities
|
|
|
|
*
|
|
|
|
* The AMF shall assign a new 5G-GUTI for a particular UE:
|
|
|
|
*
|
|
|
|
* a) during a successful initial registration procedure;
|
|
|
|
* b) during a successful registration procedure
|
|
|
|
* for mobility registration update; and
|
|
|
|
* c) after a successful service request procedure invoked
|
|
|
|
* as a response to a paging request from the network and
|
|
|
|
* before the release of the N1 NAS signalling connection
|
|
|
|
* as specified in subclause 5.4.4.1.
|
|
|
|
*
|
|
|
|
* The AMF should assign a new 5G-GUTI for a particular UE
|
|
|
|
* during a successful registration procedure
|
|
|
|
* for periodic registration update.
|
|
|
|
*
|
|
|
|
* The AMF may assign a new 5G-GUTI at any time for a particular UE
|
|
|
|
* by performing the generic UE configuration update procedure.
|
|
|
|
*/
|
2021-04-13 08:34:25 +00:00
|
|
|
amf_ue_new_guti(amf_ue);
|
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_debug(" OLD TAI[PLMN_ID:%06x,TAC:%d]",
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_plmn_id_hexdump(&amf_ue->nr_tai.plmn_id), amf_ue->nr_tai.tac.v);
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_debug(" OLD NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
|
2020-06-26 02:44:28 +00:00
|
|
|
ogs_plmn_id_hexdump(&amf_ue->nr_cgi.plmn_id),
|
|
|
|
(long long)amf_ue->nr_cgi.cell_id);
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_plmn_id_hexdump(&ran_ue->saved.nr_tai.plmn_id),
|
|
|
|
ran_ue->saved.nr_tai.tac.v);
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_debug(" NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
|
2020-06-26 02:44:28 +00:00
|
|
|
ogs_plmn_id_hexdump(&ran_ue->saved.nr_cgi.plmn_id),
|
|
|
|
(long long)ran_ue->saved.nr_cgi.cell_id);
|
2020-06-04 18:12:05 +00:00
|
|
|
|
2021-01-20 15:03:32 +00:00
|
|
|
/* Copy Stream-No/NR-TAI/NR-CGI from ran_ue */
|
2021-01-18 16:48:35 +00:00
|
|
|
amf_ue->gnb_ostream_id = ran_ue->gnb_ostream_id;
|
2021-03-08 12:25:09 +00:00
|
|
|
memcpy(&amf_ue->nr_tai, &ran_ue->saved.nr_tai, sizeof(ogs_5gs_tai_t));
|
2020-06-26 02:44:28 +00:00
|
|
|
memcpy(&amf_ue->nr_cgi, &ran_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
|
2020-07-09 05:38:09 +00:00
|
|
|
amf_ue->ue_location_timestamp = ogs_time_now();
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
/* Check TAI */
|
2021-03-08 12:25:09 +00:00
|
|
|
served_tai_index = amf_find_served_tai(&amf_ue->nr_tai);
|
2020-06-04 18:12:05 +00:00
|
|
|
if (served_tai_index < 0) {
|
2022-07-19 03:42:02 +00:00
|
|
|
ogs_error("Cannot find Served TAI[PLMN_ID:%06x,TAC:%d]",
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_plmn_id_hexdump(&amf_ue->nr_tai.plmn_id), amf_ue->nr_tai.tac.v);
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_TRACKING_AREA_NOT_ALLOWED;
|
2020-06-04 18:12:05 +00:00
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
if (registration_request->presencemask &
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT) {
|
2020-06-23 04:35:41 +00:00
|
|
|
memcpy(&amf_ue->ue_security_capability,
|
2020-06-04 18:12:05 +00:00
|
|
|
®istration_request->ue_security_capability,
|
2020-06-23 04:35:41 +00:00
|
|
|
registration_request->ue_security_capability.length +
|
|
|
|
sizeof(registration_request->ue_security_capability.length));
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
if (amf_selected_int_algorithm(amf_ue) ==
|
|
|
|
OGS_NAS_SECURITY_ALGORITHMS_NIA0) {
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_error("[UE:0x%x:0x%x], NEA0 can be used in Encrypt[0x%x], "
|
|
|
|
"but Integrity[0x%x] cannot be bypassed with NIA0",
|
2021-01-08 03:26:06 +00:00
|
|
|
ue_security_capability->nr_ea, ue_security_capability->nr_ia,
|
2022-07-19 03:42:02 +00:00
|
|
|
amf_selected_enc_algorithm(amf_ue),
|
2020-06-04 18:12:05 +00:00
|
|
|
amf_selected_int_algorithm(amf_ue));
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH;
|
2020-06-04 18:12:05 +00:00
|
|
|
}
|
|
|
|
|
2022-11-23 11:45:34 +00:00
|
|
|
if (amf_ue_is_rat_restricted(amf_ue)) {
|
|
|
|
ogs_error("Registration rejected due to RAT restrictions");
|
|
|
|
return OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED;
|
|
|
|
}
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
2020-06-04 18:12:05 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 21:48:58 +00:00
|
|
|
ogs_nas_5gmm_cause_t gmm_handle_registration_update(
|
|
|
|
ran_ue_t *ran_ue, amf_ue_t *amf_ue,
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_nas_5gs_registration_request_t *registration_request)
|
|
|
|
{
|
|
|
|
amf_sess_t *sess = NULL;
|
2020-06-25 04:37:29 +00:00
|
|
|
uint16_t psimask;
|
2023-05-14 00:05:13 +00:00
|
|
|
int i = 0, served_tai_index = 0;
|
2020-06-24 04:33:10 +00:00
|
|
|
|
|
|
|
ogs_nas_5gs_tracking_area_identity_t *last_visited_registered_tai = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_nas_uplink_data_status_t *uplink_data_status = NULL;
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_nas_pdu_session_status_t *pdu_session_status = NULL;
|
2023-02-07 13:29:53 +00:00
|
|
|
ogs_nas_5gs_update_type_t *update_type = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2024-03-21 21:48:58 +00:00
|
|
|
ogs_assert(ran_ue);
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_assert(registration_request);
|
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
last_visited_registered_tai =
|
|
|
|
®istration_request->last_visited_registered_tai;
|
|
|
|
ogs_assert(last_visited_registered_tai);
|
2020-06-22 03:07:14 +00:00
|
|
|
uplink_data_status = ®istration_request->uplink_data_status;
|
|
|
|
ogs_assert(uplink_data_status);
|
2020-06-24 04:33:10 +00:00
|
|
|
pdu_session_status = ®istration_request->pdu_session_status;
|
|
|
|
ogs_assert(pdu_session_status);
|
2023-02-07 13:29:53 +00:00
|
|
|
update_type = ®istration_request->update_type;
|
|
|
|
ogs_assert(update_type);
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2023-05-14 00:05:13 +00:00
|
|
|
served_tai_index = amf_find_served_tai(&amf_ue->nr_tai);
|
|
|
|
if (served_tai_index < 0) {
|
|
|
|
ogs_error("Cannot find Served TAI[PLMN_ID:%06x,TAC:%d]",
|
|
|
|
ogs_plmn_id_hexdump(&amf_ue->nr_tai.plmn_id), amf_ue->nr_tai.tac.v);
|
|
|
|
return OGS_5GMM_CAUSE_TRACKING_AREA_NOT_ALLOWED;
|
|
|
|
}
|
|
|
|
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
if (registration_request->presencemask &
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT) {
|
|
|
|
|
|
|
|
return gmm_handle_nas_message_container(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, amf_ue, OGS_NAS_5GS_REGISTRATION_REQUEST,
|
2022-01-05 13:39:06 +00:00
|
|
|
®istration_request->nas_message_container);
|
2020-06-25 04:37:29 +00:00
|
|
|
}
|
|
|
|
|
2021-05-07 06:07:51 +00:00
|
|
|
if (registration_request->presencemask &
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) {
|
|
|
|
ogs_nas_5gmm_capability_t *gmm_capability =
|
|
|
|
®istration_request->gmm_capability;
|
|
|
|
|
|
|
|
amf_ue->gmm_capability.lte_positioning_protocol_capability
|
|
|
|
= gmm_capability->lte_positioning_protocol_capability;
|
|
|
|
amf_ue->gmm_capability.ho_attach = gmm_capability->ho_attach;
|
|
|
|
amf_ue->gmm_capability.s1_mode = gmm_capability->s1_mode;
|
|
|
|
|
|
|
|
ogs_debug(" 5GMM Capability:[LPP:%d, HO_ATTACH:%d, S1_MODE:%d]",
|
|
|
|
amf_ue->gmm_capability.lte_positioning_protocol_capability,
|
|
|
|
amf_ue->gmm_capability.ho_attach,
|
|
|
|
amf_ue->gmm_capability.s1_mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (registration_request->presencemask &
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_PRESENT) {
|
|
|
|
memcpy(&amf_ue->ue_network_capability,
|
|
|
|
®istration_request->s1_ue_network_capability,
|
|
|
|
registration_request->s1_ue_network_capability.length +
|
|
|
|
sizeof(registration_request->s1_ue_network_capability.length));
|
|
|
|
}
|
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
if (registration_request->presencemask &
|
2020-07-03 05:03:13 +00:00
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT) {
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2021-03-08 12:25:09 +00:00
|
|
|
amf_ue->requested_nssai.num_of_s_nssai =
|
|
|
|
ogs_nas_parse_nssai(
|
|
|
|
amf_ue->requested_nssai.s_nssai,
|
|
|
|
®istration_request->requested_nssai);
|
2020-09-12 02:42:38 +00:00
|
|
|
|
2021-03-08 12:25:09 +00:00
|
|
|
for (i = 0; i < amf_ue->requested_nssai.num_of_s_nssai; i++) {
|
2020-09-12 02:42:38 +00:00
|
|
|
if (amf_find_s_nssai(
|
2021-03-08 12:25:09 +00:00
|
|
|
&amf_ue->nr_tai.plmn_id,
|
|
|
|
(ogs_s_nssai_t *)&amf_ue->requested_nssai.s_nssai[i]))
|
2020-09-12 02:42:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-03-08 12:25:09 +00:00
|
|
|
if (i == amf_ue->requested_nssai.num_of_s_nssai) {
|
2021-03-26 14:12:43 +00:00
|
|
|
ogs_error("Cannot find Requested NSSAI [%d]",
|
|
|
|
amf_ue->requested_nssai.num_of_s_nssai);
|
2021-03-08 12:25:09 +00:00
|
|
|
for (i = 0; i < amf_ue->requested_nssai.num_of_s_nssai; i++) {
|
2020-09-12 02:42:38 +00:00
|
|
|
ogs_error(" PLMN_ID[MCC:%d MNC:%d]",
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_plmn_id_mcc(&amf_ue->nr_tai.plmn_id),
|
|
|
|
ogs_plmn_id_mnc(&amf_ue->nr_tai.plmn_id));
|
2020-09-12 02:42:38 +00:00
|
|
|
ogs_error(" S_NSSAI[SST:%d SD:0x%x]",
|
2021-03-08 12:25:09 +00:00
|
|
|
amf_ue->requested_nssai.s_nssai[i].sst,
|
|
|
|
amf_ue->requested_nssai.s_nssai[i].sd.v);
|
2020-09-12 02:42:38 +00:00
|
|
|
}
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_NO_NETWORK_SLICES_AVAILABLE;
|
2020-09-12 02:42:38 +00:00
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (registration_request->presencemask &
|
2020-07-03 05:03:13 +00:00
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) {
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-07-03 05:03:13 +00:00
|
|
|
ogs_nas_to_plmn_id(&amf_ue->last_visited_plmn_id,
|
|
|
|
&last_visited_registered_tai->nas_plmn_id);
|
2020-06-22 03:07:14 +00:00
|
|
|
}
|
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
if (registration_request->presencemask &
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_USAGE_SETTING_PRESENT) {
|
|
|
|
memcpy(&amf_ue->ue_usage_setting,
|
|
|
|
®istration_request->ue_usage_setting,
|
|
|
|
registration_request->ue_usage_setting.length +
|
|
|
|
sizeof(registration_request->ue_usage_setting.length));
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
if ((registration_request->presencemask &
|
2020-09-12 02:42:38 +00:00
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT)
|
|
|
|
== 0) {
|
2020-06-25 04:37:29 +00:00
|
|
|
amf_ue->nas.present.allowed_pdu_session_status = 0;
|
|
|
|
} else {
|
|
|
|
amf_ue->nas.present.allowed_pdu_session_status = 1;
|
|
|
|
ogs_error("Not implemented for Allowed PDU Session Status IE");
|
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
if ((registration_request->presencemask &
|
2021-01-18 16:48:35 +00:00
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_PRESENT) == 0) {
|
|
|
|
amf_ue->nas.present.pdu_session_status = 0;
|
2020-06-25 04:37:29 +00:00
|
|
|
} else {
|
2021-01-18 16:48:35 +00:00
|
|
|
amf_ue->nas.present.pdu_session_status = 1;
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
psimask = 0;
|
2021-01-18 16:48:35 +00:00
|
|
|
psimask |= pdu_session_status->psi << 8;
|
|
|
|
psimask |= pdu_session_status->psi >> 8;
|
2020-06-24 04:33:10 +00:00
|
|
|
|
|
|
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
2021-01-18 16:48:35 +00:00
|
|
|
if ((psimask & (1 << sess->psi)) == 0) {
|
2020-06-27 19:21:29 +00:00
|
|
|
if (SESSION_CONTEXT_IN_SMF(sess))
|
2021-01-18 16:48:35 +00:00
|
|
|
amf_sbi_send_release_session(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT);
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-25 04:37:29 +00:00
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
if ((registration_request->presencemask &
|
2021-01-18 16:48:35 +00:00
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_PRESENT) == 0) {
|
|
|
|
amf_ue->nas.present.uplink_data_status = 0;
|
2020-06-25 04:37:29 +00:00
|
|
|
} else {
|
2021-01-18 16:48:35 +00:00
|
|
|
amf_ue->nas.present.uplink_data_status = 1;
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
psimask = 0;
|
2021-01-18 16:48:35 +00:00
|
|
|
psimask |= uplink_data_status->psi << 8;
|
|
|
|
psimask |= uplink_data_status->psi >> 8;
|
2020-06-24 04:33:10 +00:00
|
|
|
|
|
|
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
2021-01-18 16:48:35 +00:00
|
|
|
if (psimask & (1 << sess->psi)) {
|
2020-06-27 19:21:29 +00:00
|
|
|
if (SESSION_CONTEXT_IN_SMF(sess))
|
2021-01-28 19:23:54 +00:00
|
|
|
amf_sbi_send_activating_session(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess,
|
|
|
|
AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST);
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
}
|
|
|
|
|
2023-02-07 13:29:53 +00:00
|
|
|
if (registration_request->presencemask &
|
|
|
|
OGS_NAS_5GS_REGISTRATION_REQUEST_5GS_UPDATE_TYPE_PRESENT) {
|
|
|
|
if (update_type->ng_ran_radio_capability_update_needed == 1) {
|
|
|
|
/*
|
|
|
|
* Issue #2040
|
|
|
|
*
|
|
|
|
* TS23.501
|
|
|
|
* 5.4.4 UE Radio Capability handling
|
|
|
|
* 5.4.4.1 UE radio capability information storage in the AMF
|
|
|
|
*
|
|
|
|
* The AMF deletes the UE radio capability when the UE RM state
|
|
|
|
* in the AMF transitions to RM-DEREGISTERED. When the AMF receives
|
|
|
|
* Registration Request with the Registration type set to Initial
|
|
|
|
* Registration or when it receives the first Registration Request
|
|
|
|
* after E-UTRA/EPC Attach with Registration type set to Mobility
|
|
|
|
* Registration Update, the AMF deletes the UE radio capability.
|
|
|
|
*
|
|
|
|
* TS24.501
|
|
|
|
* 5.5.2 De-registration procedure
|
|
|
|
* 5.5.2.1 General
|
|
|
|
*
|
|
|
|
* When the AMF enters the state 5GMM-DEREGISTERED for 3GPP access,
|
|
|
|
* the AMF shall delete the stored UE radio capability information
|
|
|
|
* or the UE radio capability ID, if any.
|
|
|
|
*
|
|
|
|
* (DEPRECATED) Issue #1917 (from Switch-Off to De-Registration)
|
|
|
|
*
|
|
|
|
* When the UE sends a De-registration Request with Switch-Off,
|
|
|
|
* AMF should remove the the stored UE Radio Capability.
|
|
|
|
*
|
|
|
|
* Otherwise, the Radio Capability will not match
|
|
|
|
* because the gNB will not query the Radio Capability
|
|
|
|
* when the UE changes USIM.
|
|
|
|
*/
|
|
|
|
OGS_ASN_CLEAR_DATA(&amf_ue->ueRadioCapability);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
2020-06-04 18:12:05 +00:00
|
|
|
}
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
ogs_nas_5gmm_cause_t gmm_handle_service_request(amf_ue_t *amf_ue,
|
2021-05-19 04:27:31 +00:00
|
|
|
ogs_nas_security_header_type_t h, NGAP_ProcedureCode_t ngap_code,
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_5gs_service_request_t *service_request)
|
|
|
|
{
|
2020-07-09 05:38:09 +00:00
|
|
|
int served_tai_index = 0;
|
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_nas_key_set_identifier_t *ngksi = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2020-10-29 02:59:27 +00:00
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
2020-07-09 05:38:09 +00:00
|
|
|
ogs_assert(ran_ue);
|
2020-06-04 18:12:05 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ngksi = &service_request->ngksi;
|
|
|
|
ogs_assert(ngksi);
|
|
|
|
|
2023-02-06 07:46:28 +00:00
|
|
|
if (ngksi->type == OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES)
|
|
|
|
amf_metrics_inst_global_inc(AMF_METR_GLOB_CTR_MM_PAGING_5G_SUCC);
|
|
|
|
|
2021-05-08 04:24:17 +00:00
|
|
|
/*
|
|
|
|
* TS24.501
|
|
|
|
* Ch 4.4.6 Protection of initial NAS signalling messages
|
|
|
|
*
|
|
|
|
* When the initial NAS message is a SERVICE REQUEST message,
|
|
|
|
* the cleartext IEs are:
|
|
|
|
*
|
|
|
|
* - Extended protocol discriminator;
|
|
|
|
* - Security header type;
|
|
|
|
* - Spare half octet;
|
|
|
|
* - ngKSI;
|
|
|
|
* - Service request message identity;
|
|
|
|
* - Service type; and
|
|
|
|
* - 5G-S-TMSI.
|
|
|
|
*/
|
|
|
|
#define OGS_SERVICE_CLEARTEXT_PRESENT \
|
|
|
|
(OGS_NAS_5GS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT)
|
|
|
|
|
2021-05-19 04:27:31 +00:00
|
|
|
if (ngap_code == NGAP_ProcedureCode_id_InitialUEMessage &&
|
|
|
|
service_request->presencemask & ~OGS_SERVICE_CLEARTEXT_PRESENT) {
|
2021-05-08 04:24:17 +00:00
|
|
|
ogs_error("Non cleartext IEs is included [0x%llx]",
|
|
|
|
(long long)service_request->presencemask);
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2021-05-08 04:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!h.integrity_protected &&
|
|
|
|
(service_request->presencemask &
|
|
|
|
OGS_NAS_5GS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT)) {
|
|
|
|
ogs_error("NAS container present without Integrity-protected");
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2021-05-08 04:24:17 +00:00
|
|
|
}
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
amf_ue->nas.message_type = OGS_NAS_5GS_SERVICE_REQUEST;
|
2021-05-08 04:24:17 +00:00
|
|
|
|
|
|
|
amf_ue->nas.ue.tsc = ngksi->tsc;
|
|
|
|
amf_ue->nas.ue.ksi = ngksi->value;
|
|
|
|
ogs_debug(" OLD TSC[UE:%d,AMF:%d] KSI[UE:%d,AMF:%d]",
|
|
|
|
amf_ue->nas.ue.tsc, amf_ue->nas.amf.tsc,
|
|
|
|
amf_ue->nas.ue.ksi, amf_ue->nas.amf.ksi);
|
|
|
|
if (amf_ue->nas.ue.ksi < OGS_NAS_KSI_NO_KEY_IS_AVAILABLE) {
|
|
|
|
amf_ue->nas.amf.tsc = amf_ue->nas.ue.tsc;
|
|
|
|
amf_ue->nas.amf.ksi = amf_ue->nas.ue.ksi;
|
|
|
|
}
|
|
|
|
ogs_debug(" NEW TSC[UE:%d,AMF:%d] KSI[UE:%d,AMF:%d]",
|
|
|
|
amf_ue->nas.ue.tsc, amf_ue->nas.amf.tsc,
|
|
|
|
amf_ue->nas.ue.ksi, amf_ue->nas.amf.ksi);
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* REGISTRATION_REQUEST
|
|
|
|
* SERVICE_REQUEST
|
|
|
|
* Clear Timer and Message
|
|
|
|
*/
|
|
|
|
CLEAR_AMF_UE_ALL_TIMERS(amf_ue);
|
|
|
|
|
|
|
|
if (SECURITY_CONTEXT_IS_VALID(amf_ue)) {
|
|
|
|
ogs_kdf_kgnb_and_kn3iwf(
|
|
|
|
amf_ue->kamf, amf_ue->ul_count.i32,
|
2020-06-22 03:07:14 +00:00
|
|
|
amf_ue->nas.access_type, amf_ue->kgnb);
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_kdf_nh_gnb(amf_ue->kamf, amf_ue->kgnb, amf_ue->nh);
|
|
|
|
amf_ue->nhcc = 1;
|
|
|
|
}
|
|
|
|
|
2020-07-09 05:38:09 +00:00
|
|
|
ogs_debug(" OLD TAI[PLMN_ID:%06x,TAC:%d]",
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_plmn_id_hexdump(&amf_ue->nr_tai.plmn_id), amf_ue->nr_tai.tac.v);
|
2020-07-09 05:38:09 +00:00
|
|
|
ogs_debug(" OLD NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
|
|
|
|
ogs_plmn_id_hexdump(&amf_ue->nr_cgi.plmn_id),
|
|
|
|
(long long)amf_ue->nr_cgi.cell_id);
|
|
|
|
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_plmn_id_hexdump(&ran_ue->saved.nr_tai.plmn_id),
|
|
|
|
ran_ue->saved.nr_tai.tac.v);
|
2020-07-09 05:38:09 +00:00
|
|
|
ogs_debug(" NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
|
|
|
|
ogs_plmn_id_hexdump(&ran_ue->saved.nr_cgi.plmn_id),
|
|
|
|
(long long)ran_ue->saved.nr_cgi.cell_id);
|
|
|
|
|
2021-01-20 15:03:32 +00:00
|
|
|
/* Copy Stream-No/NR-TAI/NR-CGI from ran_ue */
|
2021-01-18 16:48:35 +00:00
|
|
|
amf_ue->gnb_ostream_id = ran_ue->gnb_ostream_id;
|
2021-03-08 12:25:09 +00:00
|
|
|
memcpy(&amf_ue->nr_tai, &ran_ue->saved.nr_tai, sizeof(ogs_5gs_tai_t));
|
2020-07-09 05:38:09 +00:00
|
|
|
memcpy(&amf_ue->nr_cgi, &ran_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
|
|
|
|
amf_ue->ue_location_timestamp = ogs_time_now();
|
|
|
|
|
|
|
|
/* Check TAI */
|
2021-03-08 12:25:09 +00:00
|
|
|
served_tai_index = amf_find_served_tai(&amf_ue->nr_tai);
|
2020-07-09 05:38:09 +00:00
|
|
|
if (served_tai_index < 0) {
|
2022-07-19 03:42:02 +00:00
|
|
|
ogs_error("Cannot find Served TAI[PLMN_ID:%06x,TAC:%d]",
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_plmn_id_hexdump(&amf_ue->nr_tai.plmn_id), amf_ue->nr_tai.tac.v);
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_TRACKING_AREA_NOT_ALLOWED;
|
2020-07-09 05:38:09 +00:00
|
|
|
}
|
|
|
|
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("[%s] 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]",
|
2020-06-22 03:07:14 +00:00
|
|
|
AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID",
|
2021-04-13 08:34:25 +00:00
|
|
|
ogs_amf_id_hexdump(&amf_ue->current.guti.amf_id),
|
|
|
|
amf_ue->current.guti.m_tmsi);
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 21:48:58 +00:00
|
|
|
ogs_nas_5gmm_cause_t gmm_handle_service_update(
|
|
|
|
ran_ue_t *ran_ue, amf_ue_t *amf_ue,
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_nas_5gs_service_request_t *service_request)
|
|
|
|
{
|
|
|
|
amf_sess_t *sess = NULL;
|
2020-06-25 04:37:29 +00:00
|
|
|
uint16_t psimask = 0;
|
2023-01-23 01:37:22 +00:00
|
|
|
int xact_count = 0, r;
|
2020-06-25 04:37:29 +00:00
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_nas_uplink_data_status_t *uplink_data_status = NULL;
|
|
|
|
ogs_nas_pdu_session_status_t *pdu_session_status = NULL;
|
|
|
|
ogs_nas_allowed_pdu_session_status_t *allowed_pdu_session_status = NULL;
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2024-03-21 21:48:58 +00:00
|
|
|
ogs_assert(ran_ue);
|
|
|
|
ogs_assert(service_request);
|
2020-06-24 04:33:10 +00:00
|
|
|
|
|
|
|
uplink_data_status = &service_request->uplink_data_status;
|
|
|
|
ogs_assert(uplink_data_status);
|
|
|
|
pdu_session_status = &service_request->pdu_session_status;
|
|
|
|
ogs_assert(pdu_session_status);
|
|
|
|
allowed_pdu_session_status = &service_request->allowed_pdu_session_status;
|
|
|
|
ogs_assert(allowed_pdu_session_status);
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
if (service_request->presencemask &
|
2020-06-25 04:37:29 +00:00
|
|
|
OGS_NAS_5GS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT) {
|
|
|
|
|
|
|
|
return gmm_handle_nas_message_container(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, amf_ue, OGS_NAS_5GS_SERVICE_REQUEST,
|
2022-01-05 13:39:06 +00:00
|
|
|
&service_request->nas_message_container);
|
2020-06-25 04:37:29 +00:00
|
|
|
}
|
|
|
|
|
2020-08-03 03:22:41 +00:00
|
|
|
xact_count = amf_sess_xact_count(amf_ue);
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
/*
|
|
|
|
* TS24.501
|
|
|
|
* 5.6.1.5 Service request procedure not accepted by the network
|
|
|
|
*
|
|
|
|
* If the AMF needs to initiate PDU session status synchronisation
|
|
|
|
* or a PDU session status IE was included in the SERVICE REQUEST message,
|
|
|
|
* the AMF shall include a PDU session status IE in the SERVICE REJECT
|
|
|
|
* message to indicate which PDU sessions associated with the access type
|
|
|
|
* the SERVICE REJECT message is sent over are active in the AMF.
|
|
|
|
* If the PDU session status IE is included in the SERVICE REJECT message
|
|
|
|
* and if the message is integrity protected, then the UE shall perform
|
|
|
|
* a local release of all those PDU sessions which are active
|
|
|
|
* on the UE side associated with the access type the SERVICE REJECT
|
|
|
|
* message is sent over, but are indicated by the AMF as being inactive.
|
|
|
|
*/
|
2020-06-25 04:37:29 +00:00
|
|
|
if ((service_request->presencemask &
|
|
|
|
OGS_NAS_5GS_SERVICE_REQUEST_PDU_SESSION_STATUS_PRESENT) == 0) {
|
|
|
|
amf_ue->nas.present.pdu_session_status = 0;
|
|
|
|
} else {
|
|
|
|
amf_ue->nas.present.pdu_session_status = 1;
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
psimask = 0;
|
|
|
|
psimask |= pdu_session_status->psi << 8;
|
|
|
|
psimask |= pdu_session_status->psi >> 8;
|
|
|
|
|
|
|
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
2020-06-27 19:21:29 +00:00
|
|
|
if ((psimask & (1 << sess->psi)) == 0) {
|
|
|
|
if (SESSION_CONTEXT_IN_SMF(sess))
|
2020-08-07 15:57:17 +00:00
|
|
|
amf_sbi_send_release_session(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT);
|
2020-06-27 19:21:29 +00:00
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
2020-06-25 04:37:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
if ((service_request->presencemask &
|
|
|
|
OGS_NAS_5GS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT) == 0) {
|
|
|
|
amf_ue->nas.present.allowed_pdu_session_status = 0;
|
|
|
|
} else {
|
|
|
|
amf_ue->nas.present.allowed_pdu_session_status = 1;
|
|
|
|
ogs_error("Not implemented for Allowed PDU Session Status IE");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((service_request->presencemask &
|
|
|
|
OGS_NAS_5GS_SERVICE_REQUEST_UPLINK_DATA_STATUS_PRESENT) == 0) {
|
|
|
|
amf_ue->nas.present.uplink_data_status = 0;
|
|
|
|
} else {
|
|
|
|
amf_ue->nas.present.uplink_data_status = 1;
|
|
|
|
|
|
|
|
psimask = 0;
|
|
|
|
psimask |= uplink_data_status->psi << 8;
|
|
|
|
psimask |= uplink_data_status->psi >> 8;
|
|
|
|
|
|
|
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
|
|
|
if (psimask & (1 << sess->psi)) {
|
|
|
|
if (SESSION_CONTEXT_IN_SMF(sess))
|
2021-01-28 19:23:54 +00:00
|
|
|
amf_sbi_send_activating_session(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess,
|
|
|
|
AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST);
|
2021-01-18 16:48:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
if (amf_sess_xact_count(amf_ue) == xact_count) {
|
|
|
|
r = nas_5gs_send_service_accept(amf_ue);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
|
|
|
}
|
2020-06-25 04:37:29 +00:00
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
2020-06-25 04:37:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int gmm_handle_deregistration_request(amf_ue_t *amf_ue,
|
|
|
|
ogs_nas_5gs_deregistration_request_from_ue_t *deregistration_request)
|
|
|
|
{
|
2023-02-04 11:43:31 +00:00
|
|
|
int r, state, xact_count = 0;
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue_t *ran_ue = NULL;
|
2020-06-25 04:37:29 +00:00
|
|
|
ogs_nas_de_registration_type_t *de_registration_type = NULL;
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
|
|
|
ogs_assert(ran_ue);
|
2020-06-25 04:37:29 +00:00
|
|
|
ogs_assert(deregistration_request);
|
|
|
|
|
|
|
|
de_registration_type = &deregistration_request->de_registration_type;
|
|
|
|
|
2021-05-08 04:24:17 +00:00
|
|
|
/* Set 5GS De-registration Type */
|
2020-06-25 04:37:29 +00:00
|
|
|
memcpy(&amf_ue->nas.de_registration,
|
|
|
|
de_registration_type, sizeof(ogs_nas_de_registration_type_t));
|
2022-06-21 11:39:55 +00:00
|
|
|
amf_ue->nas.message_type = OGS_NAS_5GS_DEREGISTRATION_REQUEST_FROM_UE;
|
2021-05-08 04:24:17 +00:00
|
|
|
|
|
|
|
amf_ue->nas.ue.tsc = de_registration_type->tsc;
|
|
|
|
amf_ue->nas.ue.ksi = de_registration_type->ksi;
|
|
|
|
ogs_debug(" OLD TSC[UE:%d,AMF:%d] KSI[UE:%d,AMF:%d]",
|
|
|
|
amf_ue->nas.ue.tsc, amf_ue->nas.amf.tsc,
|
|
|
|
amf_ue->nas.ue.ksi, amf_ue->nas.amf.ksi);
|
|
|
|
if (amf_ue->nas.ue.ksi < OGS_NAS_KSI_NO_KEY_IS_AVAILABLE) {
|
|
|
|
amf_ue->nas.amf.tsc = amf_ue->nas.ue.tsc;
|
|
|
|
amf_ue->nas.amf.ksi = amf_ue->nas.ue.ksi;
|
|
|
|
}
|
|
|
|
ogs_debug(" NEW TSC[UE:%d,AMF:%d] KSI[UE:%d,AMF:%d]",
|
|
|
|
amf_ue->nas.ue.tsc, amf_ue->nas.amf.tsc,
|
|
|
|
amf_ue->nas.ue.ksi, amf_ue->nas.amf.ksi);
|
2020-06-25 04:37:29 +00:00
|
|
|
|
2023-02-05 03:03:00 +00:00
|
|
|
if (deregistration_request->de_registration_type.switch_off)
|
2020-06-25 04:37:29 +00:00
|
|
|
ogs_debug(" Switch-Off");
|
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("[%s] SUCI", amf_ue->suci);
|
|
|
|
|
2023-02-04 11:43:31 +00:00
|
|
|
xact_count = amf_sess_xact_count(amf_ue);
|
2020-08-03 03:22:41 +00:00
|
|
|
|
2023-02-04 11:43:31 +00:00
|
|
|
state = AMF_UE_INITIATED_DE_REGISTERED;
|
2024-03-21 21:48:58 +00:00
|
|
|
amf_sbi_send_release_all_sessions(ran_ue, amf_ue, state);
|
2023-02-04 11:43:31 +00:00
|
|
|
|
|
|
|
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
|
|
|
|
amf_sess_xact_count(amf_ue) == xact_count) {
|
|
|
|
if (UDM_SDM_SUBSCRIBED(amf_ue)) {
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_ue_sbi_discover_and_send(
|
2023-02-04 11:43:31 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL,
|
|
|
|
amf_nudm_sdm_build_subscription_delete,
|
2023-01-31 10:38:17 +00:00
|
|
|
amf_ue, state, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2023-02-04 11:43:31 +00:00
|
|
|
} else if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) {
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_ue_sbi_discover_and_send(
|
2023-02-04 11:43:31 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL,
|
|
|
|
NULL,
|
|
|
|
amf_npcf_am_policy_control_build_delete,
|
2023-01-31 10:38:17 +00:00
|
|
|
amf_ue, state, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2023-02-04 11:43:31 +00:00
|
|
|
} else {
|
|
|
|
r = nas_5gs_send_de_registration_accept(amf_ue);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
|
|
|
}
|
2023-01-23 01:37:22 +00:00
|
|
|
}
|
2020-06-25 04:37:29 +00:00
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int gmm_handle_authentication_response(amf_ue_t *amf_ue,
|
|
|
|
ogs_nas_5gs_authentication_response_t *authentication_response)
|
|
|
|
{
|
|
|
|
ogs_nas_authentication_response_parameter_t
|
|
|
|
*authentication_response_parameter = NULL;
|
|
|
|
uint8_t hxres_star[OGS_MAX_RES_LEN];
|
2023-01-31 10:38:17 +00:00
|
|
|
int r;
|
2020-06-25 04:37:29 +00:00
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
|
|
|
ogs_assert(authentication_response);
|
|
|
|
|
|
|
|
authentication_response_parameter = &authentication_response->
|
|
|
|
authentication_response_parameter;
|
|
|
|
|
|
|
|
ogs_debug("[%s] Authentication response", amf_ue->suci);
|
|
|
|
|
|
|
|
CLEAR_AMF_UE_TIMER(amf_ue->t3560);
|
|
|
|
|
|
|
|
if (authentication_response_parameter->length != OGS_MAX_RES_LEN) {
|
|
|
|
ogs_error("[%s] Invalid length [%d]",
|
|
|
|
amf_ue->suci, authentication_response_parameter->length);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_kdf_hxres_star(
|
|
|
|
amf_ue->rand, authentication_response_parameter->res, hxres_star);
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
if (memcmp(hxres_star, amf_ue->hxres_star, OGS_MAX_RES_LEN) != 0) {
|
2020-07-26 18:54:30 +00:00
|
|
|
ogs_error("[%s] MAC failure", amf_ue->suci);
|
|
|
|
ogs_log_hexdump(OGS_LOG_ERROR,
|
2020-06-25 04:37:29 +00:00
|
|
|
authentication_response_parameter->res,
|
|
|
|
authentication_response_parameter->length);
|
2020-07-26 18:54:30 +00:00
|
|
|
ogs_log_hexdump(OGS_LOG_ERROR, hxres_star, OGS_MAX_RES_LEN);
|
|
|
|
ogs_log_hexdump(OGS_LOG_ERROR,
|
2020-06-25 04:37:29 +00:00
|
|
|
amf_ue->hxres_star, OGS_MAX_RES_LEN);
|
2020-06-24 04:33:10 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
memcpy(amf_ue->xres_star, authentication_response_parameter->res,
|
|
|
|
authentication_response_parameter->length);
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_ue_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL,
|
2023-01-31 10:38:17 +00:00
|
|
|
amf_nausf_auth_build_authenticate_confirmation, amf_ue, 0, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-25 04:37:29 +00:00
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_nas_5gmm_cause_t gmm_handle_identity_response(amf_ue_t *amf_ue,
|
2020-06-25 04:37:29 +00:00
|
|
|
ogs_nas_5gs_identity_response_t *identity_response)
|
|
|
|
{
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
2023-11-19 10:34:51 +00:00
|
|
|
uint8_t gmm_cause;
|
2020-06-25 04:37:29 +00:00
|
|
|
|
|
|
|
ogs_nas_5gs_mobile_identity_t *mobile_identity = NULL;
|
2021-05-07 14:04:48 +00:00
|
|
|
ogs_nas_5gs_mobile_identity_suci_t *mobile_identity_suci = NULL;
|
2020-06-25 04:37:29 +00:00
|
|
|
ogs_nas_5gs_mobile_identity_header_t *mobile_identity_header = NULL;
|
|
|
|
|
|
|
|
ogs_assert(identity_response);
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2020-10-29 02:59:27 +00:00
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
2020-06-25 04:37:29 +00:00
|
|
|
ogs_assert(ran_ue);
|
2024-03-21 21:48:58 +00:00
|
|
|
ogs_assert(identity_response);
|
2020-06-25 04:37:29 +00:00
|
|
|
|
|
|
|
mobile_identity = &identity_response->mobile_identity;
|
|
|
|
|
|
|
|
if (!mobile_identity->length || !mobile_identity->buffer) {
|
|
|
|
ogs_error("No Mobile Identity");
|
2023-11-19 10:34:51 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2020-06-22 03:07:14 +00:00
|
|
|
}
|
2020-06-04 18:12:05 +00:00
|
|
|
|
2024-03-05 22:19:28 +00:00
|
|
|
if (mobile_identity->length < OGS_NAS_5GS_MOBILE_IDENTITY_SUCI_MIN_SIZE) {
|
|
|
|
ogs_error("The length of Mobile Identity(%d) is less then the min(%d)",
|
|
|
|
mobile_identity->length, OGS_NAS_5GS_MOBILE_IDENTITY_SUCI_MIN_SIZE);
|
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
|
|
|
}
|
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
mobile_identity_header =
|
|
|
|
(ogs_nas_5gs_mobile_identity_header_t *)mobile_identity->buffer;
|
|
|
|
|
|
|
|
if (mobile_identity_header->type == OGS_NAS_5GS_MOBILE_IDENTITY_SUCI) {
|
2021-05-07 14:04:48 +00:00
|
|
|
mobile_identity_suci =
|
|
|
|
(ogs_nas_5gs_mobile_identity_suci_t *)mobile_identity->buffer;
|
2023-09-03 08:56:50 +00:00
|
|
|
if (mobile_identity_suci->h.supi_format !=
|
|
|
|
OGS_NAS_5GS_SUPI_FORMAT_IMSI) {
|
|
|
|
ogs_error("Not implemented SUPI format [%d]",
|
|
|
|
mobile_identity_suci->h.supi_format);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2021-05-07 14:04:48 +00:00
|
|
|
if (mobile_identity_suci->protection_scheme_id !=
|
2022-12-24 11:22:45 +00:00
|
|
|
OGS_PROTECTION_SCHEME_NULL &&
|
|
|
|
mobile_identity_suci->protection_scheme_id !=
|
|
|
|
OGS_PROTECTION_SCHEME_PROFILE_A &&
|
|
|
|
mobile_identity_suci->protection_scheme_id !=
|
|
|
|
OGS_PROTECTION_SCHEME_PROFILE_B) {
|
|
|
|
ogs_error("Invalid ProtectionSchemeID(%d) in SUCI",
|
2021-05-07 14:04:48 +00:00
|
|
|
mobile_identity_suci->protection_scheme_id);
|
2023-11-19 10:34:51 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2021-05-07 14:04:48 +00:00
|
|
|
}
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_nas_to_plmn_id(&amf_ue->home_plmn_id,
|
|
|
|
&mobile_identity_suci->nas_plmn_id);
|
|
|
|
|
|
|
|
gmm_cause = gmm_cause_from_access_control(&amf_ue->home_plmn_id);
|
|
|
|
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
ogs_error("Rejected by PLMN-ID access control");
|
|
|
|
return gmm_cause;
|
|
|
|
}
|
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
amf_ue_set_suci(amf_ue, mobile_identity);
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("[%s] SUCI", amf_ue->suci);
|
2020-06-25 04:37:29 +00:00
|
|
|
} else {
|
|
|
|
ogs_error("Not supported Identity type[%d]",
|
|
|
|
mobile_identity_header->type);
|
|
|
|
}
|
|
|
|
|
2023-11-19 10:34:51 +00:00
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
2020-06-04 18:12:05 +00:00
|
|
|
}
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
ogs_nas_5gmm_cause_t gmm_handle_security_mode_complete(amf_ue_t *amf_ue,
|
2024-03-21 21:48:58 +00:00
|
|
|
ogs_nas_5gs_security_mode_complete_t *security_mode_complete)
|
2020-06-04 18:12:05 +00:00
|
|
|
{
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue_t *ran_ue = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_5gs_mobile_identity_t *imeisv = NULL;
|
|
|
|
ogs_nas_mobile_identity_imeisv_t *mobile_identity_imeisv = NULL;
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
|
|
|
ogs_assert(ran_ue);
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_assert(security_mode_complete);
|
|
|
|
|
2021-05-07 06:07:51 +00:00
|
|
|
/*
|
|
|
|
* TS33.501
|
|
|
|
* Ch 6.4.6. Protection of initial NAS message
|
|
|
|
*
|
|
|
|
* UE should send NAS Container in Security mode complete message.
|
|
|
|
* Otherwise, Open5GS will send Registration reject message.
|
|
|
|
*
|
|
|
|
* Step 4: The UE shall send the NAS Security Mode Complete message
|
|
|
|
* to the network in response to a NAS Security Mode Command message.
|
|
|
|
* The NAS Security Mode Complete message shall be ciphered and
|
|
|
|
* integrity protected. Furthermore the NAS Security Mode Complete message
|
|
|
|
* shall include the complete initial NAS message in a NAS Container
|
|
|
|
* if either requested by the AMF or the UE sent the initial NAS message
|
|
|
|
* unprotected. The AMF shall use the complete initial NAS message
|
|
|
|
* that is in the NAS container as the message to respond to.
|
|
|
|
*/
|
|
|
|
if ((security_mode_complete->presencemask &
|
|
|
|
OGS_NAS_5GS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT)
|
|
|
|
== 0) {
|
|
|
|
ogs_error("No NAS Message Container in Security mode complete message");
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE;
|
2021-05-07 06:07:51 +00:00
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
if (security_mode_complete->presencemask &
|
2020-06-24 04:33:10 +00:00
|
|
|
OGS_NAS_5GS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT) {
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
imeisv = &security_mode_complete->imeisv;
|
|
|
|
ogs_assert(imeisv);
|
|
|
|
mobile_identity_imeisv =
|
|
|
|
(ogs_nas_mobile_identity_imeisv_t *)imeisv->buffer;
|
|
|
|
ogs_assert(mobile_identity_imeisv);
|
|
|
|
|
|
|
|
switch (mobile_identity_imeisv->type) {
|
|
|
|
case OGS_NAS_5GS_MOBILE_IDENTITY_IMEISV:
|
2021-01-29 05:10:17 +00:00
|
|
|
/* TS23.003 6.2.2 Composition of IMEISV
|
|
|
|
*
|
|
|
|
* The International Mobile station Equipment Identity and
|
|
|
|
* Software Version Number (IMEISV) is composed.
|
|
|
|
*
|
|
|
|
* TAC(8 digits) - SNR(6 digits) - SVN(2 digits)
|
|
|
|
* IMEISV(16 digits) ==> 8bytes
|
|
|
|
*/
|
|
|
|
if (imeisv->length == sizeof(ogs_nas_mobile_identity_imeisv_t)) {
|
|
|
|
memcpy(&amf_ue->nas_mobile_identity_imeisv,
|
|
|
|
mobile_identity_imeisv, imeisv->length);
|
|
|
|
ogs_nas_imeisv_to_bcd(mobile_identity_imeisv, imeisv->length,
|
|
|
|
amf_ue->imeisv_bcd);
|
|
|
|
ogs_nas_imeisv_bcd_to_buffer(amf_ue->imeisv_bcd,
|
|
|
|
amf_ue->masked_imeisv, &amf_ue->masked_imeisv_len);
|
|
|
|
amf_ue->masked_imeisv[5] = 0xff;
|
|
|
|
amf_ue->masked_imeisv[6] = 0xff;
|
|
|
|
if (amf_ue->pei)
|
|
|
|
ogs_free(amf_ue->pei);
|
|
|
|
amf_ue->pei = ogs_msprintf("imeisv-%s", amf_ue->imeisv_bcd);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(amf_ue->pei);
|
2021-01-29 05:10:17 +00:00
|
|
|
} else {
|
|
|
|
ogs_error("[%s] Unknown IMEISV Length [%d]",
|
|
|
|
amf_ue->supi, imeisv->length);
|
|
|
|
ogs_log_hexdump(OGS_LOG_ERROR, imeisv->buffer, imeisv->length);
|
|
|
|
}
|
2020-06-04 18:12:05 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_warn("[%s] Invalid IMEISV Type [%d]",
|
|
|
|
amf_ue->supi, mobile_identity_imeisv->type);
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
if (security_mode_complete->presencemask &
|
|
|
|
OGS_NAS_5GS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT) {
|
|
|
|
|
|
|
|
return gmm_handle_nas_message_container(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, amf_ue, OGS_NAS_5GS_SECURITY_MODE_COMPLETE,
|
2022-01-05 13:39:06 +00:00
|
|
|
&security_mode_complete->nas_message_container);
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
2020-06-04 18:12:05 +00:00
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2024-01-13 14:10:17 +00:00
|
|
|
int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue,
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_nas_5gs_ul_nas_transport_t *ul_nas_transport)
|
|
|
|
{
|
2023-01-23 01:37:22 +00:00
|
|
|
int r;
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_slice_data_t *selected_slice = NULL;
|
2020-07-02 05:50:23 +00:00
|
|
|
amf_sess_t *sess = NULL;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2020-07-02 05:50:23 +00:00
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_nas_payload_container_type_t *payload_container_type = NULL;
|
|
|
|
ogs_nas_payload_container_t *payload_container = NULL;
|
|
|
|
ogs_nas_pdu_session_identity_2_t *pdu_session_id = NULL;
|
2020-06-23 04:35:41 +00:00
|
|
|
ogs_nas_s_nssai_t *nas_s_nssai = NULL;
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_nas_dnn_t *dnn = NULL;
|
2020-07-02 05:50:23 +00:00
|
|
|
ogs_nas_5gsm_header_t *gsm_header = NULL;
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2024-01-13 14:10:17 +00:00
|
|
|
ogs_assert(amf_ue_cycle(amf_ue));
|
|
|
|
ogs_assert(ran_ue_cycle(ran_ue));
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_assert(ul_nas_transport);
|
|
|
|
|
|
|
|
payload_container_type = &ul_nas_transport->payload_container_type;
|
|
|
|
ogs_assert(payload_container_type);
|
|
|
|
payload_container = &ul_nas_transport->payload_container;
|
|
|
|
ogs_assert(payload_container);
|
|
|
|
|
|
|
|
if (!payload_container_type->value) {
|
|
|
|
ogs_error("[%s] No Payload container type", amf_ue->supi);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(
|
|
|
|
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!payload_container->length) {
|
|
|
|
ogs_error("[%s] No Payload container length", amf_ue->supi);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(
|
|
|
|
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!payload_container->buffer) {
|
|
|
|
ogs_error("[%s] No Payload container buffer", amf_ue->supi);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(
|
|
|
|
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2020-07-04 03:14:48 +00:00
|
|
|
if ((ul_nas_transport->presencemask &
|
|
|
|
OGS_NAS_5GS_UL_NAS_TRANSPORT_PDU_SESSION_ID_PRESENT) == 0) {
|
|
|
|
ogs_error("[%s] No PDU session ID", amf_ue->supi);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(
|
|
|
|
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-04 03:14:48 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdu_session_id = &ul_nas_transport->pdu_session_id;
|
|
|
|
if (*pdu_session_id == OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("[%s] PDU session identity is unassigned",
|
|
|
|
amf_ue->supi);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(
|
|
|
|
amf_ue, OGS_5GMM_CAUSE_INVALID_MANDATORY_INFORMATION);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-04 03:14:48 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
switch (payload_container_type->value) {
|
|
|
|
case OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION:
|
2020-07-02 05:50:23 +00:00
|
|
|
gsm_header = (ogs_nas_5gsm_header_t *)payload_container->buffer;
|
|
|
|
ogs_assert(gsm_header);
|
|
|
|
|
2020-07-04 03:14:48 +00:00
|
|
|
if (gsm_header->message_type ==
|
|
|
|
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_REQUEST) {
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, *pdu_session_id);
|
|
|
|
if (!sess) {
|
|
|
|
sess = amf_sess_add(amf_ue, *pdu_session_id);
|
|
|
|
ogs_assert(sess);
|
2024-02-03 00:41:12 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* These are variables that should be initialized
|
|
|
|
* when a PDU session establishment message is received
|
|
|
|
* for an existing session.
|
|
|
|
*
|
|
|
|
* It should be noted that XXX_recieved, which is initialized now,
|
|
|
|
* has a different initialization location than XXX_gsm_type.
|
|
|
|
*
|
|
|
|
* XXX_received is initialized in the ESTABLISHMENT phase,
|
|
|
|
* but XXX_gsm_type is initialized in the RELEASE phase
|
|
|
|
* when a PDU session release command with a Reactivation Request
|
|
|
|
* and a PDU session release complete are sent simultaneously.
|
|
|
|
*/
|
|
|
|
sess->pdu_session_resource_release_response_received = false;
|
|
|
|
sess->pdu_session_release_complete_received = false;
|
|
|
|
|
2020-07-04 03:14:48 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, *pdu_session_id);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("[%s] No Session Context [%d]",
|
|
|
|
amf_ue->supi, gsm_header->message_type);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(amf_ue,
|
|
|
|
OGS_5GMM_CAUSE_INSUFFICIENT_USER_PLANE_RESOURCES_FOR_THE_PDU_SESSION);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-04 03:14:48 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
|
2023-04-04 12:22:03 +00:00
|
|
|
/*
|
|
|
|
* To check if Reactivation Request has been used.
|
|
|
|
*
|
|
|
|
* During the PFCP recovery process,
|
|
|
|
* when a Reactivation Request is sent to PDU session release command,
|
|
|
|
* the UE simultaneously sends PDU session release complete and
|
|
|
|
* PDU session establishment request.
|
|
|
|
*
|
|
|
|
* In this case, old_gsm_type is PDU session release command and
|
|
|
|
* current_gsm_type is PDU session establishment request.
|
|
|
|
*/
|
|
|
|
sess->old_gsm_type = sess->current_gsm_type;
|
|
|
|
sess->current_gsm_type = gsm_header->message_type;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
if (sess->payload_container)
|
|
|
|
ogs_pkbuf_free(sess->payload_container);
|
|
|
|
|
|
|
|
sess->payload_container_type = payload_container_type->value;
|
|
|
|
sess->payload_container =
|
|
|
|
ogs_pkbuf_alloc(NULL, payload_container->length);
|
|
|
|
ogs_assert(sess->payload_container);
|
|
|
|
ogs_pkbuf_put_data(sess->payload_container,
|
|
|
|
payload_container->buffer, payload_container->length);
|
|
|
|
|
2020-07-04 03:14:48 +00:00
|
|
|
if (gsm_header->message_type ==
|
|
|
|
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_REQUEST) {
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2022-03-27 08:50:31 +00:00
|
|
|
int i, j, k;
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2022-03-27 08:50:31 +00:00
|
|
|
nas_s_nssai = &ul_nas_transport->s_nssai;
|
|
|
|
ogs_assert(nas_s_nssai);
|
|
|
|
dnn = &ul_nas_transport->dnn;
|
|
|
|
ogs_assert(dnn);
|
2022-03-26 14:53:53 +00:00
|
|
|
|
|
|
|
|
2022-03-27 08:50:31 +00:00
|
|
|
for (i = 0; i < amf_ue->num_of_slice; i++) {
|
2022-06-30 04:33:16 +00:00
|
|
|
if (i >= OGS_MAX_NUM_OF_SLICE) {
|
|
|
|
ogs_warn("Ignore max slice count overflow [%d>=%d]",
|
|
|
|
amf_ue->num_of_slice, OGS_MAX_NUM_OF_SLICE);
|
|
|
|
break;
|
|
|
|
}
|
2022-03-27 08:50:31 +00:00
|
|
|
if (ul_nas_transport->presencemask &
|
|
|
|
OGS_NAS_5GS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT) {
|
|
|
|
ogs_nas_s_nssai_ie_t ie;
|
|
|
|
if (ogs_nas_parse_s_nssai(&ie, nas_s_nssai) != 0) {
|
|
|
|
if (ie.sst == amf_ue->slice[i].s_nssai.sst &&
|
|
|
|
ie.sd.v == amf_ue->slice[i].s_nssai.sd.v) {
|
|
|
|
|
|
|
|
/* PASS */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (j = 0; j < amf_ue->allowed_nssai.num_of_s_nssai; j++) {
|
2022-06-30 04:33:16 +00:00
|
|
|
if (j >= OGS_MAX_NUM_OF_SLICE) {
|
|
|
|
ogs_warn("Ignore max slice count overflow [%d>=%d]",
|
|
|
|
amf_ue->allowed_nssai.num_of_s_nssai,
|
|
|
|
OGS_MAX_NUM_OF_SLICE);
|
|
|
|
break;
|
|
|
|
}
|
2022-03-27 08:50:31 +00:00
|
|
|
if (amf_ue->slice[i].s_nssai.sst ==
|
|
|
|
amf_ue->allowed_nssai.s_nssai[j].sst &&
|
|
|
|
amf_ue->slice[i].s_nssai.sd.v ==
|
|
|
|
amf_ue->allowed_nssai.s_nssai[j].sd.v) {
|
|
|
|
|
|
|
|
if (ul_nas_transport->presencemask &
|
|
|
|
OGS_NAS_5GS_UL_NAS_TRANSPORT_DNN_PRESENT) {
|
|
|
|
|
|
|
|
for (k = 0;
|
|
|
|
k < amf_ue->slice[i].num_of_session; k++) {
|
2022-06-30 04:33:16 +00:00
|
|
|
if (k >= OGS_MAX_NUM_OF_SESS) {
|
|
|
|
ogs_warn("Ignore max session "
|
|
|
|
"count overflow [%d>=%d]",
|
|
|
|
amf_ue->slice[i].num_of_session,
|
|
|
|
OGS_MAX_NUM_OF_SESS);
|
|
|
|
break;
|
|
|
|
}
|
2022-09-08 07:08:15 +00:00
|
|
|
if (!ogs_strcasecmp(dnn->value,
|
2022-03-27 08:50:31 +00:00
|
|
|
amf_ue->slice[i].session[k].name)) {
|
|
|
|
|
|
|
|
selected_slice = amf_ue->slice + i;
|
|
|
|
ogs_assert(selected_slice);
|
|
|
|
|
|
|
|
if (sess->dnn)
|
|
|
|
ogs_free(sess->dnn);
|
|
|
|
sess->dnn = ogs_strdup(dnn->value);
|
|
|
|
ogs_assert(sess->dnn);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
selected_slice = amf_ue->slice + i;
|
|
|
|
ogs_assert(selected_slice);
|
|
|
|
|
|
|
|
if (selected_slice->num_of_session) {
|
|
|
|
if (sess->dnn)
|
|
|
|
ogs_free(sess->dnn);
|
|
|
|
sess->dnn = ogs_strdup(
|
|
|
|
selected_slice->session[0].name);
|
|
|
|
ogs_assert(sess->dnn);
|
|
|
|
}
|
|
|
|
}
|
2021-03-12 13:45:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-27 08:50:31 +00:00
|
|
|
if (!selected_slice || !sess->dnn) {
|
2022-05-26 11:12:30 +00:00
|
|
|
ogs_warn("[%s] DNN Not Supported OR "
|
2022-03-27 08:50:31 +00:00
|
|
|
"Not Subscribed in the Slice", amf_ue->supi);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(amf_ue,
|
|
|
|
OGS_5GMM_CAUSE_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-03-08 12:25:09 +00:00
|
|
|
return OGS_ERROR;
|
2020-07-04 03:14:48 +00:00
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2021-03-08 12:25:09 +00:00
|
|
|
/* Store S-NSSAI */
|
|
|
|
sess->s_nssai.sst = selected_slice->s_nssai.sst;
|
|
|
|
sess->s_nssai.sd.v = selected_slice->s_nssai.sd.v;
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2023-10-23 13:35:54 +00:00
|
|
|
ogs_info("UE SUPI[%s] DNN[%s] S_NSSAI[SST:%d SD:0x%x] "
|
2024-04-18 12:13:45 +00:00
|
|
|
"smContextRef[%s] smContextResourceURI[%s]",
|
2023-10-23 13:35:54 +00:00
|
|
|
amf_ue->supi, sess->dnn, sess->s_nssai.sst, sess->s_nssai.sd.v,
|
2024-04-18 12:13:45 +00:00
|
|
|
sess->sm_context.ref ? sess->sm_context.ref : "NULL",
|
|
|
|
sess->sm_context.resource_uri ?
|
|
|
|
sess->sm_context.resource_uri : "NULL");
|
2021-01-23 03:17:01 +00:00
|
|
|
|
2021-02-04 04:49:16 +00:00
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
2021-03-08 12:25:09 +00:00
|
|
|
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
2022-09-02 14:04:57 +00:00
|
|
|
ogs_sbi_service_type_e service_type =
|
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION;
|
2022-08-26 15:12:22 +00:00
|
|
|
|
2023-10-23 13:35:54 +00:00
|
|
|
ogs_sbi_discovery_option_t *discovery_option = NULL;
|
|
|
|
|
|
|
|
discovery_option = ogs_sbi_discovery_option_new();
|
|
|
|
ogs_assert(discovery_option);
|
|
|
|
|
|
|
|
ogs_sbi_discovery_option_add_snssais(
|
|
|
|
discovery_option, &sess->s_nssai);
|
|
|
|
ogs_sbi_discovery_option_set_dnn(discovery_option, sess->dnn);
|
2023-11-22 11:37:06 +00:00
|
|
|
ogs_sbi_discovery_option_set_tai(
|
2023-10-23 13:35:54 +00:00
|
|
|
discovery_option, &amf_ue->nr_tai);
|
|
|
|
|
2024-05-17 04:36:25 +00:00
|
|
|
nf_instance = OGS_SBI_GET_NF_INSTANCE(
|
|
|
|
sess->sbi.service_type_array[service_type]);
|
2021-03-08 12:25:09 +00:00
|
|
|
if (!nf_instance) {
|
2022-10-22 02:26:04 +00:00
|
|
|
OpenAPI_nf_type_e requester_nf_type =
|
|
|
|
NF_INSTANCE_TYPE(ogs_sbi_self()->nf_instance);
|
|
|
|
ogs_assert(requester_nf_type);
|
|
|
|
|
2022-11-30 22:41:30 +00:00
|
|
|
amf_sbi_select_nf(
|
|
|
|
&sess->sbi,
|
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION,
|
|
|
|
requester_nf_type,
|
2023-10-23 13:35:54 +00:00
|
|
|
discovery_option);
|
2024-05-17 04:36:25 +00:00
|
|
|
nf_instance = OGS_SBI_GET_NF_INSTANCE(
|
|
|
|
sess->sbi.service_type_array[service_type]);
|
2023-10-23 13:35:54 +00:00
|
|
|
|
|
|
|
if (!nf_instance)
|
|
|
|
ogs_info("No SMF Instance");
|
|
|
|
else
|
|
|
|
ogs_info("SMF Instance [%s]", nf_instance->id);
|
|
|
|
} else
|
|
|
|
ogs_info("SMF Instance [%s]", nf_instance->id);
|
2021-03-08 12:25:09 +00:00
|
|
|
|
|
|
|
if (nf_instance) {
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2023-10-23 13:35:54 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION,
|
|
|
|
discovery_option,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_create_sm_context,
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL);
|
2023-01-31 10:38:17 +00:00
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-03-08 12:25:09 +00:00
|
|
|
} else {
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2023-10-23 13:35:54 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NNSSF_NSSELECTION,
|
|
|
|
discovery_option,
|
2024-03-21 21:48:58 +00:00
|
|
|
amf_nnssf_nsselection_build_get,
|
|
|
|
ran_ue, sess, 0, NULL);
|
2023-01-31 10:38:17 +00:00
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-03-08 12:25:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 15:14:27 +00:00
|
|
|
} else {
|
2021-03-08 12:25:09 +00:00
|
|
|
|
2021-02-01 15:14:27 +00:00
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.release = 1;
|
|
|
|
param.cause = OpenAPI_cause_REL_DUE_TO_DUPLICATE_SESSION_ID;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess,
|
|
|
|
AMF_UPDATE_SM_CONTEXT_DUPLICATED_PDU_SESSION_ID,
|
2023-01-31 10:38:17 +00:00
|
|
|
¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-02-01 15:14:27 +00:00
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
2020-07-04 03:14:48 +00:00
|
|
|
ogs_error("[%s:%d] Session Context is not in SMF [%d]",
|
|
|
|
amf_ue->supi, sess->psi, gsm_header->message_type);
|
2024-01-13 14:10:17 +00:00
|
|
|
r = nas_5gs_send_back_gsm_message(ran_ue, sess,
|
2023-01-23 01:37:22 +00:00
|
|
|
OGS_5GMM_CAUSE_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE, 0);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n1smbuf = sess->payload_container;
|
|
|
|
|
2020-07-09 05:38:09 +00:00
|
|
|
if (gsm_header->message_type ==
|
|
|
|
OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE) {
|
|
|
|
param.ue_location = true;
|
|
|
|
param.ue_timezone = true;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess,
|
|
|
|
AMF_UPDATE_SM_CONTEXT_N1_RELEASED, ¶m);
|
2023-01-31 10:38:17 +00:00
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-06-06 13:20:52 +00:00
|
|
|
} else {
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_MODIFIED, ¶m);
|
2023-01-31 10:38:17 +00:00
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-06-06 13:20:52 +00:00
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
switch (gsm_header->message_type) {
|
|
|
|
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE:
|
|
|
|
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_REJECT:
|
|
|
|
if (PAGING_ONGOING(amf_ue) == true) {
|
|
|
|
|
|
|
|
gmm_configuration_update_command_param_t param;
|
|
|
|
/*
|
|
|
|
* TS24.501
|
|
|
|
* 5.4.4 Generic UE configuration update procedure
|
|
|
|
* 5.4.4.1 General
|
|
|
|
*
|
|
|
|
* This procedure shall be initiated by the network to assign
|
|
|
|
* a new 5G-GUTI to the UE after a successful service request
|
|
|
|
* procedure invoked as a response to a paging request
|
|
|
|
* from the network and before the release
|
|
|
|
* of the N1 NAS signalling connection.
|
|
|
|
*
|
|
|
|
* If the service request procedure was triggered
|
|
|
|
* due to 5GSM downlink signalling pending, the procedure
|
|
|
|
* for assigning a new 5G-GUTI can be initiated by the network
|
|
|
|
* after the transport of the 5GSM downlink signalling.
|
|
|
|
*/
|
|
|
|
amf_ue_new_guti(amf_ue);
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.acknowledgement_requested = 1;
|
|
|
|
param.guti = 1;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_configuration_update_command(
|
|
|
|
amf_ue, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-14 12:07:56 +00:00
|
|
|
|
|
|
|
AMF_UE_CLEAR_PAGING_INFO(amf_ue);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE:
|
2024-02-03 00:41:12 +00:00
|
|
|
sess->pdu_session_release_complete_received = true;
|
|
|
|
if (sess->pdu_session_resource_release_response_received ==
|
|
|
|
true)
|
2024-04-18 12:13:45 +00:00
|
|
|
CLEAR_SESSION_CONTEXT(sess);
|
2021-11-14 12:07:56 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2020-07-29 02:35:43 +00:00
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("[%s] Unknown Payload container type [%d]",
|
|
|
|
amf_ue->supi, payload_container_type->value);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_gmm_status(amf_ue,
|
|
|
|
OGS_5GMM_CAUSE_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue_t *ran_ue, amf_ue_t *amf_ue, uint8_t message_type,
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_nas_message_container_t *nas_message_container)
|
|
|
|
{
|
2022-07-19 03:42:02 +00:00
|
|
|
int gmm_cause;
|
2020-06-24 04:33:10 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_t *nasbuf = NULL;
|
|
|
|
ogs_nas_5gs_message_t nas_message;
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2024-03-21 21:48:58 +00:00
|
|
|
ogs_assert(ran_ue);
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_assert(nas_message_container);
|
|
|
|
|
|
|
|
if (!nas_message_container->buffer || !nas_message_container->length) {
|
|
|
|
ogs_error("No NAS message container [%p:%d]",
|
|
|
|
nas_message_container->buffer,nas_message_container->length);
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE;
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nasbuf = ogs_pkbuf_alloc(NULL, nas_message_container->length);
|
2020-09-07 03:53:38 +00:00
|
|
|
ogs_assert(nasbuf);
|
2020-06-24 04:33:10 +00:00
|
|
|
ogs_pkbuf_put_data(nasbuf,
|
|
|
|
nas_message_container->buffer, nas_message_container->length);
|
|
|
|
|
2022-01-05 13:39:06 +00:00
|
|
|
/*
|
|
|
|
* 3GPP TS 24.501 version 16.6.0 Release 16
|
|
|
|
* 4.4 NAS security
|
|
|
|
* 4.4.6 Protection of initial NAS signalling messages
|
|
|
|
*
|
|
|
|
* 1) the UE needs to send non-cleartext IEs in a REGISTRATION REQUEST
|
|
|
|
* or SERVICE REQUEST message, the UE includes the entire REGISTRATION
|
|
|
|
* REQUEST or SERVICE REQUEST message (i.e. containing both cleartext IEs
|
|
|
|
* and non-cleartext IEs) in the NAS message container IE and shall cipher
|
|
|
|
* the value part of the NAS message container IE. The UE shall then send
|
|
|
|
* a REGISTRATION REQUEST or SERVICE REQUEST message containing
|
|
|
|
* the cleartext IEs and the NAS message container IE;
|
|
|
|
*/
|
|
|
|
switch (message_type) {
|
|
|
|
case OGS_NAS_5GS_REGISTRATION_REQUEST:
|
|
|
|
case OGS_NAS_5GS_SERVICE_REQUEST:
|
|
|
|
switch (amf_ue->selected_enc_algorithm) {
|
|
|
|
case OGS_NAS_SECURITY_ALGORITHMS_128_NEA1:
|
|
|
|
case OGS_NAS_SECURITY_ALGORITHMS_128_NEA2:
|
|
|
|
case OGS_NAS_SECURITY_ALGORITHMS_128_NEA3:
|
|
|
|
ogs_nas_encrypt(amf_ue->selected_enc_algorithm,
|
|
|
|
amf_ue->knas_enc, amf_ue->ul_count.i32,
|
|
|
|
amf_ue->nas.access_type,
|
|
|
|
OGS_NAS_SECURITY_UPLINK_DIRECTION, nasbuf);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
if (ogs_nas_5gmm_decode(&nas_message, nasbuf) != OGS_OK) {
|
|
|
|
ogs_error("ogs_nas_5gmm_decode() failed");
|
|
|
|
ogs_pkbuf_free(nasbuf);
|
2022-07-19 03:42:02 +00:00
|
|
|
return OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
|
2022-07-19 03:42:02 +00:00
|
|
|
gmm_cause = OGS_5GMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
|
|
|
|
|
2020-06-24 04:33:10 +00:00
|
|
|
switch (nas_message.gmm.h.message_type) {
|
|
|
|
case OGS_NAS_5GS_REGISTRATION_REQUEST:
|
|
|
|
ogs_debug("Registration request in NAS message container");
|
2022-07-19 03:42:02 +00:00
|
|
|
gmm_cause = gmm_handle_registration_update(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, amf_ue, &nas_message.gmm.registration_request);
|
2020-06-24 04:33:10 +00:00
|
|
|
break;
|
|
|
|
case OGS_NAS_5GS_SERVICE_REQUEST:
|
|
|
|
ogs_debug("Service request in NAS message container");
|
2022-07-19 03:42:02 +00:00
|
|
|
gmm_cause = gmm_handle_service_update(
|
2024-03-21 21:48:58 +00:00
|
|
|
ran_ue, amf_ue, &nas_message.gmm.service_request);
|
2020-06-24 04:33:10 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown message [%d]", nas_message.gmm.h.message_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_pkbuf_free(nasbuf);
|
2022-07-19 03:42:02 +00:00
|
|
|
return gmm_cause;
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
2023-03-25 00:18:20 +00:00
|
|
|
|
2024-03-20 22:07:25 +00:00
|
|
|
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);
|
|
|
|
|
2024-04-18 12:13:45 +00:00
|
|
|
sess->sm_context.ref = PduSessionContext->sm_context_ref;
|
2024-03-20 22:07:25 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-03-25 00:18:20 +00:00
|
|
|
static uint8_t gmm_cause_from_access_control(ogs_plmn_id_t *plmn_id)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
ogs_assert(plmn_id);
|
|
|
|
|
|
|
|
/* No Access Control */
|
|
|
|
if (amf_self()->num_of_access_control == 0)
|
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
|
|
|
|
|
|
|
for (i = 0; i < amf_self()->num_of_access_control; i++) {
|
|
|
|
if (memcmp(&amf_self()->access_control[i].plmn_id,
|
|
|
|
plmn_id, OGS_PLMN_ID_LEN) == 0) {
|
|
|
|
if (amf_self()->access_control[i].reject_cause)
|
|
|
|
return amf_self()->access_control[i].reject_cause;
|
|
|
|
else
|
|
|
|
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amf_self()->default_reject_cause)
|
|
|
|
return amf_self()->default_reject_cause;
|
|
|
|
|
|
|
|
return OGS_5GMM_CAUSE_PLMN_NOT_ALLOWED;
|
|
|
|
}
|