]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/addrconf.c
ipv6: Fix incorrect disable_ipv6 behavior
[net-next-2.6.git] / net / ipv6 / addrconf.c
index e83852ab4dc8fb2d6a7eb3644b3fabc3e9f9d14a..717584bad02ec76b086e4e00c079b50b25610ed6 100644 (file)
@@ -590,6 +590,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 {
        struct inet6_ifaddr *ifa = NULL;
        struct rt6_info *rt;
+       struct net *net = dev_net(idev->dev);
        int hash;
        int err = 0;
        int addr_type = ipv6_addr_type(addr);
@@ -606,6 +607,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
                goto out2;
        }
 
+       if (idev->cnf.disable_ipv6 || net->ipv6.devconf_all->disable_ipv6) {
+               err = -EACCES;
+               goto out2;
+       }
+
        write_lock(&addrconf_hash_lock);
 
        /* Ignore adding duplicate addresses on an interface */
@@ -1433,6 +1439,11 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
 void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 {
        struct inet6_dev *idev = ifp->idev;
+
+       if (net_ratelimit())
+               printk(KERN_INFO "%s: IPv6 duplicate address detected!\n",
+                       ifp->idev->dev->name);
+
        if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
                struct in6_addr addr;
 
@@ -1443,11 +1454,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
                    ipv6_addr_equal(&ifp->addr, &addr)) {
                        /* DAD failed for link-local based on MAC address */
                        idev->cnf.disable_ipv6 = 1;
+
+                       printk(KERN_INFO "%s: IPv6 being disabled!\n",
+                               ifp->idev->dev->name);
                }
        }
 
-       if (net_ratelimit())
-               printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
        addrconf_dad_stop(ifp);
 }
 
@@ -2823,11 +2835,6 @@ static void addrconf_dad_timer(unsigned long data)
                read_unlock_bh(&idev->lock);
                goto out;
        }
-       if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) {
-               read_unlock_bh(&idev->lock);
-               addrconf_dad_failure(ifp);
-               return;
-       }
        spin_lock_bh(&ifp->lock);
        if (ifp->probes == 0) {
                /*