|
@@ -397,6 +397,41 @@ out_unlock:
|
|
sctp_transport_put(transport);
|
|
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. */
|
|
/* Inject a SACK Timeout event into the state machine. */
|
|
static void sctp_generate_sack_event(unsigned long data)
|
|
static void sctp_generate_sack_event(unsigned long data)
|
|
{
|
|
{
|