aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 63a808d5af15..045597b9a7c0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -179,7 +179,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp);
179static void addrconf_dad_work(struct work_struct *w); 179static void addrconf_dad_work(struct work_struct *w);
180static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id, 180static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
181 bool send_na); 181 bool send_na);
182static void addrconf_dad_run(struct inet6_dev *idev); 182static void addrconf_dad_run(struct inet6_dev *idev, bool restart);
183static void addrconf_rs_timer(struct timer_list *t); 183static void addrconf_rs_timer(struct timer_list *t);
184static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); 184static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
185static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); 185static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
@@ -3439,6 +3439,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
3439 void *ptr) 3439 void *ptr)
3440{ 3440{
3441 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 3441 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
3442 struct netdev_notifier_change_info *change_info;
3442 struct netdev_notifier_changeupper_info *info; 3443 struct netdev_notifier_changeupper_info *info;
3443 struct inet6_dev *idev = __in6_dev_get(dev); 3444 struct inet6_dev *idev = __in6_dev_get(dev);
3444 struct net *net = dev_net(dev); 3445 struct net *net = dev_net(dev);
@@ -3513,7 +3514,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
3513 break; 3514 break;
3514 } 3515 }
3515 3516
3516 if (idev) { 3517 if (!IS_ERR_OR_NULL(idev)) {
3517 if (idev->if_flags & IF_READY) { 3518 if (idev->if_flags & IF_READY) {
3518 /* device is already configured - 3519 /* device is already configured -
3519 * but resend MLD reports, we might 3520 * but resend MLD reports, we might
@@ -3521,6 +3522,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
3521 * multicast snooping switches 3522 * multicast snooping switches
3522 */ 3523 */
3523 ipv6_mc_up(idev); 3524 ipv6_mc_up(idev);
3525 change_info = ptr;
3526 if (change_info->flags_changed & IFF_NOARP)
3527 addrconf_dad_run(idev, true);
3524 rt6_sync_up(dev, RTNH_F_LINKDOWN); 3528 rt6_sync_up(dev, RTNH_F_LINKDOWN);
3525 break; 3529 break;
3526 } 3530 }
@@ -3555,7 +3559,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
3555 3559
3556 if (!IS_ERR_OR_NULL(idev)) { 3560 if (!IS_ERR_OR_NULL(idev)) {
3557 if (run_pending) 3561 if (run_pending)
3558 addrconf_dad_run(idev); 3562 addrconf_dad_run(idev, false);
3559 3563
3560 /* Device has an address by now */ 3564 /* Device has an address by now */
3561 rt6_sync_up(dev, RTNH_F_DEAD); 3565 rt6_sync_up(dev, RTNH_F_DEAD);
@@ -4173,16 +4177,19 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
4173 addrconf_verify_rtnl(); 4177 addrconf_verify_rtnl();
4174} 4178}
4175 4179
4176static void addrconf_dad_run(struct inet6_dev *idev) 4180static void addrconf_dad_run(struct inet6_dev *idev, bool restart)
4177{ 4181{
4178 struct inet6_ifaddr *ifp; 4182 struct inet6_ifaddr *ifp;
4179 4183
4180 read_lock_bh(&idev->lock); 4184 read_lock_bh(&idev->lock);
4181 list_for_each_entry(ifp, &idev->addr_list, if_list) { 4185 list_for_each_entry(ifp, &idev->addr_list, if_list) {
4182 spin_lock(&ifp->lock); 4186 spin_lock(&ifp->lock);
4183 if (ifp->flags & IFA_F_TENTATIVE && 4187 if ((ifp->flags & IFA_F_TENTATIVE &&
4184 ifp->state == INET6_IFADDR_STATE_DAD) 4188 ifp->state == INET6_IFADDR_STATE_DAD) || restart) {
4189 if (restart)
4190 ifp->state = INET6_IFADDR_STATE_PREDAD;
4185 addrconf_dad_kick(ifp); 4191 addrconf_dad_kick(ifp);
4192 }
4186 spin_unlock(&ifp->lock); 4193 spin_unlock(&ifp->lock);
4187 } 4194 }
4188 read_unlock_bh(&idev->lock); 4195 read_unlock_bh(&idev->lock);