*/
        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
        sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
 
        return SCTP_DISPOSITION_DELETE_TCB;
-
-nomem:
-       return SCTP_DISPOSITION_NOMEM;
 }
 
 /*
                               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,
                        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"
                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));
 
        /*
 
        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;
 }
 
        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;
 
                };
        }
 
-       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
 
        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
         *
        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
         * delivers this notification to inform the application that of the
         * peers requested adaption layer.
         */
        if (new_asoc->peer.adaption_ind) {
-               ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+               ai_ev = sctp_ulpevent_make_adaption_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:
        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,
                if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk,
                                                 commands)) {
                        retval = SCTP_DISPOSITION_CONSUME;
-                       goto cleanup_asoc;
+                       goto nomem_retval;
                }
        }
 
        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;
 }
 
 /*
         */
        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,
        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;
 
                                        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:
                 * 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,
+                                            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,
                 * SCTP delivers this notification to inform the application
                 * that of the peers requested adaption layer.
                 */
-               if (new_asoc->peer.adaption_ind) {
-                       ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+               if (asoc->peer.adaption_ind) {
+                       ai_ev = sctp_ulpevent_make_adaption_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());
        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;
        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
        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
        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);
        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;
 }