parameter.multicast, parameter.no_slaac is added

This commit is contained in:
Sukchan Lee 2017-12-16 09:24:27 +09:00
parent 7de0753b2c
commit 70286b3fd0
8 changed files with 303 additions and 314 deletions

View File

@ -4,10 +4,6 @@
#include "core_list.h"
#include "core_network.h"
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#if HAVE_NETDB_H
#include <netdb.h>
#endif

View File

@ -5,6 +5,10 @@
#include "core_time.h"
#include "core_list.h"
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

View File

@ -245,6 +245,16 @@ status_t context_parse_config()
self.parameter.prefer_ipv4 =
yaml_iter_bool(&parameter_iter);
}
else if (!strcmp(parameter_key, "multicast"))
{
self.parameter.multicast =
yaml_iter_bool(&parameter_iter);
}
else if (!strcmp(parameter_key, "no_slaac"))
{
self.parameter.no_slaac =
yaml_iter_bool(&parameter_iter);
}
else
d_warn("unknown key `%s`", parameter_key);
}

View File

@ -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;

View File

@ -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;

View File

@ -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");
}
}
}
}

View File

@ -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;
}

View File

@ -10,61 +10,30 @@ logger:
others: 1
#
# <IPv4>
# parameter:
#
# o Disable use of IPv4 addresses (only IPv6)
# Type : BOOLEAN
#
# o IPv4 enabled
# parameter:
#
# o IPv4 disabled
# parameter:
# no_ipv4: true
#
#
# <IPv6>
#
# o Disable use of IPv6 addresses (only IPv4)
# Type : BOOLEAN
#
# o IPv6 enabled
# parameter:
#
# o IPv6 disabled
# parameter:
# no_ipv6: true
#
#
# <GTP Client Preference>
#
# 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
#
#
# <EPC elements>
#
# 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: