* Attempt to close a TCP control block, marking it as dropped, and freeing * the socket if we hold the only reference. */
| 2097 | * the socket if we hold the only reference. |
| 2098 | */ |
| 2099 | struct tcpcb * |
| 2100 | tcp_close(struct tcpcb *tp) |
| 2101 | { |
| 2102 | struct inpcb *inp = tp->t_inpcb; |
| 2103 | struct socket *so; |
| 2104 | |
| 2105 | INP_INFO_LOCK_ASSERT(&V_tcbinfo); |
| 2106 | INP_WLOCK_ASSERT(inp); |
| 2107 | |
| 2108 | #ifdef TCP_OFFLOAD |
| 2109 | if (tp->t_state == TCPS_LISTEN) |
| 2110 | tcp_offload_listen_stop(tp); |
| 2111 | #endif |
| 2112 | /* |
| 2113 | * This releases the TFO pending counter resource for TFO listen |
| 2114 | * sockets as well as passively-created TFO sockets that transition |
| 2115 | * from SYN_RECEIVED to CLOSED. |
| 2116 | */ |
| 2117 | if (tp->t_tfo_pending) { |
| 2118 | tcp_fastopen_decrement_counter(tp->t_tfo_pending); |
| 2119 | tp->t_tfo_pending = NULL; |
| 2120 | } |
| 2121 | in_pcbdrop(inp); |
| 2122 | TCPSTAT_INC(tcps_closed); |
| 2123 | if (tp->t_state != TCPS_CLOSED) |
| 2124 | tcp_state_change(tp, TCPS_CLOSED); |
| 2125 | KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL")); |
| 2126 | so = inp->inp_socket; |
| 2127 | soisdisconnected(so); |
| 2128 | if (inp->inp_flags & INP_SOCKREF) { |
| 2129 | KASSERT(so->so_state & SS_PROTOREF, |
| 2130 | ("tcp_close: !SS_PROTOREF")); |
| 2131 | inp->inp_flags &= ~INP_SOCKREF; |
| 2132 | INP_WUNLOCK(inp); |
| 2133 | SOCK_LOCK(so); |
| 2134 | so->so_state &= ~SS_PROTOREF; |
| 2135 | sofree(so); |
| 2136 | return (NULL); |
| 2137 | } |
| 2138 | return (tp); |
| 2139 | } |
| 2140 | |
| 2141 | void |
| 2142 | tcp_drain(void) |
no test coverage detected