summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHideaki Yoshifuji <yoshfuji@linux-ipv6.org>2004-09-25 14:49:10 +0900
committerHideaki Yoshifuji <yoshfuji@linux-ipv6.org>2004-09-25 14:49:10 +0900
commit57139421db577270de2227faddec9f311295ce72 (patch)
treec604e72e6e8cf4e182f12704a515b5463e4bc8ab
parent59cd504fb1a6d5f5b0254fa7765d03c1bf112c97 (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.h1
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/anycast.c21
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
*/