Commit 2d067869 authored by Tien Thinh NGUYEN's avatar Tien Thinh NGUYEN

Support IMEISV

parent 15ba283c
......@@ -852,7 +852,10 @@ void amf_n1::service_request_handle(
nc->imsi = old_nc->imsi;
if (old_nc->imeisv.has_value()) {
nc->imeisv =
std::make_optional<nas::IMEISV_t>(old_nc->imeisv.value());
std::make_optional<nas::IMEI_IMEISV_t>(old_nc->imeisv.value());
Logger::nas_mm().debug(
"Stored IMEISV in the new NAS Context: %s",
nc->imeisv.value().identity.c_str());
}
nc->requested_nssai = old_nc->requested_nssai;
nc->allowed_nssai = old_nc->allowed_nssai;
......@@ -1199,7 +1202,10 @@ void amf_n1::service_request_handle(
amf_ue_ngap_id_old_nas_connection = old_nc->amf_ue_ngap_id;
if (old_nc->imeisv.has_value()) {
nc->imeisv =
std::make_optional<nas::IMEISV_t>(old_nc->imeisv.value());
std::make_optional<nas::IMEI_IMEISV_t>(old_nc->imeisv.value());
Logger::nas_mm().debug(
"Stored IMEISV in the new NAS Context: %s",
nc->imeisv.value().identity.c_str());
}
nc->requested_nssai = old_nc->requested_nssai;
nc->allowed_nssai = old_nc->allowed_nssai;
......@@ -2938,9 +2944,11 @@ void amf_n1::security_mode_complete_handle(
(uint8_t*) bdata(nas_msg), blength(nas_msg));
// Store UE Id (IMEISV) if available
nas::IMEISV_t imeisv = {};
if (security_mode_complete->GetNonImeisv(imeisv)) {
nc->imeisv = std::make_optional<nas::IMEISV_t>(imeisv);
nas::IMEI_IMEISV_t imeisv = {};
if (security_mode_complete->GetImeisv(imeisv)) {
Logger::nas_mm().debug(
"Stored IMEISV in the NAS Context: %s", imeisv.identity.c_str());
nc->imeisv = std::make_optional<nas::IMEI_IMEISV_t>(imeisv);
}
// Process NAS Container
......
......@@ -889,7 +889,12 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request& itti_msg) {
// 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");
}
}
......
......@@ -524,3 +524,38 @@ 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& str, BIT_STRING_t& imeisv) {
if (str.length() != 16) return false; // Must contain 16 digits
imeisv.buf = (uint8_t*) calloc(8, sizeof(uint8_t));
if (!imeisv.buf) {
return false;
}
bstring b_str = {};
std::string imeisv_masked = {};
// TODO: last 4 digits of the SNR masked by setting the corresponding bits to
// 1
imeisv_masked = str.substr(0, 10) + "1111" + str.substr(14, 2);
uint8_t digit_low = 0;
uint8_t digit_high = 0;
int i = 0;
int len = imeisv_masked.length();
int j = 0;
while (i < len) {
string_to_int8(imeisv_masked.substr(i, 1), digit_low);
string_to_int8(imeisv_masked.substr(i + 1, 1), digit_high);
i = i + 2;
uint8_t octet = (0xf0 & (digit_high << 4)) | (digit_low & 0x0f);
imeisv.buf[j] = octet;
j++;
}
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 */
......@@ -81,7 +81,7 @@ class nas_context {
uint8_t ngksi; // 4 bits
std::string imsi; // TODO: use SUPI instead
std::optional<nas::IMEISV_t> imeisv;
std::optional<nas::IMEI_IMEISV_t> imeisv;
std::uint8_t _5gmm_capability[13];
nas::UESecurityCapability ue_security_capability;
......
......@@ -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);
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_;
};
......
......@@ -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
......@@ -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
......
......@@ -597,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 =
......@@ -623,10 +623,23 @@ void InitialContextSetupRequestMsg::getUERadioCapability(
}
//------------------------------------------------------------------------------
void InitialContextSetupRequestMsg::setMaskedIMEISV(const bstring& imeisv) {
Ngap_MaskedIMEISV_t tmp = {};
conv::bstring_2_bit_string(imeisv, tmp);
maskedIMEISV = std::make_optional<Ngap_MaskedIMEISV_t>(tmp);
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!");
}
//------------------------------------------------------------------------------
......
......@@ -107,7 +107,7 @@ class InitialContextSetupRequestMsg : public NgapUEMessage {
void setUERadioCapability(const bstring& ue_radio_capability);
void getUERadioCapability(bstring& ue_radio_capability);
void setMaskedIMEISV(const bstring& imeisv);
void setMaskedIMEISV(const std::string& imeisv);
// bool getMaskedIMEISV();
void setNasPdu(const bstring& pdu);
......
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