router advertisement use link-local-address in source ip

This commit is contained in:
Sukchan Lee 2017-12-17 07:25:36 +00:00
parent a102864428
commit cdaf1c0468
5 changed files with 74 additions and 6 deletions

View File

@ -155,6 +155,7 @@ CORE_DECLARE(status_t) core_copyaddrinfo(
c_sockaddr_t **dst, const c_sockaddr_t *src);
CORE_DECLARE(status_t) core_filteraddrinfo(c_sockaddr_t **sa_list, int family);
CORE_DECLARE(status_t) core_sortaddrinfo(c_sockaddr_t **sa_list, int family);
CORE_DECLARE(c_sockaddr_t *) core_link_local_addr_by_dev(const char *dev);
#define CORE_ADDRSTRLEN INET6_ADDRSTRLEN
#define CORE_ADDR(__aDDR, __bUF) \

View File

@ -179,6 +179,49 @@ status_t core_sortaddrinfo(c_sockaddr_t **sa_list, int family)
return CORE_OK;
}
c_sockaddr_t *core_link_local_addr_by_dev(const char *dev)
{
struct ifaddrs *iflist, *cur;
int rc;
d_assert(dev, return NULL,);
rc = getifaddrs(&iflist);
if (rc != 0)
{
d_error("getifaddrs failed(%d:%s)", errno, strerror(errno));
return NULL;
}
for (cur = iflist; cur != NULL; cur = cur->ifa_next)
{
c_sockaddr_t *addr = NULL;
if (cur->ifa_addr == NULL) /* may happen with ppp interfaces */
continue;
if (strcmp(dev, cur->ifa_name) != 0)
continue;
if (cur->ifa_addr->sa_family == AF_INET)
continue;
addr = (c_sockaddr_t *)cur->ifa_addr;
if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6.sin6_addr))
continue;
addr = core_calloc(1, sizeof(c_sockaddr_t));
d_assert(addr, return NULL,);
memcpy(&addr->sa, cur->ifa_addr, sockaddr_len(cur->ifa_addr));
freeifaddrs(iflist);
return addr;
}
freeifaddrs(iflist);
return NULL;
}
const char *core_inet_ntop(void *sa, char *buf, int buflen)
{
int family;

View File

@ -1294,6 +1294,10 @@ status_t pgw_dev_remove(pgw_dev_t *dev)
d_assert(dev, return CORE_ERROR, "Null param");
list_remove(&self.dev_list, dev);
if (dev->link_local_addr)
core_freeaddrinfo(dev->link_local_addr);
pool_free_node(&pgw_dev_pool, dev);
return CORE_OK;

View File

@ -69,7 +69,7 @@ typedef struct _pgw_dev_t {
c_int8_t ifname[IFNAMSIZ];
sock_id sock;
c_uint8_t link_local_addr[IPV6_LEN];
c_sockaddr_t *link_local_addr;
} pgw_dev_t;
typedef struct _pgw_subnet_t {

View File

@ -15,7 +15,7 @@
c_uint16_t in_cksum(c_uint16_t *addr, int len);
static status_t pgw_gtp_handle_multicast(pkbuf_t *recvbuf);
static status_t pgw_gtp_handle_slacc(pgw_sess_t *sess, pkbuf_t *recvbuf);
static status_t pgw_gtp_handle_slaac(pgw_sess_t *sess, pkbuf_t *recvbuf);
static status_t pgw_gtp_send_to_bearer(pgw_bearer_t *bearer, pkbuf_t *sendbuf);
static status_t pgw_gtp_send_router_advertisement(pgw_sess_t *sess);
@ -151,13 +151,13 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data)
/* Check IPv6 */
if (context_self()->parameter.no_slaac == 0 && ip_h->ip_v == 6)
{
rv = pgw_gtp_handle_slacc(sess, pkbuf);
rv = pgw_gtp_handle_slaac(sess, pkbuf);
if (rv == PGW_GTP_HANDLED)
{
pkbuf_free(pkbuf);
return 0;
}
d_assert(rv == CORE_OK,, "pgw_gtp_handle_slacc() failed");
d_assert(rv == CORE_OK,, "pgw_gtp_handle_slaac() failed");
}
dev = subnet->dev;
@ -251,6 +251,10 @@ status_t pgw_gtp_open()
}
}
/* Link-Local Address for PGW_TUN */
for (dev = pgw_dev_first(); dev; dev = pgw_dev_next(dev))
dev->link_local_addr = core_link_local_addr_by_dev(dev->ifname);
return CORE_OK;
}
@ -308,7 +312,7 @@ static status_t pgw_gtp_handle_multicast(pkbuf_t *recvbuf)
return CORE_OK;
}
static status_t pgw_gtp_handle_slacc(pgw_sess_t *sess, pkbuf_t *recvbuf)
static status_t pgw_gtp_handle_slaac(pgw_sess_t *sess, pkbuf_t *recvbuf)
{
status_t rv;
struct ip *ip_h = NULL;
@ -377,8 +381,14 @@ static status_t pgw_gtp_send_router_advertisement(pgw_sess_t *sess)
{
status_t rv;
pkbuf_t *pkbuf = NULL;
pgw_bearer_t *bearer = NULL;
ipsubnet_t src_ipsub, dst_ipsub;
pgw_ue_ip_t *ue_ip = NULL;
pgw_subnet_t *subnet = NULL;
pgw_dev_t *dev = NULL;
ipsubnet_t src_ipsub;
ipsubnet_t dst_ipsub;
c_uint16_t plen = 0;
c_uint8_t nxt = 0;
c_uint8_t *p = NULL;
@ -389,6 +399,12 @@ static status_t pgw_gtp_send_router_advertisement(pgw_sess_t *sess)
d_assert(sess, return CORE_ERROR,);
bearer = pgw_default_bearer_in_sess(sess);
d_assert(bearer, return CORE_ERROR,);
ue_ip = sess->ipv6;
d_assert(ue_ip, return CORE_ERROR,);
subnet = ue_ip->subnet;
d_assert(subnet, return CORE_ERROR,);
dev = subnet->dev;
d_assert(dev, return CORE_ERROR,);
pkbuf = pkbuf_alloc(GTPV1U_HEADER_LEN, 200);
d_assert(pkbuf, return CORE_ERROR,);
@ -403,6 +419,10 @@ static status_t pgw_gtp_send_router_advertisement(pgw_sess_t *sess)
rv = core_ipsubnet(&src_ipsub, "fe80::1", NULL);
d_assert(rv == CORE_OK, return CORE_ERROR,);
if (dev->link_local_addr)
memcpy(src_ipsub.sub, dev->link_local_addr->sin6.sin6_addr.s6_addr,
sizeof src_ipsub.sub);
rv = core_ipsubnet(&dst_ipsub, "ff02::1", NULL);
d_assert(rv == CORE_OK, return CORE_ERROR,);