diff options
Diffstat (limited to 'net/sctp/input.c')
| -rw-r--r-- | net/sctp/input.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index 2a570184e5a9..ea2192444ce6 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
| @@ -440,11 +440,25 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
| 440 | { | 440 | { |
| 441 | SCTP_DEBUG_PRINTK("%s\n", __func__); | 441 | SCTP_DEBUG_PRINTK("%s\n", __func__); |
| 442 | 442 | ||
| 443 | sctp_do_sm(SCTP_EVENT_T_OTHER, | 443 | if (sock_owned_by_user(sk)) { |
| 444 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | 444 | if (timer_pending(&t->proto_unreach_timer)) |
| 445 | asoc->state, asoc->ep, asoc, t, | 445 | return; |
| 446 | GFP_ATOMIC); | 446 | else { |
| 447 | if (!mod_timer(&t->proto_unreach_timer, | ||
| 448 | jiffies + (HZ/20))) | ||
| 449 | sctp_association_hold(asoc); | ||
| 450 | } | ||
| 451 | |||
| 452 | } else { | ||
| 453 | if (timer_pending(&t->proto_unreach_timer) && | ||
| 454 | del_timer(&t->proto_unreach_timer)) | ||
| 455 | sctp_association_put(asoc); | ||
| 447 | 456 | ||
| 457 | sctp_do_sm(SCTP_EVENT_T_OTHER, | ||
| 458 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | ||
| 459 | asoc->state, asoc->ep, asoc, t, | ||
| 460 | GFP_ATOMIC); | ||
| 461 | } | ||
| 448 | } | 462 | } |
| 449 | 463 | ||
| 450 | /* Common lookup code for icmp/icmpv6 error handler. */ | 464 | /* Common lookup code for icmp/icmpv6 error handler. */ |
