diff options
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r-- | net/dccp/proto.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 8b613c3017c5..a3f8a8095f81 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -402,12 +402,15 @@ void dccp_close(struct sock *sk, long timeout) | |||
402 | /* Check zero linger _after_ checking for unread data. */ | 402 | /* Check zero linger _after_ checking for unread data. */ |
403 | sk->sk_prot->disconnect(sk, 0); | 403 | sk->sk_prot->disconnect(sk, 0); |
404 | } else if (dccp_close_state(sk)) { | 404 | } else if (dccp_close_state(sk)) { |
405 | dccp_send_close(sk); | 405 | dccp_send_close(sk, 1); |
406 | } | 406 | } |
407 | 407 | ||
408 | sk_stream_wait_close(sk, timeout); | 408 | sk_stream_wait_close(sk, timeout); |
409 | 409 | ||
410 | adjudge_to_death: | 410 | adjudge_to_death: |
411 | /* | ||
412 | * It is the last release_sock in its life. It will remove backlog. | ||
413 | */ | ||
411 | release_sock(sk); | 414 | release_sock(sk); |
412 | /* | 415 | /* |
413 | * Now socket is owned by kernel and we acquire BH lock | 416 | * Now socket is owned by kernel and we acquire BH lock |
@@ -419,11 +422,26 @@ adjudge_to_death: | |||
419 | 422 | ||
420 | sock_hold(sk); | 423 | sock_hold(sk); |
421 | sock_orphan(sk); | 424 | sock_orphan(sk); |
422 | 425 | ||
423 | if (sk->sk_state != DCCP_CLOSED) | 426 | /* |
427 | * The last release_sock may have processed the CLOSE or RESET | ||
428 | * packet moving sock to CLOSED state, if not we have to fire | ||
429 | * the CLOSE/CLOSEREQ retransmission timer, see "8.3. Termination" | ||
430 | * in draft-ietf-dccp-spec-11. -acme | ||
431 | */ | ||
432 | if (sk->sk_state == DCCP_CLOSING) { | ||
433 | /* FIXME: should start at 2 * RTT */ | ||
434 | /* Timer for repeating the CLOSE/CLOSEREQ until an answer. */ | ||
435 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
436 | inet_csk(sk)->icsk_rto, | ||
437 | DCCP_RTO_MAX); | ||
438 | #if 0 | ||
439 | /* Yeah, we should use sk->sk_prot->orphan_count, etc */ | ||
424 | dccp_set_state(sk, DCCP_CLOSED); | 440 | dccp_set_state(sk, DCCP_CLOSED); |
441 | #endif | ||
442 | } | ||
425 | 443 | ||
426 | atomic_inc(&dccp_orphan_count); | 444 | atomic_inc(sk->sk_prot->orphan_count); |
427 | if (sk->sk_state == DCCP_CLOSED) | 445 | if (sk->sk_state == DCCP_CLOSED) |
428 | inet_csk_destroy_sock(sk); | 446 | inet_csk_destroy_sock(sk); |
429 | 447 | ||