Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_subr.c
Show First 20 Lines • Show All 1,551 Lines • ▼ Show 20 Lines | |||||
* Attempt to close a TCP control block, marking it as dropped, and freeing | * Attempt to close a TCP control block, marking it as dropped, and freeing | ||||
* the socket if we hold the only reference. | * the socket if we hold the only reference. | ||||
*/ | */ | ||||
struct tcpcb * | struct tcpcb * | ||||
tcp_close(struct tcpcb *tp) | tcp_close(struct tcpcb *tp) | ||||
{ | { | ||||
struct inpcb *inp = tp->t_inpcb; | struct inpcb *inp = tp->t_inpcb; | ||||
struct socket *so; | struct socket *so; | ||||
bool listening = (tp->t_state == TCPS_LISTEN); | |||||
INP_INFO_LOCK_ASSERT(&V_tcbinfo); | INP_INFO_LOCK_ASSERT(&V_tcbinfo); | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
#ifdef TCP_OFFLOAD | #ifdef TCP_OFFLOAD | ||||
if (tp->t_state == TCPS_LISTEN) | if (listening) | ||||
tcp_offload_listen_stop(tp); | tcp_offload_listen_stop(tp); | ||||
#endif | #endif | ||||
#ifdef TCP_RFC7413 | #ifdef TCP_RFC7413 | ||||
/* | /* | ||||
* This releases the TFO pending counter resource for TFO listen | * This releases the TFO pending counter resource for TFO listen | ||||
* sockets as well as passively-created TFO sockets that transition | * sockets as well as passively-created TFO sockets that transition | ||||
* from SYN_RECEIVED to CLOSED. | * from SYN_RECEIVED to CLOSED. | ||||
*/ | */ | ||||
if (tp->t_tfo_pending) { | if (tp->t_tfo_pending) { | ||||
tcp_fastopen_decrement_counter(tp->t_tfo_pending); | tcp_fastopen_decrement_counter(tp->t_tfo_pending); | ||||
tp->t_tfo_pending = NULL; | tp->t_tfo_pending = NULL; | ||||
} | } | ||||
#endif | #endif | ||||
in_pcbdrop(inp); | in_pcbdrop(inp); | ||||
TCPSTAT_INC(tcps_closed); | TCPSTAT_INC(tcps_closed); | ||||
if (tp->t_state != TCPS_CLOSED) | if (tp->t_state != TCPS_CLOSED) | ||||
tcp_state_change(tp, TCPS_CLOSED); | tcp_state_change(tp, TCPS_CLOSED); | ||||
if (listening) { | |||||
tcp_discardcb(tp); | |||||
in_pcbdetach(inp); | |||||
in_pcbfree(inp); | |||||
return (NULL); | |||||
} | |||||
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL")); | KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL")); | ||||
so = inp->inp_socket; | so = inp->inp_socket; | ||||
soisdisconnected(so); | soisdisconnected(so); | ||||
if (inp->inp_flags & INP_SOCKREF) { | if (inp->inp_flags & INP_SOCKREF) { | ||||
KASSERT(so->so_state & SS_PROTOREF, | KASSERT(so->so_state & SS_PROTOREF, | ||||
("tcp_close: !SS_PROTOREF")); | ("tcp_close: !SS_PROTOREF")); | ||||
inp->inp_flags &= ~INP_SOCKREF; | inp->inp_flags &= ~INP_SOCKREF; | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
ACCEPT_LOCK(); | |||||
SOCK_LOCK(so); | SOCK_LOCK(so); | ||||
so->so_state &= ~SS_PROTOREF; | so->so_state &= ~SS_PROTOREF; | ||||
sofree(so); | sofree(so); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
return (tp); | return (tp); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | if (inp->inp_gencnt <= gencnt) { | ||||
else if (inp->inp_flags & INP_TIMEWAIT) { | else if (inp->inp_flags & INP_TIMEWAIT) { | ||||
bzero((char *) &xt.xt_tp, sizeof xt.xt_tp); | bzero((char *) &xt.xt_tp, sizeof xt.xt_tp); | ||||
xt.xt_tp.t_state = TCPS_TIME_WAIT; | xt.xt_tp.t_state = TCPS_TIME_WAIT; | ||||
} else { | } else { | ||||
bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp); | bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp); | ||||
if (xt.xt_tp.t_timers) | if (xt.xt_tp.t_timers) | ||||
tcp_timer_to_xtimer(&xt.xt_tp, xt.xt_tp.t_timers, &xt.xt_timer); | tcp_timer_to_xtimer(&xt.xt_tp, xt.xt_tp.t_timers, &xt.xt_timer); | ||||
} | } | ||||
if (inp->inp_socket != NULL) | if (inp->inp_socket != NULL) { | ||||
sotoxsocket(inp->inp_socket, &xt.xt_socket); | if (inp->inp_flags2 & INP_LISTENING) | ||||
else { | soltoxsocket(inp->inp_solisten, | ||||
&xt.xt_socket); | |||||
else | |||||
sotoxsocket(inp->inp_socket, | |||||
&xt.xt_socket); | |||||
} else { | |||||
bzero(&xt.xt_socket, sizeof xt.xt_socket); | bzero(&xt.xt_socket, sizeof xt.xt_socket); | ||||
xt.xt_socket.xso_protocol = IPPROTO_TCP; | xt.xt_socket.xso_protocol = IPPROTO_TCP; | ||||
} | } | ||||
xt.xt_inp.inp_gencnt = inp->inp_gencnt; | xt.xt_inp.inp_gencnt = inp->inp_gencnt; | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
error = SYSCTL_OUT(req, &xt, sizeof xt); | error = SYSCTL_OUT(req, &xt, sizeof xt); | ||||
} else | } else | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
▲ Show 20 Lines • Show All 1,143 Lines • ▼ Show 20 Lines | if (inp->inp_flags & INP_TIMEWAIT) { | ||||
* type of inpcb. | * type of inpcb. | ||||
*/ | */ | ||||
tw = intotw(inp); | tw = intotw(inp); | ||||
if (tw != NULL) | if (tw != NULL) | ||||
tcp_twclose(tw, 0); | tcp_twclose(tw, 0); | ||||
else | else | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
} else if (!(inp->inp_flags & INP_DROPPED) && | } else if (!(inp->inp_flags & INP_DROPPED) && | ||||
!(inp->inp_socket->so_options & SO_ACCEPTCONN)) { | !(inp->inp_flags2 & INP_LISTENING)) { | ||||
tp = intotcpcb(inp); | tp = intotcpcb(inp); | ||||
tp = tcp_drop(tp, ECONNABORTED); | tp = tcp_drop(tp, ECONNABORTED); | ||||
if (tp != NULL) | if (tp != NULL) | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
} else | } else | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
} else | } else | ||||
error = ESRCH; | error = ESRCH; | ||||
▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines |