diff --git a/lib/core/include/arch/unix/core_arch_network.h b/lib/core/include/arch/unix/core_arch_network.h index 58d625b41..76b42a97e 100644 --- a/lib/core/include/arch/unix/core_arch_network.h +++ b/lib/core/include/arch/unix/core_arch_network.h @@ -4,10 +4,6 @@ #include "core_list.h" #include "core_network.h" -#if HAVE_ARPA_INET_H -#include -#endif - #if HAVE_NETDB_H #include #endif diff --git a/lib/core/include/core_network.h b/lib/core/include/core_network.h index c2b02ab7a..185e81e74 100644 --- a/lib/core/include/core_network.h +++ b/lib/core/include/core_network.h @@ -5,6 +5,10 @@ #include "core_time.h" #include "core_list.h" +#if HAVE_ARPA_INET_H +#include +#endif + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ diff --git a/src/app/context.c b/src/app/context.c index ca6367672..b0b783961 100644 --- a/src/app/context.c +++ b/src/app/context.c @@ -245,6 +245,16 @@ status_t context_parse_config() self.parameter.prefer_ipv4 = yaml_iter_bool(¶meter_iter); } + else if (!strcmp(parameter_key, "multicast")) + { + self.parameter.multicast = + yaml_iter_bool(¶meter_iter); + } + else if (!strcmp(parameter_key, "no_slaac")) + { + self.parameter.no_slaac = + yaml_iter_bool(¶meter_iter); + } else d_warn("unknown key `%s`", parameter_key); } diff --git a/src/app/context.h b/src/app/context.h index 26ea69518..0f4f34573 100644 --- a/src/app/context.h +++ b/src/app/context.h @@ -56,6 +56,8 @@ typedef struct _context_t { int no_ipv4; int no_ipv6; int prefer_ipv4; + int multicast; + int no_slaac; } parameter; } context_t; diff --git a/src/pgw/pgw_context.c b/src/pgw/pgw_context.c index 0b7eee13b..c96d5a5b0 100644 --- a/src/pgw/pgw_context.c +++ b/src/pgw/pgw_context.c @@ -671,6 +671,8 @@ status_t pgw_context_setup_trace_module() d_trace_level(&_tlv_msg, gtp); extern int _gtp_xact; d_trace_level(&_gtp_xact, gtp); + extern int _pgw_ipfw; + d_trace_level(&_pgw_ipfw, others); } if (others) @@ -1054,256 +1056,6 @@ pgw_bearer_t* pgw_bearer_next(pgw_bearer_t *bearer) return list_next(bearer); } -pgw_bearer_t* pgw_bearer_find_by_packet(pkbuf_t *pkt) -{ - hash_index_t *hi = NULL; - struct ip *ip_h = NULL; - struct ip6_hdr *ip6_h = NULL; - c_uint32_t *src_addr = NULL; - c_uint32_t *dst_addr = NULL; - int addr_len = 0; - c_uint8_t proto = 0; - int ip_hlen = 0; - char buf[CORE_ADDRSTRLEN]; - - d_assert(pkt, return NULL, "pkt is NULL"); - - ip_h = (struct ip *)pkt->payload; - if (ip_h->ip_v == 4) - { - ip_h = (struct ip *)pkt->payload; - ip6_h = NULL; - - proto = ip_h->ip_p; - ip_hlen = (ip_h->ip_hl)*4; - - src_addr = &ip_h->ip_src.s_addr; - dst_addr = &ip_h->ip_dst.s_addr; - addr_len = 4; - } - else if (ip_h->ip_v == 6) - { - ip_h = NULL; - ip6_h = (struct ip6_hdr *)pkt->payload; - - proto = ip6_h->ip6_nxt; - ip_hlen = 40; /* TODO */ - - src_addr = (c_uint32_t *)ip6_h->ip6_src.s6_addr; - dst_addr = (c_uint32_t *)ip6_h->ip6_dst.s6_addr; - addr_len = 16; - - } - else - d_error("Invalid IP version = %d\n", ip_h->ip_v); - - d_trace(50, "PROTO:%d SRC:%08x %08x %08x %08x\n", - proto, ntohl(src_addr[0]), ntohl(src_addr[1]), - ntohl(src_addr[2]), ntohl(src_addr[3])); - d_trace(50, "HLEN:%d DST:%08x %08x %08x %08x\n", - ip_hlen, ntohl(dst_addr[0]), ntohl(dst_addr[1]), - ntohl(dst_addr[2]), ntohl(dst_addr[3])); - - - /* TODO: Need to use the method of FAST matching algorithm and - * implementation . - * Until be ready, linear searching will be use to find the bearer. - */ - - for (hi = pgw_sess_first(); hi; hi = pgw_sess_next(hi)) - { - pgw_sess_t *sess = pgw_sess_this(hi); - d_assert(sess, return NULL,); - - if (sess->ipv4) - d_trace(50, "PAA IPv4:%s\n", INET_NTOP(&sess->ipv4->addr, buf)); - if (sess->ipv6) - d_trace(50, "PAA IPv6:%s\n", INET6_NTOP(&sess->ipv6->addr, buf)); - - if ((sess->ipv4 && memcmp(dst_addr, sess->ipv4->addr, addr_len) == 0) || - (sess->ipv6 && memcmp(dst_addr, sess->ipv6->addr, addr_len) == 0)) - { - pgw_bearer_t *default_bearer = NULL; - pgw_bearer_t *bearer = NULL; - /* Found */ - - /* Save the default bearer */ - default_bearer = pgw_default_bearer_in_sess(sess); - d_assert(default_bearer, return NULL, "No default Bearer"); - - bearer = pgw_bearer_next(default_bearer); - /* Find the bearer with matched */ - for (; bearer; bearer = pgw_bearer_next(bearer)) - { - pgw_pf_t *pf = NULL; - - if (bearer->ebi == 0) - { - /* Create Bearer Response is not received */ - continue; - } - - for (pf = pgw_pf_first(bearer); pf; pf = pgw_pf_next(pf)) - { - int k; - c_uint32_t src_mask[4]; - c_uint32_t dst_mask[4]; - - d_trace(50, "DIR:%d PROTO:%d SRC:%d-%d DST:%d-%d\n", - pf->direction, pf->rule.proto, - pf->rule.port.local.low, - pf->rule.port.local.high, - pf->rule.port.remote.low, - pf->rule.port.remote.high); - d_trace(50, "SRC:%08x %08x %08x %08x/%08x %08x %08x %08x\n", - ntohl(pf->rule.ip.local.addr[0]), - ntohl(pf->rule.ip.local.addr[1]), - ntohl(pf->rule.ip.local.addr[2]), - ntohl(pf->rule.ip.local.addr[3]), - ntohl(pf->rule.ip.local.mask[0]), - ntohl(pf->rule.ip.local.mask[1]), - ntohl(pf->rule.ip.local.mask[2]), - ntohl(pf->rule.ip.local.mask[3])); - d_trace(50, "DST:%08x %08x %08x %08x/%08x %08x %08x %08x\n", - ntohl(pf->rule.ip.remote.addr[0]), - ntohl(pf->rule.ip.remote.addr[1]), - ntohl(pf->rule.ip.remote.addr[2]), - ntohl(pf->rule.ip.remote.addr[3]), - ntohl(pf->rule.ip.remote.mask[0]), - ntohl(pf->rule.ip.remote.mask[1]), - ntohl(pf->rule.ip.remote.mask[2]), - ntohl(pf->rule.ip.remote.mask[3])); - - if (pf->direction != 1) - { - continue; - } - - for (k = 0; k < 4; k++) - { - src_mask[k] = src_addr[k] & pf->rule.ip.local.mask[k]; - dst_mask[k] = dst_addr[k] & pf->rule.ip.remote.mask[k]; - } - - if (memcmp(src_mask, pf->rule.ip.local.addr, - addr_len) == 0 && - memcmp(dst_mask, pf->rule.ip.remote.addr, - addr_len) == 0) - { - /* Protocol match */ - if (pf->rule.proto == 0) /* IP */ - { - /* No need to match port */ - break; - } - - if (pf->rule.proto == proto) - { - if (pf->rule.proto == IPPROTO_TCP) - { - struct tcphdr *tcph = - (struct tcphdr *) - ((char *)pkt->payload + ip_hlen); - - /* Source port */ - if (pf->rule.port.local.low && - ntohs(tcph->th_sport) < - pf->rule.port.local.low) - { - continue; - } - - if (pf->rule.port.local.high && - ntohs(tcph->th_sport) > - pf->rule.port.local.high) - { - continue; - } - - /* Dst Port*/ - if (pf->rule.port.remote.low && - ntohs(tcph->th_dport) < - pf->rule.port.remote.low) - { - continue; - } - - if (pf->rule.port.remote.high && - ntohs(tcph->th_dport) > - pf->rule.port.remote.high) - { - continue; - } - - /* Matched */ - break; - } - else if (pf->rule.proto == IPPROTO_UDP) - { - struct udphdr *udph = - (struct udphdr *) - ((char *)pkt->payload + ip_hlen); - - /* Source port */ - if (pf->rule.port.local.low && - ntohs(udph->uh_sport) < - pf->rule.port.local.low) - { - continue; - } - - if (pf->rule.port.local.high && - ntohs(udph->uh_sport) > - pf->rule.port.local.high) - { - continue; - } - - /* Dst Port*/ - if (pf->rule.port.remote.low && - ntohs(udph->uh_dport) < - pf->rule.port.remote.low) - { - continue; - } - - if (pf->rule.port.remote.high && - ntohs(udph->uh_dport) > - pf->rule.port.remote.high) - { - continue; - } - - /* Matched */ - break; - } - else - { - /* No need to match port */ - break; - } - - } - } - - } - - if (pf) - { - bearer = pf->bearer; - d_trace(50,"FOUND Bearer EBI = %d\n", bearer->ebi); - break; - } - - } - - return (bearer ? bearer : default_bearer); - } - } - - return NULL; -} - pgw_pf_t *pgw_pf_add(pgw_bearer_t *bearer, c_uint32_t precedence) { pgw_pf_t *pf = NULL; diff --git a/src/pgw/pgw_gtp_path.c b/src/pgw/pgw_gtp_path.c index 2b96a660e..f49ed2747 100644 --- a/src/pgw/pgw_gtp_path.c +++ b/src/pgw/pgw_gtp_path.c @@ -6,6 +6,7 @@ #include "gtp_node.h" #include "gtp_path.h" +#include "context.h" #include "pgw_context.h" #include "pgw_event.h" #include "pgw_gtp_path.h" @@ -76,31 +77,34 @@ static int _gtpv1_tun_recv_cb(sock_id sock, void *data) } else { - struct ip *ip_h = NULL; - struct ip6_hdr *ip6_h = NULL; - - ip_h = (struct ip *)recvbuf->payload; - if (ip_h->ip_v == 6) + if (context_self()->parameter.multicast) { - ip6_h = (struct ip6_hdr *)recvbuf->payload; - if (IN6_IS_ADDR_MULTICAST(&ip6_h->ip6_dst)) + struct ip *ip_h = NULL; + struct ip6_hdr *ip6_h = NULL; + + ip_h = (struct ip *)recvbuf->payload; + if (ip_h->ip_v == 6) { - hash_index_t *hi = NULL; - - /* IPv6 Multicast */ - for (hi = pgw_sess_first(); hi; hi = pgw_sess_next(hi)) + ip6_h = (struct ip6_hdr *)recvbuf->payload; + if (IN6_IS_ADDR_MULTICAST(&ip6_h->ip6_dst)) { - pgw_sess_t *sess = pgw_sess_this(hi); - d_assert(sess, return 0,); - if (sess->ipv6) - { - /* PDN IPv6 is avaiable */ - pgw_bearer_t *bearer = pgw_default_bearer_in_sess(sess); - d_assert(bearer, return 0,); + hash_index_t *hi = NULL; - rv = pgw_gtp_send_to_bearer(bearer, recvbuf); - d_assert(rv == CORE_OK,, - "pgw_gtp_send_to_bearer failed"); + /* IPv6 Multicast */ + for (hi = pgw_sess_first(); hi; hi = pgw_sess_next(hi)) + { + pgw_sess_t *sess = pgw_sess_this(hi); + d_assert(sess, return 0,); + if (sess->ipv6) + { + /* PDN IPv6 is avaiable */ + pgw_bearer_t *bearer = pgw_default_bearer_in_sess(sess); + d_assert(bearer, return 0,); + + rv = pgw_gtp_send_to_bearer(bearer, recvbuf); + d_assert(rv == CORE_OK,, + "pgw_gtp_send_to_bearer failed"); + } } } } diff --git a/src/pgw/pgw_ipfw.c b/src/pgw/pgw_ipfw.c index 9f887eb71..e265b1af3 100644 --- a/src/pgw/pgw_ipfw.c +++ b/src/pgw/pgw_ipfw.c @@ -1,5 +1,6 @@ #define TRACE_MODULE _pgw_ipfw +#include "core_network.h" #include "pgw_ipfw.h" #include "ipfw2.h" @@ -148,3 +149,254 @@ status_t pgw_compile_packet_filter(pgw_rule_t *pgw_rule, c_int8_t *description) return CORE_OK; } + +pgw_bearer_t* pgw_bearer_find_by_packet(pkbuf_t *pkt) +{ + hash_index_t *hi = NULL; + struct ip *ip_h = NULL; + struct ip6_hdr *ip6_h = NULL; + c_uint32_t *src_addr = NULL; + c_uint32_t *dst_addr = NULL; + int addr_len = 0; + c_uint8_t proto = 0; + int ip_hlen = 0; + char buf[CORE_ADDRSTRLEN]; + + d_assert(pkt, return NULL, "pkt is NULL"); + + ip_h = (struct ip *)pkt->payload; + if (ip_h->ip_v == 4) + { + ip_h = (struct ip *)pkt->payload; + ip6_h = NULL; + + proto = ip_h->ip_p; + ip_hlen = (ip_h->ip_hl)*4; + + src_addr = &ip_h->ip_src.s_addr; + dst_addr = &ip_h->ip_dst.s_addr; + addr_len = 4; + } + else if (ip_h->ip_v == 6) + { + ip_h = NULL; + ip6_h = (struct ip6_hdr *)pkt->payload; + + proto = ip6_h->ip6_nxt; + ip_hlen = 40; /* TODO */ + + src_addr = (c_uint32_t *)ip6_h->ip6_src.s6_addr; + dst_addr = (c_uint32_t *)ip6_h->ip6_dst.s6_addr; + addr_len = 16; + + } + else + d_error("Invalid IP version = %d\n", ip_h->ip_v); + + d_trace(50, "PROTO:%d SRC:%08x %08x %08x %08x\n", + proto, ntohl(src_addr[0]), ntohl(src_addr[1]), + ntohl(src_addr[2]), ntohl(src_addr[3])); + d_trace(50, "HLEN:%d DST:%08x %08x %08x %08x\n", + ip_hlen, ntohl(dst_addr[0]), ntohl(dst_addr[1]), + ntohl(dst_addr[2]), ntohl(dst_addr[3])); + + + /* TODO: Need to use the method of FAST matching algorithm and + * implementation . + * Until be ready, linear searching will be use to find the bearer. + */ + + for (hi = pgw_sess_first(); hi; hi = pgw_sess_next(hi)) + { + pgw_sess_t *sess = pgw_sess_this(hi); + d_assert(sess, return NULL,); + + if (sess->ipv4) + d_trace(50, "PAA IPv4:%s\n", INET_NTOP(&sess->ipv4->addr, buf)); + if (sess->ipv6) + d_trace(50, "PAA IPv6:%s\n", INET6_NTOP(&sess->ipv6->addr, buf)); + + if ((sess->ipv4 && memcmp(dst_addr, sess->ipv4->addr, addr_len) == 0) || + (sess->ipv6 && memcmp(dst_addr, sess->ipv6->addr, addr_len) == 0)) + { + pgw_bearer_t *default_bearer = NULL; + pgw_bearer_t *bearer = NULL; + /* Found */ + + /* Save the default bearer */ + default_bearer = pgw_default_bearer_in_sess(sess); + d_assert(default_bearer, return NULL, "No default Bearer"); + + bearer = pgw_bearer_next(default_bearer); + /* Find the bearer with matched */ + for (; bearer; bearer = pgw_bearer_next(bearer)) + { + pgw_pf_t *pf = NULL; + + if (bearer->ebi == 0) + { + /* Create Bearer Response is not received */ + continue; + } + + for (pf = pgw_pf_first(bearer); pf; pf = pgw_pf_next(pf)) + { + int k; + c_uint32_t src_mask[4]; + c_uint32_t dst_mask[4]; + + d_trace(50, "DIR:%d PROTO:%d SRC:%d-%d DST:%d-%d\n", + pf->direction, pf->rule.proto, + pf->rule.port.local.low, + pf->rule.port.local.high, + pf->rule.port.remote.low, + pf->rule.port.remote.high); + d_trace(50, "SRC:%08x %08x %08x %08x/%08x %08x %08x %08x\n", + ntohl(pf->rule.ip.local.addr[0]), + ntohl(pf->rule.ip.local.addr[1]), + ntohl(pf->rule.ip.local.addr[2]), + ntohl(pf->rule.ip.local.addr[3]), + ntohl(pf->rule.ip.local.mask[0]), + ntohl(pf->rule.ip.local.mask[1]), + ntohl(pf->rule.ip.local.mask[2]), + ntohl(pf->rule.ip.local.mask[3])); + d_trace(50, "DST:%08x %08x %08x %08x/%08x %08x %08x %08x\n", + ntohl(pf->rule.ip.remote.addr[0]), + ntohl(pf->rule.ip.remote.addr[1]), + ntohl(pf->rule.ip.remote.addr[2]), + ntohl(pf->rule.ip.remote.addr[3]), + ntohl(pf->rule.ip.remote.mask[0]), + ntohl(pf->rule.ip.remote.mask[1]), + ntohl(pf->rule.ip.remote.mask[2]), + ntohl(pf->rule.ip.remote.mask[3])); + + if (pf->direction != 1) + { + continue; + } + + for (k = 0; k < 4; k++) + { + src_mask[k] = src_addr[k] & pf->rule.ip.local.mask[k]; + dst_mask[k] = dst_addr[k] & pf->rule.ip.remote.mask[k]; + } + + if (memcmp(src_mask, pf->rule.ip.local.addr, + addr_len) == 0 && + memcmp(dst_mask, pf->rule.ip.remote.addr, + addr_len) == 0) + { + /* Protocol match */ + if (pf->rule.proto == 0) /* IP */ + { + /* No need to match port */ + break; + } + + if (pf->rule.proto == proto) + { + if (pf->rule.proto == IPPROTO_TCP) + { + struct tcphdr *tcph = + (struct tcphdr *) + ((char *)pkt->payload + ip_hlen); + + /* Source port */ + if (pf->rule.port.local.low && + ntohs(tcph->th_sport) < + pf->rule.port.local.low) + { + continue; + } + + if (pf->rule.port.local.high && + ntohs(tcph->th_sport) > + pf->rule.port.local.high) + { + continue; + } + + /* Dst Port*/ + if (pf->rule.port.remote.low && + ntohs(tcph->th_dport) < + pf->rule.port.remote.low) + { + continue; + } + + if (pf->rule.port.remote.high && + ntohs(tcph->th_dport) > + pf->rule.port.remote.high) + { + continue; + } + + /* Matched */ + break; + } + else if (pf->rule.proto == IPPROTO_UDP) + { + struct udphdr *udph = + (struct udphdr *) + ((char *)pkt->payload + ip_hlen); + + /* Source port */ + if (pf->rule.port.local.low && + ntohs(udph->uh_sport) < + pf->rule.port.local.low) + { + continue; + } + + if (pf->rule.port.local.high && + ntohs(udph->uh_sport) > + pf->rule.port.local.high) + { + continue; + } + + /* Dst Port*/ + if (pf->rule.port.remote.low && + ntohs(udph->uh_dport) < + pf->rule.port.remote.low) + { + continue; + } + + if (pf->rule.port.remote.high && + ntohs(udph->uh_dport) > + pf->rule.port.remote.high) + { + continue; + } + + /* Matched */ + break; + } + else + { + /* No need to match port */ + break; + } + + } + } + + } + + if (pf) + { + bearer = pf->bearer; + d_trace(50,"FOUND Bearer EBI = %d\n", bearer->ebi); + break; + } + + } + + return (bearer ? bearer : default_bearer); + } + } + + return NULL; +} + diff --git a/support/config/nextepc.conf.in b/support/config/nextepc.conf.in index 7da7e1733..58837fb5c 100644 --- a/support/config/nextepc.conf.in +++ b/support/config/nextepc.conf.in @@ -10,61 +10,30 @@ logger: others: 1 # -# +# parameter: # # o Disable use of IPv4 addresses (only IPv6) -# Type : BOOLEAN -# -# o IPv4 enabled -# parameter: -# -# o IPv4 disabled -# parameter: # no_ipv4: true # -# -# -# # o Disable use of IPv6 addresses (only IPv4) -# Type : BOOLEAN -# -# o IPv6 enabled -# parameter: -# -# o IPv6 disabled -# parameter: # no_ipv6: true # -# -# -# # o Prefer IPv4 instead of IPv6 for estabishing new GTP connections. -# Type : BOOLEAN -# Default : IPv6 is attempted first. -# -# o IPv6 preferred -# parameter: -# -# o IPv4 preferred -# parameter: # prefer_ipv4: true # -# -# -# # o Disable EPC elements (Only applicable `nextepc-epcd`) -# Type : BOOLEAN -# -# o Enable HSS/SGW/PGW/PCRF -# parameter: -# -# o Disable HSS/SGW/PGW/PCRF -# parameter: # no_hss: true # no_sgw: true # no_pgw: true # no_pcrf: true # +# o Enable Multicast traffic to the UE +# multicast: true +# +# o Disable Stateless Address Autoconfiguration for IPv6 +# no_slaac: true +# +# parameter: mme: