diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2017-12-25 17:57:53 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2017-12-25 17:57:53 +0300 |
commit | 4c8340c4abe04d896de8e0a190ec412d4ce4f30f (patch) | |
tree | f18a8b4f56c8007bcbcafd6ec6fe43af5d5f6cfd /accel-pppd/ipv6 | |
parent | cd9bb5cfe3afec23ef62f2aa2ed82e6dd04a32f9 (diff) | |
download | accel-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
Diffstat (limited to 'accel-pppd/ipv6')
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 15 | ||||
-rw-r--r-- | accel-pppd/ipv6/nd.c | 54 |
2 files changed, 40 insertions, 29 deletions
diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index d99165c..2122f29 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 f2a259a..231f180 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); } |