aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2007-12-13 09:25:01 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:57:48 -0500
commitb8599d20708fa3bde1e414689f3474560c2d990b (patch)
treeadeb51da63a75b03fa55ddbc4712c8359240a3bf
parent28be5440044d5b19b0331f79fb3e81845ad6d77e (diff)
[DCCP]: Support for server holding timewait state
This adds a socket option and signalling support for the case where the server holds timewait state on closing the connection, as described in RFC 4340, 8.3. Since holding timewait state at the server is the non-usual case, it is enabled via a socket option. Documentation for this socket option has been added. The setsockopt statement has been made resilient against different possible cases of expressing boolean `true' values using a suggestion by Ian McDonald. 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>
-rw-r--r--Documentation/networking/dccp.txt6
-rw-r--r--include/linux/dccp.h3
-rw-r--r--net/dccp/output.c6
-rw-r--r--net/dccp/proto.c13
4 files changed, 25 insertions, 3 deletions
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index d76905a5a087..39131a3c78f8 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -57,6 +57,12 @@ can be set before calling bind().
57DCCP_SOCKOPT_GET_CUR_MPS is read-only and retrieves the current maximum packet 57DCCP_SOCKOPT_GET_CUR_MPS is read-only and retrieves the current maximum packet
58size (application payload size) in bytes, see RFC 4340, section 14. 58size (application payload size) in bytes, see RFC 4340, section 14.
59 59
60DCCP_SOCKOPT_SERVER_TIMEWAIT enables the server (listening socket) to hold
61timewait state when closing the connection (RFC 4340, 8.3). The usual case is
62that the closing server sends a CloseReq, whereupon the client holds timewait
63state. When this boolean socket option is on, the server sends a Close instead
64and will enter TIMEWAIT. This option must be set after accept() returns.
65
60DCCP_SOCKOPT_SEND_CSCOV and DCCP_SOCKOPT_RECV_CSCOV are used for setting the 66DCCP_SOCKOPT_SEND_CSCOV and DCCP_SOCKOPT_RECV_CSCOV are used for setting the
61partial checksum coverage (RFC 4340, sec. 9.2). The default is that checksums 67partial checksum coverage (RFC 4340, sec. 9.2). The default is that checksums
62always cover the entire packet and that only fully covered application data is 68always cover the entire packet and that only fully covered application data is
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 312b989c7edb..c676021603f5 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -205,6 +205,7 @@ struct dccp_so_feat {
205#define DCCP_SOCKOPT_CHANGE_L 3 205#define DCCP_SOCKOPT_CHANGE_L 3
206#define DCCP_SOCKOPT_CHANGE_R 4 206#define DCCP_SOCKOPT_CHANGE_R 4
207#define DCCP_SOCKOPT_GET_CUR_MPS 5 207#define DCCP_SOCKOPT_GET_CUR_MPS 5
208#define DCCP_SOCKOPT_SERVER_TIMEWAIT 6
208#define DCCP_SOCKOPT_SEND_CSCOV 10 209#define DCCP_SOCKOPT_SEND_CSCOV 10
209#define DCCP_SOCKOPT_RECV_CSCOV 11 210#define DCCP_SOCKOPT_RECV_CSCOV 11
210#define DCCP_SOCKOPT_CCID_RX_INFO 128 211#define DCCP_SOCKOPT_CCID_RX_INFO 128
@@ -492,6 +493,7 @@ struct dccp_ackvec;
492 * @dccps_role - role of this sock, one of %dccp_role 493 * @dccps_role - role of this sock, one of %dccp_role
493 * @dccps_hc_rx_insert_options - receiver wants to add options when acking 494 * @dccps_hc_rx_insert_options - receiver wants to add options when acking
494 * @dccps_hc_tx_insert_options - sender wants to add options when sending 495 * @dccps_hc_tx_insert_options - sender wants to add options when sending
496 * @dccps_server_timewait - server holds timewait state on close (RFC 4340, 8.3)
495 * @dccps_xmit_timer - timer for when CCID is not ready to send 497 * @dccps_xmit_timer - timer for when CCID is not ready to send
496 * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs) 498 * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)
497 */ 499 */
@@ -528,6 +530,7 @@ struct dccp_sock {
528 enum dccp_role dccps_role:2; 530 enum dccp_role dccps_role:2;
529 __u8 dccps_hc_rx_insert_options:1; 531 __u8 dccps_hc_rx_insert_options:1;
530 __u8 dccps_hc_tx_insert_options:1; 532 __u8 dccps_hc_tx_insert_options:1;
533 __u8 dccps_server_timewait:1;
531 struct timer_list dccps_xmit_timer; 534 struct timer_list dccps_xmit_timer;
532}; 535};
533 536
diff --git a/net/dccp/output.c b/net/dccp/output.c
index e97584aa4898..b2e17910930d 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -567,8 +567,10 @@ void dccp_send_close(struct sock *sk, const int active)
567 567
568 /* Reserve space for headers and prepare control bits. */ 568 /* Reserve space for headers and prepare control bits. */
569 skb_reserve(skb, sk->sk_prot->max_header); 569 skb_reserve(skb, sk->sk_prot->max_header);
570 DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ? 570 if (dp->dccps_role == DCCP_ROLE_SERVER && !dp->dccps_server_timewait)
571 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; 571 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSEREQ;
572 else
573 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE;
572 574
573 if (active) { 575 if (active) {
574 dccp_write_xmit(sk, 1); 576 dccp_write_xmit(sk, 1);
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 8a73c8f98d76..cc87c500bfb8 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -551,6 +551,12 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
551 (struct dccp_so_feat __user *) 551 (struct dccp_so_feat __user *)
552 optval); 552 optval);
553 break; 553 break;
554 case DCCP_SOCKOPT_SERVER_TIMEWAIT:
555 if (dp->dccps_role != DCCP_ROLE_SERVER)
556 err = -EOPNOTSUPP;
557 else
558 dp->dccps_server_timewait = (val != 0);
559 break;
554 case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */ 560 case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */
555 if (val < 0 || val > 15) 561 if (val < 0 || val > 15)
556 err = -EINVAL; 562 err = -EINVAL;
@@ -653,6 +659,10 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
653 val = dp->dccps_mss_cache; 659 val = dp->dccps_mss_cache;
654 len = sizeof(val); 660 len = sizeof(val);
655 break; 661 break;
662 case DCCP_SOCKOPT_SERVER_TIMEWAIT:
663 val = dp->dccps_server_timewait;
664 len = sizeof(val);
665 break;
656 case DCCP_SOCKOPT_SEND_CSCOV: 666 case DCCP_SOCKOPT_SEND_CSCOV:
657 val = dp->dccps_pcslen; 667 val = dp->dccps_pcslen;
658 len = sizeof(val); 668 len = sizeof(val);
@@ -918,7 +928,8 @@ static void dccp_terminate_connection(struct sock *sk)
918 case DCCP_OPEN: 928 case DCCP_OPEN:
919 dccp_send_close(sk, 1); 929 dccp_send_close(sk, 1);
920 930
921 if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER) 931 if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER &&
932 !dccp_sk(sk)->dccps_server_timewait)
922 next_state = DCCP_ACTIVE_CLOSEREQ; 933 next_state = DCCP_ACTIVE_CLOSEREQ;
923 else 934 else
924 next_state = DCCP_CLOSING; 935 next_state = DCCP_CLOSING;