diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GMM/IES/CMakeLists.txt index e865dd0046..40bfcbabcd 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/IES/CMakeLists.txt +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/CMakeLists.txt @@ -1,7 +1,6 @@ add_library(fgs_5gmm_ies_lib OBJECT FGSMobileIdentity.c FGSRegistrationType.c - FGSRegistrationResult.c FGMMCapability.c NrUESecurityCapability.c FGCNasMessageContainer.c diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.c deleted file mode 100644 index 739cee7973..0000000000 --- a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file FGSRegistrationResult.c - -\brief 5GS Registration result for registration request procedures -\author Yoshio INOUE, Masayuki HARADA -\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com -\date 2020 -\version 0.1 -*/ - -#include -#include -#include - -#include "TLVEncoder.h" -#include "TLVDecoder.h" -#include "FGSRegistrationResult.h" - -int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len) -{ - int decoded = 0; - uint16_t *buffer = &value; - fgsregistrationresult->registrationresult = *buffer & 0x7; - fgsregistrationresult->smsallowed = *buffer & 0x8; - decoded = decoded + 2; - return decoded; -} - -uint16_t encode_fgs_registration_result(const FGSRegistrationResult *fgsregistrationresult) -{ - uint16_t bufferReturn; - uint16_t *buffer = &bufferReturn; - uint8_t encoded = 0; - *(buffer + encoded) = 0x00 | (fgsregistrationresult->smsallowed & 0x8) | (fgsregistrationresult->registrationresult & 0x7); - encoded = encoded + 2; - - return bufferReturn; -} diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.h deleted file mode 100644 index 04f45417b8..0000000000 --- a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file FGSRegistrationResult.h - -\brief 5GS Registration result for registration request procedures -\author Yoshio INOUE, Masayuki HARADA -\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com -\date 2020 -\version 0.1 -*/ - -#include -#include -#include - -#include "OctetString.h" - -#ifndef FGS_REGISTRATION_RESULT_H_ -#define FGS_REGISTRATION_RESULT_H_ -#define FGS_REGISTRATION_RESULT_3GPP 0b001 -#define FGS_REGISTRATION_RESULT_NON_3GPP 0b010 -#define FGS_REGISTRATION_RESULT_3GPP_AND_NON_3GPP 0b011 - -typedef struct { - uint8_t iei; - uint8_t resultlength; - uint8_t spare: 4; - uint8_t smsallowed: 1; - uint8_t registrationresult: 3; -} FGSRegistrationResult; - -uint16_t encode_fgs_registration_result(const FGSRegistrationResult *fgsregistrationresult); - -int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len); - -#endif /* FGS REGISTRATION RESULT_H_*/ diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.c index d92244a15f..bc5c86f88e 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.c @@ -33,18 +33,44 @@ #include #include #include "conversions.h" -#include "TLVEncoder.h" -#include "TLVDecoder.h" #include "RegistrationAccept.h" -#include "assertions.h" #include "fgs_nas_utils.h" +#include "common/utils/utils.h" +#include "ds/byte_array.h" +#include "fgmm_lib.h" #define IEI_5G_GUTI 0x77 +#define FGS_REGISTRATION_RESULT_LEN 2 +#define REGISTRATION_ACCEPT_MIN_LEN FGS_REGISTRATION_RESULT_LEN // (5GS registration result) 2 octets + +/** @brief Decode 5GS registration result (9.11.3.6 3GPP TS 24.501) */ +static int decode_fgs_registration_result(registration_accept_msg *out, const byte_array_t buffer) +{ + if (buffer.len < FGS_REGISTRATION_RESULT_LEN) { + PRINT_NAS_ERROR("5GS registration result decoding failure: invalid buffer length\n"); + return -1; + } + out->result = buffer.buf[1] & 0x7; // skip length of contents octet + out->sms_allowed = buffer.buf[1] & 0x8; + return 2; // length 2 octets (no IEI) +} + +static int encode_fgs_registration_result(byte_array_t buffer, const registration_accept_msg *out) +{ + if (buffer.len < FGS_REGISTRATION_RESULT_LEN) { + PRINT_NAS_ERROR("5GS registration result encoding failure: invalid buffer length\n"); + return -1; + } + uint8_t *buf = buffer.buf; + buf[0] = 1; + buf[1] = 0x00 | (out->sms_allowed & 0x8) | (out->result & 0x7); + return 2; // encoded length 2 octets (no IEI) +} /** * @brief Allowed NSSAI from Registration Accept according to 3GPP TS 24.501 Table 8.2.7.1.1 */ -static int decode_nssai_ie(nr_nas_msg_snssai_t *nssai, const uint8_t *buf) +static int decode_nssai_ie(nr_nas_msg_snssai_t *nssai, uint8_t *num_slices, uint8_t *buf) { const int length = *buf; // Length of S-NSSAI IE contents (list of S-NSSAIs) const uint32_t decoded = length + 1; // Length IE (1 octet) @@ -53,7 +79,6 @@ static int decode_nssai_ie(nr_nas_msg_snssai_t *nssai, const uint8_t *buf) const uint8_t *end = buf + length; while (buf < end) { nr_nas_msg_snssai_t *item = nssai + nssai_cnt; - item->sd = 0xffffff; const int item_len = *buf++; // Length of S-NSSAI IE item switch (item_len) { case 1: @@ -63,31 +88,38 @@ static int decode_nssai_ie(nr_nas_msg_snssai_t *nssai, const uint8_t *buf) case 2: item->sst = *buf++; - item->hplmn_sst = *buf++; + item->hplmn_sst = malloc_or_fail(sizeof(*item->hplmn_sst)); + *item->hplmn_sst = *buf++; nssai_cnt++; break; case 4: item->sst = *buf++; - item->sd = 0xffffff & ntoh_int24_buf(buf); + item->sd = malloc_or_fail(sizeof(*item->sd)); + *item->sd = 0xffffff & ntoh_int24_buf(buf); buf += 3; nssai_cnt++; break; case 5: item->sst = *buf++; - item->sd = 0xffffff & ntoh_int24_buf(buf); + item->sd = malloc_or_fail(sizeof(*item->sd)); + *item->sd = 0xffffff & ntoh_int24_buf(buf); buf += 3; - item->hplmn_sst = *buf++; + item->hplmn_sst = malloc_or_fail(sizeof(*item->hplmn_sst)); + *item->hplmn_sst = *buf++; nssai_cnt++; break; case 8: item->sst = *buf++; - item->sd = 0xffffff & ntoh_int24_buf(buf); + item->sd = malloc_or_fail(sizeof(*item->sd)); + *item->sd = 0xffffff & ntoh_int24_buf(buf); buf += 3; - item->hplmn_sst = *buf++; - item->hplmn_sd = 0xffffff & ntoh_int24_buf(buf); + item->hplmn_sst = malloc_or_fail(sizeof(*item->hplmn_sst)); + *item->hplmn_sst = *buf++; + item->hplmn_sd = malloc_or_fail(sizeof(*item->hplmn_sd)); + *item->hplmn_sd = 0xffffff & ntoh_int24_buf(buf); buf += 3; nssai_cnt++; break; @@ -97,61 +129,71 @@ static int decode_nssai_ie(nr_nas_msg_snssai_t *nssai, const uint8_t *buf) break; } } + *num_slices = nssai_cnt; return decoded; } -int decode_registration_accept(registration_accept_msg *registration_accept, const uint8_t *buffer, uint32_t len) +size_t decode_registration_accept(registration_accept_msg *registration_accept, const byte_array_t buffer) { int dec = 0; - const uint8_t *end = buffer + len; + byte_array_t ba = buffer; // local copy of buffer - /* Decoding mandatory fields */ - if ((dec = decode_fgs_registration_result(®istration_accept->fgsregistrationresult, 0, *buffer, len)) < 0) - return dec; - buffer += dec; + if (ba.len < REGISTRATION_ACCEPT_MIN_LEN) { + PRINT_NAS_ERROR("Registration Accept decoding failed: invalid buffer length\n"); + return -1; + } - if (buffer < end && *buffer == IEI_5G_GUTI) { + // 5GS registration result (Mandatory) + if ((dec = decode_fgs_registration_result(registration_accept, ba)) < 0) + return -1; + UPDATE_BYTE_ARRAY(ba, dec); + + // 5G-GUTI (Optional) + if (ba.len > 0 && ba.buf[0] == IEI_5G_GUTI) { registration_accept->guti = calloc_or_fail(1, sizeof(*registration_accept->guti)); - if ((dec = decode_5gs_mobile_identity(registration_accept->guti, IEI_5G_GUTI, buffer, end - buffer)) < 0) { + if ((dec = decode_5gs_mobile_identity(registration_accept->guti, IEI_5G_GUTI, ba.buf, ba.len)) < 0) { PRINT_NAS_ERROR("Failed to decode 5GS Mobile Identity in Registration Accept\n"); return -1; } - buffer += dec; + UPDATE_BYTE_ARRAY(ba, dec); } - // Allowed NSSAI (O) - /* Optional Presence IEs */ - while (buffer < end) { - const int iei = *buffer++; + // Decode other Optional IEs + while (ba.len > 0) { + uint8_t iei = ba.buf[0]; + UPDATE_BYTE_ARRAY(ba, 1); + switch (iei) { case 0x15: // allowed NSSAI - dec = decode_nssai_ie(registration_accept->nas_allowed_nssai, buffer); - buffer += dec; + dec = decode_nssai_ie(registration_accept->nas_allowed_nssai, ®istration_accept->num_allowed_slices, ba.buf); + UPDATE_BYTE_ARRAY(ba, dec); break; case 0x31: // configured NSSAI - dec = decode_nssai_ie(registration_accept->config_nssai, buffer); - buffer += dec; + dec = decode_nssai_ie(registration_accept->config_nssai, ®istration_accept->num_configured_slices, ba.buf); + UPDATE_BYTE_ARRAY(ba, dec); break; default: - dec = *buffer++; // content length + 1 byte (Length IE) - buffer += dec; + dec = ba.buf[0] + 1; // content length + 1 byte (Length IE) + UPDATE_BYTE_ARRAY(ba, dec); break; } } - return len; + if(ba.len != 0) { + PRINT_NAS_ERROR("Failed to decode registration accept: ba.len = %ld\n", ba.len); + return -1; + } + return buffer.len; } int encode_registration_accept(const registration_accept_msg *registration_accept, uint8_t *buffer, uint32_t len) { int encoded = 0; - LOG_FUNC_IN; - - *(buffer + encoded) = encode_fgs_registration_result(®istration_accept->fgsregistrationresult); - encoded = encoded + 2; + byte_array_t ba = {.buf = buffer, .len = len}; + encoded += encode_fgs_registration_result(ba, registration_accept); if (registration_accept->guti) { int mi_enc = encode_5gs_mobile_identity(registration_accept->guti, 0x77, buffer + encoded, len - encoded); @@ -160,6 +202,100 @@ int encode_registration_accept(const registration_accept_msg *registration_accep encoded += mi_enc; } - // todo ,Encoding optional fields - LOG_FUNC_RETURN(encoded); + return encoded; +} + +/** Equality check for NAS Registration Accept */ + +bool eq_snssai(const nr_nas_msg_snssai_t *a, const nr_nas_msg_snssai_t *b) +{ + _NAS_EQ_CHECK_INT(a->sst, b->sst); + + if ((a->hplmn_sst && !b->hplmn_sst) || (!a->hplmn_sst && b->hplmn_sst)) + return false; + if (a->hplmn_sst && b->hplmn_sst) + _NAS_EQ_CHECK_INT(*a->hplmn_sst, *b->hplmn_sst); + + if ((a->sd && !b->sd) || (!a->sd && b->sd)) + return false; + if (a->sd && b->sd) + _NAS_EQ_CHECK_INT(*a->sd, *b->sd); + + if ((a->hplmn_sd && !b->hplmn_sd) || (!a->hplmn_sd && b->hplmn_sd)) + return false; + if (a->hplmn_sd && b->hplmn_sd) + _NAS_EQ_CHECK_INT(*a->hplmn_sd, *b->hplmn_sd); + + return true; +} + + +bool eq_fgmm_registration_accept(const registration_accept_msg *a, const registration_accept_msg *b) +{ + if (!a || !b) { + PRINT_NAS_ERROR("Null pointer in registration_accept_msg_eq\n"); + return false; + } + + // 5GS registration result (mandatory) + _NAS_EQ_CHECK_INT(a->result, b->result); + _NAS_EQ_CHECK_INT(a->sms_allowed, b->sms_allowed); + + // GUTI (optional) + if (a->guti && b->guti) { + _NAS_EQ_CHECK_INT(a->guti->guti.spare, b->guti->guti.spare); + _NAS_EQ_CHECK_INT(a->guti->guti.oddeven, b->guti->guti.oddeven); + _NAS_EQ_CHECK_INT(a->guti->guti.typeofidentity, b->guti->guti.typeofidentity); + _NAS_EQ_CHECK_INT(a->guti->guti.mccdigit2, b->guti->guti.mccdigit2); + _NAS_EQ_CHECK_INT(a->guti->guti.mccdigit1, b->guti->guti.mccdigit1); + _NAS_EQ_CHECK_INT(a->guti->guti.mncdigit3, b->guti->guti.mncdigit3); + _NAS_EQ_CHECK_INT(a->guti->guti.mccdigit3, b->guti->guti.mccdigit3); + _NAS_EQ_CHECK_INT(a->guti->guti.mncdigit2, b->guti->guti.mncdigit2); + _NAS_EQ_CHECK_INT(a->guti->guti.mncdigit1, b->guti->guti.mncdigit1); + _NAS_EQ_CHECK_INT(a->guti->guti.amfregionid, b->guti->guti.amfregionid); + _NAS_EQ_CHECK_INT(a->guti->guti.amfsetid, b->guti->guti.amfsetid); + _NAS_EQ_CHECK_INT(a->guti->guti.amfpointer, b->guti->guti.amfpointer); + _NAS_EQ_CHECK_INT(a->guti->guti.tmsi, b->guti->guti.tmsi); + } else if ((a->guti && !b->guti) || (!a->guti && b->guti)) { + PRINT_NAS_ERROR("NAS Equality Check failure: One of the two GUTIs is NULL\n"); + return false; + } + + _NAS_EQ_CHECK_INT(a->num_allowed_slices, b->num_allowed_slices); + _NAS_EQ_CHECK_INT(a->num_configured_slices, b->num_configured_slices); + + // Configured NSSAI (optional) + for (int i = 0; i < a->num_configured_slices; i++) { + if (!eq_snssai(&a->config_nssai[i], &b->config_nssai[i])) { + PRINT_NAS_ERROR("NAS Equality Check failure: Configured NSSAI\n"); + return false; + } + } + // Allowed NSSAI (optional) + for (int i = 0; i < a->num_allowed_slices; i++) { + if (!eq_snssai(&a->nas_allowed_nssai[i], &b->nas_allowed_nssai[i])) { + PRINT_NAS_ERROR("NAS Equality Check failure: Allowed NSSAI\n"); + return false; + } + } + + return true; +} + +/** Memory management of NAS Registration Accept */ + +static void free_nssai(nr_nas_msg_snssai_t *msg) +{ + free(msg->hplmn_sd); + free(msg->hplmn_sst); + free(msg->sd); +} + +void free_fgmm_registration_accept(registration_accept_msg *msg) +{ + free(msg->guti); + for (int i = 0; i < NAS_MAX_NUMBER_SLICES; i++) { + free_nssai(&msg->nas_allowed_nssai[i]); + free_nssai(&msg->config_nssai[i]); + } } diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h index 6abf1e70ca..42b02407d9 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h @@ -31,21 +31,30 @@ #include #include #include +#include #include "SecurityHeaderType.h" #include "MessageType.h" -#include "FGSRegistrationResult.h" #include "FGSMobileIdentity.h" +#include "ds/byte_array.h" #ifndef REGISTRATION_ACCEPT_H_ #define REGISTRATION_ACCEPT_H_ +typedef enum { + FGS_REGISTRATION_RESULT_3GPP = 1, + FGS_REGISTRATION_RESULT_NON_3GPP = 2, + FGS_REGISTRATION_RESULT_3GPP_AND_NON_3GPP = 3 +} fgs_registration_result_t; + +#define NAS_MAX_NUMBER_SLICES 8 + // 9.11.3.37 of 3GPP TS 24.501 typedef struct { int sst; - int hplmn_sst; - int sd; - int hplmn_sd; + int *hplmn_sst; + int *sd; + int *hplmn_sd; } nr_nas_msg_snssai_t; /* @@ -56,18 +65,24 @@ typedef struct { */ typedef struct registration_accept_msg_tag { - /* Mandatory fields */ - FGSRegistrationResult fgsregistrationresult; - /* Optional fields */ + // 5GS registration result (Mandatory) + fgs_registration_result_t result; + bool sms_allowed; + // 5G-GUTI (Optional) FGSMobileIdentity *guti; - // Allowed NSSAI (O) - nr_nas_msg_snssai_t nas_allowed_nssai[8]; - // Configured NSSAI (O) - nr_nas_msg_snssai_t config_nssai[8]; + // Allowed NSSAI (Optional) + nr_nas_msg_snssai_t nas_allowed_nssai[NAS_MAX_NUMBER_SLICES]; + uint8_t num_allowed_slices; + // Configured NSSAI (Optional) + nr_nas_msg_snssai_t config_nssai[NAS_MAX_NUMBER_SLICES]; + uint8_t num_configured_slices; } registration_accept_msg; -int decode_registration_accept(registration_accept_msg *registrationaccept, const uint8_t *buffer, uint32_t len); +size_t decode_registration_accept(registration_accept_msg *registrationaccept, const byte_array_t buffer); int encode_registration_accept(const registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len); +bool eq_fgmm_registration_accept(const registration_accept_msg *a, const registration_accept_msg *b); +void free_fgmm_registration_accept(registration_accept_msg *msg); + #endif /* ! defined(REGISTRATION_ACCEPT_H_) */ diff --git a/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c b/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c index a73ee9b2be..2ccf78fa59 100644 --- a/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c +++ b/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c @@ -3,6 +3,7 @@ #include #include #include "common/utils/ds/byte_array.h" +#include "RegistrationAccept.h" #include "fgs_service_request.h" #include "fgmm_service_accept.h" #include "fgmm_service_reject.h" @@ -26,6 +27,65 @@ static bool eq_service_request(const fgs_service_request_msg_t *a, const fgs_ser return result; } +/** @brief Test regression of NAS Registration Accept decoding + * This test verifies that the NAS Registration Accept message + * is correctly decoded. It decodes a message as it received from + * the OAI CN5G and compares the output with the expected Registration Accept structure. + * The purpose of this regression test is to ensure that changes + * to the NAS decoder do not break the existing decoding behavior with OAI CN5G */ +static void test_regression_registration_accept(void) +{ + // Registration Accept message + registration_accept_msg orig = { + .guti = malloc_or_fail(sizeof(*orig.guti)), + .result = 0x01, + .nas_allowed_nssai[0].sst = 0x01, + .nas_allowed_nssai[1].sst = 0x02, + .nas_allowed_nssai[2].sst = 0x03, + .num_allowed_slices = 3, + .config_nssai[0].sst = 0x01, + .config_nssai[1].sst = 0x02, + .config_nssai[2].sst = 0x03, + .num_configured_slices = 3, + }; + + orig.guti->guti.typeofidentity = FGS_MOBILE_IDENTITY_5G_GUTI; + orig.guti->guti.amfpointer = 0x01; + orig.guti->guti.amfregionid = 0x02; + orig.guti->guti.amfsetid = 0x01; + orig.guti->guti.mccdigit1 = 0x00; + orig.guti->guti.mccdigit2 = 0x00; + orig.guti->guti.mccdigit3 = 0x01; + orig.guti->guti.mncdigit1 = 0x00; + orig.guti->guti.mncdigit2 = 0x01; + orig.guti->guti.mncdigit3 = 0x0F; + orig.guti->guti.tmsi = 0xb0207806; + orig.guti->guti.spare = 0b1111; + orig.guti->guti.oddeven = 0; + + // Encoded Registration Accept message from OAI CN5G + uint8_t cn5g_msg[] = {0x01, 0x01, // Registration Result + 0x77, 0x00, 0x0B, 0xF2, 0x00, 0xF1, 0x10, // 5G-GUTI + 0x02, 0x00, 0x41, 0xB0, 0x20, 0x78, 0x06, // 5G-GUTI + 0x15, 0x06, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, // Allowed N-NSSAI + 0x31, 0x06, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03}; // Configured N-NSSAI + + // Decode NAS Registration Accept + int encoded_length; + registration_accept_msg decoded = {0}; + byte_array_t ba = {.buf = cn5g_msg, .len = sizeof(cn5g_msg)}; + encoded_length = decode_registration_accept(&decoded, ba); + AssertFatal(encoded_length >= 0, "encode_fgs_service_request() failed\n"); + + // Compare the raw encoded buffer with expected encoded data + bool ret = eq_fgmm_registration_accept(&orig, &decoded); + AssertFatal(ret, "Encoding mismatch!\n"); + + // Free dynamic allocated memory + free_fgmm_registration_accept(&orig); + free_fgmm_registration_accept(&decoded); +} + /** * @brief Test NAS Service Request enc/dec */ @@ -172,6 +232,7 @@ static void test_service_reject(void) int main() { + test_regression_registration_accept(); test_service_request(); test_service_accept(); test_service_reject(); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 61df0fe098..8b127abf3e 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1402,11 +1402,14 @@ static void request_default_pdusession(nr_ue_nas_t *nas) itti_send_msg_to_task(TASK_NAS_NRUE, nas->UE_id, message_p); } -static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[8], const nr_ue_nas_t *nas) +static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[NAS_MAX_NUMBER_SLICES], const nr_ue_nas_t *nas) { - for (int i = 0; i < 8; i++) { + for (int i = 0; i < NAS_MAX_NUMBER_SLICES; i++) { const nr_nas_msg_snssai_t *nssai = allowed_nssai + i; - if ((nas->uicc->nssai_sst == nssai->sst) && (nas->uicc->nssai_sd == nssai->sd)) + /* If it was received in Registration Accept, check the SD + in the stored Allowed N-SSAI, else, consider the SD valid */ + bool sd_match = !nssai->sd || (nas->uicc->nssai_sd == *nssai->sd); + if ((nas->uicc->nssai_sst == nssai->sst) && sd_match) return i; } return -1; @@ -1430,7 +1433,6 @@ static void process_guti(Guti5GSMobileIdentity_t *guti, nr_ue_nas_t *nas) static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buffer, uint32_t msg_length) { - LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n"); registration_accept_msg msg = {0}; fgs_nas_message_security_header_t sp_header = {0}; const uint8_t *end = pdu_buffer + msg_length; @@ -1453,15 +1455,22 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff } pdu_buffer += decoded; // plain payload - if ((decoded = decode_registration_accept(&msg, pdu_buffer, end - pdu_buffer)) < 0) { + const byte_array_t ba = {.buf = (uint8_t *)pdu_buffer, .len = end - pdu_buffer}; + if ((decoded = decode_registration_accept(&msg, ba)) < 0) { LOG_E(NAS, "Failed to decode NAS Registration Accept\n"); return; } + LOG_I(NAS, + "Received Registration Accept with result %s\n", + msg.result == FGS_REGISTRATION_RESULT_3GPP ? "3GPP" + : msg.result == FGS_REGISTRATION_RESULT_NON_3GPP ? "non-3PP" + : "3GPP and non-3GPP"); + LOG_I(NAS, "SMS %s in 5GS Registration Result\n", msg.sms_allowed ? "allowed" : "not allowed"); + pdu_buffer += decoded; // process GUTI if (msg.guti) { process_guti(&msg.guti->guti, nas); - free(msg.guti); } else { LOG_W(NAS, "no GUTI in registration accept\n"); } @@ -1480,6 +1489,8 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff } else { request_default_pdusession(nas); } + // Free local message after processing + free_fgmm_registration_accept(&msg); } /* 3GPP TS 24.008 10.5.7.3 GPRS Timer */