diff options
-rw-r--r-- | net/ipv4/icmp.c | 19 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 24 |
2 files changed, 22 insertions, 21 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 3a4da43d8309..9bcf263f06ca 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -232,11 +232,11 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; | |||
232 | static DEFINE_PER_CPU(struct sock *, __icmp_sk) = NULL; | 232 | static DEFINE_PER_CPU(struct sock *, __icmp_sk) = NULL; |
233 | #define icmp_sk __get_cpu_var(__icmp_sk) | 233 | #define icmp_sk __get_cpu_var(__icmp_sk) |
234 | 234 | ||
235 | static inline int icmp_xmit_lock(void) | 235 | static inline int icmp_xmit_lock(struct sock *sk) |
236 | { | 236 | { |
237 | local_bh_disable(); | 237 | local_bh_disable(); |
238 | 238 | ||
239 | if (unlikely(!spin_trylock(&icmp_sk->sk_lock.slock))) { | 239 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
240 | /* This can happen if the output path signals a | 240 | /* This can happen if the output path signals a |
241 | * dst_link_failure() for an outgoing ICMP packet. | 241 | * dst_link_failure() for an outgoing ICMP packet. |
242 | */ | 242 | */ |
@@ -246,9 +246,9 @@ static inline int icmp_xmit_lock(void) | |||
246 | return 0; | 246 | return 0; |
247 | } | 247 | } |
248 | 248 | ||
249 | static inline void icmp_xmit_unlock(void) | 249 | static inline void icmp_xmit_unlock(struct sock *sk) |
250 | { | 250 | { |
251 | spin_unlock_bh(&icmp_sk->sk_lock.slock); | 251 | spin_unlock_bh(&sk->sk_lock.slock); |
252 | } | 252 | } |
253 | 253 | ||
254 | /* | 254 | /* |
@@ -387,7 +387,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
387 | if (ip_options_echo(&icmp_param->replyopts, skb)) | 387 | if (ip_options_echo(&icmp_param->replyopts, skb)) |
388 | return; | 388 | return; |
389 | 389 | ||
390 | if (icmp_xmit_lock()) | 390 | if (icmp_xmit_lock(sk)) |
391 | return; | 391 | return; |
392 | 392 | ||
393 | icmp_param->data.icmph.checksum = 0; | 393 | icmp_param->data.icmph.checksum = 0; |
@@ -415,7 +415,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
415 | icmp_push_reply(icmp_param, &ipc, rt); | 415 | icmp_push_reply(icmp_param, &ipc, rt); |
416 | ip_rt_put(rt); | 416 | ip_rt_put(rt); |
417 | out_unlock: | 417 | out_unlock: |
418 | icmp_xmit_unlock(); | 418 | icmp_xmit_unlock(sk); |
419 | } | 419 | } |
420 | 420 | ||
421 | 421 | ||
@@ -440,6 +440,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
440 | __be32 saddr; | 440 | __be32 saddr; |
441 | u8 tos; | 441 | u8 tos; |
442 | struct net *net; | 442 | struct net *net; |
443 | struct sock *sk = icmp_sk; | ||
443 | 444 | ||
444 | if (!rt) | 445 | if (!rt) |
445 | goto out; | 446 | goto out; |
@@ -507,7 +508,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
507 | } | 508 | } |
508 | } | 509 | } |
509 | 510 | ||
510 | if (icmp_xmit_lock()) | 511 | if (icmp_xmit_lock(sk)) |
511 | return; | 512 | return; |
512 | 513 | ||
513 | /* | 514 | /* |
@@ -546,7 +547,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
546 | icmp_param.data.icmph.checksum = 0; | 547 | icmp_param.data.icmph.checksum = 0; |
547 | icmp_param.skb = skb_in; | 548 | icmp_param.skb = skb_in; |
548 | icmp_param.offset = skb_network_offset(skb_in); | 549 | icmp_param.offset = skb_network_offset(skb_in); |
549 | inet_sk(icmp_sk)->tos = tos; | 550 | inet_sk(sk)->tos = tos; |
550 | ipc.addr = iph->saddr; | 551 | ipc.addr = iph->saddr; |
551 | ipc.opt = &icmp_param.replyopts; | 552 | ipc.opt = &icmp_param.replyopts; |
552 | 553 | ||
@@ -654,7 +655,7 @@ route_done: | |||
654 | ende: | 655 | ende: |
655 | ip_rt_put(rt); | 656 | ip_rt_put(rt); |
656 | out_unlock: | 657 | out_unlock: |
657 | icmp_xmit_unlock(); | 658 | icmp_xmit_unlock(sk); |
658 | out:; | 659 | out:; |
659 | } | 660 | } |
660 | 661 | ||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 875bdc725dc4..18f220a04486 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -90,11 +90,11 @@ static struct inet6_protocol icmpv6_protocol = { | |||
90 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 90 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static __inline__ int icmpv6_xmit_lock(void) | 93 | static __inline__ int icmpv6_xmit_lock(struct sock *sk) |
94 | { | 94 | { |
95 | local_bh_disable(); | 95 | local_bh_disable(); |
96 | 96 | ||
97 | if (unlikely(!spin_trylock(&icmpv6_sk->sk_lock.slock))) { | 97 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
98 | /* This can happen if the output path (f.e. SIT or | 98 | /* This can happen if the output path (f.e. SIT or |
99 | * ip6ip6 tunnel) signals dst_link_failure() for an | 99 | * ip6ip6 tunnel) signals dst_link_failure() for an |
100 | * outgoing ICMP6 packet. | 100 | * outgoing ICMP6 packet. |
@@ -105,9 +105,9 @@ static __inline__ int icmpv6_xmit_lock(void) | |||
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | 107 | ||
108 | static __inline__ void icmpv6_xmit_unlock(void) | 108 | static __inline__ void icmpv6_xmit_unlock(struct sock *sk) |
109 | { | 109 | { |
110 | spin_unlock_bh(&icmpv6_sk->sk_lock.slock); | 110 | spin_unlock_bh(&sk->sk_lock.slock); |
111 | } | 111 | } |
112 | 112 | ||
113 | /* | 113 | /* |
@@ -389,12 +389,12 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
389 | fl.fl_icmp_code = code; | 389 | fl.fl_icmp_code = code; |
390 | security_skb_classify_flow(skb, &fl); | 390 | security_skb_classify_flow(skb, &fl); |
391 | 391 | ||
392 | if (icmpv6_xmit_lock()) | ||
393 | return; | ||
394 | |||
395 | sk = icmpv6_sk; | 392 | sk = icmpv6_sk; |
396 | np = inet6_sk(sk); | 393 | np = inet6_sk(sk); |
397 | 394 | ||
395 | if (icmpv6_xmit_lock(sk)) | ||
396 | return; | ||
397 | |||
398 | if (!icmpv6_xrlim_allow(sk, type, &fl)) | 398 | if (!icmpv6_xrlim_allow(sk, type, &fl)) |
399 | goto out; | 399 | goto out; |
400 | 400 | ||
@@ -498,7 +498,7 @@ out_put: | |||
498 | out_dst_release: | 498 | out_dst_release: |
499 | dst_release(dst); | 499 | dst_release(dst); |
500 | out: | 500 | out: |
501 | icmpv6_xmit_unlock(); | 501 | icmpv6_xmit_unlock(sk); |
502 | } | 502 | } |
503 | 503 | ||
504 | EXPORT_SYMBOL(icmpv6_send); | 504 | EXPORT_SYMBOL(icmpv6_send); |
@@ -535,12 +535,12 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
535 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; | 535 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; |
536 | security_skb_classify_flow(skb, &fl); | 536 | security_skb_classify_flow(skb, &fl); |
537 | 537 | ||
538 | if (icmpv6_xmit_lock()) | ||
539 | return; | ||
540 | |||
541 | sk = icmpv6_sk; | 538 | sk = icmpv6_sk; |
542 | np = inet6_sk(sk); | 539 | np = inet6_sk(sk); |
543 | 540 | ||
541 | if (icmpv6_xmit_lock(sk)) | ||
542 | return; | ||
543 | |||
544 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 544 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
545 | fl.oif = np->mcast_oif; | 545 | fl.oif = np->mcast_oif; |
546 | 546 | ||
@@ -584,7 +584,7 @@ out_put: | |||
584 | in6_dev_put(idev); | 584 | in6_dev_put(idev); |
585 | dst_release(dst); | 585 | dst_release(dst); |
586 | out: | 586 | out: |
587 | icmpv6_xmit_unlock(); | 587 | icmpv6_xmit_unlock(sk); |
588 | } | 588 | } |
589 | 589 | ||
590 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | 590 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) |