aboutsummaryrefslogtreecommitdiffstats
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 a60c821be44c..fd9740466757 100644
--- a/include/linux/if_addr.h
+++ b/include/linux/if_addr.h
@@ -41,6 +41,7 @@ enum
41 41
42#define IFA_F_NODAD 0x02 42#define IFA_F_NODAD 0x02
43#define IFA_F_OPTIMISTIC 0x04 43#define IFA_F_OPTIMISTIC 0x04
44#define IFA_F_DADFAILED 0x08
44#define IFA_F_HOMEADDRESS 0x10 45#define IFA_F_HOMEADDRESS 0x10
45#define IFA_F_DEPRECATED 0x20 46#define IFA_F_DEPRECATED 0x20
46#define IFA_F_TENTATIVE 0x40 47#define IFA_F_TENTATIVE 0x40
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 43b3c9f89c12..c9b369034a40 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
1371 1371
1372/* Gets referenced address, destroys ifaddr */ 1372/* Gets referenced address, destroys ifaddr */
1373 1373
1374static void addrconf_dad_stop(struct inet6_ifaddr *ifp) 1374static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
1375{ 1375{
1376 if (ifp->flags&IFA_F_PERMANENT) { 1376 if (ifp->flags&IFA_F_PERMANENT) {
1377 spin_lock_bh(&ifp->lock); 1377 spin_lock_bh(&ifp->lock);
1378 addrconf_del_timer(ifp); 1378 addrconf_del_timer(ifp);
1379 ifp->flags |= IFA_F_TENTATIVE; 1379 ifp->flags |= IFA_F_TENTATIVE;
1380 if (dad_failed)
1381 ifp->flags |= IFA_F_DADFAILED;
1380 spin_unlock_bh(&ifp->lock); 1382 spin_unlock_bh(&ifp->lock);
1381 in6_ifa_put(ifp); 1383 in6_ifa_put(ifp);
1382#ifdef CONFIG_IPV6_PRIVACY 1384#ifdef CONFIG_IPV6_PRIVACY
@@ -1422,7 +1424,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1422 } 1424 }
1423 } 1425 }
1424 1426
1425 addrconf_dad_stop(ifp); 1427 addrconf_dad_stop(ifp, 1);
1426} 1428}
1427 1429
1428/* Join to solicited addr multicast group. */ 1430/* Join to solicited addr multicast group. */
@@ -2778,7 +2780,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2778 idev->cnf.accept_dad < 1 || 2780 idev->cnf.accept_dad < 1 ||
2779 !(ifp->flags&IFA_F_TENTATIVE) || 2781 !(ifp->flags&IFA_F_TENTATIVE) ||
2780 ifp->flags & IFA_F_NODAD) { 2782 ifp->flags & IFA_F_NODAD) {
2781 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); 2783 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
2782 spin_unlock_bh(&ifp->lock); 2784 spin_unlock_bh(&ifp->lock);
2783 read_unlock_bh(&idev->lock); 2785 read_unlock_bh(&idev->lock);
2784 2786
@@ -2795,7 +2797,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2795 * - otherwise, kill it. 2797 * - otherwise, kill it.
2796 */ 2798 */
2797 in6_ifa_hold(ifp); 2799 in6_ifa_hold(ifp);
2798 addrconf_dad_stop(ifp); 2800 addrconf_dad_stop(ifp, 0);
2799 return; 2801 return;
2800 } 2802 }
2801 2803
@@ -2829,7 +2831,7 @@ static void addrconf_dad_timer(unsigned long data)
2829 * DAD was successful 2831 * DAD was successful
2830 */ 2832 */
2831 2833
2832 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); 2834 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
2833 spin_unlock_bh(&ifp->lock); 2835 spin_unlock_bh(&ifp->lock);
2834 read_unlock_bh(&idev->lock); 2836 read_unlock_bh(&idev->lock);
2835 2837