aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_statefuns.c
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2009-08-22 11:24:00 +0800
committerVlad Yasevich <vladislav.yasevich@hp.com>2009-09-04 18:20:57 -0400
commita2f36eec5647548fa94fb68e2843b00fb9c0d46b (patch)
tree2f9927736f20817bdaed1d1f8a897af2c1e0d605 /net/sctp/sm_statefuns.c
parentsctp: Send user messages to the lower layer as one (diff)
downloadlinux-dev-a2f36eec5647548fa94fb68e2843b00fb9c0d46b.tar.xz
linux-dev-a2f36eec5647548fa94fb68e2843b00fb9c0d46b.zip
sctp: drop SHUTDOWN chunk if the TSN is less than the CTSN
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>
Diffstat (limited to '')
-rw-r--r--net/sctp/sm_statefuns.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 910926906a3a..73bdeb2b6c62 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -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