sctp: sctp should release assoc when sctp_make_abort_user return NULL in sctp_close
[pandora-kernel.git] / net / sctp / sm_statefuns.c
index 5ac33b6..4e0a9b9 100644 (file)
@@ -163,6 +163,9 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk,
 {
        __u16 chunk_length = ntohs(chunk->chunk_hdr->length);
 
+       /* Previously already marked? */
+       if (unlikely(chunk->pdiscard))
+               return 0;
        if (unlikely(chunk_length < required_length))
                return 0;
 
@@ -3516,9 +3519,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
        struct sctp_chunk       *asconf_ack = NULL;
        struct sctp_paramhdr    *err_param = NULL;
        sctp_addiphdr_t         *hdr;
-       union sctp_addr_param   *addr_param;
        __u32                   serial;
-       int                     length;
 
        if (!sctp_vtag_verify(chunk, asoc)) {
                sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -3543,17 +3544,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
        hdr = (sctp_addiphdr_t *)chunk->skb->data;
        serial = ntohl(hdr->serial);
 
-       addr_param = (union sctp_addr_param *)hdr->params;
-       length = ntohs(addr_param->p.length);
-       if (length < sizeof(sctp_paramhdr_t))
-               return sctp_sf_violation_paramlen(ep, asoc, type, arg,
-                          (void *)addr_param, commands);
-
        /* Verify the ASCONF chunk before processing it. */
-       if (!sctp_verify_asconf(asoc,
-                           (sctp_paramhdr_t *)((void *)addr_param + length),
-                           (void *)chunk->chunk_end,
-                           &err_param))
+       if (!sctp_verify_asconf(asoc, chunk, true, &err_param))
                return sctp_sf_violation_paramlen(ep, asoc, type, arg,
                                                  (void *)err_param, commands);
 
@@ -3670,10 +3662,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
        rcvd_serial = ntohl(addip_hdr->serial);
 
        /* Verify the ASCONF-ACK chunk before processing it. */
-       if (!sctp_verify_asconf(asoc,
-           (sctp_paramhdr_t *)addip_hdr->params,
-           (void *)asconf_ack->chunk_end,
-           &err_param))
+       if (!sctp_verify_asconf(asoc, asconf_ack, false, &err_param))
                return sctp_sf_violation_paramlen(ep, asoc, type, arg,
                           (void *)err_param, commands);
 
@@ -4751,7 +4740,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
 
        retval = SCTP_DISPOSITION_CONSUME;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+       if (abort)
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
 
        /* Even if we can't send the ABORT due to low memory delete the
         * TCB.  This is a departure from our typical NOMEM handling.
@@ -4883,7 +4873,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
        retval = SCTP_DISPOSITION_CONSUME;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+       if (abort)
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
 
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
                        SCTP_STATE(SCTP_STATE_CLOSED));
@@ -5313,7 +5304,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
        SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS);
 
        if (asoc->overall_error_count >= asoc->max_retrans) {
-               if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
+               if (asoc->peer.zero_window_announced &&
+                   asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
                        /*
                         * We are here likely because the receiver had its rwnd
                         * closed for a while and we have not been able to