diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 19 | ||||
-rw-r--r-- | net/ipv6/route.c | 14 |
2 files changed, 21 insertions, 12 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); | |||
179 | static void addrconf_dad_work(struct work_struct *w); | 179 | static void addrconf_dad_work(struct work_struct *w); |
180 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id, | 180 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id, |
181 | bool send_na); | 181 | bool send_na); |
182 | static void addrconf_dad_run(struct inet6_dev *idev); | 182 | static void addrconf_dad_run(struct inet6_dev *idev, bool restart); |
183 | static void addrconf_rs_timer(struct timer_list *t); | 183 | static void addrconf_rs_timer(struct timer_list *t); |
184 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | 184 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); |
185 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | 185 | static 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 | ||
4176 | static void addrconf_dad_run(struct inet6_dev *idev) | 4180 | static 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); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 2a7423c39456..059f0531f7c1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2232,8 +2232,7 @@ static void ip6_link_failure(struct sk_buff *skb) | |||
2232 | if (rt) { | 2232 | if (rt) { |
2233 | rcu_read_lock(); | 2233 | rcu_read_lock(); |
2234 | if (rt->rt6i_flags & RTF_CACHE) { | 2234 | if (rt->rt6i_flags & RTF_CACHE) { |
2235 | if (dst_hold_safe(&rt->dst)) | 2235 | rt6_remove_exception_rt(rt); |
2236 | rt6_remove_exception_rt(rt); | ||
2237 | } else { | 2236 | } else { |
2238 | struct fib6_info *from; | 2237 | struct fib6_info *from; |
2239 | struct fib6_node *fn; | 2238 | struct fib6_node *fn; |
@@ -2360,10 +2359,13 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu); | |||
2360 | 2359 | ||
2361 | void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) | 2360 | void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) |
2362 | { | 2361 | { |
2362 | int oif = sk->sk_bound_dev_if; | ||
2363 | struct dst_entry *dst; | 2363 | struct dst_entry *dst; |
2364 | 2364 | ||
2365 | ip6_update_pmtu(skb, sock_net(sk), mtu, | 2365 | if (!oif && skb->dev) |
2366 | sk->sk_bound_dev_if, sk->sk_mark, sk->sk_uid); | 2366 | oif = l3mdev_master_ifindex(skb->dev); |
2367 | |||
2368 | ip6_update_pmtu(skb, sock_net(sk), mtu, oif, sk->sk_mark, sk->sk_uid); | ||
2367 | 2369 | ||
2368 | dst = __sk_dst_get(sk); | 2370 | dst = __sk_dst_get(sk); |
2369 | if (!dst || !dst->obsolete || | 2371 | if (!dst || !dst->obsolete || |
@@ -3214,8 +3216,8 @@ static int ip6_del_cached_rt(struct rt6_info *rt, struct fib6_config *cfg) | |||
3214 | if (cfg->fc_flags & RTF_GATEWAY && | 3216 | if (cfg->fc_flags & RTF_GATEWAY && |
3215 | !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) | 3217 | !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) |
3216 | goto out; | 3218 | goto out; |
3217 | if (dst_hold_safe(&rt->dst)) | 3219 | |
3218 | rc = rt6_remove_exception_rt(rt); | 3220 | rc = rt6_remove_exception_rt(rt); |
3219 | out: | 3221 | out: |
3220 | return rc; | 3222 | return rc; |
3221 | } | 3223 | } |