Commit 2de79570 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by David S. Miller

ipv6: addrconf: don't remove address state on ifdown if the address is being kept

Currently, addrconf_ifdown does not delete statically configured IPv6
addresses when the interface is brought down. The intent is that when
the interface comes back up the address will be usable again. However,
this doesn't actually work, because the system stops listening on the
corresponding solicited-node multicast address, so the address cannot
respond to neighbor solicitations and thus receive traffic. Also, the
code notifies the rest of the system that the address is being deleted
(e.g, RTM_DELADDR), even though it is not. Fix it so that none of this
state is updated if the address is being kept on the interface.

Tested: Added a statically configured IPv6 address to an interface,
started ping, brought link down, brought link up again. When link came
up ping kept on going and "ip -6 maddr" showed that the host was still
subscribed to there
Signed-off-by: default avatarLorenzo Colitti <lorenzo@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8f49c270
......@@ -2740,10 +2740,6 @@ static int addrconf_ifdown(struct net_device *dev, int how)
/* Flag it for later restoration when link comes up */
ifa->flags |= IFA_F_TENTATIVE;
ifa->state = INET6_IFADDR_STATE_DAD;
write_unlock_bh(&idev->lock);
in6_ifa_hold(ifa);
} else {
list_del(&ifa->if_list);
......@@ -2758,19 +2754,15 @@ static int addrconf_ifdown(struct net_device *dev, int how)
ifa->state = INET6_IFADDR_STATE_DEAD;
spin_unlock_bh(&ifa->state_lock);
if (state == INET6_IFADDR_STATE_DEAD)
goto put_ifa;
if (state == INET6_IFADDR_STATE_DEAD) {
in6_ifa_put(ifa);
} else {
__ipv6_ifa_notify(RTM_DELADDR, ifa);
atomic_notifier_call_chain(&inet6addr_chain,
NETDEV_DOWN, ifa);
}
write_lock_bh(&idev->lock);
}
__ipv6_ifa_notify(RTM_DELADDR, ifa);
if (ifa->state == INET6_IFADDR_STATE_DEAD)
atomic_notifier_call_chain(&inet6addr_chain,
NETDEV_DOWN, ifa);
put_ifa:
in6_ifa_put(ifa);
write_lock_bh(&idev->lock);
}
list_splice(&keep_list, &idev->addr_list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment