diff options
-rw-r--r-- | accel-pppd/ifcfg.c | 5 | ||||
-rw-r--r-- | accel-pppd/ipdb.h | 3 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 17 | ||||
-rw-r--r-- | accel-pppd/ipv6/nd.c | 9 | ||||
-rw-r--r-- | accel-pppd/libnetlink/iputils.c | 32 | ||||
-rw-r--r-- | accel-pppd/libnetlink/iputils.h | 1 |
6 files changed, 61 insertions, 6 deletions
diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c index 39e87b4..685e1de 100644 --- a/accel-pppd/ifcfg.c +++ b/accel-pppd/ifcfg.c @@ -166,15 +166,16 @@ void __export ap_session_accounting_started(struct ap_session *ses) } list_for_each_entry(a, &ses->ipv6->addr_list, entry) { + a->installed = 0; /*if (a->prefix_len < 128) { build_addr(a, ses->ipv6->intf_id, &ifr6.ifr6_addr); ifr6.ifr6_prefixlen = a->prefix_len; if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) log_ppp_error("failed to add IPv6 address: %s\n", strerror(errno)); - } else*/ + } else if (ip6route_add(ses->ifindex, &a->addr, a->prefix_len, 0)) - log_ppp_error("failed to add IPv6 route: %s\n", strerror(errno)); + log_ppp_error("failed to add IPv6 route: %s\n", strerror(errno));*/ } } diff --git a/accel-pppd/ipdb.h b/accel-pppd/ipdb.h index fc0fe6f..d461c88 100644 --- a/accel-pppd/ipdb.h +++ b/accel-pppd/ipdb.h @@ -1,8 +1,6 @@ #ifndef IPDB_H #define IPDB_H -#include <netinet/in.h> - #include "ppp.h" #include "list.h" @@ -20,6 +18,7 @@ struct ipv6db_addr_t struct in6_addr addr; int prefix_len; int flag_auto:1; + int installed:1; }; struct ipv6db_item_t diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 62f20bb..3f9df71 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -21,11 +21,12 @@ #include "ppp.h" #include "ipdb.h" #include "events.h" - -#include "memdebug.h" +#include "iputils.h" #include "dhcpv6.h" +#include "memdebug.h" + #define BUF_SIZE 65536 #define MAX_DNS_COUNT 3 @@ -295,6 +296,18 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i ia_addr->pref_lifetime = htonl(conf_pref_lifetime); 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; + 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); + } + a->installed = 1; + } } list_for_each_entry(opt2, &opt->opt_list, entry) { diff --git a/accel-pppd/ipv6/nd.c b/accel-pppd/ipv6/nd.c index ff8b64b..19a3d7d 100644 --- a/accel-pppd/ipv6/nd.c +++ b/accel-pppd/ipv6/nd.c @@ -17,6 +17,7 @@ #include "events.h" #include "mempool.h" #include "ipdb.h" +#include "iputils.h" #include "memdebug.h" @@ -137,6 +138,14 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ad pinfo->nd_opt_pi_preferred_time = htonl(conf_AdvPrefixPreferredLifetime); memcpy(&pinfo->nd_opt_pi_prefix, &a->addr, 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); + a->installed = 1; + } } /*rinfo = (struct nd_opt_route_info_local *)pinfo; diff --git a/accel-pppd/libnetlink/iputils.c b/accel-pppd/libnetlink/iputils.c index 1544508..480f028 100644 --- a/accel-pppd/libnetlink/iputils.c +++ b/accel-pppd/libnetlink/iputils.c @@ -416,6 +416,38 @@ int __export ip6route_add(int ifindex, struct in6_addr *dst, int pref_len, int p } +int __export ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len) +{ + struct ipaddr_req { + struct nlmsghdr n; + struct ifaddrmsg i; + char buf[4096]; + } req; + + if (!rth) + open_rth(); + + if (!rth) + return -1; + + memset(&req, 0, sizeof(req) - 4096); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; + req.n.nlmsg_type = RTM_NEWADDR; + req.i.ifa_family = AF_INET6; + req.i.ifa_index = ifindex; + req.i.ifa_prefixlen = prefix_len; + req.i.ifa_flags = IFA_F_NODAD; + + addattr_l(&req.n, sizeof(req), IFA_ADDRESS, addr, 16); + + if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) + return -1; + + return 0; +} + in_addr_t __export iproute_get(in_addr_t dst, in_addr_t *gw) { struct ipaddr_req { diff --git a/accel-pppd/libnetlink/iputils.h b/accel-pppd/libnetlink/iputils.h index b9a6488..6097627 100644 --- a/accel-pppd/libnetlink/iputils.h +++ b/accel-pppd/libnetlink/iputils.h @@ -19,6 +19,7 @@ int iproute_del(int ifindex, in_addr_t dst, int proto); in_addr_t iproute_get(in_addr_t dst, in_addr_t *gw); int ip6route_add(int ifindex, struct in6_addr *dst, int prefix_len, int proto); +int ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len); int iprule_add(uint32_t addr, int table); int iprule_del(uint32_t addr, int table); |