summaryrefslogtreecommitdiff
path: root/accel-pppd
diff options
context:
space:
mode:
authorVladislav Grishenko <themiron@mail.ru>2016-05-12 22:20:42 +0500
committerVladislav Grishenko <themiron@mail.ru>2017-12-05 02:17:13 +0500
commit504b093a9878e758af1397aa82eda44b1bf0f608 (patch)
treeef0e96d692020d572381adab397bb75de9d7b620 /accel-pppd
parent2aa6aeaca2691403e52ea007d3574cb7f662b0e7 (diff)
downloadaccel-ppp-504b093a9878e758af1397aa82eda44b1bf0f608.tar.gz
accel-ppp-504b093a9878e758af1397aa82eda44b1bf0f608.zip
ipv6: nd: add non-/64 prefixes support
non-/64 subnets still needs Router Advertimenets for the default route & RDNSS.
Diffstat (limited to 'accel-pppd')
-rw-r--r--accel-pppd/ipv6/nd.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/accel-pppd/ipv6/nd.c b/accel-pppd/ipv6/nd.c
index 205aeefd..f2a259ad 100644
--- a/accel-pppd/ipv6/nd.c
+++ b/accel-pppd/ipv6/nd.c
@@ -129,23 +129,30 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad
pinfo = (struct nd_opt_prefix_info *)(adv + 1);
list_for_each_entry(a, &h->ses->ipv6->addr_list, entry) {
- 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, 8);
- pinfo++;
+ 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++;
+ }
if (!a->installed) {
- struct in6_addr addr;
- 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);
+ if (a->prefix_len > 64)
+ ip6route_add(h->ses->ifindex, &a->addr, a->prefix_len, 0);
+ else {
+ struct in6_addr addr;
+ 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);
+ }
a->installed = 1;
}
}
@@ -371,7 +378,7 @@ static void ev_ses_started(struct ap_session *ses)
return;
list_for_each_entry(a, &ses->ipv6->addr_list, entry) {
- if (a->prefix_len == 64) {
+ if (a->prefix_len) {
ipv6_nd_start(ses);
break;
}