diff options
Diffstat (limited to 'net/ipv4/icmp.c')
| -rw-r--r-- | net/ipv4/icmp.c | 22 |
1 files changed, 14 insertions, 8 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 | /* |
