diff options
author | Thomas Graf <tgraf@infradead.org> | 2011-07-08 04:37:46 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-08 09:53:08 -0700 |
commit | cd4fcc704f30f2064ab30b5300d44d431e46db50 (patch) | |
tree | cc08106433d2353adb5f7b52b7bfe6e4f9ebceb8 /net/sctp/ulpevent.c | |
parent | 3f97fae9482dac1dbdd870a25c89033d3a0b35dc (diff) | |
download | linux-cd4fcc704f30f2064ab30b5300d44d431e46db50.tar.gz linux-cd4fcc704f30f2064ab30b5300d44d431e46db50.tar.bz2 linux-cd4fcc704f30f2064ab30b5300d44d431e46db50.zip |
sctp: ABORT if receive, reassmbly, or reodering queue is not empty while closing socket
Trigger user ABORT if application closes a socket which has data
queued on the socket receive queue or chunks waiting on the
reassembly or ordering queue as this would imply data being lost
which defeats the point of a graceful shutdown.
This behavior is already practiced in TCP.
We do not check the input queue because that would mean to parse
all chunks on it to look for unacknowledged data which seems too
much of an effort. Control chunks or duplicated chunks may also
be in the input queue and should not be stopping a graceful
shutdown.
Signed-off-by: Thomas Graf <tgraf@infradead.org>
Acked-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/ulpevent.c')
-rw-r--r-- | net/sctp/ulpevent.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index e70e5fc87890..8a84017834c2 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -1081,9 +1081,19 @@ void sctp_ulpevent_free(struct sctp_ulpevent *event) } /* Purge the skb lists holding ulpevents. */ -void sctp_queue_purge_ulpevents(struct sk_buff_head *list) +unsigned int sctp_queue_purge_ulpevents(struct sk_buff_head *list) { struct sk_buff *skb; - while ((skb = skb_dequeue(list)) != NULL) - sctp_ulpevent_free(sctp_skb2event(skb)); + unsigned int data_unread = 0; + + while ((skb = skb_dequeue(list)) != NULL) { + struct sctp_ulpevent *event = sctp_skb2event(skb); + + if (!sctp_ulpevent_is_notification(event)) + data_unread += skb->len; + + sctp_ulpevent_free(event); + } + + return data_unread; } |