|
@@ -1872,7 +1872,6 @@ static int addrconf_dad_end(struct inet6_ifaddr *ifp)
|
|
|
|
|
|
void addrconf_dad_failure(struct inet6_ifaddr *ifp)
|
|
|
{
|
|
|
- struct in6_addr addr;
|
|
|
struct inet6_dev *idev = ifp->idev;
|
|
|
struct net *net = dev_net(ifp->idev->dev);
|
|
|
|
|
@@ -1934,18 +1933,6 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
|
|
|
in6_ifa_put(ifp2);
|
|
|
lock_errdad:
|
|
|
spin_lock_bh(&ifp->lock);
|
|
|
- } else if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
|
|
|
- addr.s6_addr32[0] = htonl(0xfe800000);
|
|
|
- addr.s6_addr32[1] = 0;
|
|
|
-
|
|
|
- if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
|
|
|
- ipv6_addr_equal(&ifp->addr, &addr)) {
|
|
|
- /* DAD failed for link-local based on MAC address */
|
|
|
- idev->cnf.disable_ipv6 = 1;
|
|
|
-
|
|
|
- pr_info("%s: IPv6 being disabled!\n",
|
|
|
- ifp->idev->dev->name);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
errdad:
|
|
@@ -3821,6 +3808,7 @@ static void addrconf_dad_work(struct work_struct *w)
|
|
|
dad_work);
|
|
|
struct inet6_dev *idev = ifp->idev;
|
|
|
struct in6_addr mcaddr;
|
|
|
+ bool disable_ipv6 = false;
|
|
|
|
|
|
enum {
|
|
|
DAD_PROCESS,
|
|
@@ -3837,6 +3825,24 @@ static void addrconf_dad_work(struct work_struct *w)
|
|
|
} else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) {
|
|
|
action = DAD_ABORT;
|
|
|
ifp->state = INET6_IFADDR_STATE_POSTDAD;
|
|
|
+
|
|
|
+ if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6 &&
|
|
|
+ !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
|
|
|
+ struct in6_addr addr;
|
|
|
+
|
|
|
+ addr.s6_addr32[0] = htonl(0xfe800000);
|
|
|
+ addr.s6_addr32[1] = 0;
|
|
|
+
|
|
|
+ if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
|
|
|
+ ipv6_addr_equal(&ifp->addr, &addr)) {
|
|
|
+ /* DAD failed for link-local based on MAC */
|
|
|
+ idev->cnf.disable_ipv6 = 1;
|
|
|
+
|
|
|
+ pr_info("%s: IPv6 being disabled!\n",
|
|
|
+ ifp->idev->dev->name);
|
|
|
+ disable_ipv6 = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
spin_unlock_bh(&ifp->lock);
|
|
|
|
|
@@ -3845,6 +3851,8 @@ static void addrconf_dad_work(struct work_struct *w)
|
|
|
goto out;
|
|
|
} else if (action == DAD_ABORT) {
|
|
|
addrconf_dad_stop(ifp, 1);
|
|
|
+ if (disable_ipv6)
|
|
|
+ addrconf_ifdown(idev->dev, 0);
|
|
|
goto out;
|
|
|
}
|
|
|
|