summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2017-12-25 17:57:53 +0300
committerDmitry Kozlov <xeb@mail.ru>2017-12-25 17:57:53 +0300
commit4c8340c4abe04d896de8e0a190ec412d4ce4f30f (patch)
treef18a8b4f56c8007bcbcafd6ec6fe43af5d5f6cfd
parentcd9bb5cfe3afec23ef62f2aa2ed82e6dd04a32f9 (diff)
downloadaccel-ppp-4c8340c4abe04d896de8e0a190ec412d4ce4f30f.tar.gz
accel-ppp-4c8340c4abe04d896de8e0a190ec412d4ce4f30f.zip
ipv6: implemented special handling of /128 prefixes
If prefix length is 128 then send RA with 64 prefix length and add point-to-point ipv6 address on interface
-rw-r--r--accel-pppd/ipv6/dhcpv6.c15
-rw-r--r--accel-pppd/ipv6/nd.c54
2 files changed, 40 insertions, 29 deletions
diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c
index d99165c6..2122f290 100644
--- a/accel-pppd/ipv6/dhcpv6.c
+++ b/accel-pppd/ipv6/dhcpv6.c
@@ -166,6 +166,9 @@ static void build_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_add
{
memcpy(addr, &a->addr, sizeof(*addr));
+ if (a->prefix_len == 128)
+ return;
+
if (a->prefix_len <= 64)
*(uint64_t *)(addr->s6_addr + 8) = intf_id;
else
@@ -310,10 +313,14 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i
ia_addr->valid_lifetime = htonl(conf_valid_lifetime);
if (!a->installed) {
- if (a->prefix_len > 64)
- ip6route_add(ses->ifindex, &a->addr, a->prefix_len, 0);
- else {
- struct in6_addr addr;
+ struct in6_addr addr, peer_addr;
+ if (a->prefix_len == 128) {
+ memcpy(addr.s6_addr, &a->addr, 8);
+ memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8);
+ memcpy(peer_addr.s6_addr, &a->addr, 8);
+ memcpy(peer_addr.s6_addr + 8, &ses->ipv6->peer_intf_id, 8);
+ ip6addr_add_peer(ses->ifindex, &addr, &peer_addr);
+ } else {
memcpy(addr.s6_addr, &a->addr, 8);
memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8);
ip6addr_add(ses->ifindex, &addr, a->prefix_len);
diff --git a/accel-pppd/ipv6/nd.c b/accel-pppd/ipv6/nd.c
index f2a259ad..231f1802 100644
--- a/accel-pppd/ipv6/nd.c
+++ b/accel-pppd/ipv6/nd.c
@@ -94,8 +94,9 @@ static void *pd_key;
#define BUF_SIZE 1024
static mempool_t buf_pool;
-static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *addr)
+static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *dst_addr)
{
+ struct ap_session *ses = h->ses;
void *buf = mempool_alloc(buf_pool), *endptr;
struct nd_router_advert *adv = buf;
struct nd_opt_prefix_info *pinfo;
@@ -105,14 +106,15 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad
struct nd_opt_dnssl_info_local *dnsslinfo;
//struct nd_opt_mtu *mtu;
struct ipv6db_addr_t *a;
- int i;
+ struct in6_addr addr, peer_addr;
+ int i, prefix_len;
if (!buf) {
log_emerg("out of memory\n");
return;
}
- if (!h->ses->ipv6) {
+ if (!ses->ipv6) {
triton_timer_del(&h->timer);
return;
}
@@ -128,30 +130,32 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad
adv->nd_ra_retransmit = htonl(conf_AdvRetransTimer);
pinfo = (struct nd_opt_prefix_info *)(adv + 1);
- list_for_each_entry(a, &h->ses->ipv6->addr_list, entry) {
- if (a->prefix_len < 128) {
- memset(pinfo, 0, sizeof(*pinfo));
- pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
- pinfo->nd_opt_pi_len = 4;
- pinfo->nd_opt_pi_prefix_len = a->prefix_len;
- pinfo->nd_opt_pi_flags_reserved =
- ((a->flag_onlink || conf_AdvPrefixOnLinkFlag) ? ND_OPT_PI_FLAG_ONLINK : 0) |
- ((a->flag_auto || (conf_AdvPrefixAutonomousFlag && a->prefix_len == 64)) ? ND_OPT_PI_FLAG_AUTO : 0);
- pinfo->nd_opt_pi_valid_time = htonl(conf_AdvPrefixValidLifetime);
- pinfo->nd_opt_pi_preferred_time = htonl(conf_AdvPrefixPreferredLifetime);
- memcpy(&pinfo->nd_opt_pi_prefix, &a->addr, (a->prefix_len + 7) / 8);
- pinfo->nd_opt_pi_prefix.s6_addr[a->prefix_len / 8] &= ~(0xff >> (a->prefix_len % 8));
- pinfo++;
- }
+ list_for_each_entry(a, &ses->ipv6->addr_list, entry) {
+ prefix_len = a->prefix_len == 128 ? 64 : a->prefix_len;
+ memset(pinfo, 0, sizeof(*pinfo));
+ pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
+ pinfo->nd_opt_pi_len = 4;
+ pinfo->nd_opt_pi_prefix_len = prefix_len;
+ pinfo->nd_opt_pi_flags_reserved =
+ ((a->flag_onlink || conf_AdvPrefixOnLinkFlag) ? ND_OPT_PI_FLAG_ONLINK : 0) |
+ ((a->flag_auto || (conf_AdvPrefixAutonomousFlag && prefix_len == 64)) ? ND_OPT_PI_FLAG_AUTO : 0);
+ pinfo->nd_opt_pi_valid_time = htonl(conf_AdvPrefixValidLifetime);
+ pinfo->nd_opt_pi_preferred_time = htonl(conf_AdvPrefixPreferredLifetime);
+ memcpy(&pinfo->nd_opt_pi_prefix, &a->addr, (prefix_len + 7) / 8);
+ pinfo->nd_opt_pi_prefix.s6_addr[prefix_len / 8] &= ~(0xff >> (prefix_len % 8));
+ pinfo++;
if (!a->installed) {
- if (a->prefix_len > 64)
- ip6route_add(h->ses->ifindex, &a->addr, a->prefix_len, 0);
- else {
- struct in6_addr addr;
+ if (a->prefix_len == 128) {
+ memcpy(addr.s6_addr, &a->addr, 8);
+ memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8);
+ memcpy(peer_addr.s6_addr, &a->addr, 8);
+ memcpy(peer_addr.s6_addr + 8, &ses->ipv6->peer_intf_id, 8);
+ ip6addr_add_peer(ses->ifindex, &addr, &peer_addr);
+ } else {
memcpy(addr.s6_addr, &a->addr, 8);
- memcpy(addr.s6_addr + 8, &h->ses->ipv6->intf_id, 8);
- ip6addr_add(h->ses->ifindex, &addr, a->prefix_len);
+ memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8);
+ ip6addr_add(ses->ifindex, &addr, a->prefix_len);
}
a->installed = 1;
}
@@ -194,7 +198,7 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad
} else
endptr = rdnss_addr;
- net->sendto(h->hnd.fd, buf, endptr - buf, 0, (struct sockaddr *)addr, sizeof(*addr));
+ net->sendto(h->hnd.fd, buf, endptr - buf, 0, (struct sockaddr *)dst_addr, sizeof(*dst_addr));
mempool_free(buf);
}