Fix the behavior of allowing both sysctl and addrconf_dad_failure()
to set the disable_ipv6 parameter without any bad side-effects.
If DAD fails and accept_dad > 1, we will still set disable_ipv6=1,
but then instead of allowing an RA to add an address then
immediately fail DAD, we simply don't allow the address to be
added in the first place. This also lets the user set this flag
and disable all IPv6 addresses on the interface, or on the entire
system.
Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Default: 16
disable_ipv6 - BOOLEAN
Default: 16
disable_ipv6 - BOOLEAN
- Disable IPv6 operation.
+ Disable IPv6 operation. If accept_dad is set to 2, this value
+ will be dynamically set to TRUE if DAD fails for the link-local
+ address.
Default: FALSE (enable IPv6 operation)
accept_dad - INTEGER
Default: FALSE (enable IPv6 operation)
accept_dad - INTEGER
{
struct inet6_ifaddr *ifa = NULL;
struct rt6_info *rt;
{
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);
int hash;
int err = 0;
int addr_type = ipv6_addr_type(addr);
+ 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 */
write_lock(&addrconf_hash_lock);
/* Ignore adding duplicate addresses on an interface */
void addrconf_dad_failure(struct inet6_ifaddr *ifp)
{
struct inet6_dev *idev = ifp->idev;
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;
if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
struct in6_addr addr;
ipv6_addr_equal(&ifp->addr, &addr)) {
/* DAD failed for link-local based on MAC address */
idev->cnf.disable_ipv6 = 1;
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);
}
addrconf_dad_stop(ifp);
}
read_unlock_bh(&idev->lock);
goto out;
}
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) {
/*
spin_lock_bh(&ifp->lock);
if (ifp->probes == 0) {
/*