Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc2b99f7 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller
Browse files

IPv6: keep permanent addresses on admin down



Permanent IPV6 addresses should not be removed when the link is
set to admin down, only when device is removed.

When link is lost permanent addresses should be marked as tentative
so that when link comes back they are subject to duplicate address
detection (if DAD was enabled for that address).

Other routing systems keep manually configured IPv6 addresses
when link is set down.

Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c0ad9845
Loading
Loading
Loading
Loading
+24 −11
Original line number Diff line number Diff line
@@ -2646,7 +2646,8 @@ static int addrconf_ifdown(struct net_device *dev, int how)

		write_lock_bh(&addrconf_hash_lock);
		while ((ifa = *bifa) != NULL) {
			if (ifa->idev == idev) {
			if (ifa->idev == idev &&
			    (how || !(ifa->flags&IFA_F_PERMANENT))) {
				*bifa = ifa->lst_next;
				ifa->lst_next = NULL;
				addrconf_del_timer(ifa);
@@ -2686,11 +2687,22 @@ static int addrconf_ifdown(struct net_device *dev, int how)
		write_lock_bh(&idev->lock);
	}
#endif
	while ((ifa = idev->addr_list) != NULL) {
		idev->addr_list = ifa->if_next;
	bifa = &idev->addr_list;
	while ((ifa = *bifa) != NULL) {
		if (how == 0 && (ifa->flags&IFA_F_PERMANENT)) {
			/* Retain permanent address on admin down */
			bifa = &ifa->if_next;

			/* Restart DAD if needed when link comes back up */
			if ( !((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) ||
			       idev->cnf.accept_dad <= 0 ||
			       (ifa->flags & IFA_F_NODAD)))
				ifa->flags |= IFA_F_TENTATIVE;
		} else {
			*bifa = ifa->if_next;
			ifa->if_next = NULL;

			ifa->dead = 1;
		addrconf_del_timer(ifa);
			write_unlock_bh(&idev->lock);

			__ipv6_ifa_notify(RTM_DELADDR, ifa);
@@ -2699,6 +2711,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)

			write_lock_bh(&idev->lock);
		}
	}
	write_unlock_bh(&idev->lock);

	/* Step 5: Discard multicast list */