Merge remote-tracking branch 'origin/nas-reg-accept-lib' into integration_2025_w16 (!3254)

Follow up on NAS Registration Accept lib

This MR is a follow up on !2984 (merged).

The goal is to enhance the NAS Registration Accept lib:
- Add regression test for NAS Registration Accept: the goal of this test is to
  prevent on the decoding of the NAS Registration Accept sent by the OAI CN5G
- Add equality check and free utility functions to NAS Registration Accept
  library
- Free NAS Registration Accept after use: heap memory is allocated for this
  message during decoding and shall be free after processing
- Remove harcoded Slice Differentiator (SD) in NAS decode_nssai_ie and update
  the processing logic: The SD stored in the allowed S-NSSAI list was hardcoded
  in the decoding function, however this IE is not mandatory but optional.
  Therefore, the check of the decoded message contents should take into account
  the presence of the field in the received message and in that scenario, check
  the stored value against the one from the UICC. If no SD was received, consider
  the UICC SD a valid one.
- Cleanup and other fixes to decode_registration_accept: (1) adopt byte array
  (2) move registration result enc/dec to registration accept library (3) check
  on buffer lengths (4) add defines whenever necessary (5) simplify the code
This commit is contained in:
Jaroslava Fiedlerova
2025-04-18 14:21:22 +02:00
7 changed files with 279 additions and 170 deletions
@@ -1,7 +1,6 @@
add_library(fgs_5gmm_ies_lib OBJECT
FGSMobileIdentity.c
FGSRegistrationType.c
FGSRegistrationResult.c
FGMMCapability.c
NrUESecurityCapability.c
FGCNasMessageContainer.c
@@ -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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#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;
}
@@ -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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#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_*/
@@ -33,18 +33,44 @@
#include <string.h>
#include <stdint.h>
#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(&registration_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, &registration_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, &registration_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(&registration_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]);
}
}
@@ -31,21 +31,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#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_) */
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <arpa/inet.h>
#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();
+17 -6
View File
@@ -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 */