diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2007-11-28 08:34:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:55:12 -0500 |
commit | f11135a3442996d78dad99933bfdb90d1f6588d3 (patch) | |
tree | 6b10cea26f0551b769097296b7e41f25d6b44f08 /include/linux/dccp.h | |
parent | f53dc67c5e7babafe239b93a11678b0e05bead51 (diff) |
[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>
Diffstat (limited to 'include/linux/dccp.h')
-rw-r--r-- | include/linux/dccp.h | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/include/linux/dccp.h b/include/linux/dccp.h index a0073268808f..8b3f9ad3cf04 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h | |||
@@ -227,29 +227,51 @@ struct dccp_so_feat { | |||
227 | #include <net/tcp_states.h> | 227 | #include <net/tcp_states.h> |
228 | 228 | ||
229 | enum dccp_state { | 229 | enum dccp_state { |
230 | DCCP_OPEN = TCP_ESTABLISHED, | 230 | DCCP_OPEN = TCP_ESTABLISHED, |
231 | DCCP_REQUESTING = TCP_SYN_SENT, | 231 | DCCP_REQUESTING = TCP_SYN_SENT, |
232 | DCCP_LISTEN = TCP_LISTEN, | 232 | DCCP_LISTEN = TCP_LISTEN, |
233 | DCCP_RESPOND = TCP_SYN_RECV, | 233 | DCCP_RESPOND = TCP_SYN_RECV, |
234 | DCCP_CLOSING = TCP_CLOSING, | 234 | /* |
235 | DCCP_TIME_WAIT = TCP_TIME_WAIT, | 235 | * States involved in closing a DCCP connection: |
236 | DCCP_CLOSED = TCP_CLOSE, | 236 | * 1) ACTIVE_CLOSEREQ is entered by a server sending a CloseReq. |
237 | DCCP_PARTOPEN = TCP_MAX_STATES, | 237 | * |
238 | * 2) CLOSING can have three different meanings (RFC 4340, 8.3): | ||
239 | * a. Client has performed active-close, has sent a Close to the server | ||
240 | * from state OPEN or PARTOPEN, and is waiting for the final Reset | ||
241 | * (in this case, SOCK_DONE == 1). | ||
242 | * b. Client is asked to perform passive-close, by receiving a CloseReq | ||
243 | * in (PART)OPEN state. It sends a Close and waits for final Reset | ||
244 | * (in this case, SOCK_DONE == 0). | ||
245 | * c. Server performs an active-close as in (a), keeps TIMEWAIT state. | ||
246 | * | ||
247 | * 3) The following intermediate states are employed to give passively | ||
248 | * closing nodes a chance to process their unread data: | ||
249 | * - PASSIVE_CLOSE (from OPEN => CLOSED) and | ||
250 | * - PASSIVE_CLOSEREQ (from (PART)OPEN to CLOSING; case (b) above). | ||
251 | */ | ||
252 | DCCP_ACTIVE_CLOSEREQ = TCP_FIN_WAIT1, | ||
253 | DCCP_PASSIVE_CLOSE = TCP_CLOSE_WAIT, /* any node receiving a Close */ | ||
254 | DCCP_CLOSING = TCP_CLOSING, | ||
255 | DCCP_TIME_WAIT = TCP_TIME_WAIT, | ||
256 | DCCP_CLOSED = TCP_CLOSE, | ||
257 | DCCP_PARTOPEN = TCP_MAX_STATES, | ||
258 | DCCP_PASSIVE_CLOSEREQ, /* clients receiving CloseReq */ | ||
238 | DCCP_MAX_STATES | 259 | DCCP_MAX_STATES |
239 | }; | 260 | }; |
240 | 261 | ||
241 | #define DCCP_STATE_MASK 0xf | 262 | #define DCCP_STATE_MASK 0x1f |
242 | #define DCCP_ACTION_FIN (1<<7) | 263 | #define DCCP_ACTION_FIN (1<<7) |
243 | 264 | ||
244 | enum { | 265 | enum { |
245 | DCCPF_OPEN = TCPF_ESTABLISHED, | 266 | DCCPF_OPEN = TCPF_ESTABLISHED, |
246 | DCCPF_REQUESTING = TCPF_SYN_SENT, | 267 | DCCPF_REQUESTING = TCPF_SYN_SENT, |
247 | DCCPF_LISTEN = TCPF_LISTEN, | 268 | DCCPF_LISTEN = TCPF_LISTEN, |
248 | DCCPF_RESPOND = TCPF_SYN_RECV, | 269 | DCCPF_RESPOND = TCPF_SYN_RECV, |
249 | DCCPF_CLOSING = TCPF_CLOSING, | 270 | DCCPF_ACTIVE_CLOSEREQ = TCPF_FIN_WAIT1, |
250 | DCCPF_TIME_WAIT = TCPF_TIME_WAIT, | 271 | DCCPF_CLOSING = TCPF_CLOSING, |
251 | DCCPF_CLOSED = TCPF_CLOSE, | 272 | DCCPF_TIME_WAIT = TCPF_TIME_WAIT, |
252 | DCCPF_PARTOPEN = 1 << DCCP_PARTOPEN, | 273 | DCCPF_CLOSED = TCPF_CLOSE, |
274 | DCCPF_PARTOPEN = (1 << DCCP_PARTOPEN), | ||
253 | }; | 275 | }; |
254 | 276 | ||
255 | static inline struct dccp_hdr *dccp_hdr(const struct sk_buff *skb) | 277 | static inline struct dccp_hdr *dccp_hdr(const struct sk_buff *skb) |