Commit dc95e838 authored by Sakthivel Velumani's avatar Sakthivel Velumani

Improve NSSAI parsing

use review suggestions from Laurent
parent 19551d12
...@@ -916,48 +916,47 @@ static void send_nas_uplink_data_req(instance_t instance, const as_nas_info_t *i ...@@ -916,48 +916,47 @@ static void send_nas_uplink_data_req(instance_t instance, const as_nas_info_t *i
static void parse_allowed_nssai(nr_nas_msg_snssai_t nssaiList[8], const uint8_t *buf, const uint32_t len) static void parse_allowed_nssai(nr_nas_msg_snssai_t nssaiList[8], const uint8_t *buf, const uint32_t len)
{ {
int offset = 0;
int nssai_cnt = 0; int nssai_cnt = 0;
while (offset < len) { const uint8_t *end = buf + len;
int length = *(buf + offset); while (buf < end) {
const int length = *buf++;
nr_nas_msg_snssai_t *nssai = nssaiList + nssai_cnt; nr_nas_msg_snssai_t *nssai = nssaiList + nssai_cnt;
nssai->sd = 0xFFFFFF; nssai->sd = 0xffffff;
switch (length) { switch (length) {
case 1: case 1:
nssai->sst = *(buf + offset + 1); nssai->sst = *buf++;
offset += 2;
nssai_cnt++; nssai_cnt++;
break; break;
case 2: case 2:
nssai->sst = *(buf + offset + 1); nssai->sst = *buf++;
nssai->hplmn_sst = *(buf + offset + 2); nssai->hplmn_sst = *buf++;
offset += 3;
nssai_cnt++; nssai_cnt++;
break; break;
case 4: case 4:
nssai->sst = *(buf + offset + 1); nssai->sst = *buf++;
nssai->sd = 0xFFFFFF & (*(buf + offset + 4) | (*(buf + offset + 3) << 8) | (*(buf + offset + 2) << 16)); nssai->sd = 0xffffff & (buf[2] | buf[1] << 8 | buf[0] << 16);
offset += 5; buf += 3;
nssai_cnt++; nssai_cnt++;
break; break;
case 5: case 5:
nssai->sst = *(buf + offset + 1); nssai->sst = *buf++;
nssai->sd = 0xFFFFFF & (*(buf + offset + 4) | (*(buf + offset + 3) << 8) | (*(buf + offset + 2) << 16)); nssai->sd = 0xffffff & (buf[2] | buf[1] << 8 | buf[0] << 16);
nssai->hplmn_sst = *(buf + offset + 5); buf += 3;
offset += 6; nssai->hplmn_sst = *buf++;
nssai_cnt++; nssai_cnt++;
break; break;
case 8: case 8:
nssai->sst = *(buf + offset + 1); nssai->sst = *buf++;
nssai->sd = 0xFFFFFF & (*(buf + offset + 4) | (*(buf + offset + 3) << 8) | (*(buf + offset + 2) << 16)); nssai->sd = 0xffffff & (buf[2] | buf[1] << 8 | buf[0] << 16);
nssai->hplmn_sst = *(buf + offset + 5); buf += 3;
nssai->hplmn_sd = 0xFFFFFF & (*(buf + offset + 8) | (*(buf + offset + 7) << 8) | (*(buf + offset + 6) << 16)); nssai->hplmn_sst = *buf++;
offset += 9; nssai->hplmn_sd = 0xffffff & (buf[2] | buf[1] << 8 | buf[0] << 16);
buf += 3;
nssai_cnt++; nssai_cnt++;
break; break;
...@@ -968,6 +967,14 @@ static void parse_allowed_nssai(nr_nas_msg_snssai_t nssaiList[8], const uint8_t ...@@ -968,6 +967,14 @@ static void parse_allowed_nssai(nr_nas_msg_snssai_t nssaiList[8], const uint8_t
} }
} }
static inline uint16_t ntohs_unaligned(const uint8_t *v)
{
// sanitize may complain on unaligned access, even if it works on Intel/AMD
uint16_t tmp;
memcpy(&tmp, v, sizeof(tmp));
return ntohs(tmp);
}
/* Extract Allowed NSSAI from Regestration Accept according to /* Extract Allowed NSSAI from Regestration Accept according to
3GPP TS 24.501 Table 8.2.7.1.1 3GPP TS 24.501 Table 8.2.7.1.1
*/ */
...@@ -976,38 +983,33 @@ static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_b ...@@ -976,38 +983,33 @@ static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_b
if ((pdu_buffer == NULL) || (pdu_length <= 0)) if ((pdu_buffer == NULL) || (pdu_length <= 0))
return; return;
int offset = 1 + 1 + 1 + 2; // Mandatory fields offset const uint8_t *end = pdu_buffer + pdu_length;
pdu_buffer += 1 + 1 + 1 + 2; // Mandatory fields offset
if (((nas_msg_header_t *)(pdu_buffer))->choice.security_protected_nas_msg_header_t.security_header_type > 0) { if (((nas_msg_header_t *)(pdu_buffer))->choice.security_protected_nas_msg_header_t.security_header_type > 0) {
offset += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH; pdu_buffer += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH;
} }
bool unknown_IEI_found = false;
/* optional fields */ /* optional fields */
int length = 0; while (pdu_buffer < end) {
while ((offset < pdu_length) && !unknown_IEI_found) { const int type = *pdu_buffer++;
int type = *(pdu_buffer + offset);
switch (type) { switch (type) {
case 0x77: // 5GS mobile identity case 0x77: // 5GS mobile identity
length = (*(pdu_buffer + offset + 1) << 8) | *(pdu_buffer + offset + 2); pdu_buffer += ntohs_unaligned(pdu_buffer) + sizeof(uint16_t);
offset += (length + 1 + 2); // 1: type, 2: length
break; break;
case 0x4A: // PLMN list case 0x4A: // PLMN list
case 0x54: // 5GS tracking area identity case 0x54: // 5GS tracking area identity
length = *((uint8_t *)(pdu_buffer + offset + 1)); pdu_buffer += *pdu_buffer + 1; // offset length + 1 byte which contains the length
offset += (length + 1 + 1); // 1: type, 2: length
break; break;
case 0x15: // allowed NSSAI case 0x15: // allowed NSSAI
length = *((uint8_t *)(pdu_buffer + offset + 1)); const int length = *pdu_buffer++;
parse_allowed_nssai(nssai, pdu_buffer + offset + 2, length); parse_allowed_nssai(nssai, pdu_buffer, length);
offset += (length + 1 + 1); // 1: type, 2: length
break; break;
default: default:
LOG_E(NAS, "This NAS IEI is not handled when extracting list of allowed NSSAI\n"); LOG_W(NAS, "This NAS IEI is not handled when extracting list of allowed NSSAI\n");
unknown_IEI_found = true; pdu_buffer = end;
break; break;
} }
} }
......
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