diff options
| -rw-r--r-- | net/ipv4/icmp.c | 22 | ||||
| -rw-r--r-- | net/ipv6/icmp.c | 23 |
2 files changed, 26 insertions, 19 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 860558633b2c..55c355e63234 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
| @@ -204,18 +204,22 @@ static struct sock *icmp_sk(struct net *net) | |||
| 204 | return net->ipv4.icmp_sk[smp_processor_id()]; | 204 | return net->ipv4.icmp_sk[smp_processor_id()]; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | static inline int icmp_xmit_lock(struct sock *sk) | 207 | static inline struct sock *icmp_xmit_lock(struct net *net) |
| 208 | { | 208 | { |
| 209 | struct sock *sk; | ||
| 210 | |||
| 209 | local_bh_disable(); | 211 | local_bh_disable(); |
| 210 | 212 | ||
| 213 | sk = icmp_sk(net); | ||
| 214 | |||
| 211 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { | 215 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
| 212 | /* This can happen if the output path signals a | 216 | /* This can happen if the output path signals a |
| 213 | * dst_link_failure() for an outgoing ICMP packet. | 217 | * dst_link_failure() for an outgoing ICMP packet. |
| 214 | */ | 218 | */ |
| 215 | local_bh_enable(); | 219 | local_bh_enable(); |
| 216 | return 1; | 220 | return NULL; |
| 217 | } | 221 | } |
| 218 | return 0; | 222 | return sk; |
| 219 | } | 223 | } |
| 220 | 224 | ||
| 221 | static inline void icmp_xmit_unlock(struct sock *sk) | 225 | static inline void icmp_xmit_unlock(struct sock *sk) |
| @@ -354,15 +358,17 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
| 354 | struct ipcm_cookie ipc; | 358 | struct ipcm_cookie ipc; |
| 355 | struct rtable *rt = skb->rtable; | 359 | struct rtable *rt = skb->rtable; |
| 356 | struct net *net = dev_net(rt->u.dst.dev); | 360 | struct net *net = dev_net(rt->u.dst.dev); |
| 357 | struct sock *sk = icmp_sk(net); | 361 | struct sock *sk; |
| 358 | struct inet_sock *inet = inet_sk(sk); | 362 | struct inet_sock *inet; |
| 359 | __be32 daddr; | 363 | __be32 daddr; |
| 360 | 364 | ||
| 361 | if (ip_options_echo(&icmp_param->replyopts, skb)) | 365 | if (ip_options_echo(&icmp_param->replyopts, skb)) |
| 362 | return; | 366 | return; |
| 363 | 367 | ||
| 364 | if (icmp_xmit_lock(sk)) | 368 | sk = icmp_xmit_lock(net); |
| 369 | if (sk == NULL) | ||
| 365 | return; | 370 | return; |
| 371 | inet = inet_sk(sk); | ||
| 366 | 372 | ||
| 367 | icmp_param->data.icmph.checksum = 0; | 373 | icmp_param->data.icmph.checksum = 0; |
| 368 | 374 | ||
| @@ -419,7 +425,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
| 419 | if (!rt) | 425 | if (!rt) |
| 420 | goto out; | 426 | goto out; |
| 421 | net = dev_net(rt->u.dst.dev); | 427 | net = dev_net(rt->u.dst.dev); |
| 422 | sk = icmp_sk(net); | ||
| 423 | 428 | ||
| 424 | /* | 429 | /* |
| 425 | * Find the original header. It is expected to be valid, of course. | 430 | * Find the original header. It is expected to be valid, of course. |
| @@ -483,7 +488,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
| 483 | } | 488 | } |
| 484 | } | 489 | } |
| 485 | 490 | ||
| 486 | if (icmp_xmit_lock(sk)) | 491 | sk = icmp_xmit_lock(net); |
| 492 | if (sk == NULL) | ||
| 487 | return; | 493 | return; |
| 488 | 494 | ||
| 489 | /* | 495 | /* |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index abedf95fdf2d..b3157a0cc15d 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -91,19 +91,22 @@ static struct inet6_protocol icmpv6_protocol = { | |||
| 91 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 91 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | static __inline__ int icmpv6_xmit_lock(struct sock *sk) | 94 | static __inline__ struct sock *icmpv6_xmit_lock(struct net *net) |
| 95 | { | 95 | { |
| 96 | struct sock *sk; | ||
| 97 | |||
| 96 | local_bh_disable(); | 98 | local_bh_disable(); |
| 97 | 99 | ||
| 100 | sk = icmpv6_sk(net); | ||
| 98 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { | 101 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
| 99 | /* This can happen if the output path (f.e. SIT or | 102 | /* This can happen if the output path (f.e. SIT or |
| 100 | * ip6ip6 tunnel) signals dst_link_failure() for an | 103 | * ip6ip6 tunnel) signals dst_link_failure() for an |
| 101 | * outgoing ICMP6 packet. | 104 | * outgoing ICMP6 packet. |
| 102 | */ | 105 | */ |
| 103 | local_bh_enable(); | 106 | local_bh_enable(); |
| 104 | return 1; | 107 | return NULL; |
| 105 | } | 108 | } |
| 106 | return 0; | 109 | return sk; |
| 107 | } | 110 | } |
| 108 | 111 | ||
| 109 | static __inline__ void icmpv6_xmit_unlock(struct sock *sk) | 112 | static __inline__ void icmpv6_xmit_unlock(struct sock *sk) |
| @@ -392,11 +395,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
| 392 | fl.fl_icmp_code = code; | 395 | fl.fl_icmp_code = code; |
| 393 | security_skb_classify_flow(skb, &fl); | 396 | security_skb_classify_flow(skb, &fl); |
| 394 | 397 | ||
| 395 | sk = icmpv6_sk(net); | 398 | sk = icmpv6_xmit_lock(net); |
| 396 | np = inet6_sk(sk); | 399 | if (sk == NULL) |
| 397 | |||
| 398 | if (icmpv6_xmit_lock(sk)) | ||
| 399 | return; | 400 | return; |
| 401 | np = inet6_sk(sk); | ||
| 400 | 402 | ||
| 401 | if (!icmpv6_xrlim_allow(sk, type, &fl)) | 403 | if (!icmpv6_xrlim_allow(sk, type, &fl)) |
| 402 | goto out; | 404 | goto out; |
| @@ -539,11 +541,10 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
| 539 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; | 541 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; |
| 540 | security_skb_classify_flow(skb, &fl); | 542 | security_skb_classify_flow(skb, &fl); |
| 541 | 543 | ||
| 542 | sk = icmpv6_sk(net); | 544 | sk = icmpv6_xmit_lock(net); |
| 543 | np = inet6_sk(sk); | 545 | if (sk == NULL) |
| 544 | |||
| 545 | if (icmpv6_xmit_lock(sk)) | ||
| 546 | return; | 546 | return; |
| 547 | np = inet6_sk(sk); | ||
| 547 | 548 | ||
| 548 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 549 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
| 549 | fl.oif = np->mcast_oif; | 550 | fl.oif = np->mcast_oif; |
