diff options
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
| -rw-r--r-- | net/sctp/sm_sideeffect.c | 35 | 
1 files changed, 35 insertions, 0 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index d5ae450b6f02..eb1f42f45fdd 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -397,6 +397,41 @@ out_unlock:  	sctp_transport_put(transport);  } +/* Handle the timeout of the ICMP protocol unreachable timer.  Trigger + * the correct state machine transition that will close the association. + */ +void sctp_generate_proto_unreach_event(unsigned long data) +{ +	struct sctp_transport *transport = (struct sctp_transport *) data; +	struct sctp_association *asoc = transport->asoc; +	 +	sctp_bh_lock_sock(asoc->base.sk); +	if (sock_owned_by_user(asoc->base.sk)) { +		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); + +		/* Try again later.  */ +		if (!mod_timer(&transport->proto_unreach_timer, +				jiffies + (HZ/20))) +			sctp_association_hold(asoc); +		goto out_unlock; +	} + +	/* Is this structure just waiting around for us to actually +	 * get destroyed? +	 */ +	if (asoc->base.dead) +		goto out_unlock; + +	sctp_do_sm(SCTP_EVENT_T_OTHER, +		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), +		   asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); + +out_unlock: +	sctp_bh_unlock_sock(asoc->base.sk); +	sctp_association_put(asoc); +} + +  /* Inject a SACK Timeout event into the state machine.  */  static void sctp_generate_sack_event(unsigned long data)  {  |