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,
+                                          __u16 error, int sk_err,
                                           const struct sctp_association *asoc,
                                           struct sctp_transport *transport);
 
        __u32 init_tag;
        struct sctp_chunk *err_chunk;
        struct sctp_packet *packet;
-       sctp_disposition_t ret;
+       __u16 error;
 
        if (!sctp_vtag_verify(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
                        goto nomem;
 
                sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
-               sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-                               SCTP_STATE(SCTP_STATE_CLOSED));
-               SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
-               sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
-               return SCTP_DISPOSITION_DELETE_TCB;
+               return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM,
+                                             ECONNREFUSED, asoc,
+                                             chunk->transport);
        }
 
        /* Verify the INIT chunk before processing it. */
                                sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
                                                SCTP_PACKET(packet));
                                SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
-                               sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-                                               SCTP_STATE(SCTP_STATE_CLOSED));
-                               sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
-                                               SCTP_NULL());
-                               return SCTP_DISPOSITION_CONSUME;
+                               error = SCTP_ERROR_INV_PARAM;
                        } else {
-                               sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-                                               SCTP_STATE(SCTP_STATE_CLOSED));
-                               sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
-                                               SCTP_NULL());
-                               return SCTP_DISPOSITION_NOMEM;
+                               error = SCTP_ERROR_NO_RESOURCE;
                        }
                } else {
-                       ret = sctp_sf_tabort_8_4_8(ep, asoc, type, arg,
-                                                  commands);
-                       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-                                       SCTP_STATE(SCTP_STATE_CLOSED));
-                       sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
-                                       SCTP_NULL());
-                       return ret;
+                       sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+                       error = SCTP_ERROR_INV_PARAM;
                }
+               return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
+                                               asoc, chunk->transport);
        }
 
        /* Tag the variable length parameters.  Note that we never
        struct sctp_transport *transport = (struct sctp_transport *) arg;
 
        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));
        int attempts = asoc->init_err_counter + 1;
 
        if (attempts > asoc->max_init_attempts) {
+               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));
                return SCTP_DISPOSITION_DELETE_TCB;
        if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
                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));
        SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
        if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
                error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
-       return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport);
+       return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc,
+                                     chunk->transport);
 }
 
 /*
                                        void *arg,
                                        sctp_cmd_seq_t *commands)
 {
-       return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc,
+       return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR,
+                                     ENOPROTOOPT, asoc,
                                      (struct sctp_transport *)arg);
 }
 
  * 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,
+                                          __u16 error, int sk_err,
                                           const struct sctp_association *asoc,
                                           struct sctp_transport *transport)
 {
        SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+       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_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                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_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
                                SCTP_U32(SCTP_ERROR_ASCONF_ACK));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
                 * processing the rest of the chunks in the packet.
                 */
                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_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
                                SCTP_U32(SCTP_ERROR_ASCONF_ACK));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
        if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+               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));
        } else {
+               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_PROTO_VIOLATION));
                SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
         * TCB.  This is a departure from our typical NOMEM handling.
         */
 
+       sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+                       SCTP_ERROR(ECONNABORTED));
        /* Delete the established association. */
        sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
                        SCTP_U32(SCTP_ERROR_USER_ABORT));
         * TCB.  This is a departure from our typical NOMEM handling.
         */
 
+       sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+                       SCTP_ERROR(ECONNREFUSED));
        /* Delete the established association. */
        sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
                        SCTP_U32(SCTP_ERROR_USER_ABORT));
        struct sctp_transport *transport = arg;
 
        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_DEBUG_PRINTK("Giving up on INIT, attempts: %d"
                                  " max_init_attempts: %d\n",
                                  attempts, asoc->max_init_attempts);
+               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));
                return SCTP_DISPOSITION_DELETE_TCB;
 
                sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
        } else {
+               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));
                return SCTP_DISPOSITION_DELETE_TCB;
 
        SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
        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));
        if (asoc->overall_error_count >= asoc->max_retrans) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+               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_INC_STATS(SCTP_MIB_ABORTEDS);
                goto nomem;
 
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
+       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));
 
                 * processing the rest of the chunks in the packet.
                 */
                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_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
                                SCTP_U32(SCTP_ERROR_NO_DATA));
                SCTP_INC_STATS(SCTP_MIB_ABORTEDS);