sctp: drop SHUTDOWN chunk if the TSN is less than the CTSN
Wei Yongjun [Sat, 22 Aug 2009 03:24:00 +0000 (11:24 +0800)]
If Cumulative TSN Ack field of SHUTDOWN chunk is less than the
Cumulative TSN Ack Point then drop the SHUTDOWN chunk.

Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>

net/sctp/sm_statefuns.c

index 9109269..73bdeb2 100644 (file)
@@ -2570,6 +2570,12 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
        chunk->subh.shutdown_hdr = sdh;
        ctsn = ntohl(sdh->cum_tsn_ack);
 
+       if (TSN_lt(ctsn, asoc->ctsn_ack_point)) {
+               SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn);
+               SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", asoc->ctsn_ack_point);
+               return SCTP_DISPOSITION_DISCARD;
+       }
+
        /* If Cumulative TSN Ack beyond the max tsn currently
         * send, terminating the association and respond to the
         * sender with an ABORT.
@@ -2633,6 +2639,7 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
 {
        struct sctp_chunk *chunk = arg;
        sctp_shutdownhdr_t *sdh;
+       __u32 ctsn;
 
        if (!sctp_vtag_verify(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2644,12 +2651,19 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
                                                  commands);
 
        sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
+       ctsn = ntohl(sdh->cum_tsn_ack);
+
+       if (TSN_lt(ctsn, asoc->ctsn_ack_point)) {
+               SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn);
+               SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", asoc->ctsn_ack_point);
+               return SCTP_DISPOSITION_DISCARD;
+       }
 
        /* If Cumulative TSN Ack beyond the max tsn currently
         * send, terminating the association and respond to the
         * sender with an ABORT.
         */
-       if (!TSN_lt(ntohl(sdh->cum_tsn_ack), asoc->next_tsn))
+       if (!TSN_lt(ctsn, asoc->next_tsn))
                return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
 
        /* verify, by checking the Cumulative TSN Ack field of the