From f5601a95f75fc40e7ed782340dc8aea36e1600a0 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 20 Sep 2020 23:35:10 -0400 Subject: [PATCH] Fix semantic error in packet filter [#338] RX : permit out from to GX : permit out from to PFCP : permit out from to RULE : Source Destination TFT : Local REMOTE RX : permit in from to GX : permit out from to PFCP : permit out from to RULE : Source Destination TFT : Local REMOTE --- lib/ipfw/ogs-ipfw.c | 167 ++++++++++++++++++++++------------ lib/ipfw/ogs-ipfw.h | 38 ++++++-- lib/pfcp/context.c | 11 ++- lib/pfcp/context.h | 17 ++-- lib/pfcp/handler.c | 71 +++++++++++++++ src/pcrf/pcrf-gx-path.c | 16 +++- src/sgwu/context.c | 8 +- src/sgwu/context.h | 4 +- src/smf/bearer-binding.c | 174 ++++++++++++++++++++++++------------ src/smf/s5c-handler.c | 98 +++++++++++++------- src/upf/context.c | 17 +--- src/upf/context.h | 3 +- src/upf/gtp-path.c | 4 +- src/upf/rule-match.c | 142 ++++++++++++++--------------- tests/volte/bearer-test.c | 8 +- tests/volte/pcscf-fd-path.c | 24 ++--- tests/volte/rx-test.c | 8 +- tests/volte/session-test.c | 8 +- 18 files changed, 527 insertions(+), 291 deletions(-) diff --git a/lib/ipfw/ogs-ipfw.c b/lib/ipfw/ogs-ipfw.c index 9049c29ea..87db15f8b 100644 --- a/lib/ipfw/ogs-ipfw.c +++ b/lib/ipfw/ogs-ipfw.c @@ -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 + * + * + * RULE : Source Destination + * --> + * GX : permit out from to + * PFCP : permit out from to + * + * + * RULE : Source Destination + * --> + * GX : permit out from to + * PFCP : permit out from to + */ + 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)); +} diff --git a/lib/ipfw/ogs-ipfw.h b/lib/ipfw/ogs-ipfw.h index 145d9cca7..6c98b178c 100644 --- a/lib/ipfw/ogs-ipfw.h +++ b/lib/ipfw/ogs-ipfw.h @@ -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 + * + * + * RX : permit out from to + * GX : permit out from to + * PFCP : permit out from to + * RULE : Source Destination + * TFT : Local REMOTE + * + * + * RX : permit in from to + * GX : permit out from to + * PFCP : permit out from to + * RULE : Source Destination + * TFT : Local REMOTE + */ +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 diff --git a/lib/pfcp/context.c b/lib/pfcp/context.c index 2966cdac6..db41c6529 100644 --- a/lib/pfcp/context.c +++ b/lib/pfcp/context.c @@ -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) diff --git a/lib/pfcp/context.h b/lib/pfcp/context.h index f7b4c1be0..240999fb0 100644 --- a/lib/pfcp/context.h +++ b/lib/pfcp/context.h @@ -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); diff --git a/lib/pfcp/handler.c b/lib/pfcp/handler.c index 39c5231c4..755ede3f5 100644 --- a/lib/pfcp/handler.c +++ b/lib/pfcp/handler.c @@ -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 + * + * + * GX : permit out from to + * RULE : Source Destination + * + * + * GX : permit out from to + * RULE : Source Destination + */ + + /* 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 + * + * + * GX : permit out from to + * RULE : Source Destination + * + * + * GX : permit out from to + * RULE : Source Destination + */ + + /* Uplink data flow */ + if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) + ogs_ipfw_rule_swap(&rule->ipfw); + ogs_free(flow_description); } diff --git a/src/pcrf/pcrf-gx-path.c b/src/pcrf/pcrf-gx-path.c index 9b36daad3..dbd4704d3 100644 --- a/src/pcrf/pcrf-gx-path.c +++ b/src/pcrf/pcrf-gx-path.c @@ -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); diff --git a/src/sgwu/context.c b/src/sgwu/context.c index f7650fc8b..7c91ba6b5 100644 --- a/src/sgwu/context.c +++ b/src/sgwu/context.c @@ -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); diff --git a/src/sgwu/context.h b/src/sgwu/context.h index 5bc969b42..3914f4562 100644 --- a/src/sgwu/context.h +++ b/src/sgwu/context.h @@ -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); diff --git a/src/smf/bearer-binding.c b/src/smf/bearer-binding.c index 20f0c8d8e..403e8d043 100644 --- a/src/smf/bearer-binding.c +++ b/src/smf/bearer-binding.c @@ -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 + * + * + * RULE : Source Destination + * TFT : Local REMOTE + * + * + * RULE : Source Destination + * TFT : Local REMOTE + */ 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 + * + * + * GX : permit out from to + * --> + * RULE : Source Destination + * + * + * GX : permit out from to + * --> + * RULE : Source Destination + */ + 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); diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index e970a79ac..3ed8920f1 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -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 + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + */ + 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 + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + */ + 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; } diff --git a/src/upf/context.c b/src/upf/context.c index 3caa5f351..75fa54811 100644 --- a/src/upf/context.c +++ b/src/upf/context.c @@ -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); diff --git a/src/upf/context.h b/src/upf/context.h index 13f23a082..5e624f952 100644 --- a/src/upf/context.h +++ b/src/upf/context.h @@ -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); diff --git a/src/upf/gtp-path.c b/src/upf/gtp-path.c index 635f0b7ce..01e394dff 100644 --- a/src/upf/gtp-path.c +++ b/src/upf/gtp-path.c @@ -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); diff --git a/src/upf/rule-match.c b/src/upf/rule-match.c index 8600cfde3..3782b9dfe 100644 --- a/src/upf/rule-match.c +++ b/src/upf/rule-match.c @@ -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"); } diff --git a/tests/volte/bearer-test.c b/tests/volte/bearer-test.c index fcaa7d524..8c8ea7019 100644 --- a/tests/volte/bearer-test.c +++ b/tests/volte/bearer-test.c @@ -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\" } }" "]" "}" diff --git a/tests/volte/pcscf-fd-path.c b/tests/volte/pcscf-fd-path.c index 2de00c6af..8b0377e71 100644 --- a/tests/volte/pcscf-fd-path.c +++ b/tests/volte/pcscf-fd-path.c @@ -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); diff --git a/tests/volte/rx-test.c b/tests/volte/rx-test.c index 502e90f11..d5f24dd1c 100644 --- a/tests/volte/rx-test.c +++ b/tests/volte/rx-test.c @@ -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\" } }" "]" "}" diff --git a/tests/volte/session-test.c b/tests/volte/session-test.c index ed819d68d..f01e255da 100644 --- a/tests/volte/session-test.c +++ b/tests/volte/session-test.c @@ -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\" } }" "]" "}"