aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/addrconf.h1
-rw-r--r--net/ipv6/addrconf.c8
-rw-r--r--net/ipv6/anycast.c21
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
205int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); 205int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
206int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); 206int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
207void ipv6_ac_destroy_dev(struct inet6_dev *idev);
207bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, 208bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
208 const struct in6_addr *addr); 209 const struct in6_addr *addr);
209bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev, 210bool 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
354void 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()