aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/addrconf.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index df8425fcbc2c..f418d2eaeddd 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1872,7 +1872,6 @@ static int addrconf_dad_end(struct inet6_ifaddr *ifp)
1872 1872
1873void addrconf_dad_failure(struct inet6_ifaddr *ifp) 1873void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1874{ 1874{
1875 struct in6_addr addr;
1876 struct inet6_dev *idev = ifp->idev; 1875 struct inet6_dev *idev = ifp->idev;
1877 struct net *net = dev_net(ifp->idev->dev); 1876 struct net *net = dev_net(ifp->idev->dev);
1878 1877
@@ -1934,18 +1933,6 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1934 in6_ifa_put(ifp2); 1933 in6_ifa_put(ifp2);
1935lock_errdad: 1934lock_errdad:
1936 spin_lock_bh(&ifp->lock); 1935 spin_lock_bh(&ifp->lock);
1937 } else if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
1938 addr.s6_addr32[0] = htonl(0xfe800000);
1939 addr.s6_addr32[1] = 0;
1940
1941 if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
1942 ipv6_addr_equal(&ifp->addr, &addr)) {
1943 /* DAD failed for link-local based on MAC address */
1944 idev->cnf.disable_ipv6 = 1;
1945
1946 pr_info("%s: IPv6 being disabled!\n",
1947 ifp->idev->dev->name);
1948 }
1949 } 1936 }
1950 1937
1951errdad: 1938errdad:
@@ -3821,6 +3808,7 @@ static void addrconf_dad_work(struct work_struct *w)
3821 dad_work); 3808 dad_work);
3822 struct inet6_dev *idev = ifp->idev; 3809 struct inet6_dev *idev = ifp->idev;
3823 struct in6_addr mcaddr; 3810 struct in6_addr mcaddr;
3811 bool disable_ipv6 = false;
3824 3812
3825 enum { 3813 enum {
3826 DAD_PROCESS, 3814 DAD_PROCESS,
@@ -3837,6 +3825,24 @@ static void addrconf_dad_work(struct work_struct *w)
3837 } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) { 3825 } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) {
3838 action = DAD_ABORT; 3826 action = DAD_ABORT;
3839 ifp->state = INET6_IFADDR_STATE_POSTDAD; 3827 ifp->state = INET6_IFADDR_STATE_POSTDAD;
3828
3829 if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6 &&
3830 !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
3831 struct in6_addr addr;
3832
3833 addr.s6_addr32[0] = htonl(0xfe800000);
3834 addr.s6_addr32[1] = 0;
3835
3836 if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
3837 ipv6_addr_equal(&ifp->addr, &addr)) {
3838 /* DAD failed for link-local based on MAC */
3839 idev->cnf.disable_ipv6 = 1;
3840
3841 pr_info("%s: IPv6 being disabled!\n",
3842 ifp->idev->dev->name);
3843 disable_ipv6 = true;
3844 }
3845 }
3840 } 3846 }
3841 spin_unlock_bh(&ifp->lock); 3847 spin_unlock_bh(&ifp->lock);
3842 3848
@@ -3845,6 +3851,8 @@ static void addrconf_dad_work(struct work_struct *w)
3845 goto out; 3851 goto out;
3846 } else if (action == DAD_ABORT) { 3852 } else if (action == DAD_ABORT) {
3847 addrconf_dad_stop(ifp, 1); 3853 addrconf_dad_stop(ifp, 1);
3854 if (disable_ipv6)
3855 addrconf_ifdown(idev->dev, 0);
3848 goto out; 3856 goto out;
3849 } 3857 }
3850 3858