diff options
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 4 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 21 |
2 files changed, 17 insertions, 8 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 7185e4c41e59..ec5de02f543f 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -1043,7 +1043,9 @@ max_addresses - INTEGER | |||
1043 | Default: 16 | 1043 | Default: 16 |
1044 | 1044 | ||
1045 | disable_ipv6 - BOOLEAN | 1045 | disable_ipv6 - BOOLEAN |
1046 | Disable IPv6 operation. | 1046 | Disable IPv6 operation. If accept_dad is set to 2, this value |
1047 | will be dynamically set to TRUE if DAD fails for the link-local | ||
1048 | address. | ||
1047 | Default: FALSE (enable IPv6 operation) | 1049 | Default: FALSE (enable IPv6 operation) |
1048 | 1050 | ||
1049 | accept_dad - INTEGER | 1051 | accept_dad - INTEGER |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e83852ab4dc8..717584bad02e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -590,6 +590,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
590 | { | 590 | { |
591 | struct inet6_ifaddr *ifa = NULL; | 591 | struct inet6_ifaddr *ifa = NULL; |
592 | struct rt6_info *rt; | 592 | struct rt6_info *rt; |
593 | struct net *net = dev_net(idev->dev); | ||
593 | int hash; | 594 | int hash; |
594 | int err = 0; | 595 | int err = 0; |
595 | int addr_type = ipv6_addr_type(addr); | 596 | 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, | |||
606 | goto out2; | 607 | goto out2; |
607 | } | 608 | } |
608 | 609 | ||
610 | if (idev->cnf.disable_ipv6 || net->ipv6.devconf_all->disable_ipv6) { | ||
611 | err = -EACCES; | ||
612 | goto out2; | ||
613 | } | ||
614 | |||
609 | write_lock(&addrconf_hash_lock); | 615 | write_lock(&addrconf_hash_lock); |
610 | 616 | ||
611 | /* Ignore adding duplicate addresses on an interface */ | 617 | /* Ignore adding duplicate addresses on an interface */ |
@@ -1433,6 +1439,11 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp) | |||
1433 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1439 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) |
1434 | { | 1440 | { |
1435 | struct inet6_dev *idev = ifp->idev; | 1441 | struct inet6_dev *idev = ifp->idev; |
1442 | |||
1443 | if (net_ratelimit()) | ||
1444 | printk(KERN_INFO "%s: IPv6 duplicate address detected!\n", | ||
1445 | ifp->idev->dev->name); | ||
1446 | |||
1436 | if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { | 1447 | if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { |
1437 | struct in6_addr addr; | 1448 | struct in6_addr addr; |
1438 | 1449 | ||
@@ -1443,11 +1454,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1443 | ipv6_addr_equal(&ifp->addr, &addr)) { | 1454 | ipv6_addr_equal(&ifp->addr, &addr)) { |
1444 | /* DAD failed for link-local based on MAC address */ | 1455 | /* DAD failed for link-local based on MAC address */ |
1445 | idev->cnf.disable_ipv6 = 1; | 1456 | idev->cnf.disable_ipv6 = 1; |
1457 | |||
1458 | printk(KERN_INFO "%s: IPv6 being disabled!\n", | ||
1459 | ifp->idev->dev->name); | ||
1446 | } | 1460 | } |
1447 | } | 1461 | } |
1448 | 1462 | ||
1449 | if (net_ratelimit()) | ||
1450 | printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); | ||
1451 | addrconf_dad_stop(ifp); | 1463 | addrconf_dad_stop(ifp); |
1452 | } | 1464 | } |
1453 | 1465 | ||
@@ -2823,11 +2835,6 @@ static void addrconf_dad_timer(unsigned long data) | |||
2823 | read_unlock_bh(&idev->lock); | 2835 | read_unlock_bh(&idev->lock); |
2824 | goto out; | 2836 | goto out; |
2825 | } | 2837 | } |
2826 | if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) { | ||
2827 | read_unlock_bh(&idev->lock); | ||
2828 | addrconf_dad_failure(ifp); | ||
2829 | return; | ||
2830 | } | ||
2831 | spin_lock_bh(&ifp->lock); | 2838 | spin_lock_bh(&ifp->lock); |
2832 | if (ifp->probes == 0) { | 2839 | if (ifp->probes == 0) { |
2833 | /* | 2840 | /* |