summaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2007-12-16 16:06:03 -0800
committerDavid S. Miller <davem@davemloft.net>2008-01-28 14:55:01 -0800
commitd83bd95bf11444993b9c405b255ffa644c32d414 (patch)
tree57311d4ffaa31ea73ca4a18a58fed985a14576cc /net/dccp
parentdcfbc7e97a2e3a0d73a2e41e1bddb988dcca701e (diff)
[DCCP]: Check for unread data on close
This removes one FIXME with regard to close when there is still unread data. The mechanism is implemented similar to TCP: with regard to DCCP-specifics, a Reset with Code 2, "Aborted" is sent to the peer. This corresponds in part to RFC 4340, 8.1.1 and 8.1.5. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/proto.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index d48005f653c..5f47b458ed8 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -891,6 +891,7 @@ void dccp_close(struct sock *sk, long timeout)
{
struct dccp_sock *dp = dccp_sk(sk);
struct sk_buff *skb;
+ u32 data_was_unread = 0;
int state;
lock_sock(sk);
@@ -913,12 +914,17 @@ void dccp_close(struct sock *sk, long timeout)
* descriptor close, not protocol-sourced closes, because the
*reader process may not have drained the data yet!
*/
- /* FIXME: check for unread data */
while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ data_was_unread += skb->len;
__kfree_skb(skb);
}
- if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
+ if (data_was_unread) {
+ /* Unread data was tossed, send an appropriate Reset Code */
+ DCCP_WARN("DCCP: ABORT -- %u bytes unread\n", data_was_unread);
+ dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
+ dccp_set_state(sk, DCCP_CLOSED);
+ } else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
/* Check zero linger _after_ checking for unread data. */
sk->sk_prot->disconnect(sk, 0);
} else if (dccp_close_state(sk)) {