diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-05-18 18:56:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-18 18:56:06 -0400 |
commit | 622ccdf107bcb49c4d8fb65512652566d4c8928a (patch) | |
tree | b25ec5eaade9307a516c87f49f091af25e134590 | |
parent | f2344a131bccdbfc5338e17fa71a807dee7944fa (diff) |
ipv6: Never schedule DAD timer on dead address
This patch ensures that all places that schedule the DAD timer
look at the address state in a safe manner before scheduling the
timer. This ensures that we don't end up with pending timers
after deleting an address.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/addrconf.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7c769fa81d97..e1a698df5706 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2853,10 +2853,10 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2853 | net_srandom(ifp->addr.s6_addr32[3]); | 2853 | net_srandom(ifp->addr.s6_addr32[3]); |
2854 | 2854 | ||
2855 | read_lock_bh(&idev->lock); | 2855 | read_lock_bh(&idev->lock); |
2856 | spin_lock(&ifp->lock); | ||
2856 | if (ifp->state == INET6_IFADDR_STATE_DEAD) | 2857 | if (ifp->state == INET6_IFADDR_STATE_DEAD) |
2857 | goto out; | 2858 | goto out; |
2858 | 2859 | ||
2859 | spin_lock(&ifp->lock); | ||
2860 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2860 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
2861 | idev->cnf.accept_dad < 1 || | 2861 | idev->cnf.accept_dad < 1 || |
2862 | !(ifp->flags&IFA_F_TENTATIVE) || | 2862 | !(ifp->flags&IFA_F_TENTATIVE) || |
@@ -2890,8 +2890,8 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2890 | ip6_ins_rt(ifp->rt); | 2890 | ip6_ins_rt(ifp->rt); |
2891 | 2891 | ||
2892 | addrconf_dad_kick(ifp); | 2892 | addrconf_dad_kick(ifp); |
2893 | spin_unlock(&ifp->lock); | ||
2894 | out: | 2893 | out: |
2894 | spin_unlock(&ifp->lock); | ||
2895 | read_unlock_bh(&idev->lock); | 2895 | read_unlock_bh(&idev->lock); |
2896 | } | 2896 | } |
2897 | 2897 | ||
@@ -2911,6 +2911,12 @@ static void addrconf_dad_timer(unsigned long data) | |||
2911 | } | 2911 | } |
2912 | 2912 | ||
2913 | spin_lock(&ifp->lock); | 2913 | spin_lock(&ifp->lock); |
2914 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | ||
2915 | spin_unlock(&ifp->lock); | ||
2916 | read_unlock(&idev->lock); | ||
2917 | goto out; | ||
2918 | } | ||
2919 | |||
2914 | if (ifp->probes == 0) { | 2920 | if (ifp->probes == 0) { |
2915 | /* | 2921 | /* |
2916 | * DAD was successful | 2922 | * DAD was successful |