mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-18 07:00:30 +00:00
Compare commits
5 Commits
develop
...
nas_reg_ac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f59dd18a49 | ||
|
|
ec1ff035fb | ||
|
|
dfe2f7da74 | ||
|
|
dfa7047a33 | ||
|
|
d9d61a8b26 |
@@ -33,13 +33,12 @@
|
||||
#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"
|
||||
|
||||
#define IEI_5G_GUTI 0x77
|
||||
#define REGISTRATION_ACCEPT_MIN_LEN 2 // (5GS registration result) 2 octets
|
||||
|
||||
/**
|
||||
* @brief Allowed NSSAI from Registration Accept according to 3GPP TS 24.501 Table 8.2.7.1.1
|
||||
@@ -53,7 +52,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 +61,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;
|
||||
@@ -105,11 +110,17 @@ int decode_registration_accept(registration_accept_msg *registration_accept, con
|
||||
int dec = 0;
|
||||
const uint8_t *end = buffer + len;
|
||||
|
||||
/* Decoding mandatory fields */
|
||||
if (len < REGISTRATION_ACCEPT_MIN_LEN) {
|
||||
PRINT_NAS_ERROR("%s: buffer length is too short.\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 5GS registration result (M)
|
||||
if ((dec = decode_fgs_registration_result(®istration_accept->fgsregistrationresult, 0, *buffer, len)) < 0)
|
||||
return dec;
|
||||
buffer += dec;
|
||||
|
||||
// 5G-GUTI (O)
|
||||
if (buffer < end && *buffer == 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) {
|
||||
@@ -119,8 +130,7 @@ int decode_registration_accept(registration_accept_msg *registration_accept, con
|
||||
buffer += dec;
|
||||
}
|
||||
|
||||
// Allowed NSSAI (O)
|
||||
/* Optional Presence IEs */
|
||||
// Other optional IEs
|
||||
while (buffer < end) {
|
||||
const int iei = *buffer++;
|
||||
switch (iei) {
|
||||
@@ -148,8 +158,6 @@ int encode_registration_accept(const registration_accept_msg *registration_accep
|
||||
{
|
||||
int encoded = 0;
|
||||
|
||||
LOG_FUNC_IN;
|
||||
|
||||
*(buffer + encoded) = encode_fgs_registration_result(®istration_accept->fgsregistrationresult);
|
||||
encoded = encoded + 2;
|
||||
|
||||
@@ -160,6 +168,81 @@ 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)
|
||||
_NAS_EQ_CHECK_INT(*a->hplmn_sst, *b->hplmn_sst);
|
||||
if (a->sd && b->sd)
|
||||
_NAS_EQ_CHECK_INT(*a->sd, *b->sd);
|
||||
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;
|
||||
}
|
||||
|
||||
// fgsregistrationresult (M)
|
||||
_NAS_EQ_CHECK_INT(a->fgsregistrationresult.iei, b->fgsregistrationresult.iei);
|
||||
_NAS_EQ_CHECK_INT(a->fgsregistrationresult.resultlength, b->fgsregistrationresult.resultlength);
|
||||
_NAS_EQ_CHECK_INT(a->fgsregistrationresult.spare, b->fgsregistrationresult.spare);
|
||||
_NAS_EQ_CHECK_INT(a->fgsregistrationresult.smsallowed, b->fgsregistrationresult.smsallowed);
|
||||
_NAS_EQ_CHECK_INT(a->fgsregistrationresult.registrationresult, b->fgsregistrationresult.registrationresult);
|
||||
|
||||
// GUTI (O)
|
||||
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) {
|
||||
PRINT_NAS_ERROR("NAS Equality Check failure: One of the two GUTIs is NULL\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allowed NSSAI (O), Configured NSSAI(O)
|
||||
for (int i = 0; i < NAS_MAX_NUMBER_SLICES; i++) {
|
||||
eq_snssai(&a->config_nssai[i], &b->config_nssai[i]);
|
||||
eq_snssai(&a->nas_allowed_nssai[i], &b->nas_allowed_nssai[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Memory management of NAS Registration Accept */
|
||||
|
||||
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,6 +31,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "SecurityHeaderType.h"
|
||||
#include "MessageType.h"
|
||||
@@ -40,12 +41,14 @@
|
||||
#ifndef REGISTRATION_ACCEPT_H_
|
||||
#define REGISTRATION_ACCEPT_H_
|
||||
|
||||
#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 +59,21 @@ typedef struct {
|
||||
*/
|
||||
|
||||
typedef struct registration_accept_msg_tag {
|
||||
/* Mandatory fields */
|
||||
// 5GS registration result (M)
|
||||
FGSRegistrationResult fgsregistrationresult;
|
||||
/* Optional fields */
|
||||
// 5G-GUTI (O)
|
||||
FGSMobileIdentity *guti;
|
||||
// Allowed NSSAI (O)
|
||||
nr_nas_msg_snssai_t nas_allowed_nssai[8];
|
||||
nr_nas_msg_snssai_t nas_allowed_nssai[NAS_MAX_NUMBER_SLICES];
|
||||
// Configured NSSAI (O)
|
||||
nr_nas_msg_snssai_t config_nssai[8];
|
||||
nr_nas_msg_snssai_t config_nssai[NAS_MAX_NUMBER_SLICES];
|
||||
} registration_accept_msg;
|
||||
|
||||
int decode_registration_accept(registration_accept_msg *registrationaccept, const uint8_t *buffer, uint32_t len);
|
||||
|
||||
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 "nr_nas_msg.h"
|
||||
@@ -25,6 +26,59 @@ 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
|
||||
* decode the message received from OAI CN5G
|
||||
* and compare with the expected one */
|
||||
static void test_regression_registration_accept(void)
|
||||
{
|
||||
// Registration Accept message
|
||||
registration_accept_msg orig = {
|
||||
.guti = malloc_or_fail(sizeof(*orig.guti)),
|
||||
.fgsregistrationresult.registrationresult = 0x01,
|
||||
.nas_allowed_nssai[0].sst = 0x01,
|
||||
.nas_allowed_nssai[1].sst = 0x01,
|
||||
.nas_allowed_nssai[2].sst = 0x01,
|
||||
.config_nssai[0].sst = 0x01,
|
||||
.config_nssai[1].sst = 0x01,
|
||||
.config_nssai[2].sst = 0x01,
|
||||
};
|
||||
|
||||
orig.guti->guti.typeofidentity = FGS_MOBILE_IDENTITY_5G_GUTI;
|
||||
orig.guti->guti.amfpointer = 0x01;
|
||||
orig.guti->guti.amfregionid = 0x01;
|
||||
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
|
||||
0x01, 0x00, 0x41, 0xB0, 0x20, 0x78, 0x06, // 5G-GUTI
|
||||
0x15, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // Allowed N-NSSAI
|
||||
0x31, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; // Configured N-NSSAI
|
||||
|
||||
// Decode NAS Registration Accept
|
||||
int encoded_length;
|
||||
registration_accept_msg decoded = {0};
|
||||
AssertFatal((encoded_length = decode_registration_accept(&decoded, cn5g_msg, sizeof(cn5g_msg))) >= 0,
|
||||
"encode_fgs_service_request() failed\n");
|
||||
|
||||
// Compare the raw encoded buffer with expected encoded data
|
||||
bool ret = eq_fgmm_registration_accept((const registration_accept_msg *)&orig, (const registration_accept_msg *)&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
|
||||
*/
|
||||
@@ -129,6 +183,7 @@ static void test_service_accept(void)
|
||||
|
||||
int main()
|
||||
{
|
||||
test_regression_registration_accept();
|
||||
test_service_request();
|
||||
test_service_accept();
|
||||
return 0;
|
||||
|
||||
@@ -1409,11 +1409,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 ? true : false) : true;
|
||||
if ((nas->uicc->nssai_sst == nssai->sst) && sd_match)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
@@ -1468,7 +1471,6 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff
|
||||
// process GUTI
|
||||
if (msg.guti) {
|
||||
process_guti(&msg.guti->guti, nas);
|
||||
free(msg.guti);
|
||||
} else {
|
||||
LOG_W(NAS, "no GUTI in registration accept\n");
|
||||
}
|
||||
@@ -1487,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 */
|
||||
|
||||
Reference in New Issue
Block a user