summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_addr.h1
-rw-r--r--net/ipv6/addrconf.c12
2 files changed, 8 insertions, 5 deletions
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
index a60c821be44..fd974046675 100644
--- a/include/linux/if_addr.h
+++ b/include/linux/if_addr.h
@@ -41,6 +41,7 @@ enum
#define IFA_F_NODAD 0x02
#define IFA_F_OPTIMISTIC 0x04
+#define IFA_F_DADFAILED 0x08
#define IFA_F_HOMEADDRESS 0x10
#define IFA_F_DEPRECATED 0x20
#define IFA_F_TENTATIVE 0x40
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 43b3c9f89c1..c9b369034a4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1371,12 +1371,14 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add
/* Gets referenced address, destroys ifaddr */
-static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
+static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
{
if (ifp->flags&IFA_F_PERMANENT) {
spin_lock_bh(&ifp->lock);
addrconf_del_timer(ifp);
ifp->flags |= IFA_F_TENTATIVE;
+ if (dad_failed)
+ ifp->flags |= IFA_F_DADFAILED;
spin_unlock_bh(&ifp->lock);
in6_ifa_put(ifp);
#ifdef CONFIG_IPV6_PRIVACY
@@ -1422,7 +1424,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
}
}
- addrconf_dad_stop(ifp);
+ addrconf_dad_stop(ifp, 1);
}
/* Join to solicited addr multicast group. */
@@ -2778,7 +2780,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
idev->cnf.accept_dad < 1 ||
!(ifp->flags&IFA_F_TENTATIVE) ||
ifp->flags & IFA_F_NODAD) {
- ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
+ ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
spin_unlock_bh(&ifp->lock);
read_unlock_bh(&idev->lock);
@@ -2795,7 +2797,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
* - otherwise, kill it.
*/
in6_ifa_hold(ifp);
- addrconf_dad_stop(ifp);
+ addrconf_dad_stop(ifp, 0);
return;
}
@@ -2829,7 +2831,7 @@ static void addrconf_dad_timer(unsigned long data)
* DAD was successful
*/
- ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
+ ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
spin_unlock_bh(&ifp->lock);
read_unlock_bh(&idev->lock);