summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2016-04-12 00:23:16 +0300
committerDmitry Kozlov <xeb@mail.ru>2016-04-12 00:23:16 +0300
commitd49a25b9f48ef5c65fe91a79e62c2f677169eac7 (patch)
tree659e1bd47ea9d1bc24bb8d31708c655ab85f5378
parentf285b9e7bd4c8d1eada3ca315618bbd8f9401e4b (diff)
downloadaccel-ppp-d49a25b9f48ef5c65fe91a79e62c2f677169eac7.tar.gz
accel-ppp-d49a25b9f48ef5c65fe91a79e62c2f677169eac7.zip
ipv6: remove ipv6 address and routes on session termination
-rw-r--r--accel-pppd/ifcfg.c40
-rw-r--r--accel-pppd/ipv6/dhcpv6.c9
-rw-r--r--accel-pppd/libnetlink/iputils.c63
-rw-r--r--accel-pppd/libnetlink/iputils.h2
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);