diff options
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/proto.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index d48005f653c7..5f47b458ed8f 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -891,6 +891,7 @@ void dccp_close(struct sock *sk, long timeout) | |||
891 | { | 891 | { |
892 | struct dccp_sock *dp = dccp_sk(sk); | 892 | struct dccp_sock *dp = dccp_sk(sk); |
893 | struct sk_buff *skb; | 893 | struct sk_buff *skb; |
894 | u32 data_was_unread = 0; | ||
894 | int state; | 895 | int state; |
895 | 896 | ||
896 | lock_sock(sk); | 897 | lock_sock(sk); |
@@ -913,12 +914,17 @@ void dccp_close(struct sock *sk, long timeout) | |||
913 | * descriptor close, not protocol-sourced closes, because the | 914 | * descriptor close, not protocol-sourced closes, because the |
914 | *reader process may not have drained the data yet! | 915 | *reader process may not have drained the data yet! |
915 | */ | 916 | */ |
916 | /* FIXME: check for unread data */ | ||
917 | while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) { | 917 | while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) { |
918 | data_was_unread += skb->len; | ||
918 | __kfree_skb(skb); | 919 | __kfree_skb(skb); |
919 | } | 920 | } |
920 | 921 | ||
921 | if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { | 922 | if (data_was_unread) { |
923 | /* Unread data was tossed, send an appropriate Reset Code */ | ||
924 | DCCP_WARN("DCCP: ABORT -- %u bytes unread\n", data_was_unread); | ||
925 | dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED); | ||
926 | dccp_set_state(sk, DCCP_CLOSED); | ||
927 | } else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { | ||
922 | /* Check zero linger _after_ checking for unread data. */ | 928 | /* Check zero linger _after_ checking for unread data. */ |
923 | sk->sk_prot->disconnect(sk, 0); | 929 | sk->sk_prot->disconnect(sk, 0); |
924 | } else if (dccp_close_state(sk)) { | 930 | } else if (dccp_close_state(sk)) { |