From d49a25b9f48ef5c65fe91a79e62c2f677169eac7 Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Tue, 12 Apr 2016 00:23:16 +0300 Subject: ipv6: remove ipv6 address and routes on session termination --- accel-pppd/ifcfg.c | 40 +++++++++++++++----------- accel-pppd/ipv6/dhcpv6.c | 9 +++++- accel-pppd/libnetlink/iputils.c | 63 +++++++++++++++++++++++++++++++++++++++++ accel-pppd/libnetlink/iputils.h | 2 ++ 4 files changed, 96 insertions(+), 18 deletions(-) diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c index 9c6f4dcf..3a1fffd0 100644 --- a/accel-pppd/ifcfg.c +++ b/accel-pppd/ifcfg.c @@ -45,7 +45,7 @@ static void devconf(struct ap_session *ses, const char *attr, const char *val) close(fd); } -static void build_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_addr *addr) +/*static void build_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_addr *addr) { memcpy(addr, &a->addr, sizeof(*addr)); @@ -53,7 +53,7 @@ static void build_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_add *(uint64_t *)(addr->s6_addr + 8) = intf_id; else *(uint64_t *)(addr->s6_addr + 8) |= intf_id & ((1 << (128 - a->prefix_len)) - 1); -} +}*/ void ap_session_ifup(struct ap_session *ses) { @@ -222,13 +222,14 @@ void __export ap_session_ifdown(struct ap_session *ses) struct in6_ifreq ifr6; struct ipv6db_addr_t *a; - if (ses->ctrl->dont_ifcfg || ses->ifindex == -1) + if (ses->ifindex == -1) return; - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, ses->ifname); - - net->sock_ioctl(SIOCSIFFLAGS, &ifr); + if (!ses->ctrl->dont_ifcfg) { + strcpy(ifr.ifr_name, ses->ifname); + ifr.ifr_flags = 0; + net->sock_ioctl(SIOCSIFFLAGS, &ifr); + } if (ses->ipv4) { memset(&addr, 0, sizeof(addr)); @@ -239,21 +240,26 @@ void __export ap_session_ifdown(struct ap_session *ses) if (ses->ipv6) { memset(&ifr6, 0, sizeof(ifr6)); - ifr6.ifr6_addr.s6_addr32[0] = htonl(0xfe800000); - *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ses->ipv6->intf_id; - ifr6.ifr6_prefixlen = 64; ifr6.ifr6_ifindex = ses->ifindex; - ioctl(sock6_fd, SIOCDIFADDR, &ifr6); + if (ses->ctrl->ppp) { + ifr6.ifr6_addr.s6_addr32[0] = htonl(0xfe800000); + *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ses->ipv6->intf_id; + ifr6.ifr6_prefixlen = 64; + ioctl(sock6_fd, SIOCDIFADDR, &ifr6); + } list_for_each_entry(a, &ses->ipv6->addr_list, entry) { - if (a->prefix_len == 128) + if (!a->installed) continue; - - build_addr(a, ses->ipv6->intf_id, &ifr6.ifr6_addr); - ifr6.ifr6_prefixlen = a->prefix_len; - - ioctl(sock6_fd, SIOCDIFADDR, &ifr6); + if (a->prefix_len > 64) + ip6route_del(ses->ifindex, &a->addr, a->prefix_len); + else { + struct in6_addr addr; + memcpy(addr.s6_addr, &a->addr, 8); + memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8); + ip6addr_del(ses->ifindex, &addr, a->prefix_len); + } } } } diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 93801ace..595b5974 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -142,8 +142,15 @@ static void ev_ses_finished(struct ap_session *ses) if (pd->clientid) _free(pd->clientid); - if (ses->ipv6_dp) + if (ses->ipv6_dp) { + if (pd->dp_active) { + struct ipv6db_addr_t *p; + list_for_each_entry(p, &ses->ipv6_dp->prefix_list, entry) + ip6route_del(0, &p->addr, p->prefix_len); + } + ipdb_put_ipv6_prefix(ses, ses->ipv6_dp); + } triton_md_unregister_handler(&pd->hnd, 1); diff --git a/accel-pppd/libnetlink/iputils.c b/accel-pppd/libnetlink/iputils.c index 7ba288ef..30a06d1f 100644 --- a/accel-pppd/libnetlink/iputils.c +++ b/accel-pppd/libnetlink/iputils.c @@ -491,7 +491,39 @@ int __export ip6route_add(int ifindex, struct in6_addr *dst, int pref_len, int p return -1; return 0; +} + +int __export ip6route_del(int ifindex, struct in6_addr *dst, int pref_len) +{ + struct ipaddr_req { + struct nlmsghdr n; + struct rtmsg 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 rtmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; + req.n.nlmsg_type = RTM_DELROUTE; + req.i.rtm_family = AF_INET6; + req.i.rtm_table = RT_TABLE_MAIN; + req.i.rtm_scope = RT_SCOPE_LINK; + req.i.rtm_type = RTN_UNICAST; + req.i.rtm_dst_len = pref_len; + + addattr_l(&req.n, sizeof(req), RTA_DST, dst, sizeof(*dst)); + + if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) + return -1; + + return 0; } int __export ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len) @@ -526,6 +558,37 @@ int __export ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len) return 0; } +int __export ip6addr_del(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_DELADDR; + req.i.ifa_family = AF_INET6; + req.i.ifa_index = ifindex; + req.i.ifa_prefixlen = prefix_len; + + 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 d5f9701d..dad06870 100644 --- a/accel-pppd/libnetlink/iputils.h +++ b/accel-pppd/libnetlink/iputils.h @@ -20,7 +20,9 @@ int iproute_del(int ifindex, in_addr_t dst, int proto, int mask); 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 ip6route_del(int ifindex, struct in6_addr *dst, int prefix_len); int ip6addr_add(int ifindex, struct in6_addr *addr, int prefix_len); +int ip6addr_del(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); -- cgit v1.2.3