Fix TFT bug in Bearer resource modification [#338]

This commit is contained in:
Sukchan Lee 2020-09-21 00:33:36 -04:00
parent f5601a95f7
commit 65d1ac1718
3 changed files with 90 additions and 63 deletions

View File

@ -174,34 +174,16 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
char buf[OGS_ADDRSTRLEN];
ogs_sockaddr_t sa;
int prefixlen = 0;
ogs_ipfw_rule_t permit_out_rule;
p = flow_description;
last = flow_description + OGS_HUGE_LEN;
ogs_assert(ipfw_rule);
/*
* Issue #338
*
* <DOWNLINK>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
* -->
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
*
* <UPLINK>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* -->
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
*/
ogs_ipfw_copy_and_swap(&permit_out_rule, ipfw_rule);
p = ogs_slprintf(p, last, "permit out");
if (permit_out_rule.proto) {
p = ogs_slprintf(p, last, " %d", permit_out_rule.proto);
if (ipfw_rule->proto) {
p = ogs_slprintf(p, last, " %d", ipfw_rule->proto);
} else {
p = ogs_slprintf(p, last, " ip");
}
@ -212,21 +194,21 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
p = ogs_slprintf(p, last, " from");
memset(&sa, 0, sizeof(sa));
if (permit_out_rule.ipv4_src) {
if (ipfw_rule->ipv4_src) {
sa.ogs_sa_family = AF_INET;
memcpy(&sa.sin.sin_addr,
permit_out_rule.ip.src.addr, sizeof(struct in_addr));
ipfw_rule->ip.src.addr, sizeof(struct in_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)permit_out_rule.ip.src.mask, IPV4_BITLEN);
(uint8_t *)ipfw_rule->ip.src.mask, IPV4_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
permit_out_rule.ip.src.mask[0],
permit_out_rule.ip.src.mask[1],
permit_out_rule.ip.src.mask[2],
permit_out_rule.ip.src.mask[3]);
ipfw_rule->ip.src.mask[0],
ipfw_rule->ip.src.mask[1],
ipfw_rule->ip.src.mask[2],
ipfw_rule->ip.src.mask[3]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -239,21 +221,21 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
ogs_assert_if_reached();
}
} else if (permit_out_rule.ipv6_src) {
} else if (ipfw_rule->ipv6_src) {
sa.ogs_sa_family = AF_INET6;
memcpy(&sa.sin6.sin6_addr,
permit_out_rule.ip.src.addr, sizeof(struct in6_addr));
ipfw_rule->ip.src.addr, sizeof(struct in6_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)permit_out_rule.ip.src.mask, IPV6_BITLEN);
(uint8_t *)ipfw_rule->ip.src.mask, IPV6_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
permit_out_rule.ip.src.mask[0],
permit_out_rule.ip.src.mask[1],
permit_out_rule.ip.src.mask[2],
permit_out_rule.ip.src.mask[3]);
ipfw_rule->ip.src.mask[0],
ipfw_rule->ip.src.mask[1],
ipfw_rule->ip.src.mask[2],
ipfw_rule->ip.src.mask[3]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -268,35 +250,35 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
} else
p = ogs_slprintf(p, last, " any");
if (permit_out_rule.port.src.low == permit_out_rule.port.src.high) {
if (permit_out_rule.port.src.low == 0) {
if (ipfw_rule->port.src.low == ipfw_rule->port.src.high) {
if (ipfw_rule->port.src.low == 0) {
/* Nothing */
} else {
p = ogs_slprintf(p, last, " %d", permit_out_rule.port.src.low);
p = ogs_slprintf(p, last, " %d", ipfw_rule->port.src.low);
}
} else {
p = ogs_slprintf(p, last, " %d-%d",
permit_out_rule.port.src.low, permit_out_rule.port.src.high);
ipfw_rule->port.src.low, ipfw_rule->port.src.high);
}
p = ogs_slprintf(p, last, " to");
memset(&sa, 0, sizeof(sa));
if (permit_out_rule.ipv4_dst) {
if (ipfw_rule->ipv4_dst) {
sa.ogs_sa_family = AF_INET;
memcpy(&sa.sin.sin_addr,
permit_out_rule.ip.dst.addr, sizeof(struct in_addr));
ipfw_rule->ip.dst.addr, sizeof(struct in_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)permit_out_rule.ip.dst.mask, IPV4_BITLEN);
(uint8_t *)ipfw_rule->ip.dst.mask, IPV4_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
permit_out_rule.ip.dst.mask[0],
permit_out_rule.ip.dst.mask[1],
permit_out_rule.ip.dst.mask[2],
permit_out_rule.ip.dst.mask[3]);
ipfw_rule->ip.dst.mask[0],
ipfw_rule->ip.dst.mask[1],
ipfw_rule->ip.dst.mask[2],
ipfw_rule->ip.dst.mask[3]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -309,21 +291,21 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
ogs_assert_if_reached();
}
} else if (permit_out_rule.ipv6_dst) {
} else if (ipfw_rule->ipv6_dst) {
sa.ogs_sa_family = AF_INET6;
memcpy(&sa.sin6.sin6_addr,
permit_out_rule.ip.dst.addr, sizeof(struct in6_addr));
ipfw_rule->ip.dst.addr, sizeof(struct in6_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)permit_out_rule.ip.dst.mask, IPV6_BITLEN);
(uint8_t *)ipfw_rule->ip.dst.mask, IPV6_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
permit_out_rule.ip.dst.mask[0],
permit_out_rule.ip.dst.mask[1],
permit_out_rule.ip.dst.mask[2],
permit_out_rule.ip.dst.mask[3]);
ipfw_rule->ip.dst.mask[0],
ipfw_rule->ip.dst.mask[1],
ipfw_rule->ip.dst.mask[2],
ipfw_rule->ip.dst.mask[3]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -338,15 +320,15 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
} else
p = ogs_slprintf(p, last, " any");
if (permit_out_rule.port.dst.low == permit_out_rule.port.dst.high) {
if (permit_out_rule.port.dst.low == 0) {
if (ipfw_rule->port.dst.low == ipfw_rule->port.dst.high) {
if (ipfw_rule->port.dst.low == 0) {
/* Nothing */
} else {
p = ogs_slprintf(p, last, " %d", permit_out_rule.port.dst.low);
p = ogs_slprintf(p, last, " %d", ipfw_rule->port.dst.low);
}
} else {
p = ogs_slprintf(p, last, " %d-%d",
permit_out_rule.port.dst.low, permit_out_rule.port.dst.high);
ipfw_rule->port.dst.low, ipfw_rule->port.dst.high);
}
return ogs_strdup(flow_description);

View File

@ -715,8 +715,30 @@ void smf_s5c_handle_bearer_resource_command(
if (pf->flow_description)
ogs_free(pf->flow_description);
pf->flow_description =
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
/*
* Issue #338
*
* <DOWNLINK>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
* -->
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
*
* <UPLINK>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* -->
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
*/
if (pf->direction == OGS_FLOW_UPLINK_ONLY) {
ogs_ipfw_rule_t tmp;
ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule);
pf->flow_description =
ogs_ipfw_encode_flow_description(&tmp);
} else {
pf->flow_description =
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
}
}
tft_update = 1;
@ -759,8 +781,31 @@ void smf_s5c_handle_bearer_resource_command(
if (pf->flow_description)
ogs_free(pf->flow_description);
pf->flow_description =
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
/*
* Issue #338
*
* <DOWNLINK>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
* -->
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
*
* <UPLINK>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* -->
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
*/
if (pf->direction == OGS_FLOW_UPLINK_ONLY) {
ogs_ipfw_rule_t tmp;
ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule);
pf->flow_description =
ogs_ipfw_encode_flow_description(&tmp);
} else {
pf->flow_description =
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
}
tft_update = 1;
}

View File

@ -424,7 +424,7 @@ ogs_pkbuf_t *testesm_build_bearer_resource_modification_request(
} else if (tft.code ==
OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT) {
tft.num_of_packet_filter = 1;
tft.pf[0].direction = 1;
tft.pf[0].direction = 2;
tft.pf[0].identifier = 4;
tft.pf[0].precedence = 0x0f;
@ -433,14 +433,14 @@ ogs_pkbuf_t *testesm_build_bearer_resource_modification_request(
#if 1
tft.pf[0].length = 18;
tft.pf[0].component[0].type =
GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(tft.pf[0].component[0].ipv6.addr, ipsubnet.sub,
sizeof(tft.pf[0].component[0].ipv6.addr));
tft.pf[0].component[0].ipv6.prefixlen = 120;
#else
tft.pf[0].length = 33;
tft.pf[0].component[0].type =
GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE;
GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE;
memcpy(tft.pf[0].component[0].ipv6_mask.addr, ipsubnet.sub,
sizeof(tft.pf[0].component[0].ipv6_mask.addr));
memcpy(tft.pf[0].component[0].ipv6_mask.mask, ipsubnet.mask,