diff options
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/output.c | 6 | ||||
-rw-r--r-- | net/dccp/proto.c | 13 |
2 files changed, 16 insertions, 3 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c index e97584aa489..b2e17910930 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) /* Reserve space for headers and prepare control bits. */ skb_reserve(skb, sk->sk_prot->max_header); - DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ? - DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; + if (dp->dccps_role == DCCP_ROLE_SERVER && !dp->dccps_server_timewait) + DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSEREQ; + else + DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE; if (active) { dccp_write_xmit(sk, 1); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 8a73c8f98d7..cc87c500bfb 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, (struct dccp_so_feat __user *) optval); break; + case DCCP_SOCKOPT_SERVER_TIMEWAIT: + if (dp->dccps_role != DCCP_ROLE_SERVER) + err = -EOPNOTSUPP; + else + dp->dccps_server_timewait = (val != 0); + break; case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */ if (val < 0 || val > 15) err = -EINVAL; @@ -653,6 +659,10 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, val = dp->dccps_mss_cache; len = sizeof(val); break; + case DCCP_SOCKOPT_SERVER_TIMEWAIT: + val = dp->dccps_server_timewait; + len = sizeof(val); + break; case DCCP_SOCKOPT_SEND_CSCOV: val = dp->dccps_pcslen; len = sizeof(val); @@ -918,7 +928,8 @@ static void dccp_terminate_connection(struct sock *sk) case DCCP_OPEN: dccp_send_close(sk, 1); - if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER) + if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER && + !dccp_sk(sk)->dccps_server_timewait) next_state = DCCP_ACTIVE_CLOSEREQ; else next_state = DCCP_CLOSING; |