Commit 69567d0b authored by Gerrit Renker's avatar Gerrit Renker Committed by David S. Miller

[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: default avatarGerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: default avatarIan McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 96eba69d
...@@ -22,16 +22,27 @@ ...@@ -22,16 +22,27 @@
/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */ /* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */
int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8; int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8;
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_pull(skb, dccp_hdr(skb)->dccph_doff * 4);
__skb_queue_tail(&sk->sk_receive_queue, skb); __skb_queue_tail(&sk->sk_receive_queue, skb);
skb_set_owner_r(skb, sk); skb_set_owner_r(skb, sk);
sk->sk_data_ready(sk, 0); 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 int dccp_rcv_close(struct sock *sk, struct sk_buff *skb) static int dccp_rcv_close(struct sock *sk, struct sk_buff *skb)
{ {
int queued = 0; int queued = 0;
...@@ -282,10 +293,7 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, ...@@ -282,10 +293,7 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
* - sk_shutdown == RCV_SHUTDOWN, use Code 1, "Not Listening" * - sk_shutdown == RCV_SHUTDOWN, use Code 1, "Not Listening"
* - sk_receive_queue is full, use Code 2, "Receive Buffer" * - sk_receive_queue is full, use Code 2, "Receive Buffer"
*/ */
__skb_pull(skb, dh->dccph_doff * 4); dccp_enqueue_skb(sk, skb);
__skb_queue_tail(&sk->sk_receive_queue, skb);
skb_set_owner_r(skb, sk);
sk->sk_data_ready(sk, 0);
return 0; return 0;
case DCCP_PKT_ACK: case DCCP_PKT_ACK:
goto discard; goto discard;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment