-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNASHelperNGAP_RegistrationRequest.cpp
More file actions
150 lines (134 loc) · 4.78 KB
/
NASHelperNGAP_RegistrationRequest.cpp
File metadata and controls
150 lines (134 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "NASHelperNGAP.hpp"
namespace {
bool registrationRequestOptionalIsTlvE(std::uint8_t iei) {
switch (iei) {
case 0x77:
case 0x70:
case 0x74:
case 0x7B:
case 0x71:
case 0x72:
return true;
default:
return false;
}
}
bool registrationRequestOptionalIsTlv(std::uint8_t iei) {
switch (iei) {
case 0x10:
case 0x2E:
case 0x2F:
case 0x52:
case 0x17:
case 0x40:
case 0x50:
case 0x2B:
case 0x25:
case 0x18:
case 0x51:
case 0x53:
case 0x41:
case 0x42:
case 0x60:
case 0x6E:
case 0x6A:
case 0x67:
case 0x35:
case 0x48:
case 0x1A:
case 0x30:
case 0x29:
case 0x28:
case 0x32:
case 0x16:
case 0x2A:
case 0x3B:
case 0x3C:
case 0x3F:
case 0x56:
case 0x64:
return true;
default:
return false;
}
}
bool registrationRequestOptionalTv1HighNibble(std::uint8_t firstOctet) {
const unsigned h = firstOctet >> 4U;
return h >= 8U && h <= 12U;
}
} // namespace
bool NASHelperNGAP::tryParseRegistrationRequestInformationElements(
const std::uint8_t* const informationElements,
const std::size_t informationElementOctetCount,
RegistrationRequestInformationElementsParse& out) {
out = RegistrationRequestInformationElementsParse{};
if (informationElements == nullptr || informationElementOctetCount < 1U + 2U) {
return false;
}
const std::uint8_t regNgKsi = informationElements[0];
const std::uint16_t mobileIdentityValueLength =
static_cast<std::uint16_t>((static_cast<unsigned>(informationElements[1]) << 8U) |
static_cast<unsigned>(informationElements[2]));
const std::size_t mandatoryTotal = 1U + 2U + static_cast<std::size_t>(mobileIdentityValueLength);
if (mandatoryTotal < 3U || informationElementOctetCount < mandatoryTotal) {
return false;
}
out.mandatory.registration_type_and_ngksi_octet = regNgKsi;
out.mandatory.five_gs_mobile_identity_value = informationElements + 3U;
out.mandatory.five_gs_mobile_identity_value_octet_count = mobileIdentityValueLength;
out.mandatory.mandatory_total_octets = mandatoryTotal;
std::size_t i = mandatoryTotal;
while (i < informationElementOctetCount) {
const std::uint8_t b = informationElements[i];
if (registrationRequestOptionalIsTlvE(b)) {
if (i + 3U > informationElementOctetCount) {
break;
}
const std::uint16_t len =
static_cast<std::uint16_t>((static_cast<unsigned>(informationElements[i + 1]) << 8U) |
static_cast<unsigned>(informationElements[i + 2]));
const std::size_t chunk = 3U + static_cast<std::size_t>(len);
if (i + chunk > informationElementOctetCount || i + chunk < i) {
break;
}
RegistrationRequestOptionalInformationElement opt{};
opt.iei = b;
opt.encoding = RegistrationRequestOptionalInformationElement::Encoding::TlvE;
opt.value.assign(informationElements + i + 3, informationElements + i + 3 + len);
out.optionals.push_back(std::move(opt));
i += chunk;
continue;
}
if (registrationRequestOptionalIsTlv(b)) {
if (i + 2U > informationElementOctetCount) {
break;
}
const std::uint8_t len = informationElements[i + 1];
const std::size_t chunk = 2U + static_cast<std::size_t>(len);
if (i + chunk > informationElementOctetCount || i + chunk < i) {
break;
}
RegistrationRequestOptionalInformationElement opt{};
opt.iei = b;
opt.encoding = RegistrationRequestOptionalInformationElement::Encoding::Tlv;
opt.value.assign(informationElements + i + 2, informationElements + i + 2 + len);
out.optionals.push_back(std::move(opt));
i += chunk;
continue;
}
if (registrationRequestOptionalTv1HighNibble(b)) {
RegistrationRequestOptionalInformationElement opt{};
opt.iei = static_cast<std::uint8_t>(b >> 4U);
opt.encoding = RegistrationRequestOptionalInformationElement::Encoding::Tv1;
opt.tv1_octet = b;
out.optionals.push_back(std::move(opt));
i += 1U;
continue;
}
out.unparsed_begin = informationElements + i;
out.unparsed_octet_count = informationElementOctetCount - i;
break;
}
out.ok = true;
return true;
}