Commit 5d602d80 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge branch 'service_accept_fix' into 'develop'

Fix Service Request handling (Service Type: Signalling)

See merge request oai/cn5g/oai-cn5g-amf!207
parents 4dfc5d6a 965f52d3
common-build @ 63ebefe5
Subproject commit a28192ecfcb85d39ea9c39792e3b0fae2422a340
Subproject commit 63ebefe554a739ba1c686d5c2d70946b4af471c0
This diff is collapsed.
......@@ -923,6 +923,12 @@ class amf_n1 {
std::shared_ptr<nas_context> nc, const uint32_t ran_ue_ngap_id,
const long amf_ue_ngap_id, bstring nas);
void service_request_handle(
std::shared_ptr<nas_context> nc, const uint32_t ran_ue_ngap_id,
const long amf_ue_ngap_id, bstring nas, uint8_t ulCount);
void send_service_reject(std::shared_ptr<nas_context>& nc, uint8_t cause);
/*
* Handle Identity Response message
* @param [const uint32_t] ran_ue_ngap_id: RAN UE NGAP ID
......
......@@ -848,12 +848,6 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request& itti_msg) {
guami.AmfSetID = amf_cfg.guami.AmfSetID;
guami.AmfPointer = amf_cfg.guami.AmfPointer;
msg->setGuami(guami);
msg->setUESecurityCapability(
0xe000, 0xe000, 0xe000,
0xe000); // TODO: remove hardcoded value
msg->setSecurityKey((uint8_t*) bdata(itti_msg.kgnb));
msg->setNasPdu(itti_msg.nas);
// Get the list allowed NSSAI from the common PLMN between gNB and AMF
std::vector<S_Nssai> list;
/* for (auto p : amf_cfg.plmn_list) {
......@@ -877,6 +871,36 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request& itti_msg) {
}
msg->setAllowedNssai(list);
// TODO: get from ue_security_capability@NAS Context
msg->setUESecurityCapability(
0xe000, 0xe000, 0x0000,
0x0000); // TODO: remove hardcoded value
msg->setSecurityKey((uint8_t*) bdata(itti_msg.kgnb));
ngap::PlmnId plmn_id = {};
plmn_id.set(amf_cfg.guami.mcc, amf_cfg.guami.mnc);
msg->setMobilityRestrictionList(plmn_id);
// IMEISV
std::shared_ptr<nas_context> nc = {};
if (!amf_n1_inst->amf_ue_id_2_nas_context(itti_msg.amf_ue_ngap_id, nc)) {
Logger::amf_n2().warn(
"No existed nas_context with amf_ue_ngap_id(" AMF_UE_NGAP_ID_FMT ")",
itti_msg.amf_ue_ngap_id);
// TODO:
} else {
if (nc->imeisv.has_value()) {
Logger::nas_mm().debug(
"Set IMEISV InitialContextSetupRequestMsg: %s",
nc->imeisv.value().identity.c_str());
msg->setMaskedIMEISV(nc->imeisv.value().identity);
} else {
Logger::nas_mm().debug("No IMEISV info available");
}
}
msg->setNasPdu(itti_msg.nas);
if (itti_msg.is_sr or itti_msg.is_pdu_exist) {
// Set UE Radio Capability if available
if (gc->ue_radio_cap_ind) {
......@@ -885,7 +909,7 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request& itti_msg) {
}
if (itti_msg.is_sr)
Logger::amf_n2().debug("Encoding parameters for Service Request");
Logger::amf_n2().debug("Encoding parameters for Service Accept");
else
Logger::amf_n2().debug(
"Encoding parameters for Initial Context Setup Request");
......@@ -1317,20 +1341,21 @@ void amf_n2::handle_itti_message(itti_ue_context_release_complete& itti_msg) {
}
std::shared_ptr<gnb_context> gc = {};
if (!assoc_id_2_gnb_context(itti_msg.assoc_id, gc)) {
Logger::amf_n2().error(
"gNB with assoc_id (%d) is illegal", itti_msg.assoc_id);
return;
}
if (!assoc_id_2_gnb_context(itti_msg.assoc_id, gc)) {
Logger::amf_n2().error(
"gNB with assoc_id (%d) is illegal", itti_msg.assoc_id);
return;
}
//verify release cause -> if HandoverSuccessful no further operations required
if(unc->release_cause == Ngap_CauseRadioNetwork_successful_handover && gc->gnb_id == unc->release_gnb){
// verify release cause -> if HandoverSuccessful no further operations
// required
if (unc->release_cause == Ngap_CauseRadioNetwork_successful_handover &&
gc->gnb_id == unc->release_gnb) {
remove_ran_ue_ngap_id_2_ngap_context(ran_ue_ngap_id, gc->gnb_id);
unc->release_cause = 0;
return;
}
// Change UE status from CM-CONNECTED to CM-IDLE
std::shared_ptr<nas_context> nc = {};
if (!amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id, nc)) {
......@@ -1340,6 +1365,12 @@ void amf_n2::handle_itti_message(itti_ue_context_release_complete& itti_msg) {
}
if (nc != nullptr) {
// Do nothing in case of old NAS Context (Service Request handling)
if ((nc->old_amf_ue_ngap_id != INVALID_AMF_UE_NGAP_ID) and
(!nc->guti.has_value())) {
Logger::amf_n2().debug("UE Context Release Complete for the old context");
return;
}
amf_n1_inst->set_5gcm_state(nc, CM_IDLE);
// Start/reset the Mobile Reachable Timer
......@@ -1450,7 +1481,8 @@ void amf_n2::handle_itti_message(itti_ue_context_release_complete& itti_msg) {
}
// Remove UE NGAP context
remove_ue_context_with_ran_ue_ngap_id(ran_ue_ngap_id, uc->gnb_id);
remove_amf_ue_ngap_id_2_ue_ngap_context(amf_ue_ngap_id);
remove_ran_ue_ngap_id_2_ngap_context(ran_ue_ngap_id, gc->gnb_id);
}
//------------------------------------------------------------------------------
......@@ -2062,7 +2094,7 @@ void amf_n2::handle_itti_message(itti_handover_notify& itti_msg) {
return;
}
//update the NGAP Context
// update the NGAP Context
unc->release_cause = Ngap_CauseRadioNetwork_successful_handover;
unc->release_gnb = uc->gnb_id;
unc->ran_ue_ngap_id = ran_ue_ngap_id; // store new RAN ID
......@@ -2070,12 +2102,12 @@ void amf_n2::handle_itti_message(itti_handover_notify& itti_msg) {
unc->ng_ue_state = NGAP_UE_CONNECTED;
unc->gnb_assoc_id = itti_msg.assoc_id; // update serving gNB
//update NAS Context
// update NAS Context
nc->ran_ue_ngap_id = ran_ue_ngap_id;
//update User Context
// update User Context
uc->ran_ue_ngap_id = ran_ue_ngap_id;
uc->gnb_id = gc->gnb_id;
uc->gnb_id = gc->gnb_id;
set_ran_ue_ngap_id_2_ue_ngap_context(ran_ue_ngap_id, gc->gnb_id, unc);
}
......@@ -2297,11 +2329,11 @@ void amf_n2::remove_ue_context_with_ran_ue_ngap_id(
// Remove all NAS context if still exist
std::shared_ptr<nas_context> nc = {};
if (amf_n1_inst->amf_ue_id_2_nas_context(unc->amf_ue_ngap_id, nc)) {
// TODO: Verify where it's current context
// Remove all NAS context
string supi = conv::imsi_to_supi(nc->imsi);
if (nc->is_stacs_available) {
stacs.update_5gmm_state(nc->imsi, "5GMM-DEREGISTERED");
}
stacs.update_5gmm_state(nc->imsi, "5GMM-DEREGISTERED");
// Trigger UE Loss of Connectivity Status Notify
Logger::amf_n1().debug(
"Signal the UE Loss of Connectivity Event notification for SUPI %s",
......@@ -2384,9 +2416,8 @@ void amf_n2::remove_ue_context_with_amf_ue_ngap_id(const long& amf_ue_ngap_id) {
// Remove all NAS context
string supi = conv::imsi_to_supi(nc->imsi);
// Update UE status
if (nc->is_stacs_available) {
stacs.update_5gmm_state(nc->imsi, "5GMM-DEREGISTERED");
}
stacs.update_5gmm_state(nc->imsi, "5GMM-DEREGISTERED");
// Trigger UE Loss of Connectivity Status Notify
Logger::amf_n1().debug(
"Signal the UE Loss of Connectivity Event notification for SUPI %s",
......
......@@ -987,7 +987,7 @@ bool amf_sbi::send_ue_authentication_request(
url, "POST", body, response_data, response_code, http_version);
Logger::amf_sbi().debug(
"UE Authentication, response from AUSF, HTTP Code: %d", response_code);
"UE Authentication, response from AUSF, HTTP Code: %lu", response_code);
if ((static_cast<http_response_codes_e>(response_code) ==
http_response_codes_e::HTTP_RESPONSE_CODE_200_OK) or
......@@ -1113,7 +1113,7 @@ void amf_sbi::curl_http_client(
bstring n1sm_hex = nullptr;
bstring n2sm_hex = nullptr;
Logger::amf_sbi().info("Get response with HTTP code (%d)", httpCode);
Logger::amf_sbi().info("Get response with HTTP code (%ld)", httpCode);
Logger::amf_sbi().info("Response body %s", response.c_str());
if (static_cast<http_response_codes_e>(httpCode) ==
......@@ -1404,7 +1404,7 @@ void amf_sbi::curl_http_client(
n2sm_msg = {};
json_data = {};
Logger::amf_sbi().info("Get response with HTTP code (%d)", httpCode);
Logger::amf_sbi().info("Get response with HTTP code (%ld)", httpCode);
Logger::amf_sbi().info("Response body %s", response.c_str());
response_code = httpCode;
......@@ -1542,7 +1542,7 @@ void amf_sbi::curl_http_client(
std::string response = *httpData.get();
std::string resMsg = {};
bool is_response_ok = true;
Logger::amf_sbi().info("Get response with HTTP code (%d)", httpCode);
Logger::amf_sbi().info("Get response with HTTP code (%ld)", httpCode);
response_code = httpCode;
......
......@@ -22,6 +22,8 @@
#ifndef FILE_3GPP_24_501_SEEN
#define FILE_3GPP_24_501_SEEN
#define T3502_TIMER_DEFAULT_VALUE_MIN 12 // 12 minutes
// Table 10.3.1 @3GPP TS 24.501 V16.1.0 (2019-06)
#define T3512_TIMER_VALUE_SEC 3240 // 54 minutes
#define T3512_TIMER_VALUE_MIN 54 // 54 minutes
......
......@@ -80,4 +80,7 @@ constexpr uint32_t DEFAULT_HTTP2_PORT = 8080;
constexpr auto DEFAULT_SBI_API_VERSION = "v1";
constexpr auto DEFAULT_SUPI_TYPE =
"imsi"; // Set to "imsi" when supporting both IMSI and NAI as SUPI
constexpr auto DEFAULT_SST = 1;
constexpr auto DEFAULT_DNN = "default";
#endif
......@@ -303,25 +303,19 @@ bool conv::octet_string_2_bit_string(
//------------------------------------------------------------------------------
bool conv::bstring_2_bit_string(const bstring& b_str, BIT_STRING_t& bit_str) {
//OCTET_STRING_t octet_str;
//bstring_2_octet_string(b_str, octet_str);
// octet_string_2_bit_string(octet_str, bit_str, 0);
int size = blength(b_str);
if (!b_str or size <= 0) return false;
if (!bdata(b_str)) return false;
int size = blength(b_str);
if (!b_str or size <= 0) return false;
if (!bdata(b_str)) return false;
bit_str.buf = (uint8_t*) calloc(size + 1, sizeof(uint8_t));
if (!bit_str.buf) return false;
bit_str.buf = (uint8_t*) calloc(size + 1, sizeof(uint8_t));
if (!bit_str.buf) return false;
if (check_bstring (b_str)) memcpy((void*) bit_str.buf, (char*)b_str->data,
blength(b_str));
((uint8_t*) bit_str.buf)[size] = '\0';
bit_str.size = size;
if (check_bstring(b_str))
memcpy((void*) bit_str.buf, (char*) b_str->data, blength(b_str));
((uint8_t*) bit_str.buf)[size] = '\0';
bit_str.size = size;
bit_str.bits_unused = 0;
bit_str.bits_unused = 0;
return true;
}
......@@ -526,3 +520,36 @@ std::string conv::get_imsi(
const std::string& mcc, const std::string& mnc, const std::string& msin) {
return {mcc + mnc + msin};
}
//------------------------------------------------------------------------------
bool conv::string_2_masked_imeisv(
const std::string& imeisv_str, BIT_STRING_t& imeisv) {
int len = imeisv_str.length();
if (len != 16) return false; // Must contain 16 digits
imeisv.buf = (uint8_t*) calloc(8, sizeof(uint8_t));
if (!imeisv.buf) {
return false;
}
uint8_t digit_low = 0;
uint8_t digit_high = 0;
int i = 0;
int j = 0;
while (i < len) {
string_to_int8(imeisv_str.substr(i, 1), digit_low);
string_to_int8(imeisv_str.substr(i + 1, 1), digit_high);
i = i + 2;
uint8_t octet = (0xf0 & (digit_high << 4)) | (digit_low & 0x0f);
imeisv.buf[j] = octet;
j++;
}
// last 4 digits of the SNR masked by setting the corresponding bits to 1
imeisv.buf[5] = 0xff;
imeisv.buf[6] = 0xff;
imeisv.size = 8;
imeisv.bits_unused = 0;
return true;
}
......@@ -110,5 +110,7 @@ class conv {
static std::string imsi_to_supi(const std::string& imsi);
static std::string get_imsi(
const std::string& mcc, const std::string& mnc, const std::string& msin);
static bool string_2_masked_imeisv(
const std::string& str, BIT_STRING_t& imeisv);
};
#endif /* FILE_CONVERSIONS_HPP_SEEN */
......@@ -21,25 +21,28 @@
#include "nas_context.hpp"
#include "amf.hpp"
//------------------------------------------------------------------------------
nas_context::nas_context() : _5g_he_av(), _5g_av(), kamf(), _5gmm_capability() {
is_imsi_present = false;
is_stacs_available = false;
is_auth_vectors_present = false;
auts = nullptr;
ctx_avaliability_ind = false;
amf_ue_ngap_id = 0;
ran_ue_ngap_id = 0;
_5gmm_state = {};
registration_type = 0;
follow_on_req_pending_ind = false;
ngksi = 0;
ue_security_capability = {};
is_specific_procedure_for_registration_running = false;
is_specific_procedure_for_deregistration_running = false;
is_specific_procedure_for_eCell_inactivity_running = false;
is_common_procedure_for_authentication_running = false;
is_common_procedure_for_identification_running = false;
is_imsi_present = false;
is_auth_vectors_present = false;
auts = nullptr;
ctx_avaliability_ind = false;
amf_ue_ngap_id = 0;
ran_ue_ngap_id = 0;
old_amf_ue_ngap_id = INVALID_AMF_UE_NGAP_ID;
old_ran_ue_ngap_id = 0;
_5gmm_state = {};
registration_type = 0;
follow_on_req_pending_ind = false;
ngksi = 0;
ue_security_capability = {};
is_specific_procedure_for_registration_running = false;
is_specific_procedure_for_deregistration_running = false;
is_specific_procedure_for_eCell_inactivity_running = false;
is_common_procedure_for_authentication_running = false;
is_common_procedure_for_identification_running = false;
is_common_procedure_for_security_mode_control_running = false;
is_common_procedure_for_nas_transport_running = false;
security_ctx = std::nullopt;
......@@ -56,6 +59,8 @@ nas_context::nas_context() : _5g_he_av(), _5g_av(), kamf(), _5gmm_capability() {
mobile_reachable_timer = ITTI_INVALID_TIMER_ID;
implicit_deregistration_timer = ITTI_INVALID_TIMER_ID;
href = {};
imeisv = std::nullopt;
guti = std::nullopt;
}
//------------------------------------------------------------------------------
......
......@@ -66,9 +66,11 @@ class nas_context {
nas_context();
~nas_context();
bool ctx_avaliability_ind;
bool is_stacs_available;
long amf_ue_ngap_id;
uint32_t ran_ue_ngap_id;
long old_amf_ue_ngap_id;
uint32_t old_ran_ue_ngap_id;
cm_state_t nas_status;
_5gmm_state_t _5gmm_state;
bool is_mobile_reachable_timer_timeout;
......@@ -81,6 +83,9 @@ class nas_context {
uint8_t ngksi; // 4 bits
std::string imsi; // TODO: use SUPI instead
std::optional<nas::IMEI_IMEISV_t> imeisv;
std::optional<std::string> guti;
std::uint8_t _5gmm_capability[13];
nas::UESecurityCapability ue_security_capability;
......
......@@ -45,6 +45,7 @@
#include "GprsTimer3.hpp"
#include "ImeisvRequest.hpp"
#include "LADN_Indication.hpp"
#include "LadnInformation.hpp"
#include "MaPduSessionInformation.hpp"
#include "NasMessageContainer.hpp"
#include "NasSecurityAlgorithms.hpp"
......
......@@ -111,11 +111,11 @@ int _5GSMobileIdentity::Decode(uint8_t* buf, int len, bool is_iei) {
type_of_identity_ = _5G_GUTI;
decoded_size += Decode5gGuti(buf + decoded_size, len - decoded_size);
} break;
// TODO: IMEI
case _5G_S_TMSI: {
type_of_identity_ = _5G_S_TMSI;
decoded_size += Decode5gSTmsi(buf + decoded_size, len - decoded_size);
} break;
// TODO: IMEI
case IMEISV: {
type_of_identity_ = IMEISV;
decoded_size += DecodeImeisv(buf + decoded_size, ie_len);
......@@ -625,13 +625,29 @@ int _5GSMobileIdentity::EncodeImeisv(uint8_t* buf, int len) {
if (encoded_header_size == KEncodeDecodeError) return KEncodeDecodeError;
encoded_size += encoded_header_size;
int size = encode_bstring(
imeisv_.value().identity, (buf + encoded_size), len - encoded_size);
encoded_size += size;
uint8_t octet = {0};
uint8_t digit_low = 0;
uint8_t digit_high = 0;
// Update Type of identity (3 bits of Octet 3/4)
*(buf + GetHeaderLength()) |= (0x01 << 3) | IMEISV;
// TODO: odd/even indic
int i = 0;
while (i < imeisv_.value().identity.length()) {
if (i == 0) {
digit_low = 0x07 & IMEISV; // TODO: odd/even indic
conv::string_to_int8(imeisv_.value().identity.substr(i, 1), digit_high);
} else if (i < imeisv_.value().identity.length() - 1) {
conv::string_to_int8(imeisv_.value().identity.substr(i, 1), digit_low);
conv::string_to_int8(
imeisv_.value().identity.substr(i + 1, 1), digit_high);
i++;
} else if (i == imeisv_.value().identity.length() - 1) {
conv::string_to_int8(imeisv_.value().identity.substr(i, 1), digit_low);
digit_high = 0x0f;
}
uint8_t octet = (0xf0 & (digit_high << 4)) | (digit_low & 0x0f);
ENCODE_U8(buf + encoded_size, octet, encoded_size);
i++;
}
// Encode length
int encoded_len_ie = 0;
......@@ -644,39 +660,57 @@ int _5GSMobileIdentity::EncodeImeisv(uint8_t* buf, int len) {
//------------------------------------------------------------------------------
int _5GSMobileIdentity::DecodeImeisv(uint8_t* buf, int len) {
Logger::nas_mm().debug("Decoding 5GSMobilityIdentity IMEISV");
int decoded_size = 0;
IMEISV_t imeisv_tmp = {};
decode_bstring(
&(imeisv_tmp.identity), len, (buf + decoded_size), len - decoded_size);
decoded_size += len;
int decoded_size = 0;
IMEI_IMEISV_t imeisv_tmp = {};
imeisv_tmp.type_of_identity_ = IMEISV;
imeisv_tmp.identity = {};
uint8_t digit_low = 0;
uint8_t digit_high = 0;
uint8_t octet = 0;
for (int i = 0; i < len; i++) {
Logger::nas_mm().debug(
"Decoded 5GSMobilityIdentity IMEISV value(0x%x)",
(uint8_t) imeisv_tmp.identity->data[i]);
DECODE_U8(buf + decoded_size, octet, decoded_size);
digit_high = (octet & 0xf0) >> 4;
digit_low = octet & 0x0f;
if (i == 0) {
imeisv_tmp.identity += (const std::string)(std::to_string(
digit_high)); // octet 4 (Identity digit 1 4bits, odd/even indic 1
// bit, type of identity 3 bits)
} else if (i < (len - 1)) {
imeisv_tmp.identity +=
((const std::string)(std::to_string(digit_low)) +
(const std::string)(std::to_string(digit_high)));
} else { // Bits 5 to 8 of the last octet: end mark coded as "1111"
imeisv_tmp.identity += (const std::string)(std::to_string(digit_low));
if (digit_high != 0x0f) {
Logger::nas_mm().warn(
"IMEISV: Bits 5 to 8 of the last octet should filled with an end "
"mark coded as 1111");
}
}
}
imeisv_ = std::optional<IMEISV_t>(imeisv_tmp);
Logger::nas_mm().debug(
"Decoded 5GSMobilityIdentity IMEISV: %s", imeisv_tmp.identity.c_str());
imeisv_ = std::optional<IMEI_IMEISV_t>(imeisv_tmp);
Logger::nas_mm().debug(
"decoded 5GSMobilityIdentity IMEISV len (%d)", decoded_size);
"Decoded 5GSMobilityIdentity IMEISV len (%d)", decoded_size);
return decoded_size;
}
//------------------------------------------------------------------------------
void _5GSMobileIdentity::SetImeisv(const IMEISV_t& imeisv) {
void _5GSMobileIdentity::SetImeisv(const IMEI_IMEISV_t& imeisv) {
// Clear all identity types first
ClearIe();
// Set value for IMEISV
type_of_identity_ = IMEISV;
// length = blength(imeisv.identity) - 1 + 4;
IMEISV_t imeisv_tmp = {};
imeisv_tmp.identity = bstrcpy(imeisv.identity);
imeisv_tmp.identity->data[blength(imeisv.identity) - 1] |= 0xf0;
imeisv_ = std::optional<IMEISV_t>(imeisv_tmp);
imeisv_ = std::optional<IMEI_IMEISV_t>(imeisv);
}
//------------------------------------------------------------------------------
bool _5GSMobileIdentity::GetImeisv(IMEISV_t& imeisv) const {
bool _5GSMobileIdentity::GetImeisv(IMEI_IMEISV_t& imeisv) const {
if (!imeisv_.has_value()) return false;
imeisv.identity = bstrcpy(imeisv_.value().identity);
imeisv = imeisv_.value();
return true;
}
......@@ -31,53 +31,6 @@ constexpr auto k5gsMobileIdentityIeName = "5GS Mobile Identity";
namespace nas {
// 5G-GUTI
typedef struct _5G_GUTI_s {
std::string mcc;
std::string mnc;
uint8_t amf_region_id;
uint8_t amf_set_id;
uint16_t amf_pointer;
uint32_t _5g_tmsi;
} _5G_GUTI_t;
// IMEI or IMEISV
typedef struct IMEI_or_IMEISV_s {
uint8_t type_of_identity_ : 3;
bool odd_even_indic; // for imei, even means bits 5 to 8 of last octet is
// "1111", for imeisv, bits 5 to 8 of last octet is
// "1111"
std::string identity; // "46011000001"
} IMEI_IMEISV_t;
// TODO:
// 5GS mobile identity information element for type of identity "SUCI" and SUPI
// format "IMSI"
// SUCI and SUPI format IMSI and
// Protection scheme Id "Null scheme"
typedef struct SUCI_imsi_s {
uint8_t supi_format : 3;
std::string mcc;
std::string mnc;
std::optional<std::string> routing_indicator; //"1234"
uint8_t protection_scheme_id : 4; // 0000
uint8_t home_network_pki; // 00000000
std::string msin; // two types of coding; BCD & hexadecimal
} SUCI_imsi_t; // SUPI format "IMSI"
// TODO: SUCI and SUPI format "Network specific identifier"
// 5G-S-TMSI
typedef struct _5G_S_TMSI_s {
uint16_t amf_set_id;
uint8_t amf_pointer;
std::string _5g_tmsi;
} _5G_S_TMSI_t;
// TODO: 5GS mobile identity information element for type of identity "MAC
// address"
class _5GSMobileIdentity : public Type6NasIe {
public:
_5GSMobileIdentity();
......@@ -128,12 +81,12 @@ class _5GSMobileIdentity : public Type6NasIe {
bool Get5gSTmsi(
uint16_t& amf_set_id, uint8_t& amf_pointer, std::string& tmsi) const;
// IMEISV
// IMEI/IMEISV
int EncodeImeisv(uint8_t* buf, int len);
int DecodeImeisv(uint8_t* buf, int len);
void SetImeisv(const IMEISV_t& imeisv);
bool GetImeisv(IMEISV_t& imeisv) const;
void SetImeisv(const IMEI_IMEISV_t& imeisv);
bool GetImeisv(IMEI_IMEISV_t& imeisv) const;
private:
uint8_t type_of_identity_ : 3;
......@@ -141,7 +94,7 @@ class _5GSMobileIdentity : public Type6NasIe {
std::optional<SUCI_imsi_t> supi_format_imsi_;
std::optional<_5G_GUTI_t> _5g_guti_;
std::optional<IMEI_IMEISV_t> imei_; // TODO:
std::optional<IMEISV_t> imeisv_;
std::optional<IMEI_IMEISV_t> imeisv_;
std::optional<_5G_S_TMSI_t> _5g_s_tmsi_;
};
......
......@@ -35,6 +35,12 @@ DNN::DNN(bstring dnn) : Type4NasIe(kIeiDnn) {
SetLengthIndicator(blength(dnn));
}
//------------------------------------------------------------------------------
DNN::DNN(bool iei) : Type4NasIe(), _DNN() {
if (iei) SetIei(kIeiDnn);
SetLengthIndicator(1);
}
//------------------------------------------------------------------------------
DNN::~DNN() {}
......
......@@ -34,6 +34,7 @@ class DNN : public Type4NasIe {
public:
DNN();
DNN(bstring dnn);
DNN(bool iei);
~DNN();
static std::string GetIeName() { return kDnnIeName; }
......
......@@ -19,13 +19,13 @@
* contact@openairinterface.org
*/
#ifndef _LADN_Indication_H_
#define _LADN_Indication_H_
#ifndef _LADN_INDICATION_H_
#define _LADN_INDICATION_H_
#include "Type6NasIe.hpp"
constexpr uint8_t kLadnIndicationMinimumLength = 3;
constexpr uint16_t kLadnIndicationMaximumLength = 1715;
constexpr uint16_t kLadnIndicationMaximumLength = 811;
constexpr auto kLadnIndicationIeName = "LADN Indication";
namespace nas {
......
/*
* 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
*/
#include "Ladn.hpp"
#include "3gpp_24.501.hpp"
#include "common_defs.h"
#include "Ie_Const.hpp"
#include "logger.hpp"
using namespace nas;
//------------------------------------------------------------------------------
ladn::ladn() : dnn(false), ta_list(false) {}
//------------------------------------------------------------------------------
ladn::~ladn() {}
//------------------------------------------------------------------------------
void ladn::Set(const DNN& value) {
dnn = value;
}
//------------------------------------------------------------------------------
void ladn::Set(const _5GSTrackingAreaIdList& value) {
ta_list = value;
}
//------------------------------------------------------------------------------
uint32_t ladn::GetLength() const {
return (dnn.GetIeLength() + ta_list.GetIeLength());
}
//------------------------------------------------------------------------------
int ladn::Encode(uint8_t* buf, int len) {
Logger::nas_mm().debug("Encoding LADN");
int ie_len = dnn.GetIeLength();
ie_len += ta_list.GetIeLength();
if (len < ie_len) { // Length of the content + IEI/Len
Logger::nas_mm().error(
"Size of the buffer is not enough to store this IE (IE len %d)",
ie_len);
return KEncodeDecodeError;
}
int encoded_size = 0;
int encoded_ie_size = 0;
encoded_ie_size = dnn.Encode(buf + encoded_size, len);
if (encoded_ie_size == KEncodeDecodeError) return KEncodeDecodeError;
encoded_size += encoded_ie_size;
encoded_ie_size = ta_list.Encode(buf + encoded_size, len);
if (encoded_ie_size == KEncodeDecodeError) return KEncodeDecodeError;
encoded_size += encoded_ie_size;
Logger::nas_mm().debug("Encoded LADN, len (%d)", encoded_size);
return encoded_size;
}
//------------------------------------------------------------------------------
int ladn::Decode(uint8_t* buf, int len) {
Logger::nas_mm().debug("Decoding LADN");
int decoded_size = 0;
// TODO:
Logger::nas_mm().debug("Decoded LADN (len %d)", decoded_size);
return decoded_size;
}
/*
* 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
*/
#ifndef _LADN_H_
#define _LADN_H_
#include "DNN.hpp"
#include "_5GSTrackingAreaIdList.hpp"
#include "Type6NasIe.hpp"
namespace nas {
class ladn {
public:
ladn();
~ladn();
void Set(const DNN& value);
void Set(const _5GSTrackingAreaIdList& value);
uint32_t GetLength() const;
int Encode(uint8_t* buf, int len);
int Decode(uint8_t* buf, int len);
private:
DNN dnn;
_5GSTrackingAreaIdList ta_list;
};
} // namespace nas
#endif
/*
* 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
*/
#include "LadnInformation.hpp"
#include "3gpp_24.501.hpp"
#include "common_defs.h"
#include "Ie_Const.hpp"
#include "logger.hpp"
using namespace nas;
//------------------------------------------------------------------------------
LadnInformation::LadnInformation() : Type6NasIe(kIeiLadnInformation) {
SetLengthIndicator(0);
}
//------------------------------------------------------------------------------
LadnInformation::~LadnInformation() {}
//------------------------------------------------------------------------------
void LadnInformation::Set(const vector<ladn>& value) {
ladn_list.assign(value.begin(), value.end());
}
//------------------------------------------------------------------------------
void LadnInformation::Add(const ladn& value) {
// TODO: Check maximum items - 8
ladn_list.push_back(value);
int ie_len = GetIeLength();
ie_len += value.GetLength();
}
//------------------------------------------------------------------------------
int LadnInformation::Encode(uint8_t* buf, int len) {
Logger::nas_mm().debug("Encoding %s", GetIeName().c_str());
int ie_len = GetIeLength();
if (len < ie_len) { // Length of the content + IEI/Len
Logger::nas_mm().error(
"Size of the buffer is not enough to store this IE (IE len %d)",
ie_len);
return KEncodeDecodeError;
}
int encoded_size = 0;
/*
// IEI and Length (later)
int len_pos = 0;
int encoded_header_size =
Type6NasIe::Encode(buf + encoded_size, len, len_pos);
if (encoded_header_size == KEncodeDecodeError) return KEncodeDecodeError;
encoded_size += encoded_header_size;
for (int i = 0; i < LADN.size(); i++) {
ENCODE_U8(buf + encoded_size, blength(LADN.at(i)), encoded_size);
encoded_size +=
encode_bstring(LADN.at(i), (buf + encoded_size), len - encoded_size);
}
// Encode length
int encoded_len_ie = 0;
ENCODE_U16(buf + len_pos, encoded_size - GetHeaderLength(), encoded_len_ie);
*/
Logger::nas_mm().debug(
"Encoded %s, len (%d)", GetIeName().c_str(), encoded_size);
return encoded_size;
}
//------------------------------------------------------------------------------
int LadnInformation::Decode(uint8_t* buf, int len, bool is_iei) {
Logger::nas_mm().debug("Decoding EPS_NAS_Message_Container");
int decoded_size = 0;
// IEI and Length
uint16_t ie_len = 0;
int decoded_header_size = Type6NasIe::Decode(buf + decoded_size, len, is_iei);
if (decoded_header_size == KEncodeDecodeError) return KEncodeDecodeError;
decoded_size += decoded_header_size;
ie_len = GetLengthIndicator();
/*
uint8_t dnn_len = 0;
bstring dnn = {};
while (ie_len) {
DECODE_U8(buf + decoded_size, dnn_len, decoded_size);
ie_len--;
decode_bstring(&dnn, dnn_len, (buf + decoded_size), len - decoded_size);
decoded_size += dnn_len;
ie_len -= dnn_len;
LADN.insert(LADN.end(), dnn);
}
for (int i = 0; i < LADN.size(); i++) {
for (int j = 0; j < blength(LADN.at(i)); j++) {
Logger::nas_mm().debug(
"Decoded LadnInformation value (0x%x)",
(uint8_t) LADN.at(i)->data[j]);
}
}
*/
Logger::nas_mm().debug(
"Decoded EPS_NAS_Message_Container (len %d)", decoded_size);
return decoded_size;
}
/*
* 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
*/
#ifndef _LADN_INFORMATION_H_
#define _LADN_INFORMATION_H_
#include "DNN.hpp"
#include "_5GSTrackingAreaIdList.hpp"
#include "Ladn.hpp"
#include "Type6NasIe.hpp"
constexpr uint8_t kLadnInformationMinimumLength = 3;
constexpr uint16_t kLadnInformationMaximumLength = 1715;
constexpr auto kLadnInformationIeName = "LADN Information";
namespace nas {
class LadnInformation : Type6NasIe {
public:
LadnInformation();
~LadnInformation();
static std::string GetIeName() { return kLadnInformationIeName; }
void Set(const vector<ladn>& value);
void Add(const ladn& value);
int Encode(uint8_t* buf, int len);
int Decode(uint8_t* buf, int len, bool is_option);
private:
std::vector<ladn> ladn_list;
};
} // namespace nas
#endif
......@@ -36,6 +36,18 @@ _5GSTrackingAreaIdList::_5GSTrackingAreaIdList()
k5gsTrackingAreaIdListMinimumLength -
2); // Minimim length - 2 bytes for header
}
//------------------------------------------------------------------------------
_5GSTrackingAreaIdList::_5GSTrackingAreaIdList(bool iei)
: Type4NasIe(), m_tai_list() {
if (iei) {
SetIei(kIei5gsTrackingAreaIdentityList);
}
SetLengthIndicator(
k5gsTrackingAreaIdListMinimumLength -
2); // Minimim length - 2 bytes for header
}
//------------------------------------------------------------------------------
_5GSTrackingAreaIdList::_5GSTrackingAreaIdList(
const std::vector<p_tai_t>& tai_list)
......
......@@ -36,6 +36,7 @@ namespace nas {
class _5GSTrackingAreaIdList : public Type4NasIe {
public:
_5GSTrackingAreaIdList();
_5GSTrackingAreaIdList(bool iei);
_5GSTrackingAreaIdList(const std::vector<p_tai_t>& tai_list);
int Encode(uint8_t* buf, int len);
......
......@@ -107,6 +107,52 @@ typedef struct {
std::vector<uint32_t> tac_list;
} p_tai_t;
// 5G-GUTI
typedef struct _5G_GUTI_s {
std::string mcc;
std::string mnc;
uint8_t amf_region_id;
uint8_t amf_set_id;
uint16_t amf_pointer;
uint32_t _5g_tmsi;
} _5G_GUTI_t;
// IMEI or IMEISV
typedef struct IMEI_or_IMEISV_s {
uint8_t type_of_identity_ : 3;
bool odd_even_indic; // for imei, even means bits 5 to 8 of last octet is
// "1111", for imeisv, bits 5 to 8 of last octet is
// "1111"
std::string identity; // "46011000001": without 1111
} IMEI_IMEISV_t;
// TODO:
// 5GS mobile identity information element for type of identity "SUCI" and SUPI
// format "IMSI"
// SUCI and SUPI format IMSI and
// Protection scheme Id "Null scheme"
typedef struct SUCI_imsi_s {
uint8_t supi_format : 3;
std::string mcc;
std::string mnc;
std::optional<std::string> routing_indicator; //"1234"
uint8_t protection_scheme_id : 4; // 0000
uint8_t home_network_pki; // 00000000
std::string msin; // two types of coding; BCD & hexadecimal
} SUCI_imsi_t; // SUPI format "IMSI"
// TODO: SUCI and SUPI format "Network specific identifier"
// 5G-S-TMSI
typedef struct _5G_S_TMSI_s {
uint16_t amf_set_id;
uint8_t amf_pointer;
std::string _5g_tmsi;
} _5G_S_TMSI_t;
// TODO: 5GS mobile identity information element for type of identity "MAC
// address"
} // namespace nas
#endif
......@@ -37,25 +37,25 @@ RegistrationAccept::RegistrationAccept()
ie_pdu_session_status = std::nullopt;
ie_pdu_session_reactivation_result = std::nullopt;
ie_pdu_session_reactivation_result_error_cause = std::nullopt;
// ie_ladn_information = std::nullopt;
ie_mico_indication = std::nullopt;
ie_network_slicing_indication = std::nullopt;
ie_t3512_value = std::nullopt;
ie_non_3gpp_deregistration_timer_value = std::nullopt;
ie_t3502_value = std::nullopt;
ie_sor_transparent_container = std::nullopt;
ie_eap_message = std::nullopt;
ie_nssai_inclusion_mode = std::nullopt;
ie_negotiated_drx_parameters = std::nullopt;
ie_non_3gpp_nw_policies = std::nullopt;
ie_eps_bearer_context_status = std::nullopt;
ie_extended_drx_parameters = std::nullopt;
ie_t3447_value = std::nullopt;
ie_t3448_value = std::nullopt;
ie_t3324_value = std::nullopt;
ie_ue_radio_capability_id = std::nullopt;
ie_pending_nssai = std::nullopt;
ie_tai_list = std::nullopt;
ie_ladn_information = std::nullopt;
ie_mico_indication = std::nullopt;
ie_network_slicing_indication = std::nullopt;
ie_t3512_value = std::nullopt;
ie_non_3gpp_deregistration_timer_value = std::nullopt;
ie_t3502_value = std::nullopt;
ie_sor_transparent_container = std::nullopt;
ie_eap_message = std::nullopt;
ie_nssai_inclusion_mode = std::nullopt;
ie_negotiated_drx_parameters = std::nullopt;
ie_non_3gpp_nw_policies = std::nullopt;
ie_eps_bearer_context_status = std::nullopt;
ie_extended_drx_parameters = std::nullopt;
ie_t3447_value = std::nullopt;
ie_t3448_value = std::nullopt;
ie_t3324_value = std::nullopt;
ie_ue_radio_capability_id = std::nullopt;
ie_pending_nssai = std::nullopt;
ie_tai_list = std::nullopt;
}
//------------------------------------------------------------------------------
......@@ -184,12 +184,11 @@ void RegistrationAccept::SetMicoIndication(bool sprti, bool raai) {
ie_mico_indication = std::make_optional<MicoIndication>(sprti, raai);
}
/*
//------------------------------------------------------------------------------
void RegistrationAccept::setLADN_Information(std::vector<bstring> ladnValue) {
ie_ladn_information = std::make_optional<LadnInformation>(ladnValue);
void RegistrationAccept::SetLadnInformation(
const LadnInformation& ladn_information) {
ie_ladn_information = std::make_optional<LadnInformation>(ladn_information);
}
*/
//------------------------------------------------------------------------------
void RegistrationAccept::SetNetworkSlicingIndication(bool dcni, bool nssci) {
......@@ -466,18 +465,20 @@ int RegistrationAccept::Encode(uint8_t* buf, int len) {
return KEncodeDecodeError;
}
}
/*
if (!ie_ladn_information.has_value()) {
Logger::nas_mm().warn("IE ie_ladn_information is not available");
} else {
if (int size = ie_ladn_information.value().Encode(
buf + encoded_size, len - encoded_size)) {
int size = ie_ladn_information.value().Encode(
buf + encoded_size, len - encoded_size);
if (size != KEncodeDecodeError) {
encoded_size += size;
} else {
Logger::nas_mm().error("encoding ie_ladn_information error");
return 0;
Logger::nas_mm().error(
"Encoding %s error", LadnInformation::GetIeName().c_str());
return KEncodeDecodeError;
}
}*/
}
if (!ie_mico_indication.has_value()) {
Logger::nas_mm().debug(
......@@ -994,18 +995,24 @@ int RegistrationAccept::Decode(uint8_t* buf, int len) {
ie_pdu_session_reactivation_result_error_cause_tmp);
DECODE_U8_VALUE(buf + decoded_size, octet);
Logger::nas_mm().debug("Next IEI (0x%x)", octet);
} break; /*
case kIeiLadnInformation: {
Logger::nas_mm().debug("Decoding IEI(0x74)");
LadnInformation ie_ladn_information_tmp = {};
decoded_size += ie_ladn_information_tmp.Decode(
buf + decoded_size, len - decoded_size, true);
ie_ladn_information =
std::optional<LadnInformation>(ie_ladn_information_tmp);
octet = *(buf + decoded_size);
Logger::nas_mm().debug("Next IEI 0x%x", octet);
} break;
*/
} break;
case kIeiLadnInformation: {
Logger::nas_mm().debug("Decoding IEI 0x%x", kIeiLadnInformation);
LadnInformation ie_ladn_information_tmp = {};
if ((decoded_result = ie_ladn_information_tmp.Decode(
buf + decoded_size, len - decoded_size, true)) ==
KEncodeDecodeError) {
Logger::nas_mm().error(
"Decoding %s error", LadnInformation::GetIeName().c_str());
return KEncodeDecodeError;
}
decoded_size += decoded_result;
ie_ladn_information =
std::optional<LadnInformation>(ie_ladn_information_tmp);
DECODE_U8_VALUE(buf + decoded_size, octet);
Logger::nas_mm().debug("Next IEI 0x%x", octet);
} break;
case kIeiGprsTimer3T3512: {
Logger::nas_mm().debug("Decoding IEI 0x%x", kIeiGprsTimer3T3512);
GprsTimer3 ie_t3512_value_tmp(kIeiGprsTimer3T3512);
......
......@@ -89,6 +89,7 @@ class RegistrationAccept : public NasMmPlainHeader {
// TODO: Get
// TODO: LADN information
void SetLadnInformation(const LadnInformation& ladn_information);
void SetMicoIndication(bool sprti, bool raai);
// TODO: Get
......@@ -164,7 +165,7 @@ class RegistrationAccept : public NasMmPlainHeader {
ie_pdu_session_reactivation_result; // Optional
std::optional<PDU_Session_Reactivation_Result_Error_Cause>
ie_pdu_session_reactivation_result_error_cause; // Optional
// TODO: std::optional<LadnInformation> ie_ladn_information; //
std::optional<LadnInformation> ie_ladn_information; //
// Optional
std::optional<MicoIndication> ie_mico_indication; // Optional
std::optional<NetworkSlicingIndication>
......
......@@ -144,7 +144,15 @@ int SecurityModeCommand::Encode(uint8_t* buf, int len) {
// NAS key set identifier
size = ie_ng_ksi.Encode(buf + encoded_size, len - encoded_size);
if (size != KEncodeDecodeError) {
encoded_size++; // 1/2 octet for ngKSI, 1/2 for Spare half octet
// 1/2 octet for ngKSI, 1/2 for Spare half octet
// TODO:do it in NAS Key Set Identifier
uint8_t octet = 0;
int decoded_size = 0;
DECODE_U8(buf + encoded_size, octet, decoded_size);
// clear spare half
octet = octet & 0x0f;
ENCODE_U8(buf + encoded_size, octet, encoded_size);
// encoded_size++; // 1/2 octet for ngKSI, 1/2 for Spare half octet
} else {
Logger::nas_mm().error(
"Encoding %s error", NasKeySetIdentifier::GetIeName().c_str());
......
......@@ -40,7 +40,7 @@ void SecurityModeComplete::SetHeader(uint8_t security_header_type) {
}
//------------------------------------------------------------------------------
void SecurityModeComplete::SetImeisv(const IMEISV_t& imeisv) {
void SecurityModeComplete::SetImeisv(const IMEI_IMEISV_t& imeisv) {
ie_imeisv =
std::make_optional<_5GSMobileIdentity>(kIei5gsMobileIdentityImeiSv);
// ie_imeisv->SetIei(kIei5gsMobileIdentityImeiSv);
......@@ -53,7 +53,7 @@ void SecurityModeComplete::SetNasMessageContainer(const bstring& value) {
}
//------------------------------------------------------------------------------
void SecurityModeComplete::SetNonImeisv(const IMEISV_t& imeisv) {
void SecurityModeComplete::SetNonImeisv(const IMEI_IMEISV_t& imeisv) {
ie_non_imeisvpei =
std::make_optional<_5GSMobileIdentity>(kIei5gsMobileIdentityNonImeiSvPei);
// ie_non_imeisvpei->SetIei(kIei5gsMobileIdentityNonImeiSvPei);
......@@ -61,7 +61,7 @@ void SecurityModeComplete::SetNonImeisv(const IMEISV_t& imeisv) {
}
//------------------------------------------------------------------------------
bool SecurityModeComplete::GetImeisv(IMEISV_t& imeisv) const {
bool SecurityModeComplete::GetImeisv(IMEI_IMEISV_t& imeisv) const {
if (ie_imeisv.has_value()) {
ie_imeisv.value().GetImeisv(imeisv);
return true;
......@@ -81,7 +81,7 @@ bool SecurityModeComplete::GetNasMessageContainer(bstring& nas) const {
}
//------------------------------------------------------------------------------
bool SecurityModeComplete::GetNonImeisv(IMEISV_t& imeisv) const {
bool SecurityModeComplete::GetNonImeisv(IMEI_IMEISV_t& imeisv) const {
if (ie_non_imeisvpei.has_value()) {
ie_non_imeisvpei.value().GetImeisv(imeisv);
return true;
......
......@@ -36,14 +36,14 @@ class SecurityModeComplete : public NasMmPlainHeader {
int Encode(uint8_t* buf, int len);
int Decode(uint8_t* buf, int len);
void SetImeisv(const IMEISV_t& imeisv);
bool GetImeisv(IMEISV_t& imeisv) const;
void SetImeisv(const IMEI_IMEISV_t& imeisv);
bool GetImeisv(IMEI_IMEISV_t& imeisv) const;
void SetNasMessageContainer(const bstring& value);
bool GetNasMessageContainer(bstring& nas) const;
void SetNonImeisv(const IMEISV_t& imeisv);
bool GetNonImeisv(IMEISV_t& imeisv) const;
void SetNonImeisv(const IMEI_IMEISV_t& imeisv);
bool GetNonImeisv(IMEI_IMEISV_t& imeisv) const;
public:
std::optional<_5GSMobileIdentity> ie_imeisv; // Optional
......
......@@ -28,13 +28,13 @@ MobilityRestrictionList::MobilityRestrictionList() {}
MobilityRestrictionList::~MobilityRestrictionList() {}
//------------------------------------------------------------------------------
void MobilityRestrictionList::setPLMN(const PlmnId& sPLMN) {
servingPLMN = sPLMN;
void MobilityRestrictionList::setPLMN(const PlmnId& plmn) {
servingPLMN = plmn;
}
//------------------------------------------------------------------------------
void MobilityRestrictionList::getPLMN(PlmnId& sPLMN) {
sPLMN = servingPLMN;
void MobilityRestrictionList::getPLMN(PlmnId& plmn) const {
plmn = servingPLMN;
}
//------------------------------------------------------------------------------
......
......@@ -32,8 +32,8 @@ class MobilityRestrictionList {
MobilityRestrictionList();
virtual ~MobilityRestrictionList();
void setPLMN(const PlmnId& sPlmn);
void getPLMN(PlmnId& sPlmn);
void setPLMN(const PlmnId& plmn);
void getPLMN(PlmnId& plmn) const;
bool encode(Ngap_MobilityRestrictionList_t* mobility_restriction_list);
bool decode(Ngap_MobilityRestrictionList_t* mobility_restriction_list);
......
......@@ -21,6 +21,8 @@
#include "PDUSessionResourceFailedToSetupItemSURes.hpp"
#include "conversions.hpp"
namespace ngap {
//------------------------------------------------------------------------------
......@@ -56,9 +58,10 @@ bool PDUSessionResourceFailedToSetupItemSURes::encode(
if (!pdu_session_id_.encode(
pdu_session_resource_failed_to_setup_item_su_res->pDUSessionID))
return false;
pdu_session_resource_failed_to_setup_item_su_res
->pDUSessionResourceSetupUnsuccessfulTransfer =
pdu_session_resource_setup_unsuccessful_transfer_;
conv::octet_string_copy(
pdu_session_resource_failed_to_setup_item_su_res
->pDUSessionResourceSetupUnsuccessfulTransfer,
pdu_session_resource_setup_unsuccessful_transfer_);
return true;
}
......@@ -70,10 +73,10 @@ bool PDUSessionResourceFailedToSetupItemSURes::decode(
if (!pdu_session_id_.decode(
pdu_session_resource_failed_to_setup_item_su_res->pDUSessionID))
return false;
pdu_session_resource_setup_unsuccessful_transfer_ =
conv::octet_string_copy(
pdu_session_resource_setup_unsuccessful_transfer_,
pdu_session_resource_failed_to_setup_item_su_res
->pDUSessionResourceSetupUnsuccessfulTransfer;
->pDUSessionResourceSetupUnsuccessfulTransfer);
return true;
}
......
......@@ -132,7 +132,7 @@ std::string S_NSSAI::getSd() const {
//------------------------------------------------------------------------------
bool S_NSSAI::encode(Ngap_S_NSSAI_t* s_NSSAI) {
conv::int8_2_octet_string(sst_, s_NSSAI->sST);
if (sd_.has_value()) {
if (sd_.has_value() && (sd_.value() != SD_NO_VALUE)) {
s_NSSAI->sD = (Ngap_SD_t*) calloc(1, sizeof(Ngap_SD_t));
if (!s_NSSAI->sD) return false;
if (!EncodeSD(s_NSSAI->sD)) {
......
......@@ -113,8 +113,7 @@ class HandoverRequest : public NgapMessage {
// Masked IMEISV (TODO: Optional)
Ngap_SourceToTarget_TransparentContainer_t
SourceToTarget_TransparentContainer; // TODO: Mandatory
std::optional<MobilityRestrictionList>
mobilityRestrictionList; // TODO: Optional
std::optional<MobilityRestrictionList> mobilityRestrictionList;
// Location Reporting Request Type (TODO: Optional)
// RRC Inactive Transition Report Request (TODO: Optional)
GUAMI guami; // Mandatory
......
......@@ -39,6 +39,7 @@ InitialContextSetupRequestMsg::InitialContextSetupRequestMsg()
coreNetworkAssistanceInfo = std::nullopt;
pduSessionResourceSetupRequestList = std::nullopt;
ueRadioCapability = std::nullopt;
maskedIMEISV = std::nullopt;
nasPdu = std::nullopt;
setMessageType(NgapMessageType::INITIAL_CONTEXT_SETUP_REQUEST);
......@@ -528,6 +529,35 @@ bool InitialContextSetupRequestMsg::getSecurityKey(uint8_t*& key) {
return true;
}
//------------------------------------------------------------------------------
void InitialContextSetupRequestMsg::setMobilityRestrictionList(
const PlmnId& plmn_id) {
MobilityRestrictionList tmp = {};
tmp.setPLMN(plmn_id);
mobilityRestrictionList = std::optional<MobilityRestrictionList>(tmp);
Ngap_InitialContextSetupRequestIEs_t* ie =
(Ngap_InitialContextSetupRequestIEs_t*) calloc(
1, sizeof(Ngap_InitialContextSetupRequestIEs_t));
ie->id = Ngap_ProtocolIE_ID_id_MobilityRestrictionList;
ie->criticality = Ngap_Criticality_ignore;
ie->value.present =
Ngap_InitialContextSetupRequestIEs__value_PR_MobilityRestrictionList;
int ret = mobilityRestrictionList.value().encode(
&ie->value.choice.MobilityRestrictionList);
if (!ret) {
Logger::ngap().error("Encode MobilityRestrictionList IE error!");
free_wrapper((void**) &ie);
return;
}
ret = ASN_SEQUENCE_ADD(&initialContextSetupRequestIEs->protocolIEs.list, ie);
if (ret != 0)
Logger::ngap().error("Encode MobilityRestrictionList IE error!");
}
//------------------------------------------------------------------------------
void InitialContextSetupRequestMsg::setNasPdu(const bstring& pdu) {
NAS_PDU tmp = {};
......@@ -567,7 +597,7 @@ void InitialContextSetupRequestMsg::setUERadioCapability(
Ngap_InitialContextSetupRequestIEs_t* ie =
(Ngap_InitialContextSetupRequestIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestIEs_t));
1, sizeof(Ngap_InitialContextSetupRequestIEs_t));
ie->id = Ngap_ProtocolIE_ID_id_UERadioCapability;
ie->criticality = Ngap_Criticality_ignore;
ie->value.present =
......@@ -592,6 +622,26 @@ void InitialContextSetupRequestMsg::getUERadioCapability(
ueRadioCapability.value().get(ue_radio_capability);
}
//------------------------------------------------------------------------------
void InitialContextSetupRequestMsg::setMaskedIMEISV(const std::string& imeisv) {
Ngap_InitialContextSetupRequestIEs_t* ie =
(Ngap_InitialContextSetupRequestIEs_t*) calloc(
1, sizeof(Ngap_InitialContextSetupRequestIEs_t));
ie->id = Ngap_ProtocolIE_ID_id_MaskedIMEISV;
ie->criticality = Ngap_Criticality_ignore;
ie->value.present = Ngap_InitialContextSetupRequestIEs__value_PR_MaskedIMEISV;
if (!conv::string_2_masked_imeisv(imeisv, ie->value.choice.MaskedIMEISV)) {
Logger::ngap().error("Encode MaskedIMEISV IE error!");
free_wrapper((void**) &ie);
return;
}
int ret =
ASN_SEQUENCE_ADD(&initialContextSetupRequestIEs->protocolIEs.list, ie);
if (ret != 0) Logger::ngap().error("Encode MaskedIMEISV IE error!");
}
//------------------------------------------------------------------------------
bool InitialContextSetupRequestMsg::decodeFromPdu(Ngap_NGAP_PDU_t* ngapMsgPdu) {
ngapPdu = ngapMsgPdu;
......
......@@ -32,6 +32,7 @@
#include "UERadioCapability.hpp"
#include "UESecurityCapabilities.hpp"
#include "NgapUEMessage.hpp"
#include "MobilityRestrictionList.hpp"
#include <optional>
......@@ -100,9 +101,15 @@ class InitialContextSetupRequestMsg : public NgapUEMessage {
void setSecurityKey(uint8_t* key); // 256bits
bool getSecurityKey(uint8_t*& key); // 256bits
void setMobilityRestrictionList(const PlmnId& plmn_id);
// TODO: getMobilityRestrictionList
void setUERadioCapability(const bstring& ue_radio_capability);
void getUERadioCapability(bstring& ue_radio_capability);
void setMaskedIMEISV(const std::string& imeisv);
// bool getMaskedIMEISV();
void setNasPdu(const bstring& pdu);
bool getNasPdu(bstring& pdu);
......@@ -120,11 +127,11 @@ class InitialContextSetupRequestMsg : public NgapUEMessage {
UESecurityCapabilities uESecurityCapabilities; // Mandatory
SecurityKey securityKey; // Mandatory
// TODO: Trace Activation (Optional)
// TODO: Mobility Restriction List
std::optional<MobilityRestrictionList> mobilityRestrictionList;
std::optional<UERadioCapability> ueRadioCapability; // Optional
// TODO: Index to RAT/Frequency Selection Priority
// TODO: Masked IMEISV
std::optional<NAS_PDU> nasPdu; // Optional
std::optional<Ngap_MaskedIMEISV_t> maskedIMEISV; // Optional
std::optional<NAS_PDU> nasPdu; // Optional
// TODO: Emergency Fallback Indicator
// TODO: RRC Inactive Transition Report Request
// TODO: UE Radio Capability for Paging
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment