[DCCP]: Dedicated auxiliary states to support passive-close

This adds two auxiliary states to deal with passive closes:
  * PASSIVE_CLOSE    (reached from OPEN via reception of Close)    and
  * PASSIVE_CLOSEREQ (reached from OPEN via reception of CloseReq)
as internal intermediate states.

These states are used to allow a receiver to process unread data before
acknowledging the received connection-termination-request (the Close/CloseReq).

Without such support, it will happen that passively-closed sockets enter CLOSED
state while there is still unprocessed data in the queue; leading to unexpected
and erratic API behaviour.

PASSIVE_CLOSE has been mapped into TCPF_CLOSE_WAIT, so that the code will
seamlessly work with inet_accept() (which tests for this state).

The state names are thanks to Arnaldo, who suggested this naming scheme
following an earlier revision of this patch.

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Gerrit Renker
2007-11-28 11:34:53 -02:00
committed by David S. Miller
parent f53dc67c5e
commit f11135a344
2 changed files with 51 additions and 27 deletions
+39 -17
View File
@@ -227,29 +227,51 @@ struct dccp_so_feat {
#include <net/tcp_states.h>
enum dccp_state {
DCCP_OPEN = TCP_ESTABLISHED,
DCCP_REQUESTING = TCP_SYN_SENT,
DCCP_LISTEN = TCP_LISTEN,
DCCP_RESPOND = TCP_SYN_RECV,
DCCP_CLOSING = TCP_CLOSING,
DCCP_TIME_WAIT = TCP_TIME_WAIT,
DCCP_CLOSED = TCP_CLOSE,
DCCP_PARTOPEN = TCP_MAX_STATES,
DCCP_OPEN = TCP_ESTABLISHED,
DCCP_REQUESTING = TCP_SYN_SENT,
DCCP_LISTEN = TCP_LISTEN,
DCCP_RESPOND = TCP_SYN_RECV,
/*
* States involved in closing a DCCP connection:
* 1) ACTIVE_CLOSEREQ is entered by a server sending a CloseReq.
*
* 2) CLOSING can have three different meanings (RFC 4340, 8.3):
* a. Client has performed active-close, has sent a Close to the server
* from state OPEN or PARTOPEN, and is waiting for the final Reset
* (in this case, SOCK_DONE == 1).
* b. Client is asked to perform passive-close, by receiving a CloseReq
* in (PART)OPEN state. It sends a Close and waits for final Reset
* (in this case, SOCK_DONE == 0).
* c. Server performs an active-close as in (a), keeps TIMEWAIT state.
*
* 3) The following intermediate states are employed to give passively
* closing nodes a chance to process their unread data:
* - PASSIVE_CLOSE (from OPEN => CLOSED) and
* - PASSIVE_CLOSEREQ (from (PART)OPEN to CLOSING; case (b) above).
*/
DCCP_ACTIVE_CLOSEREQ = TCP_FIN_WAIT1,
DCCP_PASSIVE_CLOSE = TCP_CLOSE_WAIT, /* any node receiving a Close */
DCCP_CLOSING = TCP_CLOSING,
DCCP_TIME_WAIT = TCP_TIME_WAIT,
DCCP_CLOSED = TCP_CLOSE,
DCCP_PARTOPEN = TCP_MAX_STATES,
DCCP_PASSIVE_CLOSEREQ, /* clients receiving CloseReq */
DCCP_MAX_STATES
};
#define DCCP_STATE_MASK 0xf
#define DCCP_STATE_MASK 0x1f
#define DCCP_ACTION_FIN (1<<7)
enum {
DCCPF_OPEN = TCPF_ESTABLISHED,
DCCPF_REQUESTING = TCPF_SYN_SENT,
DCCPF_LISTEN = TCPF_LISTEN,
DCCPF_RESPOND = TCPF_SYN_RECV,
DCCPF_CLOSING = TCPF_CLOSING,
DCCPF_TIME_WAIT = TCPF_TIME_WAIT,
DCCPF_CLOSED = TCPF_CLOSE,
DCCPF_PARTOPEN = 1 << DCCP_PARTOPEN,
DCCPF_OPEN = TCPF_ESTABLISHED,
DCCPF_REQUESTING = TCPF_SYN_SENT,
DCCPF_LISTEN = TCPF_LISTEN,
DCCPF_RESPOND = TCPF_SYN_RECV,
DCCPF_ACTIVE_CLOSEREQ = TCPF_FIN_WAIT1,
DCCPF_CLOSING = TCPF_CLOSING,
DCCPF_TIME_WAIT = TCPF_TIME_WAIT,
DCCPF_CLOSED = TCPF_CLOSE,
DCCPF_PARTOPEN = (1 << DCCP_PARTOPEN),
};
static inline struct dccp_hdr *dccp_hdr(const struct sk_buff *skb)