mirror of
https://github.com/open5gs/open5gs.git
synced 2025-10-23 07:41:57 +00:00
[5G-NAS] Improve QoS Rules parsing
The older version of the code was wrong (or at least not exactly correct) in many (corner) cases. * Split the parsing of Packet Filter List into its own helper function to simplify the code * Improve error logging to provide more info on which QoS rule failed. * Add some extra logic checking match between 'Length of QoS rule' and existance of m+1 and m+2 bytes. * Correct logic checking expected/unexpected presence of m+1 and m+2 octets based on Rule Operation Code according to specs.
This commit is contained in:
committed by
Sukchan Lee
parent
1bdbaa4ef2
commit
b11350f969
@@ -805,14 +805,214 @@ int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules,
|
|||||||
return OGS_OK;
|
return OGS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse "Packet filter list", 3GPP TS 24.501 Figure 9.11.4.13.3 and Figure 9.11.4.13. */
|
||||||
|
static int parse_qos_rules_packet_filter_list(ogs_nas_qos_rule_t *rule, const uint8_t *buffer, uint16_t length) {
|
||||||
|
uint16_t size = 0;
|
||||||
|
int i, j, len = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < rule->num_of_packet_filter && i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) {
|
||||||
|
if (size+sizeof(rule->pf[i].flags) > length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] length[%d]", i, size, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].flags, buffer+size, sizeof(rule->pf[i].flags));
|
||||||
|
size += sizeof(rule->pf[i].flags);
|
||||||
|
|
||||||
|
if (rule->code ==
|
||||||
|
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (size+sizeof(rule->pf[i].content.length) > length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] length[%d]", i, size, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.length, buffer+size,
|
||||||
|
sizeof(rule->pf[i].content.length));
|
||||||
|
size += sizeof(rule->pf[i].content.length);
|
||||||
|
|
||||||
|
j = 0; len = 0;
|
||||||
|
while(len < rule->pf[i].content.length) {
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].type) > length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].type,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].type));
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].type);
|
||||||
|
switch(rule->pf[i].content.component[j].type) {
|
||||||
|
case OGS_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].proto) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].proto,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].proto));
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].proto);
|
||||||
|
break;
|
||||||
|
case OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
|
||||||
|
case OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].ipv4.addr) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].ipv4.addr,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].ipv4.addr));
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].ipv4.addr);
|
||||||
|
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].ipv4.mask) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].ipv4.mask,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].ipv4.mask));
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].ipv4.mask);
|
||||||
|
break;
|
||||||
|
case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
|
||||||
|
case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].ipv6.addr) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].ipv6.addr,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].ipv6.addr));
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].ipv6.addr);
|
||||||
|
|
||||||
|
if (size+len+
|
||||||
|
sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6.prefixlen) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].ipv6.prefixlen,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6.prefixlen));
|
||||||
|
len += sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6.prefixlen);
|
||||||
|
break;
|
||||||
|
case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE:
|
||||||
|
case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
|
||||||
|
if (size+len+
|
||||||
|
sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6_mask.addr) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].ipv6_mask.addr,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6_mask.addr));
|
||||||
|
len += sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6_mask.addr);
|
||||||
|
|
||||||
|
if (size+len+
|
||||||
|
sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6_mask.mask) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].ipv6_mask.mask,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6_mask.mask));
|
||||||
|
len += sizeof(
|
||||||
|
rule->pf[i].content.component[j].ipv6_mask.mask);
|
||||||
|
break;
|
||||||
|
case OGS_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
|
||||||
|
case OGS_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].port.low) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].port.low,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].port.low));
|
||||||
|
rule->pf[i].content.component[j].port.low =
|
||||||
|
be16toh(rule->pf[i].content.component[j].port.low);
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].port.low);
|
||||||
|
break;
|
||||||
|
case OGS_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
|
||||||
|
case OGS_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].port.low) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].port.low,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].port.low));
|
||||||
|
rule->pf[i].content.component[j].port.low =
|
||||||
|
be16toh(rule->pf[i].content.component[j].port.low);
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].port.low);
|
||||||
|
|
||||||
|
if (size+len+
|
||||||
|
sizeof(rule->pf[i].content.component[j].port.high) >
|
||||||
|
length) {
|
||||||
|
ogs_error("PF[%d] Overflow: size[%d] len[%d] length[%d]",
|
||||||
|
i, size, len, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->pf[i].content.component[j].port.high,
|
||||||
|
buffer+size+len,
|
||||||
|
sizeof(rule->pf[i].content.component[j].port.high));
|
||||||
|
rule->pf[i].content.component[j].port.high =
|
||||||
|
be16toh(rule->pf[i].content.component[j].port.high);
|
||||||
|
len += sizeof(rule->pf[i].content.component[j].port.high);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ogs_error("PF[%d] Unknown Packet Filter Type(%d)",
|
||||||
|
i, rule->pf[i].content.component[j].type);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
rule->pf[i].content.num_of_component = j;
|
||||||
|
size += len;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
cleanup:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse "QoS rules", 3GPP TS 24.501 Figure 9.11.4.13.1. */
|
||||||
int ogs_nas_parse_qos_rules(
|
int ogs_nas_parse_qos_rules(
|
||||||
ogs_nas_qos_rule_t *rule, ogs_nas_qos_rules_t *rules)
|
ogs_nas_qos_rule_t *rule, ogs_nas_qos_rules_t *rules)
|
||||||
{
|
{
|
||||||
ogs_nas_qos_rule_t *first = rule;
|
ogs_nas_qos_rule_t *first = rule;
|
||||||
|
|
||||||
char *buffer;
|
uint8_t *buffer;
|
||||||
uint16_t length, size = 0;
|
uint16_t length, size;
|
||||||
int i, j, len = 0;
|
int rc;
|
||||||
|
|
||||||
ogs_assert(rule);
|
ogs_assert(rule);
|
||||||
ogs_assert(rules);
|
ogs_assert(rules);
|
||||||
@@ -828,9 +1028,10 @@ int ogs_nas_parse_qos_rules(
|
|||||||
|
|
||||||
length = rules->length;
|
length = rules->length;
|
||||||
buffer = rules->buffer;
|
buffer = rules->buffer;
|
||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
while (size < length) {
|
while (size < length) {
|
||||||
|
bool have_octet_m1, have_octet_m2;
|
||||||
memset(rule, 0, sizeof(*rule));
|
memset(rule, 0, sizeof(*rule));
|
||||||
|
|
||||||
if (size+sizeof(rule->identifier) > length) {
|
if (size+sizeof(rule->identifier) > length) {
|
||||||
@@ -841,244 +1042,106 @@ int ogs_nas_parse_qos_rules(
|
|||||||
size += sizeof(rule->identifier);
|
size += sizeof(rule->identifier);
|
||||||
|
|
||||||
if (size+sizeof(rule->length) > length) {
|
if (size+sizeof(rule->length) > length) {
|
||||||
ogs_error("Overflow : size[%d] length[%d]", size, length);
|
ogs_error("RuleId[%u] Overflow: size[%d] length[%d]", rule->identifier, size, length);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
memcpy(&rule->length, buffer+size, sizeof(rule->length));
|
memcpy(&rule->length, buffer+size, sizeof(rule->length));
|
||||||
rule->length = be16toh(rule->length);
|
rule->length = be16toh(rule->length);
|
||||||
size += sizeof(rule->length);
|
size += sizeof(rule->length);
|
||||||
|
|
||||||
|
if (rule->length == 0) {
|
||||||
|
ogs_error("RuleId[%u] Wrong 'Length of QoS rule' (0)", rule->identifier);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (size+sizeof(rule->flags) > length) {
|
if (size+sizeof(rule->flags) > length) {
|
||||||
ogs_error("Overflow : size[%d] length[%d]", size, length);
|
ogs_error("RuleId[%u] Overflow: size[%d] length[%d]", rule->identifier, size, length);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
memcpy(&rule->flags, buffer+size, sizeof(rule->flags));
|
memcpy(&rule->flags, buffer+size, sizeof(rule->flags));
|
||||||
size += sizeof(rule->flags);
|
size += sizeof(rule->flags);
|
||||||
|
|
||||||
if (rule->code == 0 || rule->code == 7) { /* Reserved */
|
if (rule->code == 0 || rule->code == 7) { /* Reserved */
|
||||||
ogs_error("Reserved Rule Code [%d]", rule->code);
|
ogs_error("RuleId[%u] Reserved Rule Code [%d]", rule->identifier, rule->code);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rule->code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE ||
|
if (rule->code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE ||
|
||||||
rule->code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) {
|
rule->code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) {
|
||||||
if (rule->num_of_packet_filter != 0) {
|
if (rule->num_of_packet_filter != 0) {
|
||||||
ogs_error("Invalue QoS rule code[%d] "
|
ogs_error("RuleId[%u] Invalid QoS rule code[%d] and number of packet filter[%d]",
|
||||||
"and number of packet filter[%d]",
|
rule->identifier, rule->code, rule->num_of_packet_filter);
|
||||||
rule->code, rule->num_of_packet_filter);
|
|
||||||
rule->num_of_packet_filter = 0;
|
rule->num_of_packet_filter = 0;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < rule->num_of_packet_filter &&
|
rc = parse_qos_rules_packet_filter_list(rule, buffer + size, rule->length - 1);
|
||||||
i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) {
|
if (rc < 0)
|
||||||
if (size+sizeof(rule->pf[i].flags) > length) {
|
goto cleanup;
|
||||||
ogs_error("Overflow : size[%d] length[%d]", size, length);
|
size += rc;
|
||||||
|
|
||||||
|
if (rule->length == (sizeof(rule->flags) + rc)) {
|
||||||
|
have_octet_m1 = false;
|
||||||
|
have_octet_m2 = false;
|
||||||
|
} else if (rule->length == (sizeof(rule->flags) + rc + sizeof(rule->precedence))) {
|
||||||
|
have_octet_m1 = true;
|
||||||
|
have_octet_m2 = false;
|
||||||
|
} else if (rule->length == (sizeof(rule->flags) + rc + sizeof(rule->precedence) + sizeof(rule->flow.flags))) {
|
||||||
|
have_octet_m1 = true;
|
||||||
|
have_octet_m2 = true;
|
||||||
|
} else {
|
||||||
|
ogs_error("RuleId[%u] 'Length of QoS rule' (%d) doesn't match parsed length (%zu..%zu)",
|
||||||
|
rule->identifier, rule->length,
|
||||||
|
sizeof(rule->flags) + rc,
|
||||||
|
sizeof(rule->flags) + rc + sizeof(rule->precedence) + sizeof(rule->flow.flags));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].flags, buffer+size, sizeof(rule->pf[i].flags));
|
|
||||||
size += sizeof(rule->pf[i].flags);
|
|
||||||
|
|
||||||
if (rule->code ==
|
|
||||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (size+sizeof(rule->pf[i].content.length) > length) {
|
|
||||||
ogs_error("Overflow : size[%d] length[%d]", size, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.length, buffer+size,
|
|
||||||
sizeof(rule->pf[i].content.length));
|
|
||||||
size += sizeof(rule->pf[i].content.length);
|
|
||||||
|
|
||||||
j = 0; len = 0;
|
|
||||||
while(len < rule->pf[i].content.length) {
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].type) > length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].type,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].type));
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].type);
|
|
||||||
switch(rule->pf[i].content.component[j].type) {
|
|
||||||
case OGS_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].proto) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].proto,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].proto));
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].proto);
|
|
||||||
break;
|
|
||||||
case OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
|
|
||||||
case OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].ipv4.addr) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].ipv4.addr,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].ipv4.addr));
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].ipv4.addr);
|
|
||||||
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].ipv4.mask) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].ipv4.mask,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].ipv4.mask));
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].ipv4.mask);
|
|
||||||
break;
|
|
||||||
case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
|
|
||||||
case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].ipv6.addr) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].ipv6.addr,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].ipv6.addr));
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].ipv6.addr);
|
|
||||||
|
|
||||||
if (size+len+
|
|
||||||
sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6.prefixlen) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].ipv6.prefixlen,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6.prefixlen));
|
|
||||||
len += sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6.prefixlen);
|
|
||||||
break;
|
|
||||||
case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE:
|
|
||||||
case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
|
|
||||||
if (size+len+
|
|
||||||
sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6_mask.addr) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].ipv6_mask.addr,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6_mask.addr));
|
|
||||||
len += sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6_mask.addr);
|
|
||||||
|
|
||||||
if (size+len+
|
|
||||||
sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6_mask.mask) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].ipv6_mask.mask,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6_mask.mask));
|
|
||||||
len += sizeof(
|
|
||||||
rule->pf[i].content.component[j].ipv6_mask.mask);
|
|
||||||
break;
|
|
||||||
case OGS_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
|
|
||||||
case OGS_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].port.low) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].port.low,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].port.low));
|
|
||||||
rule->pf[i].content.component[j].port.low =
|
|
||||||
be16toh(rule->pf[i].content.component[j].port.low);
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].port.low);
|
|
||||||
break;
|
|
||||||
case OGS_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
|
|
||||||
case OGS_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].port.low) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].port.low,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].port.low));
|
|
||||||
rule->pf[i].content.component[j].port.low =
|
|
||||||
be16toh(rule->pf[i].content.component[j].port.low);
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].port.low);
|
|
||||||
|
|
||||||
if (size+len+
|
|
||||||
sizeof(rule->pf[i].content.component[j].port.high) >
|
|
||||||
length) {
|
|
||||||
ogs_error("Overflow : size[%d] len[%d] length[%d]",
|
|
||||||
size, len, length);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(&rule->pf[i].content.component[j].port.high,
|
|
||||||
buffer+size+len,
|
|
||||||
sizeof(rule->pf[i].content.component[j].port.high));
|
|
||||||
rule->pf[i].content.component[j].port.high =
|
|
||||||
be16toh(rule->pf[i].content.component[j].port.high);
|
|
||||||
len += sizeof(rule->pf[i].content.component[j].port.high);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ogs_error("Unknown Packet Filter Type(%d)",
|
|
||||||
rule->pf[i].content.component[j].type);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
rule->pf[i].content.num_of_component = j;
|
|
||||||
size += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rule->code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE &&
|
if (have_octet_m1) {
|
||||||
rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS &&
|
if ((size + sizeof(rule->precedence)) > length) {
|
||||||
rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) {
|
ogs_error("RuleId[%u] Overflow m+1: size[%d] length[%d]", rule->identifier, size, length);
|
||||||
|
|
||||||
if (size+sizeof(rule->precedence) > length) {
|
|
||||||
ogs_error("Overflow : size[%d] length[%d]", size, length);
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
memcpy(&rule->precedence, buffer+size, sizeof(rule->precedence));
|
memcpy(&rule->precedence, buffer+size, sizeof(rule->precedence));
|
||||||
size += sizeof(rule->precedence);
|
size += sizeof(rule->precedence);
|
||||||
|
/* 'For the "delete existing QoS rule" operation, the QoS rule precedence value field shall not
|
||||||
if (size+sizeof(rule->flow.flags) > length) {
|
* be included.'
|
||||||
ogs_error("Overflow : size[%d] length[%d]", size, length);
|
* This implicitly means also m+2 shall neither be present, following Table 9.11.4.13. "NOTE 1". */
|
||||||
|
if (rule->code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE) {
|
||||||
|
ogs_error("RuleId[%u] Invalid QoS rule code[%d] and presence of Precedence octet [%u]",
|
||||||
|
rule->identifier, rule->code, rule->precedence);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
memcpy(&rule->flow.flags, buffer+size, sizeof(rule->flow.flags));
|
|
||||||
size += sizeof(rule->flow.flags);
|
if (have_octet_m2) {
|
||||||
|
if ((size + sizeof(rule->flow.flags)) > length) {
|
||||||
|
ogs_error("RuleId[%u] Overflow m+2: size[%d] length[%d]", rule->identifier, size, length);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(&rule->flow.flags, buffer+size, sizeof(rule->flow.flags));
|
||||||
|
size += sizeof(rule->flow.flags);
|
||||||
|
/* 'For the "delete existing QoS rule" operation, the QoS rule precedence value field shall not
|
||||||
|
* be included.'
|
||||||
|
* This implicitly means also m+2 shall neither be present, following Table 9.11.4.13. "NOTE 1". */
|
||||||
|
if (rule->code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE) {
|
||||||
|
ogs_error("RuleId[%u] Invalid QoS rule code[%d] and presence of QFI octet [%u]",
|
||||||
|
rule->identifier, rule->code, rule->flow.flags);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else if (rule->code == OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE) {
|
||||||
|
/* 'For the "create new QoS rule" operation, the QoS flow identifier value field shall
|
||||||
|
* be included.' */
|
||||||
|
ogs_error("RuleId[%u] Invalid QoS rule code[%d] without QFI octet",
|
||||||
|
rule->identifier, rule->code);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else if (rule->code == OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE) {
|
||||||
|
/* 'For the "create new QoS rule" operation, the QoS rule precedence value field shall
|
||||||
|
* be included.' */
|
||||||
|
ogs_error("RuleId[%u] Invalid QoS rule code[%d] without Precedence octet",
|
||||||
|
rule->identifier, rule->code);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
rule++;
|
rule++;
|
||||||
|
Reference in New Issue
Block a user