* User issued close, and wish to trail through shutdown states: * if never received SYN, just forget it. If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state. In all other cases, have already sent FIN to peer (e.g. * after PRU_SHUTDOWN), and just have to play tedious game wa
| 2690 | * We can let the user exit from the close as soon as the FIN is acked. |
| 2691 | */ |
| 2692 | static void |
| 2693 | tcp_usrclosed(struct tcpcb *tp) |
| 2694 | { |
| 2695 | |
| 2696 | NET_EPOCH_ASSERT(); |
| 2697 | INP_WLOCK_ASSERT(tp->t_inpcb); |
| 2698 | |
| 2699 | switch (tp->t_state) { |
| 2700 | case TCPS_LISTEN: |
| 2701 | #ifdef TCP_OFFLOAD |
| 2702 | tcp_offload_listen_stop(tp); |
| 2703 | #endif |
| 2704 | tcp_state_change(tp, TCPS_CLOSED); |
| 2705 | /* FALLTHROUGH */ |
| 2706 | case TCPS_CLOSED: |
| 2707 | tp = tcp_close(tp); |
| 2708 | /* |
| 2709 | * tcp_close() should never return NULL here as the socket is |
| 2710 | * still open. |
| 2711 | */ |
| 2712 | KASSERT(tp != NULL, |
| 2713 | ("tcp_usrclosed: tcp_close() returned NULL")); |
| 2714 | break; |
| 2715 | |
| 2716 | case TCPS_SYN_SENT: |
| 2717 | case TCPS_SYN_RECEIVED: |
| 2718 | tp->t_flags |= TF_NEEDFIN; |
| 2719 | break; |
| 2720 | |
| 2721 | case TCPS_ESTABLISHED: |
| 2722 | tcp_state_change(tp, TCPS_FIN_WAIT_1); |
| 2723 | break; |
| 2724 | |
| 2725 | case TCPS_CLOSE_WAIT: |
| 2726 | tcp_state_change(tp, TCPS_LAST_ACK); |
| 2727 | break; |
| 2728 | } |
| 2729 | if (tp->t_state >= TCPS_FIN_WAIT_2) { |
| 2730 | soisdisconnected(tp->t_inpcb->inp_socket); |
| 2731 | /* Prevent the connection hanging in FIN_WAIT_2 forever. */ |
| 2732 | if (tp->t_state == TCPS_FIN_WAIT_2) { |
| 2733 | int timeout; |
| 2734 | |
| 2735 | timeout = (tcp_fast_finwait2_recycle) ? |
| 2736 | tcp_finwait2_timeout : TP_MAXIDLE(tp); |
| 2737 | tcp_timer_activate(tp, TT_2MSL, timeout); |
| 2738 | } |
| 2739 | } |
| 2740 | } |
| 2741 | |
| 2742 | #ifdef DDB |
| 2743 | static void |
no test coverage detected