Fix semantic error in packet filter [#338]

<DOWNLINK>
RX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <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>
RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>

<UPLINK>
RX : permit in from <UE_IP> <UE_PORT> to <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>
RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
This commit is contained in:
Sukchan Lee 2020-09-20 23:35:10 -04:00
parent cc873269a4
commit f5601a95f7
18 changed files with 527 additions and 291 deletions

View File

@ -106,52 +106,52 @@ int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description)
case O_IP_SRC:
case O_IP_SRC_MASK:
a = ((ipfw_insn_u32 *)cmd)->d;
ipfw_rule->ipv4_local = 1;
ipfw_rule->ip.local.addr[0] = a[0];
ipfw_rule->ipv4_src = 1;
ipfw_rule->ip.src.addr[0] = a[0];
if (cmd->opcode == O_IP_SRC_MASK)
ipfw_rule->ip.local.mask[0] = a[1];
ipfw_rule->ip.src.mask[0] = a[1];
else
ipfw_rule->ip.local.mask[0] = 0xffffffff;
ipfw_rule->ip.src.mask[0] = 0xffffffff;
break;
case O_IP_DST:
case O_IP_DST_MASK:
a = ((ipfw_insn_u32 *)cmd)->d;
ipfw_rule->ipv4_remote = 1;
ipfw_rule->ip.remote.addr[0] = a[0];
ipfw_rule->ipv4_dst = 1;
ipfw_rule->ip.dst.addr[0] = a[0];
if (cmd->opcode == O_IP_DST_MASK)
ipfw_rule->ip.remote.mask[0] = a[1];
ipfw_rule->ip.dst.mask[0] = a[1];
else
ipfw_rule->ip.remote.mask[0] = 0xffffffff;
ipfw_rule->ip.dst.mask[0] = 0xffffffff;
break;
case O_IP6_SRC:
case O_IP6_SRC_MASK:
a = ((ipfw_insn_u32 *)cmd)->d;
ipfw_rule->ipv6_local = 1;
memcpy(ipfw_rule->ip.local.addr, a, OGS_IPV6_LEN);
ipfw_rule->ipv6_src = 1;
memcpy(ipfw_rule->ip.src.addr, a, OGS_IPV6_LEN);
if (cmd->opcode == O_IP6_SRC_MASK)
memcpy(ipfw_rule->ip.local.mask, a+4, OGS_IPV6_LEN);
memcpy(ipfw_rule->ip.src.mask, a+4, OGS_IPV6_LEN);
else
n2mask((struct in6_addr *)ipfw_rule->ip.local.mask, 128);
n2mask((struct in6_addr *)ipfw_rule->ip.src.mask, 128);
break;
case O_IP6_DST:
case O_IP6_DST_MASK:
a = ((ipfw_insn_u32 *)cmd)->d;
ipfw_rule->ipv6_remote = 1;
memcpy(ipfw_rule->ip.remote.addr, a, OGS_IPV6_LEN);
ipfw_rule->ipv6_dst = 1;
memcpy(ipfw_rule->ip.dst.addr, a, OGS_IPV6_LEN);
if (cmd->opcode == O_IP6_DST_MASK)
memcpy(ipfw_rule->ip.remote.mask, a+4, OGS_IPV6_LEN);
memcpy(ipfw_rule->ip.dst.mask, a+4, OGS_IPV6_LEN);
else
n2mask((struct in6_addr *)ipfw_rule->ip.remote.mask, 128);
n2mask((struct in6_addr *)ipfw_rule->ip.dst.mask, 128);
break;
case O_IP_SRCPORT:
p = ((ipfw_insn_u16 *)cmd)->ports;
ipfw_rule->port.local.low = p[0];
ipfw_rule->port.local.high = p[1];
ipfw_rule->port.src.low = p[0];
ipfw_rule->port.src.high = p[1];
break;
case O_IP_DSTPORT:
p = ((ipfw_insn_u16 *)cmd)->ports;
ipfw_rule->port.remote.low = p[0];
ipfw_rule->port.remote.high = p[1];
ipfw_rule->port.dst.low = p[0];
ipfw_rule->port.dst.high = p[1];
break;
}
}
@ -174,15 +174,34 @@ 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 (ipfw_rule->proto) {
p = ogs_slprintf(p, last, " %d", ipfw_rule->proto);
if (permit_out_rule.proto) {
p = ogs_slprintf(p, last, " %d", permit_out_rule.proto);
} else {
p = ogs_slprintf(p, last, " ip");
}
@ -193,21 +212,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 (ipfw_rule->ipv4_local) {
if (permit_out_rule.ipv4_src) {
sa.ogs_sa_family = AF_INET;
memcpy(&sa.sin.sin_addr,
ipfw_rule->ip.local.addr, sizeof(struct in_addr));
permit_out_rule.ip.src.addr, sizeof(struct in_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)ipfw_rule->ip.local.mask, IPV4_BITLEN);
(uint8_t *)permit_out_rule.ip.src.mask, IPV4_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
ipfw_rule->ip.local.mask[0],
ipfw_rule->ip.local.mask[1],
ipfw_rule->ip.local.mask[2],
ipfw_rule->ip.local.mask[3]);
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]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -220,21 +239,21 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
ogs_assert_if_reached();
}
} else if (ipfw_rule->ipv6_local) {
} else if (permit_out_rule.ipv6_src) {
sa.ogs_sa_family = AF_INET6;
memcpy(&sa.sin6.sin6_addr,
ipfw_rule->ip.local.addr, sizeof(struct in6_addr));
permit_out_rule.ip.src.addr, sizeof(struct in6_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)ipfw_rule->ip.local.mask, IPV6_BITLEN);
(uint8_t *)permit_out_rule.ip.src.mask, IPV6_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
ipfw_rule->ip.local.mask[0],
ipfw_rule->ip.local.mask[1],
ipfw_rule->ip.local.mask[2],
ipfw_rule->ip.local.mask[3]);
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]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -249,35 +268,35 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
} else
p = ogs_slprintf(p, last, " any");
if (ipfw_rule->port.local.low == ipfw_rule->port.local.high) {
if (ipfw_rule->port.local.low == 0) {
if (permit_out_rule.port.src.low == permit_out_rule.port.src.high) {
if (permit_out_rule.port.src.low == 0) {
/* Nothing */
} else {
p = ogs_slprintf(p, last, " %d", ipfw_rule->port.local.low);
p = ogs_slprintf(p, last, " %d", permit_out_rule.port.src.low);
}
} else {
p = ogs_slprintf(p, last, " %d-%d",
ipfw_rule->port.local.low, ipfw_rule->port.local.high);
permit_out_rule.port.src.low, permit_out_rule.port.src.high);
}
p = ogs_slprintf(p, last, " to");
memset(&sa, 0, sizeof(sa));
if (ipfw_rule->ipv4_remote) {
if (permit_out_rule.ipv4_dst) {
sa.ogs_sa_family = AF_INET;
memcpy(&sa.sin.sin_addr,
ipfw_rule->ip.remote.addr, sizeof(struct in_addr));
permit_out_rule.ip.dst.addr, sizeof(struct in_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)ipfw_rule->ip.remote.mask, IPV4_BITLEN);
(uint8_t *)permit_out_rule.ip.dst.mask, IPV4_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
ipfw_rule->ip.remote.mask[0],
ipfw_rule->ip.remote.mask[1],
ipfw_rule->ip.remote.mask[2],
ipfw_rule->ip.remote.mask[3]);
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]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -290,21 +309,21 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
ogs_assert_if_reached();
}
} else if (ipfw_rule->ipv6_remote) {
} else if (permit_out_rule.ipv6_dst) {
sa.ogs_sa_family = AF_INET6;
memcpy(&sa.sin6.sin6_addr,
ipfw_rule->ip.remote.addr, sizeof(struct in6_addr));
permit_out_rule.ip.dst.addr, sizeof(struct in6_addr));
OGS_ADDR(&sa, buf);
prefixlen = contigmask(
(uint8_t *)ipfw_rule->ip.remote.mask, IPV6_BITLEN);
(uint8_t *)permit_out_rule.ip.dst.mask, IPV6_BITLEN);
if (prefixlen < 0) {
ogs_error("Invalid mask[%x:%x:%x:%x]",
ipfw_rule->ip.remote.mask[0],
ipfw_rule->ip.remote.mask[1],
ipfw_rule->ip.remote.mask[2],
ipfw_rule->ip.remote.mask[3]);
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]);
return NULL;
} else if (prefixlen == 0) {
p = ogs_slprintf(p, last, " any");
@ -319,16 +338,48 @@ char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule)
} else
p = ogs_slprintf(p, last, " any");
if (ipfw_rule->port.remote.low == ipfw_rule->port.remote.high) {
if (ipfw_rule->port.remote.low == 0) {
if (permit_out_rule.port.dst.low == permit_out_rule.port.dst.high) {
if (permit_out_rule.port.dst.low == 0) {
/* Nothing */
} else {
p = ogs_slprintf(p, last, " %d", ipfw_rule->port.remote.low);
p = ogs_slprintf(p, last, " %d", permit_out_rule.port.dst.low);
}
} else {
p = ogs_slprintf(p, last, " %d-%d",
ipfw_rule->port.remote.low, ipfw_rule->port.remote.high);
permit_out_rule.port.dst.low, permit_out_rule.port.dst.high);
}
return ogs_strdup(flow_description);
}
ogs_ipfw_rule_t *ogs_ipfw_copy_and_swap(
ogs_ipfw_rule_t *dst, ogs_ipfw_rule_t *src)
{
ogs_assert(src);
ogs_assert(dst);
ogs_assert(src != dst);
memcpy(dst, src, sizeof(ogs_ipfw_rule_t));
dst->ipv4_src = src->ipv4_dst;
dst->ipv4_dst = src->ipv4_src;
dst->ipv6_src = src->ipv6_dst;
dst->ipv6_dst = src->ipv6_src;
memcpy(&dst->ip.src, &src->ip.dst, sizeof(dst->ip.src));
memcpy(&dst->ip.dst, &src->ip.src, sizeof(dst->ip.dst));
memcpy(&dst->port.src, &src->port.dst, sizeof(dst->port.src));
memcpy(&dst->port.dst, &src->port.src, sizeof(dst->port.dst));
return dst;
}
void ogs_ipfw_rule_swap(ogs_ipfw_rule_t *ipfw_rule)
{
ogs_ipfw_rule_t dst;
ogs_assert(ipfw_rule);
ogs_ipfw_copy_and_swap(&dst, ipfw_rule);
memcpy(ipfw_rule, &dst, sizeof(ogs_ipfw_rule_t));
}

View File

@ -29,30 +29,30 @@ extern "C" {
typedef struct ogs_ipfw_rule_s {
uint8_t proto;
uint8_t ipv4_local;
uint8_t ipv4_remote;
uint8_t ipv6_local;
uint8_t ipv6_remote;
uint8_t ipv4_src;
uint8_t ipv4_dst;
uint8_t ipv6_src;
uint8_t ipv6_dst;
struct {
struct {
uint32_t addr[4];
uint32_t mask[4];
} local;
} src;
struct {
uint32_t addr[4];
uint32_t mask[4];
} remote;
} dst;
} ip;
struct {
struct {
uint16_t low;
uint16_t high;
} local;
} src;
struct {
uint16_t low;
uint16_t high;
} remote;
} dst;
} port;
uint16_t tos_traffic_class;
@ -64,6 +64,28 @@ typedef struct ogs_ipfw_rule_s {
int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description);
char *ogs_ipfw_encode_flow_description(ogs_ipfw_rule_t *ipfw_rule);
/*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* RX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <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>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*
* <UPLINK>
* RX : permit in from <UE_IP> <UE_PORT> to <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>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
ogs_ipfw_rule_t *ogs_ipfw_copy_and_swap(
ogs_ipfw_rule_t *dst, ogs_ipfw_rule_t *src);
void ogs_ipfw_rule_swap(ogs_ipfw_rule_t *ipfw_rule);
#ifdef __cplusplus
}
#endif

View File

@ -789,10 +789,17 @@ void ogs_pfcp_gtpu_resource_remove_all(ogs_list_t *list)
ogs_pfcp_gtpu_resource_remove(list, resource);
}
ogs_pfcp_pdr_t *ogs_pfcp_sess_default_pdr(ogs_pfcp_sess_t *sess)
ogs_pfcp_pdr_t *ogs_pfcp_sess_default_pdr(
ogs_pfcp_sess_t *sess, ogs_pfcp_interface_t src_if)
{
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess);
return sess->default_pdr;
for (pdr = ogs_list_last(&sess->pdr_list); pdr; pdr = ogs_list_prev(pdr))
if (pdr->src_if == src_if) return pdr;
return NULL;
}
void ogs_pfcp_sess_clear(ogs_pfcp_sess_t *sess)

View File

@ -231,9 +231,6 @@ typedef struct ogs_pfcp_sess_s {
OGS_POOL(urr_id_pool, uint8_t);
OGS_POOL(qer_id_pool, uint8_t);
OGS_POOL(bar_id_pool, uint8_t);
/* Related Context */
ogs_pfcp_pdr_t *default_pdr; /* Used by UPF */
} ogs_pfcp_sess_t;
typedef struct ogs_pfcp_subnet_s ogs_pfcp_subnet_t;
@ -308,14 +305,12 @@ void ogs_pfcp_gtpu_resource_remove(ogs_list_t *list,
ogs_pfcp_gtpu_resource_t *resource);
void ogs_pfcp_gtpu_resource_remove_all(ogs_list_t *list);
#define OGS_SETUP_DEFAULT_PDR(__sESS, __pDR) \
do { \
ogs_assert((__sESS)); \
ogs_assert((__pDR)); \
(__sESS)->default_pdr = __pDR; \
ogs_assert((__sESS)->default_pdr); \
} while(0)
ogs_pfcp_pdr_t *ogs_pfcp_sess_default_pdr(ogs_pfcp_sess_t *sess);
#define OGS_DEFAULT_DL_PDR(__sESS) \
ogs_pfcp_sess_default_pdr(__sESS, OGS_PFCP_INTERFACE_CORE)
#define OGS_DEFAULT_UL_PDR(__sESS) \
ogs_pfcp_sess_default_pdr(__sESS, OGS_PFCP_INTERFACE_ACCESS)
ogs_pfcp_pdr_t *ogs_pfcp_sess_default_pdr(
ogs_pfcp_sess_t *sess, ogs_pfcp_interface_t src_if);
void ogs_pfcp_sess_clear(ogs_pfcp_sess_t *sess);
ogs_pfcp_pdr_t *ogs_pfcp_pdr_add(ogs_pfcp_sess_t *sess);

View File

@ -241,9 +241,45 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
rule = ogs_pfcp_rule_add(pdr);
ogs_assert(rule);
rv = ogs_ipfw_compile_rule(&rule->ipfw, flow_description);
ogs_assert(rv == OGS_OK);
/*
*
* TS29.244 Ch 5.2.1A.2A
*
* The UP function shall apply the SDF filter based on the Source Interface
* of the PDR as follows (see also clause 8.2.5):
*
* - when the Source Interface is CORE, this indicates that the filter is
* for downlink data flow, so the UP function shall apply
* the Flow Description as is;
*
* - when the Source Interface is ACCESS, this indicates that the filter is
* for uplink data flow, so the UP function shall swap the source and
* destination address/port in the Flow Description;
*
* - when the Source Interface is CP-function or SGi-LAN,
* the UP function shall use the Flow Description as is.
*
*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
*
* <UPLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
/* Uplink data flow */
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS)
ogs_ipfw_rule_swap(&rule->ipfw);
ogs_free(flow_description);
}
}
@ -368,6 +404,41 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess,
rv = ogs_ipfw_compile_rule(&rule->ipfw, flow_description);
ogs_assert(rv == OGS_OK);
/*
*
* TS29.244 Ch 5.2.1A.2A
*
* The UP function shall apply the SDF filter based on the Source Interface
* of the PDR as follows (see also clause 8.2.5):
*
* - when the Source Interface is CORE, this indicates that the filter is
* for downlink data flow, so the UP function shall apply
* the Flow Description as is;
*
* - when the Source Interface is ACCESS, this indicates that the filter is
* for uplink data flow, so the UP function shall swap the source and
* destination address/port in the Flow Description;
*
* - when the Source Interface is CP-function or SGi-LAN,
* the UP function shall use the Flow Description as is.
*
*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
*
* <UPLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
/* Uplink data flow */
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS)
ogs_ipfw_rule_swap(&rule->ipfw);
ogs_free(flow_description);
}

View File

@ -1338,6 +1338,7 @@ static int encode_pcc_rule_definition(
static int flow_rx_to_gx(ogs_flow_t *rx_flow, ogs_flow_t *gx_flow)
{
int len;
char *from_str, *to_str;
ogs_assert(rx_flow);
ogs_assert(gx_flow);
@ -1358,8 +1359,19 @@ static int flow_rx_to_gx(ogs_flow_t *rx_flow, ogs_flow_t *gx_flow)
len = strlen(rx_flow->description)+2;
gx_flow->description = ogs_malloc(len);
strcpy(gx_flow->description, "permit out");
strcat(gx_flow->description,
&rx_flow->description[strlen("permit in")]);
from_str = strstr(&rx_flow->description[strlen("permit in")], "from");
ogs_assert(from_str);
to_str = strstr(&rx_flow->description[strlen("permit in")], "to");
ogs_assert(to_str);
strncat(gx_flow->description,
&rx_flow->description[strlen("permit in")],
strlen(rx_flow->description) -
strlen("permit in") - strlen(from_str));
strcat(gx_flow->description, "from");
strcat(gx_flow->description, &to_str[strlen("to")]);
strcat(gx_flow->description, " to");
strncat(gx_flow->description, &from_str[strlen("from")],
strlen(from_str) - strlen(to_str) - strlen("from") - 1);
ogs_assert(len == strlen(gx_flow->description)+1);
} else {
ogs_error("Invalid Flow Descripton : [%s]", rx_flow->description);

View File

@ -362,8 +362,8 @@ int sgwu_context_parse_config(void)
return OGS_OK;
}
sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *cp_f_seid,
const char *apn, uint8_t pdn_type, ogs_pfcp_pdr_id_t default_pdr_id)
sgwu_sess_t *sgwu_sess_add(
ogs_pfcp_f_seid_t *cp_f_seid, const char *apn, uint8_t pdn_type)
{
sgwu_sess_t *sess = NULL;
@ -449,7 +449,6 @@ sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message)
ogs_pfcp_f_seid_t *f_seid = NULL;
char apn[OGS_MAX_APN_LEN];
ogs_pfcp_pdr_id_t default_pdr_id = 0;
ogs_pfcp_session_establishment_request_t *req =
&message->pfcp_session_establishment_request;;
@ -497,8 +496,7 @@ sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message)
sess = sgwu_sess_find_by_cp_seid(f_seid->seid);
if (!sess) {
sess = sgwu_sess_add(
f_seid, apn, req->pdn_type.u8, default_pdr_id);
sess = sgwu_sess_add(f_seid, apn, req->pdn_type.u8);
if (!sess) return NULL;
}
ogs_assert(sess);

View File

@ -72,8 +72,8 @@ int sgwu_context_parse_config(void);
sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message);
sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *f_seid,
const char *apn, uint8_t pdn_type, ogs_pfcp_pdr_id_t default_pdr_id);
sgwu_sess_t *sgwu_sess_add(
ogs_pfcp_f_seid_t *f_seid, const char *apn, uint8_t pdn_type);
int sgwu_sess_remove(sgwu_sess_t *sess);
void sgwu_sess_remove_all(void);
sgwu_sess_t *sgwu_sess_find(uint32_t index);

View File

@ -35,6 +35,17 @@ static void timeout(ogs_gtp_xact_t *xact, void *data)
"Message-Type[%d]", sess->sgw_s5c_teid, sess->smf_n4_teid, type);
}
/*
* Issue #338
*
* <DOWNLINK>
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*
* <UPLINK>
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
static void encode_traffic_flow_template(
ogs_gtp_tft_t *tft, smf_bearer_t *bearer)
{
@ -62,76 +73,107 @@ static void encode_traffic_flow_template(
j++; len += 2;
}
if (pf->ipfw_rule.ipv4_local) {
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
tft->pf[i].component[j].ipv4.addr = pf->ipfw_rule.ip.local.addr[0];
tft->pf[i].component[j].ipv4.mask = pf->ipfw_rule.ip.local.mask[0];
j++; len += 9;
}
if (pf->ipfw_rule.ipv4_remote) {
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
tft->pf[i].component[j].ipv4.addr = pf->ipfw_rule.ip.remote.addr[0];
tft->pf[i].component[j].ipv4.mask = pf->ipfw_rule.ip.remote.mask[0];
j++; len += 9;
}
if (pf->ipfw_rule.ipv6_local) {
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(tft->pf[i].component[j].ipv6.addr,
pf->ipfw_rule.ip.local.addr,
sizeof pf->ipfw_rule.ip.local.addr);
tft->pf[i].component[j].ipv6.prefixlen =
contigmask((uint8_t *)pf->ipfw_rule.ip.local.mask, 128);
j++; len += 18;
}
if (pf->ipfw_rule.ipv6_remote) {
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(tft->pf[i].component[j].ipv6.addr,
pf->ipfw_rule.ip.remote.addr,
sizeof pf->ipfw_rule.ip.remote.addr);
tft->pf[i].component[j].ipv6.prefixlen =
contigmask((uint8_t *)pf->ipfw_rule.ip.remote.mask, 128);
j++; len += 18;
}
if (pf->ipfw_rule.port.local.low) {
if (pf->ipfw_rule.port.local.low == pf->ipfw_rule.port.local.high)
{
if (pf->ipfw_rule.ipv4_src) {
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE;
tft->pf[i].component[j].port.low = pf->ipfw_rule.port.local.low;
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
tft->pf[i].component[j].ipv4.addr = pf->ipfw_rule.ip.src.addr[0];
tft->pf[i].component[j].ipv4.mask = pf->ipfw_rule.ip.src.mask[0];
j++; len += 9;
}
if (pf->ipfw_rule.ipv4_dst) {
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
tft->pf[i].component[j].ipv4.addr = pf->ipfw_rule.ip.dst.addr[0];
tft->pf[i].component[j].ipv4.mask = pf->ipfw_rule.ip.dst.mask[0];
j++; len += 9;
}
if (pf->ipfw_rule.ipv6_src) {
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(tft->pf[i].component[j].ipv6.addr,
pf->ipfw_rule.ip.src.addr,
sizeof pf->ipfw_rule.ip.src.addr);
tft->pf[i].component[j].ipv6.prefixlen =
contigmask((uint8_t *)pf->ipfw_rule.ip.src.mask, 128);
j++; len += 18;
}
if (pf->ipfw_rule.ipv6_dst) {
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(tft->pf[i].component[j].ipv6.addr,
pf->ipfw_rule.ip.dst.addr,
sizeof pf->ipfw_rule.ip.dst.addr);
tft->pf[i].component[j].ipv6.prefixlen =
contigmask((uint8_t *)pf->ipfw_rule.ip.dst.mask, 128);
j++; len += 18;
}
if (pf->ipfw_rule.port.src.low) {
if (pf->ipfw_rule.port.src.low == pf->ipfw_rule.port.src.high) {
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE;
tft->pf[i].component[j].port.low = pf->ipfw_rule.port.src.low;
j++; len += 3;
} else {
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE;
tft->pf[i].component[j].port.low = pf->ipfw_rule.port.local.low;
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE;
tft->pf[i].component[j].port.low = pf->ipfw_rule.port.src.low;
tft->pf[i].component[j].port.high =
pf->ipfw_rule.port.local.high;
pf->ipfw_rule.port.src.high;
j++; len += 5;
}
}
if (pf->ipfw_rule.port.remote.low) {
if (pf->ipfw_rule.port.remote.low ==
pf->ipfw_rule.port.remote.high) {
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE;
if (pf->ipfw_rule.port.dst.low) {
if (pf->ipfw_rule.port.dst.low == pf->ipfw_rule.port.dst.high) {
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE;
tft->pf[i].component[j].port.low =
pf->ipfw_rule.port.remote.low;
pf->ipfw_rule.port.dst.low;
j++; len += 3;
} else {
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE;
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE;
else
tft->pf[i].component[j].type =
GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE;
tft->pf[i].component[j].port.low =
pf->ipfw_rule.port.remote.low;
pf->ipfw_rule.port.dst.low;
tft->pf[i].component[j].port.high =
pf->ipfw_rule.port.remote.high;
pf->ipfw_rule.port.dst.high;
j++; len += 5;
}
}
@ -264,8 +306,26 @@ void smf_bearer_binding(smf_sess_t *sess)
pf->direction = flow->direction;
pf->flow_description = ogs_strdup(flow->description);
rv = ogs_ipfw_compile_rule(
&pf->ipfw_rule, pf->flow_description);
/*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* -->
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
*
* <UPLINK>
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
* -->
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
if (flow->direction == OGS_FLOW_UPLINK_ONLY)
ogs_ipfw_rule_swap(&pf->ipfw_rule);
if (rv != OGS_OK) {
ogs_error("Invalid Flow-Description[%s]",
pf->flow_description);

View File

@ -535,71 +535,75 @@ static int reconfigure_packet_filter(smf_pf_t *pf, ogs_gtp_tft_t *tft, int i)
{
int j;
ogs_assert(pf);
ogs_assert(tft);
memset(&pf->ipfw_rule, 0, sizeof(ogs_ipfw_rule_t));
pf->direction = tft->pf[i].direction;
for (j = 0; j < tft->pf[i].num_of_component; j++) {
switch(tft->pf[i].component[j].type) {
case GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
pf->ipfw_rule.proto = tft->pf[i].component[j].proto;
break;
case GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
pf->ipfw_rule.ipv4_remote = 1;
pf->ipfw_rule.ip.remote.addr[0] = tft->pf[i].component[j].ipv4.addr;
pf->ipfw_rule.ip.remote.mask[0] = tft->pf[i].component[j].ipv4.mask;
pf->ipfw_rule.ipv4_dst = 1;
pf->ipfw_rule.ip.dst.addr[0] = tft->pf[i].component[j].ipv4.addr;
pf->ipfw_rule.ip.dst.mask[0] = tft->pf[i].component[j].ipv4.mask;
break;
case GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
pf->ipfw_rule.ipv4_local = 1;
pf->ipfw_rule.ip.local.addr[0] = tft->pf[i].component[j].ipv4.addr;
pf->ipfw_rule.ip.local.mask[0] = tft->pf[i].component[j].ipv4.mask;
pf->ipfw_rule.ipv4_src = 1;
pf->ipfw_rule.ip.src.addr[0] = tft->pf[i].component[j].ipv4.addr;
pf->ipfw_rule.ip.src.mask[0] = tft->pf[i].component[j].ipv4.mask;
break;
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
pf->ipfw_rule.ipv6_remote = 1;
memcpy(pf->ipfw_rule.ip.remote.addr,
pf->ipfw_rule.ipv6_dst = 1;
memcpy(pf->ipfw_rule.ip.dst.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->ipfw_rule.ip.remote.addr));
memcpy(pf->ipfw_rule.ip.remote.mask,
sizeof(pf->ipfw_rule.ip.dst.addr));
memcpy(pf->ipfw_rule.ip.dst.mask,
tft->pf[i].component[j].ipv6_mask.mask,
sizeof(pf->ipfw_rule.ip.remote.mask));
sizeof(pf->ipfw_rule.ip.dst.mask));
break;
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
pf->ipfw_rule.ipv6_remote = 1;
memcpy(pf->ipfw_rule.ip.remote.addr,
pf->ipfw_rule.ipv6_dst = 1;
memcpy(pf->ipfw_rule.ip.dst.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->ipfw_rule.ip.remote.addr));
n2mask((struct in6_addr *)pf->ipfw_rule.ip.remote.mask,
sizeof(pf->ipfw_rule.ip.dst.addr));
n2mask((struct in6_addr *)pf->ipfw_rule.ip.dst.mask,
tft->pf[i].component[j].ipv6.prefixlen);
break;
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE:
pf->ipfw_rule.ipv6_local = 1;
memcpy(pf->ipfw_rule.ip.local.addr,
pf->ipfw_rule.ipv6_src = 1;
memcpy(pf->ipfw_rule.ip.src.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->ipfw_rule.ip.local.addr));
memcpy(pf->ipfw_rule.ip.local.mask,
sizeof(pf->ipfw_rule.ip.src.addr));
memcpy(pf->ipfw_rule.ip.src.mask,
tft->pf[i].component[j].ipv6_mask.mask,
sizeof(pf->ipfw_rule.ip.local.mask));
sizeof(pf->ipfw_rule.ip.src.mask));
break;
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
pf->ipfw_rule.ipv6_local = 1;
memcpy(pf->ipfw_rule.ip.local.addr,
pf->ipfw_rule.ipv6_src = 1;
memcpy(pf->ipfw_rule.ip.src.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->ipfw_rule.ip.local.addr));
n2mask((struct in6_addr *)pf->ipfw_rule.ip.local.mask,
sizeof(pf->ipfw_rule.ip.src.addr));
n2mask((struct in6_addr *)pf->ipfw_rule.ip.src.mask,
tft->pf[i].component[j].ipv6.prefixlen);
break;
case GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
pf->ipfw_rule.port.local.low = pf->ipfw_rule.port.local.high =
pf->ipfw_rule.port.src.low = pf->ipfw_rule.port.src.high =
tft->pf[i].component[j].port.low;
break;
case GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
pf->ipfw_rule.port.remote.low = pf->ipfw_rule.port.remote.high =
pf->ipfw_rule.port.dst.low = pf->ipfw_rule.port.dst.high =
tft->pf[i].component[j].port.low;
break;
case GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
pf->ipfw_rule.port.local.low = tft->pf[i].component[j].port.low;
pf->ipfw_rule.port.local.high = tft->pf[i].component[j].port.high;
pf->ipfw_rule.port.src.low = tft->pf[i].component[j].port.low;
pf->ipfw_rule.port.src.high = tft->pf[i].component[j].port.high;
break;
case GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
pf->ipfw_rule.port.remote.low = tft->pf[i].component[j].port.low;
pf->ipfw_rule.port.remote.high = tft->pf[i].component[j].port.high;
pf->ipfw_rule.port.dst.low = tft->pf[i].component[j].port.low;
pf->ipfw_rule.port.dst.high = tft->pf[i].component[j].port.high;
break;
default:
ogs_error("Unknown Packet Filter Type(%d)",
@ -692,12 +696,27 @@ void smf_s5c_handle_bearer_resource_command(
OGS_GTP_CAUSE_SEMANTIC_ERROR_IN_THE_TAD_OPERATION);
return;
}
/*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* -->
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
*
* <UPLINK>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* -->
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
ogs_ipfw_rule_swap(&pf->ipfw_rule);
if (pf->flow_description)
ogs_free(pf->flow_description);
pf->flow_description =
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
pf->direction = tft.pf[i].direction;
}
tft_update = 1;
@ -721,12 +740,27 @@ void smf_s5c_handle_bearer_resource_command(
OGS_GTP_CAUSE_SEMANTIC_ERROR_IN_THE_TAD_OPERATION);
return;
}
/*
* Refer to lib/ipfw/ogs-ipfw.h
* Issue #338
*
* <DOWNLINK>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* -->
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
*
* <UPLINK>
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
* -->
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
*/
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
ogs_ipfw_rule_swap(&pf->ipfw_rule);
if (pf->flow_description)
ogs_free(pf->flow_description);
pf->flow_description =
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
pf->direction = tft.pf[i].direction;
tft_update = 1;
}

View File

@ -373,8 +373,7 @@ int upf_context_parse_config(void)
}
upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid,
const char *apn, uint8_t pdn_type, ogs_pfcp_ue_ip_addr_t *ue_ip,
ogs_pfcp_pdr_id_t default_pdr_id)
const char *apn, uint8_t pdn_type, ogs_pfcp_ue_ip_addr_t *ue_ip)
{
char buf1[OGS_ADDRSTRLEN];
char buf2[OGS_ADDRSTRLEN];
@ -442,17 +441,12 @@ upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid,
goto cleanup;
}
/* Set Default PDR */
OGS_SETUP_DEFAULT_PDR(&sess->pfcp,
ogs_pfcp_pdr_find_or_add(&sess->pfcp, default_pdr_id));
ogs_info("UE F-SEID[CP:0x%lx,UP:0x%lx] "
"APN[%s] PDN-Type[%d] IPv4[%s] IPv6[%s], Default PDR ID[%d]",
"APN[%s] PDN-Type[%d] IPv4[%s] IPv6[%s]",
(long)sess->upf_n4_seid, (long)sess->smf_n4_seid,
apn, pdn_type,
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "",
sess->pfcp.default_pdr->id);
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
ogs_list_add(&self.sess_list, sess);
@ -541,7 +535,6 @@ upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message)
char apn[OGS_MAX_APN_LEN];
ogs_pfcp_ue_ip_addr_t *addr = NULL;
bool default_pdr_found = false;
ogs_pfcp_pdr_id_t default_pdr_id;
ogs_pfcp_session_establishment_request_t *req =
&message->pfcp_session_establishment_request;;
@ -587,7 +580,6 @@ upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message)
if (message->pdi.source_interface.u8 != OGS_PFCP_INTERFACE_CORE)
continue;
default_pdr_id = message->pdr_id.u16;
ogs_fqdn_parse(apn,
message->pdi.network_instance.data,
message->pdi.network_instance.len);
@ -614,8 +606,7 @@ upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message)
sess = upf_sess_find_by_cp_seid(f_seid->seid);
if (!sess) {
sess = upf_sess_add(
f_seid, apn, req->pdn_type.u8, addr, default_pdr_id);
sess = upf_sess_add(f_seid, apn, req->pdn_type.u8, addr);
if (!sess) return NULL;
}
ogs_assert(sess);

View File

@ -89,8 +89,7 @@ int upf_context_parse_config(void);
upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message);
upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *f_seid,
const char *apn, uint8_t pdn_type, ogs_pfcp_ue_ip_addr_t *ue_ip,
ogs_pfcp_pdr_id_t default_pdr_id);
const char *apn, uint8_t pdn_type, ogs_pfcp_ue_ip_addr_t *ue_ip);
int upf_sess_remove(upf_sess_t *sess);
void upf_sess_remove_all(void);
upf_sess_t *upf_sess_find(uint32_t index);

View File

@ -372,7 +372,7 @@ static void upf_gtp_handle_multicast(ogs_pkbuf_t *recvbuf)
/* PDN IPv6 is avaiable */
ogs_pfcp_pdr_t *pdr = NULL;
pdr = ogs_pfcp_sess_default_pdr(&sess->pfcp);
pdr = OGS_DEFAULT_DL_PDR(&sess->pfcp);
ogs_assert(pdr);
ogs_pfcp_up_handle_pdr(pdr, recvbuf, &report);
@ -434,7 +434,7 @@ static int upf_gtp_send_router_advertisement(
struct nd_opt_prefix_info *prefix = NULL;
ogs_assert(sess);
pdr = ogs_pfcp_sess_default_pdr(&sess->pfcp);
pdr = OGS_DEFAULT_DL_PDR(&sess->pfcp);
ogs_assert(pdr);
far = pdr->far;
ogs_assert(far);

View File

@ -153,7 +153,7 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
if (sess) {
ogs_pfcp_pdr_t *default_pdr = NULL;
ogs_pfcp_pdr_t *fallback_pdr = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_pfcp_rule_t *rule = NULL;
@ -163,79 +163,71 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
if (ip6_h && sess->ipv6)
ogs_debug("PAA IPv6:%s", OGS_INET6_NTOP(&sess->ipv6->addr, buf));
/* Save the default PDR */
default_pdr = ogs_pfcp_sess_default_pdr(&sess->pfcp);
ogs_assert(default_pdr);
/* Found */
ogs_debug("Found Session : Default PDR-ID[%d]", default_pdr->id);
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
far = pdr->far;
ogs_assert(far);
/* Check if PDR is Downlink */
if (pdr->src_if != OGS_PFCP_INTERFACE_CORE)
continue;
/* Check if FAR is Downlink */
if (far->dst_if != OGS_PFCP_INTERFACE_ACCESS)
continue;
/* Save the Fallback PDR : Lowest precedence downlink PDR */
fallback_pdr = pdr;
/* Check if Outer header creation */
if (far->outer_header_creation.teid == 0)
continue;
ogs_list_for_each(&pdr->rule_list, rule) {
int k;
uint32_t src_mask[4];
uint32_t dst_mask[4];
ogs_ipfw_rule_t *ipfw = NULL;
pdr = rule->pdr;
ogs_assert(pdr);
far = pdr->far;
ogs_assert(far);
ipfw = &rule->ipfw;
ogs_assert(ipfw);
/* Skip if PDR is default */
if (pdr->id == default_pdr->id)
continue;
/* Check if PDR is Downlink */
if (pdr->src_if != OGS_PFCP_INTERFACE_CORE)
continue;
/* Check if FAR is Downlink */
if (far->dst_if != OGS_PFCP_INTERFACE_ACCESS)
continue;
/* Check if Outer header creation */
if (far->outer_header_creation.teid == 0)
continue;
ogs_debug("PROTO:%d SRC:%d-%d DST:%d-%d",
ipfw->proto,
ipfw->port.local.low,
ipfw->port.local.high,
ipfw->port.remote.low,
ipfw->port.remote.high);
ipfw->port.src.low,
ipfw->port.src.high,
ipfw->port.dst.low,
ipfw->port.dst.high);
ogs_debug("SRC:%08x %08x %08x %08x/%08x %08x %08x %08x",
be32toh(ipfw->ip.local.addr[0]),
be32toh(ipfw->ip.local.addr[1]),
be32toh(ipfw->ip.local.addr[2]),
be32toh(ipfw->ip.local.addr[3]),
be32toh(ipfw->ip.local.mask[0]),
be32toh(ipfw->ip.local.mask[1]),
be32toh(ipfw->ip.local.mask[2]),
be32toh(ipfw->ip.local.mask[3]));
be32toh(ipfw->ip.src.addr[0]),
be32toh(ipfw->ip.src.addr[1]),
be32toh(ipfw->ip.src.addr[2]),
be32toh(ipfw->ip.src.addr[3]),
be32toh(ipfw->ip.src.mask[0]),
be32toh(ipfw->ip.src.mask[1]),
be32toh(ipfw->ip.src.mask[2]),
be32toh(ipfw->ip.src.mask[3]));
ogs_debug("DST:%08x %08x %08x %08x/%08x %08x %08x %08x",
be32toh(ipfw->ip.remote.addr[0]),
be32toh(ipfw->ip.remote.addr[1]),
be32toh(ipfw->ip.remote.addr[2]),
be32toh(ipfw->ip.remote.addr[3]),
be32toh(ipfw->ip.remote.mask[0]),
be32toh(ipfw->ip.remote.mask[1]),
be32toh(ipfw->ip.remote.mask[2]),
be32toh(ipfw->ip.remote.mask[3]));
be32toh(ipfw->ip.dst.addr[0]),
be32toh(ipfw->ip.dst.addr[1]),
be32toh(ipfw->ip.dst.addr[2]),
be32toh(ipfw->ip.dst.addr[3]),
be32toh(ipfw->ip.dst.mask[0]),
be32toh(ipfw->ip.dst.mask[1]),
be32toh(ipfw->ip.dst.mask[2]),
be32toh(ipfw->ip.dst.mask[3]));
for (k = 0; k < 4; k++) {
src_mask[k] = src_addr[k] & ipfw->ip.local.mask[k];
dst_mask[k] = dst_addr[k] & ipfw->ip.remote.mask[k];
src_mask[k] = src_addr[k] & ipfw->ip.src.mask[k];
dst_mask[k] = dst_addr[k] & ipfw->ip.dst.mask[k];
}
if (memcmp(src_mask, ipfw->ip.local.addr, addr_len) == 0 &&
memcmp(dst_mask, ipfw->ip.remote.addr, addr_len) == 0) {
if (memcmp(src_mask, ipfw->ip.src.addr, addr_len) == 0 &&
memcmp(dst_mask, ipfw->ip.dst.addr, addr_len) == 0) {
/* Protocol match */
if (ipfw->proto == 0) { /* IP */
/* No need to match port */
break;
goto found;
}
if (ipfw->proto == proto) {
@ -244,80 +236,84 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
(struct tcphdr *)((char *)pkt->data + ip_hlen);
/* Source port */
if (ipfw->port.local.low &&
if (ipfw->port.src.low &&
be16toh(tcph->th_sport) <
ipfw->port.local.low) {
ipfw->port.src.low) {
continue;
}
if (ipfw->port.local.high &&
if (ipfw->port.src.high &&
be16toh(tcph->th_sport) >
ipfw->port.local.high) {
ipfw->port.src.high) {
continue;
}
/* Dst Port*/
if (ipfw->port.remote.low &&
if (ipfw->port.dst.low &&
be16toh(tcph->th_dport) <
ipfw->port.remote.low) {
ipfw->port.dst.low) {
continue;
}
if (ipfw->port.remote.high &&
if (ipfw->port.dst.high &&
be16toh(tcph->th_dport) >
ipfw->port.remote.high) {
ipfw->port.dst.high) {
continue;
}
/* Matched */
break;
goto found;
} else if (ipfw->proto == IPPROTO_UDP) {
struct udphdr *udph =
(struct udphdr *)((char *)pkt->data + ip_hlen);
/* Source port */
if (ipfw->port.local.low &&
if (ipfw->port.src.low &&
be16toh(udph->uh_sport) <
ipfw->port.local.low) {
ipfw->port.src.low) {
continue;
}
if (ipfw->port.local.high &&
if (ipfw->port.src.high &&
be16toh(udph->uh_sport) >
ipfw->port.local.high) {
ipfw->port.src.high) {
continue;
}
/* Dst Port*/
if (ipfw->port.remote.low &&
if (ipfw->port.dst.low &&
be16toh(udph->uh_dport) <
ipfw->port.remote.low) {
ipfw->port.dst.low) {
continue;
}
if (ipfw->port.remote.high &&
if (ipfw->port.dst.high &&
be16toh(udph->uh_dport) >
ipfw->port.remote.high) {
ipfw->port.dst.high) {
continue;
}
/* Matched */
break;
goto found;
} else {
/* No need to match port */
break;
goto found;
}
}
}
}
}
found:
if (rule) {
ogs_debug("Found Dedicated PDR : PDR ID[%d]", pdr->id);
ogs_fatal("Found Dedicated PDR : PDR ID[%d]", pdr->id);
return pdr;
}
return default_pdr;
ogs_assert(fallback_pdr);
ogs_debug("Found Session : Fallback PDR-ID[%d]", fallback_pdr->id);
return fallback_pdr;
} else {
ogs_debug("No Session");
}

View File

@ -72,16 +72,16 @@ static void test1_func(abts_case *tc, void *data)
"},"
"\"flow\" : ["
"{ \"direction\" : 2,"
"\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23454\","
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to any 1-65535\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } },"
"{ \"direction\" : 1,"
"\"description\" : \"permit out udp from any 50020 to 10.200.136.98/32 1-65535\","
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50020\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } },"
"{ \"direction\" : 2,"
"\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23455\","
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to any 1-65535\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } },"
"{ \"direction\" : 1,"
"\"description\" : \"permit out udp from any 50021 to 10.200.136.98/32 1-65535\","
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50021\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } }"
"]"
"}"

View File

@ -377,7 +377,7 @@ void pcscf_rx_send_aar(uint8_t **rx_sid,
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC1 \
"permit out 17 from 172.20.166.84 to 172.18.128.20 20001"
"permit out 17 from 172.20.166.84 to 10.45.0.2 20001"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC1;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC1);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -388,7 +388,7 @@ void pcscf_rx_send_aar(uint8_t **rx_sid,
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC2 \
"permit in 17 from 172.18.128.20 to 172.20.166.84 20360"
"permit in 17 from 10.45.0.2 to 172.20.166.84 20360"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC2;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC2);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -421,7 +421,7 @@ void pcscf_rx_send_aar(uint8_t **rx_sid,
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC3 \
"permit out 17 from 172.20.166.84 to 172.18.128.20 20002"
"permit out 17 from 172.20.166.84 to 10.45.0.2 20002"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC3;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC3);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -432,7 +432,7 @@ void pcscf_rx_send_aar(uint8_t **rx_sid,
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC4 \
"permit in 17 from 172.18.128.20 to 172.20.166.84 20361"
"permit in 17 from 10.45.0.2 to 172.20.166.84 20361"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC4;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC4);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -670,7 +670,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC5 \
"permit out 17 from 45.45.0.3 50022 to 45.45.0.5 50026"
"permit out 17 from 45.45.0.5 50026 to 45.45.0.3 50022"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC5;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC5);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -681,7 +681,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC6 \
"permit in 17 from 45.45.0.5 50026 to 45.45.0.3 50022"
"permit in 17 from 45.45.0.3 50022 to 45.45.0.5 50026"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC6;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC6);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -692,7 +692,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC7 \
"permit out 17 from 45.45.0.3 50023 to 45.45.0.5 50027"
"permit out 17 from 45.45.0.5 50027 to 45.45.0.3 50023"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC7;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC7);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -703,7 +703,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC8 \
"permit in 17 from 45.45.0.5 50027 to 45.45.0.3 50023"
"permit in 17 from 45.45.0.3 50023 to 45.45.0.5 50027"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC8;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC8);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -854,7 +854,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC9 \
"permit out 17 from 45.45.0.3 60010 to 45.45.0.5 60010"
"permit out 17 from 45.45.0.5 60010 to 45.45.0.3 60010"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC9;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC9);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -865,7 +865,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC10 \
"permit in 17 from 45.45.0.5 60010 to 45.45.0.3 60010"
"permit in 17 from 45.45.0.3 60010 to 45.45.0.5 60010"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC10;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC10);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -876,7 +876,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC11 \
"permit out 17 from 45.45.0.3 60011 to 45.45.0.5 60011"
"permit out 17 from 45.45.0.5 60011 to 45.45.0.3 60011"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC11;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC11);
ret = fd_msg_avp_setvalue (avpch2, &val);
@ -887,7 +887,7 @@ void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type)
ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2);
ogs_assert(ret == 0);
#define TEST_OGS_DIAM_RX_FLOW_DESC12 \
"permit in 17 from 45.45.0.5 60011 to 45.45.0.3 60011"
"permit in 17 from 45.45.0.3 60011 to 45.45.0.5 60011"
val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC12;
val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC12);
ret = fd_msg_avp_setvalue (avpch2, &val);

View File

@ -695,16 +695,16 @@ static void test2_func(abts_case *tc, void *data)
"},"
"\"flow\" : ["
"{ \"direction\" : 2,"
"\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23454\","
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to any 1-65535\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } },"
"{ \"direction\" : 1,"
"\"description\" : \"permit out udp from any 50020 to 10.200.136.98/32 1-65535\","
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50020\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } },"
"{ \"direction\" : 2,"
"\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23455\","
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to any 1-65535\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } },"
"{ \"direction\" : 1,"
"\"description\" : \"permit out udp from any 50021 to 10.200.136.98/32 1-65535\","
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50021\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } }"
"]"
"}"

View File

@ -85,16 +85,16 @@ static void test1_func(abts_case *tc, void *data)
"},"
"\"flow\" : ["
"{ \"direction\" : 2,"
"\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23454\","
"\"description\" : \"permit out udp from 10.200.136.98/32 23454 to any 1-65535\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } },"
"{ \"direction\" : 1,"
"\"description\" : \"permit out udp from any 50020 to 10.200.136.98/32 1-65535\","
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50020\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } },"
"{ \"direction\" : 2,"
"\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23455\","
"\"description\" : \"permit out udp from 10.200.136.98/32 23455 to any 1-65535\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } },"
"{ \"direction\" : 1,"
"\"description\" : \"permit out udp from any 50021 to 10.200.136.98/32 1-65535\","
"\"description\" : \"permit out udp from 10.200.136.98/32 1-65535 to any 50021\","
"\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } }"
"]"
"}"