diff options
-rw-r--r-- | include/net/addrconf.h | 1 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 8 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 21 |
3 files changed, 27 insertions, 3 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index f679877bb601..ec51e673b4b6 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -204,6 +204,7 @@ void ipv6_sock_ac_close(struct sock *sk); | |||
204 | 204 | ||
205 | int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); | 205 | int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); |
206 | int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); | 206 | int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); |
207 | void ipv6_ac_destroy_dev(struct inet6_dev *idev); | ||
207 | bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | 208 | bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, |
208 | const struct in6_addr *addr); | 209 | const struct in6_addr *addr); |
209 | bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev, | 210 | bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev, |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fc1fac2a0528..3342ee64f2e3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3094,11 +3094,13 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3094 | 3094 | ||
3095 | write_unlock_bh(&idev->lock); | 3095 | write_unlock_bh(&idev->lock); |
3096 | 3096 | ||
3097 | /* Step 5: Discard multicast list */ | 3097 | /* Step 5: Discard anycast and multicast list */ |
3098 | if (how) | 3098 | if (how) { |
3099 | ipv6_ac_destroy_dev(idev); | ||
3099 | ipv6_mc_destroy_dev(idev); | 3100 | ipv6_mc_destroy_dev(idev); |
3100 | else | 3101 | } else { |
3101 | ipv6_mc_down(idev); | 3102 | ipv6_mc_down(idev); |
3103 | } | ||
3102 | 3104 | ||
3103 | idev->tstamp = jiffies; | 3105 | idev->tstamp = jiffies; |
3104 | 3106 | ||
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index ff2de7d9d8e6..9a386842fd62 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -351,6 +351,27 @@ static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr) | |||
351 | return __ipv6_dev_ac_dec(idev, addr); | 351 | return __ipv6_dev_ac_dec(idev, addr); |
352 | } | 352 | } |
353 | 353 | ||
354 | void ipv6_ac_destroy_dev(struct inet6_dev *idev) | ||
355 | { | ||
356 | struct ifacaddr6 *aca; | ||
357 | |||
358 | write_lock_bh(&idev->lock); | ||
359 | while ((aca = idev->ac_list) != NULL) { | ||
360 | idev->ac_list = aca->aca_next; | ||
361 | write_unlock_bh(&idev->lock); | ||
362 | |||
363 | addrconf_leave_solict(idev, &aca->aca_addr); | ||
364 | |||
365 | dst_hold(&aca->aca_rt->dst); | ||
366 | ip6_del_rt(aca->aca_rt); | ||
367 | |||
368 | aca_put(aca); | ||
369 | |||
370 | write_lock_bh(&idev->lock); | ||
371 | } | ||
372 | write_unlock_bh(&idev->lock); | ||
373 | } | ||
374 | |||
354 | /* | 375 | /* |
355 | * check if the interface has this anycast address | 376 | * check if the interface has this anycast address |
356 | * called with rcu_read_lock() | 377 | * called with rcu_read_lock() |