Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-drm-fsl-dcu.git] / net / sctp / sm_statefuns.c
index 5b5ae79583223244ef2c85ed8aa5d331b0c829dd..b3cad8a03736c1a05b34fe6c9264a3b192eb6e19 100644 (file)
@@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
 static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
 
 static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
-                                          __u16 error, int sk_err,
+                                          __be16 error, int sk_err,
                                           const struct sctp_association *asoc,
                                           struct sctp_transport *transport);
 
@@ -187,10 +187,9 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
         */
        ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP,
                                             0, 0, 0, GFP_ATOMIC);
-       if (!ev)
-               goto nomem;
-
-       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+       if (ev)
+               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+                               SCTP_ULPEVENT(ev));
 
        /* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint
         * will verify that it is in SHUTDOWN-ACK-SENT state, if it is
@@ -215,9 +214,6 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
 
        return SCTP_DISPOSITION_DELETE_TCB;
-
-nomem:
-       return SCTP_DISPOSITION_NOMEM;
 }
 
 /*
@@ -232,7 +228,7 @@ nomem:
  *    Verification Tag field to Tag_A, and also provide its own
  *    Verification Tag (Tag_Z) in the Initiate Tag field.
  *
- * Verification Tag: Must be 0. 
+ * Verification Tag: Must be 0.
  *
  * Inputs
  * (endpoint, asoc, chunk)
@@ -260,7 +256,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
        /* 6.10 Bundling
         * An endpoint MUST NOT bundle INIT, INIT ACK or
         * SHUTDOWN COMPLETE with any other chunks.
-        * 
+        *
         * IG Section 2.11.2
         * Furthermore, we require that the receiver of an INIT chunk MUST
         * enforce these rules by silently discarding an arriving packet
@@ -286,7 +282,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
                return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 
        /* 3.1 A packet containing an INIT chunk MUST have a zero Verification
-        * Tag. 
+        * Tag.
         */
        if (chunk->sctp_hdr->vtag != 0)
                return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
@@ -330,7 +326,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
                }
        }
 
-        /* Grab the INIT header.  */
+       /* Grab the INIT header.  */
        chunk->subh.init_hdr = (sctp_inithdr_t *)chunk->skb->data;
 
        /* Tag the variable length parameters.  */
@@ -347,8 +343,6 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
                               GFP_ATOMIC))
                goto nomem_init;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
-
        /* B) "Z" shall respond immediately with an INIT ACK chunk.  */
 
        /* If there are errors need to be reported for unknown parameters,
@@ -360,11 +354,11 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
                        sizeof(sctp_chunkhdr_t);
 
        if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
-               goto nomem_ack;
+               goto nomem_init;
 
        repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
        if (!repl)
-               goto nomem_ack;
+               goto nomem_init;
 
        /* If there are errors need to be reported for unknown parameters,
         * include them in the outgoing INIT ACK as "Unrecognized parameter"
@@ -388,6 +382,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
                sctp_chunk_free(err_chunk);
        }
 
+       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
+
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
 
        /*
@@ -400,12 +396,11 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
 
        return SCTP_DISPOSITION_DELETE_TCB;
 
-nomem_ack:
-       if (err_chunk)
-               sctp_chunk_free(err_chunk);
 nomem_init:
        sctp_association_free(new_asoc);
 nomem:
+       if (err_chunk)
+               sctp_chunk_free(err_chunk);
        return SCTP_DISPOSITION_NOMEM;
 }
 
@@ -445,10 +440,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
 {
        struct sctp_chunk *chunk = arg;
        sctp_init_chunk_t *initchunk;
-       __u32 init_tag;
        struct sctp_chunk *err_chunk;
        struct sctp_packet *packet;
-       __u16 error;
+       sctp_error_t error;
 
        if (!sctp_vtag_verify(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -467,24 +461,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
        /* Grab the INIT header.  */
        chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
 
-       init_tag = ntohl(chunk->subh.init_hdr->init_tag);
-
-       /* Verification Tag: 3.3.3
-        *   If the value of the Initiate Tag in a received INIT ACK
-        *   chunk is found to be 0, the receiver MUST treat it as an
-        *   error and close the association by transmitting an ABORT.
-        */
-       if (!init_tag) {
-               struct sctp_chunk *reply = sctp_make_abort(asoc, chunk, 0);
-               if (!reply)
-                       goto nomem;
-
-               sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
-               return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM,
-                                             ECONNREFUSED, asoc,
-                                             chunk->transport);
-       }
-
        /* Verify the INIT chunk before processing it. */
        err_chunk = NULL;
        if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
@@ -555,9 +531,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
                        SCTP_CHUNK(err_chunk));
 
        return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-       return SCTP_DISPOSITION_NOMEM;
 }
 
 /*
@@ -600,7 +573,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
        struct sctp_association *new_asoc;
        sctp_init_chunk_t *peer_init;
        struct sctp_chunk *repl;
-       struct sctp_ulpevent *ev;
+       struct sctp_ulpevent *ev, *ai_ev = NULL;
        int error = 0;
        struct sctp_chunk *err_chk_p;
 
@@ -621,7 +594,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
        /* "Decode" the chunk.  We have no optional parameters so we
         * are in good shape.
         */
-        chunk->subh.cookie_hdr =
+       chunk->subh.cookie_hdr =
                (struct sctp_signed_cookie *)chunk->skb->data;
        if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
                                         sizeof(sctp_chunkhdr_t)))
@@ -659,20 +632,10 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
                };
        }
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
-       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-                       SCTP_STATE(SCTP_STATE_ESTABLISHED));
-       SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
-       SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);
-       sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
 
-       if (new_asoc->autoclose)
-               sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
-                               SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
-
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
-
-       /* Re-build the bind address for the association is done in
+       /* Delay state machine commands until later.
+        *
+        * Re-build the bind address for the association is done in
         * the sctp_unpack_cookie() already.
         */
        /* This is a brand-new association, so these are not yet side
@@ -687,9 +650,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
 
        repl = sctp_make_cookie_ack(new_asoc, chunk);
        if (!repl)
-               goto nomem_repl;
-
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+               goto nomem_init;
 
        /* RFC 2960 5.1 Normal Establishment of an Association
         *
@@ -704,28 +665,53 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
        if (!ev)
                goto nomem_ev;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
-
-       /* Sockets API Draft Section 5.3.1.6    
-        * When a peer sends a Adaption Layer Indication parameter , SCTP
+       /* Sockets API Draft Section 5.3.1.6
+        * When a peer sends a Adaptation Layer Indication parameter , SCTP
         * delivers this notification to inform the application that of the
-        * peers requested adaption layer.
+        * peers requested adaptation layer.
         */
-       if (new_asoc->peer.adaption_ind) {
-               ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+       if (new_asoc->peer.adaptation_ind) {
+               ai_ev = sctp_ulpevent_make_adaptation_indication(new_asoc,
                                                            GFP_ATOMIC);
-               if (!ev)
-                       goto nomem_ev;
+               if (!ai_ev)
+                       goto nomem_aiev;
+       }
+
+       /* Add all the state machine commands now since we've created
+        * everything.  This way we don't introduce memory corruptions
+        * during side-effect processing and correclty count established
+        * associations.
+        */
+       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
+       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+                       SCTP_STATE(SCTP_STATE_ESTABLISHED));
+       SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
+       SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);
+       sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
+
+       if (new_asoc->autoclose)
+               sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
+                               SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
+
+       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
+       /* This will send the COOKIE ACK */
+       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+
+       /* Queue the ASSOC_CHANGE event */
+       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+
+       /* Send up the Adaptation Layer Indication event */
+       if (ai_ev)
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
-                               SCTP_ULPEVENT(ev));
-       }
+                               SCTP_ULPEVENT(ai_ev));
 
        return SCTP_DISPOSITION_CONSUME;
 
+nomem_aiev:
+       sctp_ulpevent_free(ev);
 nomem_ev:
        sctp_chunk_free(repl);
-nomem_repl:
 nomem_init:
        sctp_association_free(new_asoc);
 nomem:
@@ -812,12 +798,12 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
 
        /* Sockets API Draft Section 5.3.1.6
-        * When a peer sends a Adaption Layer Indication parameter , SCTP
+        * When a peer sends a Adaptation Layer Indication parameter , SCTP
         * delivers this notification to inform the application that of the
-        * peers requested adaption layer.
+        * peers requested adaptation layer.
         */
-       if (asoc->peer.adaption_ind) {
-               ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+       if (asoc->peer.adaptation_ind) {
+               ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
                if (!ev)
                        goto nomem;
 
@@ -878,7 +864,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
                                SCTP_ERROR(ETIMEDOUT));
                /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_NO_ERROR));
+                               SCTP_PERR(SCTP_ERROR_NO_ERROR));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
                return SCTP_DISPOSITION_DELETE_TCB;
@@ -905,7 +891,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,
                        SCTP_TRANSPORT(transport));
 
-        return SCTP_DISPOSITION_CONSUME;
+       return SCTP_DISPOSITION_CONSUME;
 }
 
 /*
@@ -1294,7 +1280,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
        /* 3.1 A packet containing an INIT chunk MUST have a zero Verification
-        * Tag. 
+        * Tag.
         */
        if (chunk->sctp_hdr->vtag != 0)
                return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
@@ -1360,10 +1346,8 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
        if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type,
                               sctp_source(chunk),
                               (sctp_init_chunk_t *)chunk->chunk_hdr,
-                              GFP_ATOMIC)) {
-               retval = SCTP_DISPOSITION_NOMEM;
-               goto nomem_init;
-       }
+                              GFP_ATOMIC))
+               goto nomem;
 
        /* Make sure no new addresses are being added during the
         * restart.   Do not do this check for COOKIE-WAIT state,
@@ -1374,7 +1358,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
                if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk,
                                                 commands)) {
                        retval = SCTP_DISPOSITION_CONSUME;
-                       goto cleanup_asoc;
+                       goto nomem_retval;
                }
        }
 
@@ -1430,17 +1414,17 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
        sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
        retval = SCTP_DISPOSITION_CONSUME;
 
+       return retval;
+
+nomem:
+       retval = SCTP_DISPOSITION_NOMEM;
+nomem_retval:
+       if (new_asoc)
+               sctp_association_free(new_asoc);
 cleanup:
        if (err_chunk)
                sctp_chunk_free(err_chunk);
        return retval;
-nomem:
-       retval = SCTP_DISPOSITION_NOMEM;
-       goto cleanup;
-nomem_init:
-cleanup_asoc:
-       sctp_association_free(new_asoc);
-       goto cleanup;
 }
 
 /*
@@ -1547,6 +1531,28 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep,
 }
 
 
+/*
+ * Unexpected INIT-ACK handler.
+ *
+ * Section 5.2.3
+ * If an INIT ACK received by an endpoint in any state other than the
+ * COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk.
+ * An unexpected INIT ACK usually indicates the processing of an old or
+ * duplicated INIT chunk.
+*/
+sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
+                                           const struct sctp_association *asoc,
+                                           const sctp_subtype_t type,
+                                           void *arg, sctp_cmd_seq_t *commands)
+{
+       /* Per the above section, we'll discard the chunk if we have an
+        * endpoint.  If this is an OOTB INIT-ACK, treat it as such.
+        */
+       if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
+               return sctp_sf_ootb(ep, asoc, type, arg, commands);
+       else
+               return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+}
 
 /* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A')
  *
@@ -1611,15 +1617,10 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
         */
        sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
 
-       /* Update the content of current association. */
-       sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
-
        repl = sctp_make_cookie_ack(new_asoc, chunk);
        if (!repl)
                goto nomem;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
-
        /* Report association restart to upper layer. */
        ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0,
                                             new_asoc->c.sinit_num_ostreams,
@@ -1628,6 +1629,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
        if (!ev)
                goto nomem_ev;
 
+       /* Update the content of current association. */
+       sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
+       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
        sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
        return SCTP_DISPOSITION_CONSUME;
 
@@ -1694,12 +1698,12 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
 
        /* Sockets API Draft Section 5.3.1.6
-        * When a peer sends a Adaption Layer Indication parameter , SCTP
+        * When a peer sends a Adaptation Layer Indication parameter , SCTP
         * delivers this notification to inform the application that of the
-        * peers requested adaption layer.
+        * peers requested adaptation layer.
         */
-       if (asoc->peer.adaption_ind) {
-               ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+       if (asoc->peer.adaptation_ind) {
+               ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
                if (!ev)
                        goto nomem_ev;
 
@@ -1751,14 +1755,14 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
                                        sctp_cmd_seq_t *commands,
                                        struct sctp_association *new_asoc)
 {
-       struct sctp_ulpevent *ev = NULL;
+       struct sctp_ulpevent *ev = NULL, *ai_ev = NULL;
        struct sctp_chunk *repl;
 
        /* Clarification from Implementor's Guide:
         * D) When both local and remote tags match the endpoint should
-         * enter the ESTABLISHED state, if it is in the COOKIE-ECHOED state.
-         * It should stop any cookie timer that may be running and send
-         * a COOKIE ACK.
+        * enter the ESTABLISHED state, if it is in the COOKIE-ECHOED state.
+        * It should stop any cookie timer that may be running and send
+        * a COOKIE ACK.
         */
 
        /* Don't accidentally move back into established state. */
@@ -1778,29 +1782,25 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
                 * SCTP user upon reception of a valid COOKIE
                 * ECHO chunk.
                 */
-               ev = sctp_ulpevent_make_assoc_change(new_asoc, 0,
+               ev = sctp_ulpevent_make_assoc_change(asoc, 0,
                                             SCTP_COMM_UP, 0,
-                                            new_asoc->c.sinit_num_ostreams,
-                                            new_asoc->c.sinit_max_instreams,
-                                             GFP_ATOMIC);
+                                            asoc->c.sinit_num_ostreams,
+                                            asoc->c.sinit_max_instreams,
+                                            GFP_ATOMIC);
                if (!ev)
                        goto nomem;
-               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
-                               SCTP_ULPEVENT(ev));
 
                /* Sockets API Draft Section 5.3.1.6
-                * When a peer sends a Adaption Layer Indication parameter,
+                * When a peer sends a Adaptation Layer Indication parameter,
                 * SCTP delivers this notification to inform the application
-                * that of the peers requested adaption layer.
+                * that of the peers requested adaptation layer.
                 */
-               if (new_asoc->peer.adaption_ind) {
-                       ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+               if (asoc->peer.adaptation_ind) {
+                       ai_ev = sctp_ulpevent_make_adaptation_indication(asoc,
                                                                 GFP_ATOMIC);
-                       if (!ev)
+                       if (!ai_ev)
                                goto nomem;
 
-                       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
-                                       SCTP_ULPEVENT(ev));
                }
        }
        sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
@@ -1809,12 +1809,21 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
        if (!repl)
                goto nomem;
 
+       if (ev)
+               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+                               SCTP_ULPEVENT(ev));
+       if (ai_ev)
+               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+                                       SCTP_ULPEVENT(ai_ev));
+
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
        sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
        return SCTP_DISPOSITION_CONSUME;
 
 nomem:
+       if (ai_ev)
+               sctp_ulpevent_free(ai_ev);
        if (ev)
                sctp_ulpevent_free(ev);
        return SCTP_DISPOSITION_NOMEM;
@@ -1861,7 +1870,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
        /* "Decode" the chunk.  We have no optional parameters so we
         * are in good shape.
         */
-        chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
+       chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
        if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
                                        sizeof(sctp_chunkhdr_t)))
                goto nomem;
@@ -1927,7 +1936,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
        default: /* Discard packet for all others. */
                retval = sctp_sf_pdiscard(ep, asoc, type, arg, commands);
                break;
-        };
+       };
 
        /* Delete the tempory new association. */
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
@@ -2074,7 +2083,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
         */
        sctp_walk_errors(err, chunk->chunk_hdr) {
                if (SCTP_ERROR_STALE_COOKIE == err->cause)
-                       return sctp_sf_do_5_2_6_stale(ep, asoc, type, 
+                       return sctp_sf_do_5_2_6_stale(ep, asoc, type,
                                                        arg, commands);
        }
 
@@ -2129,7 +2138,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ETIMEDOUT));
                sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-                               SCTP_U32(SCTP_ERROR_STALE_COOKIE));
+                               SCTP_PERR(SCTP_ERROR_STALE_COOKIE));
                return SCTP_DISPOSITION_DELETE_TCB;
        }
 
@@ -2149,7 +2158,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
         * to give ample time to retransmit the new cookie and thus
         * yield a higher probability of success on the reattempt.
         */
-       stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t)));
+       stale = ntohl(*(__be32 *)((u8 *)err + sizeof(sctp_errhdr_t)));
        stale = (stale * 2) / 1000;
 
        bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE;
@@ -2176,10 +2185,10 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
         */
        sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
 
-       /* If we've sent any data bundled with COOKIE-ECHO we will need to 
-        * resend 
+       /* If we've sent any data bundled with COOKIE-ECHO we will need to
+        * resend
         */
-       sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, 
+       sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN,
                        SCTP_TRANSPORT(asoc->peer.primary_path));
 
        /* Cast away the const modifier, as we want to just
@@ -2241,7 +2250,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
 {
        struct sctp_chunk *chunk = arg;
        unsigned len;
-       __u16 error = SCTP_ERROR_NO_ERROR;
+       __be16 error = SCTP_ERROR_NO_ERROR;
 
        if (!sctp_vtag_verify_either(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2265,8 +2274,8 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
                error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
        sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
-       /* ASSOC_FAILED will DELETE_TCB. */
-       sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
+       /* ASSOC_FAILED will DELETE_TCB. */
+       sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error));
        SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
        SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
 
@@ -2286,7 +2295,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
 {
        struct sctp_chunk *chunk = arg;
        unsigned len;
-       __u16 error = SCTP_ERROR_NO_ERROR;
+       __be16 error = SCTP_ERROR_NO_ERROR;
 
        if (!sctp_vtag_verify_either(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2348,7 +2357,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
  * This is common code called by several sctp_sf_*_abort() functions above.
  */
 static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
-                                          __u16 error, int sk_err,
+                                          __be16 error, int sk_err,
                                           const struct sctp_association *asoc,
                                           struct sctp_transport *transport)
 {
@@ -2361,7 +2370,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
        sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
        /* CMD_INIT_FAILED will DELETE_TCB. */
        sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-                       SCTP_U32(error));
+                       SCTP_PERR(error));
        return SCTP_DISPOSITION_ABORT;
 }
 
@@ -2430,7 +2439,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
        ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
        if (!ev) {
                disposition = SCTP_DISPOSITION_NOMEM;
-               goto out;       
+               goto out;
        }
        sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
 
@@ -2457,7 +2466,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
         *    received by the SHUTDOWN sender.
         */
        sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
-                       SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack));
+                       SCTP_BE32(chunk->subh.shutdown_hdr->cum_tsn_ack));
 
 out:
        return disposition;
@@ -2536,6 +2545,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
 {
        sctp_cwrhdr_t *cwr;
        struct sctp_chunk *chunk = arg;
+       u32 lowest_tsn;
 
        if (!sctp_vtag_verify(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2543,18 +2553,18 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
        if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t)))
                return sctp_sf_violation_chunklen(ep, asoc, type, arg,
                                                  commands);
-               
+
        cwr = (sctp_cwrhdr_t *) chunk->skb->data;
        skb_pull(chunk->skb, sizeof(sctp_cwrhdr_t));
 
-       cwr->lowest_tsn = ntohl(cwr->lowest_tsn);
+       lowest_tsn = ntohl(cwr->lowest_tsn);
 
        /* Does this CWR ack the last sent congestion notification? */
-       if (TSN_lte(asoc->last_ecne_tsn, cwr->lowest_tsn)) {
+       if (TSN_lte(asoc->last_ecne_tsn, lowest_tsn)) {
                /* Stop sending ECNE. */
                sctp_add_cmd_sf(commands,
                                SCTP_CMD_ECN_CWR,
-                               SCTP_U32(cwr->lowest_tsn));
+                               SCTP_U32(lowest_tsn));
        }
        return SCTP_DISPOSITION_CONSUME;
 }
@@ -2651,7 +2661,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
                sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
                                SCTP_NULL());
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-        }
+       }
 
        if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t)))
                return sctp_sf_violation_chunklen(ep, asoc, type, arg,
@@ -2663,9 +2673,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
                break;
        case SCTP_IERROR_HIGH_TSN:
        case SCTP_IERROR_BAD_STREAM:
+               SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
                goto discard_noforce;
        case SCTP_IERROR_DUP_TSN:
        case SCTP_IERROR_IGNORE_TSN:
+               SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
                goto discard_force;
        case SCTP_IERROR_NO_DATA:
                goto consume;
@@ -2731,7 +2743,7 @@ discard_noforce:
        return SCTP_DISPOSITION_DISCARD;
 consume:
        return SCTP_DISPOSITION_CONSUME;
-       
+
 }
 
 /*
@@ -2918,7 +2930,7 @@ sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
                /* Make an ABORT. The T bit will be set if the asoc
                 * is NULL.
                 */
-               abort = sctp_make_abort(asoc, chunk, 0);
+               abort = sctp_make_abort(asoc, chunk, 0);
                if (!abort) {
                        sctp_ootb_pkt_free(packet);
                        return SCTP_DISPOSITION_NOMEM;
@@ -2982,7 +2994,7 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
                }
 
                sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
-                               SCTP_CHUNK(chunk));     
+                               SCTP_CHUNK(chunk));
        }
        return SCTP_DISPOSITION_CONSUME;
 
@@ -3017,7 +3029,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
        if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
                return sctp_sf_violation_chunklen(ep, asoc, type, arg,
                                                  commands);
-
        /* 10.2 H) SHUTDOWN COMPLETE notification
         *
         * When SCTP completes the shutdown procedures (section 9.2) this
@@ -3028,6 +3039,14 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
        if (!ev)
                goto nomem;
 
+       /* ...send a SHUTDOWN COMPLETE chunk to its peer, */
+       reply = sctp_make_shutdown_complete(asoc, chunk);
+       if (!reply)
+               goto nomem_chunk;
+
+       /* Do all the commands now (after allocation), so that we
+        * have consistent state if memory allocation failes
+        */
        sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
 
        /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall
@@ -3039,11 +3058,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
 
-       /* ...send a SHUTDOWN COMPLETE chunk to its peer, */
-       reply = sctp_make_shutdown_complete(asoc, chunk);
-       if (!reply)
-               goto nomem;
-
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
                        SCTP_STATE(SCTP_STATE_CLOSED));
        SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
@@ -3054,6 +3068,8 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
        return SCTP_DISPOSITION_DELETE_TCB;
 
+nomem_chunk:
+       sctp_ulpevent_free(ev);
 nomem:
        return SCTP_DISPOSITION_NOMEM;
 }
@@ -3112,7 +3128,7 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
                 */
                if (SCTP_CID_ABORT == ch->type)
                        return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-                       
+
                ch = (sctp_chunkhdr_t *) ch_end;
        } while (ch_end < skb->tail);
 
@@ -3159,8 +3175,8 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
 
        if (packet) {
                /* Make an SHUTDOWN_COMPLETE.
-                * The T bit will be set if the asoc is NULL.
-                */
+                * The T bit will be set if the asoc is NULL.
+                */
                shut = sctp_make_shutdown_complete(asoc, chunk);
                if (!shut) {
                        sctp_ootb_pkt_free(packet);
@@ -3245,10 +3261,10 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
 
        /* ADDIP 4.2 C1) Compare the value of the serial number to the value
         * the endpoint stored in a new association variable
-        * 'Peer-Serial-Number'. 
+        * 'Peer-Serial-Number'.
         */
        if (serial == asoc->peer.addip_serial + 1) {
-               /* ADDIP 4.2 C2) If the value found in the serial number is
+               /* ADDIP 4.2 C2) If the value found in the serial number is
                 * equal to the ('Peer-Serial-Number' + 1), the endpoint MUST
                 * do V1-V5.
                 */
@@ -3269,9 +3285,9 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
                else
                        return SCTP_DISPOSITION_DISCARD;
        } else {
-               /* ADDIP 4.2 C4) Otherwise, the ASCONF Chunk is discarded since 
+               /* ADDIP 4.2 C4) Otherwise, the ASCONF Chunk is discarded since
                 * it must be either a stale packet or from an attacker.
-                */     
+                */
                return SCTP_DISPOSITION_DISCARD;
        }
 
@@ -3280,7 +3296,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
         * being responded to.
         */
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack));
-       
+
        return SCTP_DISPOSITION_CONSUME;
 }
 
@@ -3291,7 +3307,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
  */
 sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
                                         const struct sctp_association *asoc,
-                                        const sctp_subtype_t type, void *arg,
+                                        const sctp_subtype_t type, void *arg,
                                         sctp_cmd_seq_t *commands)
 {
        struct sctp_chunk       *asconf_ack = arg;
@@ -3343,9 +3359,9 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
                sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-                               SCTP_ERROR(ECONNABORTED));
+                               SCTP_ERROR(ECONNABORTED));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_ASCONF_ACK));
+                               SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
                return SCTP_DISPOSITION_ABORT;
@@ -3371,9 +3387,9 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
                 */
                sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-                               SCTP_ERROR(ECONNABORTED));
+                               SCTP_ERROR(ECONNABORTED));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_ASCONF_ACK));
+                               SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
                return SCTP_DISPOSITION_ABORT;
@@ -3435,17 +3451,17 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
 
        sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn));
        if (len > sizeof(struct sctp_fwdtsn_hdr))
-               sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 
+               sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN,
                                SCTP_CHUNK(chunk));
-       
+
        /* Count this as receiving DATA. */
        if (asoc->autoclose) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
-       
+
        /* FIXME: For now send a SACK, but DATA processing may
-        * send another. 
+        * send another.
         */
        sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
 
@@ -3495,9 +3511,9 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
 
        sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn));
        if (len > sizeof(struct sctp_fwdtsn_hdr))
-               sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 
+               sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN,
                                SCTP_CHUNK(chunk));
-       
+
        /* Go a head and force a SACK, since we are shutting down. */
 gen_shutdown:
        /* Implementor's Guide.
@@ -3511,7 +3527,7 @@ gen_shutdown:
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
 
-        return SCTP_DISPOSITION_CONSUME;
+       return SCTP_DISPOSITION_CONSUME;
 }
 
 /*
@@ -3652,6 +3668,7 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep,
                                    void *arg,
                                    sctp_cmd_seq_t *commands)
 {
+       SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS);
        sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
 
        return SCTP_DISPOSITION_CONSUME;
@@ -3689,7 +3706,7 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
  * if it's length is set to be smaller then the size of sctp_sack_chunk_t.
  *
  * We inform the other end by sending an ABORT with a Protocol Violation
- * error code. 
+ * error code.
  *
  * Section: Not specified
  * Verification Tag:  Nothing to do
@@ -3727,19 +3744,19 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ECONNREFUSED));
                sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-                               SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
+                               SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
        } else {
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-                               SCTP_ERROR(ECONNABORTED));
+                               SCTP_ERROR(ECONNABORTED));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
+                               SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
        }
 
        sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
 
        SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
-       
+
        return SCTP_DISPOSITION_ABORT;
 
 nomem:
@@ -4046,7 +4063,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
                        SCTP_ERROR(ECONNABORTED));
        /* Delete the established association. */
        sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                       SCTP_U32(SCTP_ERROR_USER_ABORT));
+                       SCTP_PERR(SCTP_ERROR_USER_ABORT));
 
        SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
        SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
@@ -4183,7 +4200,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
                        SCTP_ERROR(ECONNREFUSED));
        /* Delete the established association. */
        sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-                       SCTP_U32(SCTP_ERROR_USER_ABORT));
+                       SCTP_PERR(SCTP_ERROR_USER_ABORT));
 
        return retval;
 }
@@ -4420,7 +4437,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
        /* sctp-implguide 2.10 Issues with Heartbeating and failover
         *
         * HEARTBEAT ... is discontinued after sending either SHUTDOWN
-         * or SHUTDOWN-ACK.
+        * or SHUTDOWN-ACK.
         */
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL());
 
@@ -4498,7 +4515,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
        /* sctp-implguide 2.10 Issues with Heartbeating and failover
         *
         * HEARTBEAT ... is discontinued after sending either SHUTDOWN
-         * or SHUTDOWN-ACK.
+        * or SHUTDOWN-ACK.
         */
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL());
 
@@ -4548,12 +4565,14 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
 {
        struct sctp_transport *transport = arg;
 
+       SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS);
+
        if (asoc->overall_error_count >= asoc->max_retrans) {
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ETIMEDOUT));
                /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_NO_ERROR));
+                               SCTP_PERR(SCTP_ERROR_NO_ERROR));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
                return SCTP_DISPOSITION_DELETE_TCB;
@@ -4616,6 +4635,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
                                       void *arg,
                                       sctp_cmd_seq_t *commands)
 {
+       SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS);
        sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
        return SCTP_DISPOSITION_CONSUME;
 }
@@ -4650,6 +4670,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
        int attempts = asoc->init_err_counter + 1;
 
        SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
+       SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS);
 
        if (attempts <= asoc->max_init_attempts) {
                bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
@@ -4673,7 +4694,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ETIMEDOUT));
                sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-                               SCTP_U32(SCTP_ERROR_NO_ERROR));
+                               SCTP_PERR(SCTP_ERROR_NO_ERROR));
                return SCTP_DISPOSITION_DELETE_TCB;
        }
 
@@ -4709,6 +4730,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
        int attempts = asoc->init_err_counter + 1;
 
        SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
+       SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS);
 
        if (attempts <= asoc->max_init_attempts) {
                repl = sctp_make_cookie_echo(asoc, NULL);
@@ -4724,7 +4746,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ETIMEDOUT));
                sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-                               SCTP_U32(SCTP_ERROR_NO_ERROR));
+                               SCTP_PERR(SCTP_ERROR_NO_ERROR));
                return SCTP_DISPOSITION_DELETE_TCB;
        }
 
@@ -4753,12 +4775,14 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
        struct sctp_chunk *reply = NULL;
 
        SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
+       SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
+
        if (asoc->overall_error_count >= asoc->max_retrans) {
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ETIMEDOUT));
                /* Note:  CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_NO_ERROR));
+                               SCTP_PERR(SCTP_ERROR_NO_ERROR));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
                return SCTP_DISPOSITION_DELETE_TCB;
@@ -4814,6 +4838,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
        struct sctp_chunk *chunk = asoc->addip_last_asconf;
        struct sctp_transport *transport = chunk->transport;
 
+       SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS);
+
        /* ADDIP 4.1 B1) Increment the error counters and perform path failure
         * detection on the appropriate destination address as defined in
         * RFC2960 [5] section 8.1 and 8.2.
@@ -4834,7 +4860,7 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ETIMEDOUT));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_NO_ERROR));
+                               SCTP_PERR(SCTP_ERROR_NO_ERROR));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
                return SCTP_DISPOSITION_ABORT;
@@ -4848,7 +4874,7 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
        /* ADDIP 4.1 B4) Re-transmit the ASCONF Chunk last sent and if possible
         * choose an alternate destination address (please refer to RFC2960
         * [5] section 6.4.1). An endpoint MUST NOT add new parameters to this
-        * chunk, it MUST be the same (including its serial number) as the last 
+        * chunk, it MUST be the same (including its serial number) as the last
         * ASCONF sent.
         */
        sctp_chunk_hold(asoc->addip_last_asconf);
@@ -4880,6 +4906,7 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
        struct sctp_chunk *reply = NULL;
 
        SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
+       SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
 
        reply = sctp_make_abort(asoc, NULL, 0);
        if (!reply)
@@ -4889,7 +4916,7 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                        SCTP_ERROR(ETIMEDOUT));
        sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                       SCTP_U32(SCTP_ERROR_NO_ERROR));
+                       SCTP_PERR(SCTP_ERROR_NO_ERROR));
 
        return SCTP_DISPOSITION_DELETE_TCB;
 nomem:
@@ -4910,6 +4937,8 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(
 {
        int disposition;
 
+       SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS);
+
        /* From 9.2 Shutdown of an Association
         * Upon receipt of the SHUTDOWN primitive from its upper
         * layer, the endpoint enters SHUTDOWN-PENDING state and
@@ -4924,7 +4953,7 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(
        /* sctpimpguide-05 Section 2.12.2
         * The sender of the SHUTDOWN MAY also start an overall guard timer
         * 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
-        */
+        */
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
        disposition = SCTP_DISPOSITION_CONSUME;
@@ -5098,7 +5127,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
                        vtag = ntohl(init->init_hdr.init_tag);
                        break;
                }
-               default:        
+               default:
                        vtag = ntohl(chunk->sctp_hdr->vtag);
                        break;
                }
@@ -5147,7 +5176,7 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
                        /* Override the OOTB vtag from the cookie. */
                        cookie = chunk->subh.cookie_hdr;
                        packet->vtag = cookie->c.peer_vtag;
-                       
+
                        /* Set the skb to the belonging sock for accounting. */
                        err_chunk->skb->sk = ep->base.sk;
                        sctp_packet_append_chunk(packet, err_chunk);
@@ -5281,7 +5310,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
                sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL());
        }
 
-        /* Spill over rwnd a little bit.  Note: While allowed, this spill over
+       /* Spill over rwnd a little bit.  Note: While allowed, this spill over
         * seems a bit troublesome in that frag_point varies based on
         * PMTU.  In cases, such as loopback, this might be a rather
         * large spill over.
@@ -5337,7 +5366,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
                sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
                                SCTP_ERROR(ECONNABORTED));
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_U32(SCTP_ERROR_NO_DATA));
+                               SCTP_PERR(SCTP_ERROR_NO_DATA));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
                return SCTP_IERROR_NO_DATA;