sctp: Follow security requirement of responding with 1 packet
[pandora-kernel.git] / net / sctp / sm_statefuns.c
index 6545b5f..b66a41d 100644 (file)
@@ -795,8 +795,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
                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));
 
@@ -883,7 +881,6 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
        if (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());
 
        /* It may also notify its ULP about the successful
         * establishment of the association with a Communication Up
@@ -1226,7 +1223,6 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
                                       sctp_cmd_seq_t *commands)
 {
        struct sctp_transport *new_addr, *addr;
-       struct list_head *pos, *pos2;
        int found;
 
        /* Implementor's Guide - Sectin 5.2.2
@@ -1243,12 +1239,11 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
        new_addr = NULL;
        found = 0;
 
-       list_for_each(pos, &new_asoc->peer.transport_addr_list) {
-               new_addr = list_entry(pos, struct sctp_transport, transports);
+       list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list,
+                       transports) {
                found = 0;
-               list_for_each(pos2, &asoc->peer.transport_addr_list) {
-                       addr = list_entry(pos2, struct sctp_transport,
-                                         transports);
+               list_for_each_entry(addr, &asoc->peer.transport_addr_list,
+                               transports) {
                        if (sctp_cmp_addr_exact(&new_addr->ipaddr,
                                                &addr->ipaddr)) {
                                found = 1;
@@ -1783,7 +1778,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
                goto nomem;
 
        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
        /* RFC 2960 5.1 Normal Establishment of an Association
         *
@@ -1900,12 +1894,13 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
 
                }
        }
-       sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
        repl = sctp_make_cookie_ack(new_asoc, chunk);
        if (!repl)
                goto nomem;
 
+       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+
        if (ev)
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                SCTP_ULPEVENT(ev));
@@ -1913,9 +1908,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
                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:
@@ -3135,12 +3127,8 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
                if (!ev)
                        goto nomem;
 
-               if (!sctp_add_cmd(commands, SCTP_CMD_EVENT_ULP,
-                                 SCTP_ULPEVENT(ev))) {
-                       sctp_ulpevent_free(ev);
-                       goto nomem;
-               }
-
+               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+                               SCTP_ULPEVENT(ev));
                sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
                                SCTP_CHUNK(chunk));
        }
@@ -3976,9 +3964,6 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
                break;
        case SCTP_CID_ACTION_DISCARD_ERR:
-               /* Discard the packet.  */
-               sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-
                /* Generate an ERROR chunk as response. */
                hdr = unk_chunk->chunk_hdr;
                err_chunk = sctp_make_op_error(asoc, unk_chunk,
@@ -3988,6 +3973,9 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(err_chunk));
                }
+
+               /* Discard the packet.  */
+               sctp_sf_pdiscard(ep, asoc, type, arg, commands);
                return SCTP_DISPOSITION_CONSUME;
                break;
        case SCTP_CID_ACTION_SKIP:
@@ -4144,6 +4132,24 @@ static sctp_disposition_t sctp_sf_abort_violation(
                goto nomem;
 
        if (asoc) {
+               /* Treat INIT-ACK as a special case during COOKIE-WAIT. */
+               if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK &&
+                   !asoc->peer.i.init_tag) {
+                       sctp_initack_chunk_t *initack;
+
+                       initack = (sctp_initack_chunk_t *)chunk->chunk_hdr;
+                       if (!sctp_chunk_length_valid(chunk,
+                                                    sizeof(sctp_initack_chunk_t)))
+                               abort->chunk_hdr->flags |= SCTP_CHUNK_FLAG_T;
+                       else {
+                               unsigned int inittag;
+
+                               inittag = ntohl(initack->init_hdr.init_tag);
+                               sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_INITTAG,
+                                               SCTP_U32(inittag));
+                       }
+               }
+
                sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
                SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
 
@@ -4349,6 +4355,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep,
                                       sctp_cmd_seq_t *commands)
 {
        struct sctp_chunk *repl;
+       struct sctp_association* my_asoc;
 
        /* The comment below says that we enter COOKIE-WAIT AFTER
         * sending the INIT, but that doesn't actually work in our
@@ -4372,8 +4379,8 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep,
        /* Cast away the const modifier, as we want to just
         * rerun it through as a sideffect.
         */
-       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC,
-                       SCTP_ASOC((struct sctp_association *) asoc));
+       my_asoc = (struct sctp_association *)asoc;
+       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(my_asoc));
 
        /* Choose transport for INIT. */
        sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,