Bugfix packet filter for pre rel11 LTE devices (#1393)

* Fix conversion from IPFilterRule to packet filter

As per 3GPP TS 24.008, following Packet filter component type identifier
are not supported on the LTE pre release-11 UEs:

IPv4 local address type
IPv6 remote address/prefix length type
IPv6 local address/prefix length type

And,
IPv6 remote address/prefix length type and
IPv6 local address/prefix length type shall be used when both MS and
Network support Local Address in TFTs.

This commit add logic to omit adding local address in packet filters
for compatibility with pre-release LTE 11 devices. The following parameter
could be used to toggle omit/no to omit behavior.

parameter:
	no_ipv4v6_local_addr_in_packet_filter: <true/false>

* Remove logic of supporting pre-release LTE 11 devices in PCRF
This commit is contained in:
Supreeth Herle 2022-02-25 14:11:51 +01:00 committed by GitHub
parent 3b6da3ddb2
commit 52bc4be547
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 154 deletions

View File

@ -40,11 +40,6 @@ pcrf:
# o Prefer IPv4 instead of IPv6 for estabishing new GTP connections.
# prefer_ipv4: true
#
# o Legacy support for pre-release LTE 11 devices to do calling
# - Replace IPv4/v6 local addr field in AAR Media-Subcomponent AVP
# by 'any local port'
# no_ipv4v6_local_addr_in_packet_filter: true
#
parameter:
#

View File

@ -458,6 +458,10 @@ upf:
# o Disable selection of UPF PFCP in Round-Robin manner
# no_pfcp_rr_select: true
#
# o Legacy support for pre-release LTE 11 devices
# - Omits adding local address in packet filters for compatibility
# no_ipv4v6_local_addr_in_packet_filter: true
#
parameter:
#

View File

@ -365,7 +365,8 @@ void ogs_ipfw_rule_swap(ogs_ipfw_rule_t *ipfw_rule)
}
void ogs_pf_content_from_ipfw_rule(
uint8_t direction, ogs_pf_content_t *content, ogs_ipfw_rule_t *rule)
uint8_t direction, ogs_pf_content_t *content, ogs_ipfw_rule_t *rule,
bool no_ipv4v6_local_addr_in_packet_filter)
{
int j, len;
@ -380,57 +381,112 @@ void ogs_pf_content_from_ipfw_rule(
j++; len += 2;
}
if (rule->ipv4_src) {
if (direction == OGS_FLOW_DOWNLINK_ONLY)
content->component[j].type =
OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
else
content->component[j].type =
OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
/*
* As per 3GPP TS 24.008, following Packet filter component type identifier
* are not supported on the LTE pre release-11 UEs:
*
* IPv4 local address type
* IPv6 remote address/prefix length type
* IPv6 local address/prefix length type
*
* And,
* IPv6 remote address/prefix length type and
* IPv6 local address/prefix length type shall be used when both MS and
* Network support Local Address in TFTs.
*/
if (rule->ipv4_src && (direction == OGS_FLOW_DOWNLINK_ONLY)) {
content->component[j].type = OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
content->component[j].ipv4.addr = rule->ip.src.addr[0];
content->component[j].ipv4.mask = rule->ip.src.mask[0];
j++; len += 9;
}
if (rule->ipv4_dst) {
if (direction == OGS_FLOW_DOWNLINK_ONLY)
content->component[j].type =
OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
else
content->component[j].type =
OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
if (rule->ipv4_src && (direction == OGS_FLOW_UPLINK_ONLY) &&
!no_ipv4v6_local_addr_in_packet_filter) {
content->component[j].type = OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
content->component[j].ipv4.addr = rule->ip.src.addr[0];
content->component[j].ipv4.mask = rule->ip.src.mask[0];
j++; len += 9;
}
if (rule->ipv4_dst && (direction == OGS_FLOW_DOWNLINK_ONLY) &&
!no_ipv4v6_local_addr_in_packet_filter) {
content->component[j].type = OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
content->component[j].ipv4.addr = rule->ip.dst.addr[0];
content->component[j].ipv4.mask = rule->ip.dst.mask[0];
j++; len += 9;
}
if (rule->ipv6_src) {
if (direction == OGS_FLOW_DOWNLINK_ONLY)
content->component[j].type =
OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
else
content->component[j].type =
OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(content->component[j].ipv6.addr,
rule->ip.src.addr, sizeof rule->ip.src.addr);
content->component[j].ipv6.prefixlen =
contigmask((uint8_t *)rule->ip.src.mask, 128);
j++; len += 18;
if (rule->ipv4_dst && (direction == OGS_FLOW_UPLINK_ONLY)) {
content->component[j].type = OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
content->component[j].ipv4.addr = rule->ip.dst.addr[0];
content->component[j].ipv4.mask = rule->ip.dst.mask[0];
j++; len += 9;
}
if (rule->ipv6_dst) {
if (direction == OGS_FLOW_DOWNLINK_ONLY)
if (rule->ipv6_src && (direction == OGS_FLOW_DOWNLINK_ONLY)) {
if (no_ipv4v6_local_addr_in_packet_filter) {
content->component[j].type =
OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
else
OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE;
memcpy(content->component[j].ipv6_mask.addr,
rule->ip.src.addr, sizeof rule->ip.src.addr);
memcpy(content->component[j].ipv6_mask.mask,
rule->ip.src.mask, sizeof rule->ip.src.mask);
j++; len += 33;
} else {
content->component[j].type =
OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(content->component[j].ipv6.addr,
memcpy(content->component[j].ipv6.addr,
rule->ip.src.addr, sizeof rule->ip.src.addr);
content->component[j].ipv6.prefixlen =
contigmask((uint8_t *)rule->ip.src.mask, 128);
j++; len += 18;
}
}
if (rule->ipv6_src && (direction == OGS_FLOW_UPLINK_ONLY)) {
if (!no_ipv4v6_local_addr_in_packet_filter) {
content->component[j].type =
OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(content->component[j].ipv6.addr,
rule->ip.src.addr, sizeof rule->ip.src.addr);
content->component[j].ipv6.prefixlen =
contigmask((uint8_t *)rule->ip.src.mask, 128);
j++; len += 18;
}
}
if (rule->ipv6_dst && (direction == OGS_FLOW_DOWNLINK_ONLY)) {
if (!no_ipv4v6_local_addr_in_packet_filter) {
content->component[j].type =
OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(content->component[j].ipv6.addr,
rule->ip.dst.addr, sizeof rule->ip.dst.addr);
content->component[j].ipv6.prefixlen =
contigmask((uint8_t *)rule->ip.dst.mask, 128);
j++; len += 18;
content->component[j].ipv6.prefixlen =
contigmask((uint8_t *)rule->ip.dst.mask, 128);
j++; len += 18;
}
}
if (rule->ipv6_dst && (direction == OGS_FLOW_UPLINK_ONLY)) {
if (no_ipv4v6_local_addr_in_packet_filter) {
content->component[j].type =
OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE;
memcpy(content->component[j].ipv6_mask.addr,
rule->ip.dst.addr, sizeof rule->ip.dst.addr);
memcpy(content->component[j].ipv6_mask.mask,
rule->ip.dst.mask, sizeof rule->ip.dst.mask);
j++; len += 33;
} else {
content->component[j].type =
OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(content->component[j].ipv6.addr,
rule->ip.dst.addr, sizeof rule->ip.dst.addr);
content->component[j].ipv6.prefixlen =
contigmask((uint8_t *)rule->ip.dst.mask, 128);
j++; len += 18;
}
}
if (rule->port.src.low) {

View File

@ -130,7 +130,8 @@ typedef struct ogs_pf_content_s {
} ogs_pf_content_t;
void ogs_pf_content_from_ipfw_rule(
uint8_t direction, ogs_pf_content_t *content, ogs_ipfw_rule_t *rule);
uint8_t direction, ogs_pf_content_t *content, ogs_ipfw_rule_t *rule,
bool no_ipv4v6_local_addr_in_packet_filter);
#ifdef __cplusplus
}

View File

@ -92,8 +92,6 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp,
{
int rv;
int ret;
int len;
char *from_str, *to_str, *rx_flow, *to_port, *to_ip, *from_ip, *from_port;
struct msg *ans, *qry;
struct avp *avpch1, *avpch2, *avpch3;
@ -295,117 +293,10 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp,
ogs_assert(sub->num_of_flow <
OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT);
flow = &sub->flow[sub->num_of_flow];
/* IE (IPV4-local-addr field ) is not supported on
* the LTE pre release-11 UEs. In order for the call
* to work the local address in packet filter must
* be replaced by 'any local port'.
*/
if (ogs_app()->
parameter.no_ipv4v6_local_addr_in_packet_filter
== true) {
rx_flow = NULL;
rx_flow = (char*)hdr->avp_value->os.data;
len = hdr->avp_value->os.len;
from_str = NULL;
to_str = NULL;
to_ip = NULL;
to_port = NULL;
from_ip = NULL;
from_port = NULL;
from_str = strstr(rx_flow, "from");
ogs_assert(from_str);
to_str = strstr(rx_flow, "to");
ogs_assert(to_str);
if (!strncmp(rx_flow,
"permit out", strlen("permit out"))) {
to_ip = strstr(to_str, " ");
ogs_assert(to_ip);
// Exclude the starting whitespace
to_ip += 1;
to_port = strstr(to_ip, " ");
// Test for no port
if (to_port != NULL) {
flow->description = ogs_calloc(1,
len - strlen(to_str) +
strlen("to any")
+ strlen(to_port) + 1);
ogs_assert(flow->description);
} else {
flow->description = ogs_calloc(1,
len - strlen(to_str) +
strlen("to any") + 1);
ogs_assert(flow->description);
}
ogs_assert(flow->description);
strncat(flow->description,
rx_flow,
len - strlen(to_str));
strcat(flow->description, "to any");
if (to_port != NULL) {
strncat(flow->description,
to_port, strlen(to_port));
}
} else if (!strncmp(rx_flow,
"permit in", strlen("permit in"))) {
from_ip = strstr(from_str, " ");
ogs_assert(from_ip);
/* Exclude the starting whitespace */
from_ip += 1;
from_port = strstr(from_ip, " ");
/* Test for no port +
* whether from_port is at "to"
* without any from port */
if (from_port != NULL &&
strncmp(from_port, " to", 3)) {
flow->description = ogs_calloc(1,
len - strlen(from_str) +
strlen(to_str)
+ strlen("from any") + 1
+ (strlen(from_port) -
strlen(to_str)));
ogs_assert(flow->description);
} else {
flow->description = ogs_calloc(1,
len - strlen(from_str) +
strlen(to_str)
+ strlen("from any ") + 1);
ogs_assert(flow->description);
}
ogs_assert(flow->description);
strncat(flow->description,
rx_flow,
len - strlen(from_str));
if (from_port != NULL &&
strncmp(from_port, " to", 3)) {
strcat(flow->description, "from any");
strncat(flow->description,
from_port,
strlen(from_port) - strlen(to_str));
} else {
strcat(flow->description, "from any ");
}
strncat(flow->description,
to_str,
strlen(to_str));
}
} else {
flow->description = ogs_strndup(
flow->description = ogs_strndup(
(char*)hdr->avp_value->os.data,
hdr->avp_value->os.len);
ogs_assert(flow->description);
}
ogs_assert(flow->description);
sub->num_of_flow++;
break;
default:

View File

@ -101,7 +101,9 @@ static void encode_traffic_flow_template(
tft->pf[i].precedence = pf->precedence - 1;
ogs_pf_content_from_ipfw_rule(
pf->direction, &tft->pf[i].content, &pf->ipfw_rule);
pf->direction, &tft->pf[i].content, &pf->ipfw_rule,
ogs_app()->
parameter.no_ipv4v6_local_addr_in_packet_filter);
}
i++;

View File

@ -282,7 +282,8 @@ static void encode_qos_rule_packet_filter(
qos_rule->pf[i].identifier = pf->identifier;
ogs_pf_content_from_ipfw_rule(
pf->direction, &qos_rule->pf[i].content, &pf->ipfw_rule);
pf->direction, &qos_rule->pf[i].content, &pf->ipfw_rule,
ogs_app()->parameter.no_ipv4v6_local_addr_in_packet_filter);
i++;
}
qos_rule->num_of_packet_filter = i;