Skip to contentSkip to conversation

: Perform SHUT_RD and SHUT_WR on receiving close

PATCH In review Gerrit Renker 1 participant 1 message Apr 5, 2007 Networking

lore
Share & tools
lore
#0 lore raw

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.

---
 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;