aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/input.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2007-12-13 08:28:43 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:57:45 -0500
commit69567d0b63b7f4ffeb53fe746c87bd6efe1c284b (patch)
treed2ce8ff37ecc6481684cddd386bc302f47a0a468 /net/dccp/input.c
parent96eba69dbac767f4e287df39e6fa489d37f1aa7b (diff)
[DCCP]: Perform SHUT_RD and SHUT_WR on receiving close
This patch performs two changes: 1) 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. RFC 4340 says in this respect that 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. 2) Minor change: I noted that code appears twice in different places and think it makes sense to put this into a self-contained function (dccp_enqueue()). 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/input.c')
-rw-r--r--net/dccp/input.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c
index decf2f21149b..dacd4fd3c63c 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -22,16 +22,27 @@
22/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */ 22/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */
23int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8; 23int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8;
24 24
25static void dccp_fin(struct sock *sk, struct sk_buff *skb) 25static void dccp_enqueue_skb(struct sock *sk, struct sk_buff *skb)
26{ 26{
27 sk->sk_shutdown |= RCV_SHUTDOWN;
28 sock_set_flag(sk, SOCK_DONE);
29 __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4); 27 __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4);
30 __skb_queue_tail(&sk->sk_receive_queue, skb); 28 __skb_queue_tail(&sk->sk_receive_queue, skb);
31 skb_set_owner_r(skb, sk); 29 skb_set_owner_r(skb, sk);
32 sk->sk_data_ready(sk, 0); 30 sk->sk_data_ready(sk, 0);
33} 31}
34 32
33static void dccp_fin(struct sock *sk, struct sk_buff *skb)
34{
35 /*
36 * On receiving Close/CloseReq, both RD/WR shutdown are performed.
37 * RFC 4340, 8.3 says that we MAY send further Data/DataAcks after
38 * receiving the closing segment, but there is no guarantee that such
39 * data will be processed at all.
40 */
41 sk->sk_shutdown = SHUTDOWN_MASK;
42 sock_set_flag(sk, SOCK_DONE);
43 dccp_enqueue_skb(sk, skb);
44}
45
35static int dccp_rcv_close(struct sock *sk, struct sk_buff *skb) 46static int dccp_rcv_close(struct sock *sk, struct sk_buff *skb)
36{ 47{
37 int queued = 0; 48 int queued = 0;
@@ -282,10 +293,7 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
282 * - sk_shutdown == RCV_SHUTDOWN, use Code 1, "Not Listening" 293 * - sk_shutdown == RCV_SHUTDOWN, use Code 1, "Not Listening"
283 * - sk_receive_queue is full, use Code 2, "Receive Buffer" 294 * - sk_receive_queue is full, use Code 2, "Receive Buffer"
284 */ 295 */
285 __skb_pull(skb, dh->dccph_doff * 4); 296 dccp_enqueue_skb(sk, skb);
286 __skb_queue_tail(&sk->sk_receive_queue, skb);
287 skb_set_owner_r(skb, sk);
288 sk->sk_data_ready(sk, 0);
289 return 0; 297 return 0;
290 case DCCP_PKT_ACK: 298 case DCCP_PKT_ACK:
291 goto discard; 299 goto discard;