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 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; |