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:
parent
3b6da3ddb2
commit
52bc4be547
|
@ -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:
|
||||
|
||||
#
|
||||
|
|
|
@ -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:
|
||||
|
||||
#
|
||||
|
|
|
@ -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,36 +381,72 @@ 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)
|
||||
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_src && (direction == OGS_FLOW_DOWNLINK_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.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;
|
||||
else
|
||||
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,
|
||||
|
@ -418,12 +455,30 @@ void ogs_pf_content_from_ipfw_rule(
|
|||
contigmask((uint8_t *)rule->ip.src.mask, 128);
|
||||
j++; len += 18;
|
||||
}
|
||||
}
|
||||
|
||||
if (rule->ipv6_dst) {
|
||||
if (direction == OGS_FLOW_DOWNLINK_ONLY)
|
||||
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;
|
||||
else
|
||||
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->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,
|
||||
|
@ -432,6 +487,7 @@ void ogs_pf_content_from_ipfw_rule(
|
|||
contigmask((uint8_t *)rule->ip.dst.mask, 128);
|
||||
j++; len += 18;
|
||||
}
|
||||
}
|
||||
|
||||
if (rule->port.src.low) {
|
||||
if (rule->port.src.low == rule->port.src.high) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
(char*)hdr->avp_value->os.data,
|
||||
hdr->avp_value->os.len);
|
||||
ogs_assert(flow->description);
|
||||
}
|
||||
|
||||
sub->num_of_flow++;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue