diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 43b3c9f89c12..55f486d89c88 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -137,6 +137,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock); static void addrconf_join_anycast(struct inet6_ifaddr *ifp); static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); +static void addrconf_bonding_change(struct net_device *dev, + unsigned long event); static int addrconf_ifdown(struct net_device *dev, int how); static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); @@ -1371,12 +1373,14 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add /* Gets referenced address, destroys ifaddr */ -static void addrconf_dad_stop(struct inet6_ifaddr *ifp) +static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) { if (ifp->flags&IFA_F_PERMANENT) { spin_lock_bh(&ifp->lock); addrconf_del_timer(ifp); ifp->flags |= IFA_F_TENTATIVE; + if (dad_failed) + ifp->flags |= IFA_F_DADFAILED; spin_unlock_bh(&ifp->lock); in6_ifa_put(ifp); #ifdef CONFIG_IPV6_PRIVACY @@ -1403,8 +1407,8 @@ 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); + printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", + ifp->idev->dev->name, &ifp->addr); if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { struct in6_addr addr; @@ -1422,7 +1426,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) } } - addrconf_dad_stop(ifp); + addrconf_dad_stop(ifp, 1); } /* Join to solicited addr multicast group. */ @@ -2580,6 +2584,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, return notifier_from_errno(err); } break; + case NETDEV_BONDING_OLDTYPE: + case NETDEV_BONDING_NEWTYPE: + addrconf_bonding_change(dev, event); + break; } return NOTIFY_OK; @@ -2593,6 +2601,19 @@ static struct notifier_block ipv6_dev_notf = { .priority = 0 }; +static void addrconf_bonding_change(struct net_device *dev, unsigned long event) +{ + struct inet6_dev *idev; + ASSERT_RTNL(); + + idev = __in6_dev_get(dev); + + if (event == NETDEV_BONDING_NEWTYPE) + ipv6_mc_remap(idev); + else if (event == NETDEV_BONDING_OLDTYPE) + ipv6_mc_unmap(idev); +} + static int addrconf_ifdown(struct net_device *dev, int how) { struct inet6_dev *idev; @@ -2778,7 +2799,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) idev->cnf.accept_dad < 1 || !(ifp->flags&IFA_F_TENTATIVE) || ifp->flags & IFA_F_NODAD) { - ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); + ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); spin_unlock_bh(&ifp->lock); read_unlock_bh(&idev->lock); @@ -2795,7 +2816,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) * - otherwise, kill it. */ in6_ifa_hold(ifp); - addrconf_dad_stop(ifp); + addrconf_dad_stop(ifp, 0); return; } @@ -2829,7 +2850,7 @@ static void addrconf_dad_timer(unsigned long data) * DAD was successful */ - ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); + ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); spin_unlock_bh(&ifp->lock); read_unlock_bh(&idev->lock); |