diff options
| author | Hideaki Yoshifuji <yoshfuji@linux-ipv6.org> | 2004-09-25 14:49:10 +0900 |
|---|---|---|
| committer | Hideaki Yoshifuji <yoshfuji@linux-ipv6.org> | 2004-09-25 14:49:10 +0900 |
| commit | 57139421db577270de2227faddec9f311295ce72 (patch) | |
| tree | c604e72e6e8cf4e182f12704a515b5463e4bc8ab | |
| parent | 59cd504fb1a6d5f5b0254fa7765d03c1bf112c97 (diff) | |
[IPV6] leave subnet-routers anycast address during device deletion.
Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
| -rw-r--r-- | include/net/addrconf.h | 1 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 2 | ||||
| -rw-r--r-- | net/ipv6/anycast.c | 21 |
3 files changed, 14 insertions, 10 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index a0566bb6387f..50f4c2c4df86 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -112,6 +112,7 @@ extern void ipv6_sock_ac_close(struct sock *sk); extern int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex); extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr); +extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr); extern int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr); extern int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 910b21052174..9a3d82f6dd0d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3000,7 +3000,7 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); if (!ipv6_addr_any(&addr)) - ipv6_dev_ac_dec(ifp->idev->dev, &addr); + __ipv6_dev_ac_dec(ifp->idev, &addr); } dst_hold(&ifp->rt->u.dst); if (ip6_del_rt(ifp->rt, NULL, NULL)) diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 1963903cb90e..a0de548c56ca 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -377,15 +377,10 @@ out: /* * device anycast group decrement */ -int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) +int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) { - struct inet6_dev *idev; struct ifacaddr6 *aca, *prev_aca; - idev = in6_dev_get(dev); - if (idev == NULL) - return -ENODEV; - write_lock_bh(&idev->lock); prev_aca = NULL; for (aca = idev->ac_list; aca; aca = aca->aca_next) { @@ -395,12 +390,10 @@ int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) } if (!aca) { write_unlock_bh(&idev->lock); - in6_dev_put(idev); return -ENOENT; } if (--aca->aca_users > 0) { write_unlock_bh(&idev->lock); - in6_dev_put(idev); return 0; } if (prev_aca) @@ -417,10 +410,20 @@ int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) dst_release(&aca->aca_rt->u.dst); aca_put(aca); - in6_dev_put(idev); return 0; } +int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) +{ + int ret; + struct inet6_dev *idev = in6_dev_get(dev); + if (idev == NULL) + return -ENODEV; + ret = __ipv6_dev_ac_dec(idev, addr); + in6_dev_put(idev); + return ret; +} + /* * check if the interface has this anycast address */ |
