: Perform SHUT_RD and SHUT_WR on receiving close
PATCH 34/43 : Perform SHUT_RD and SHUT_WR on receiving close
[DCCP]: Perform SHUT_RD and SHUT_WR on receiving close
The first change is to close the write-end in addition to the read-end when a fin-like segment (Close or CloseReq) is received by DCCP. This accounts for the fact that DCCP, in contrast to TCP, does not have a half-close. I checked the specification - when a fin-like segment has been sent there is no guarantee at all that any further data will be processed.
Thus this patch performs SHUT_WR in addition to the SHUT_RD when a fin-like segment is encountered.
The second change is minor; I noted that code appears twice in different places and think it makes sense to put this into a self-contained function.
Signed-off-by Gerrit Renker <[email protected]>
--- net/dccp/input.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
net/dccp/input.c +15 -7
@@ -19,16 +19,27 @@#include "ccid.h" #include "dccp.h" -static void dccp_fin (struct sock *sk,struct sk_buff *skb) +static void dccp_enqueue_skb (struct sock *sk,struct sk_buff *skb) { - sk->sk_shutdown |=RCV_SHUTDOWN ; -sock_set_flag (sk,SOCK_DONE );__skb_pull (skb,dccp_hdr (skb)->dccph_doff *4 );__skb_queue_tail (&sk->sk_receive_queue, skb);skb_set_owner_r (skb, sk); sk->sk_data_ready (sk,0 ); } +static void dccp_fin (struct sock *sk,struct sk_buff *skb) +{ +/* +* On receiving Close/CloseReq, both RD/WR shutdown are performed. +* RFC 4340, 8.3 says that we MAY send further Data/DataAcks after +* receiving the closing segment, but there is no guarantee that such +* data will be processed at all. +*/ + sk->sk_shutdown =SHUTDOWN_MASK ; +sock_set_flag (sk,SOCK_DONE ); +dccp_enqueue_skb (sk, skb); +} +static void dccp_rcv_close (struct sock *sk,struct sk_buff *skb) {if (sk->sk_state =DCCP_CLOSEREQ ) {
@@ -176,10 +187,7 @@ static int __dccp_rcv_established(struct* FIXME: check if sk_receive_queue is full, schedule DATA_DROPPED * option if it is. */ -__skb_pull (skb, dh->dccph_doff *4 ); -__skb_queue_tail (&sk->sk_receive_queue, skb); -skb_set_owner_r (skb, sk); - sk->sk_data_ready (sk,0 ); +dccp_enqueue_skb (sk, skb);return 0 ;case DCCP_PKT_ACK : goto discard;