Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_syncache.c
Show First 20 Lines • Show All 771 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Build a new TCP socket structure from a syncache entry. | * Build a new TCP socket structure from a syncache entry. | ||||
* | * | ||||
* On success return the newly created socket with its underlying inp locked. | * On success return the newly created socket with its underlying inp locked. | ||||
*/ | */ | ||||
static struct socket * | static struct socket * | ||||
syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) | syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) | ||||
{ | { | ||||
struct tcp_function_block *blk; | struct tcp_function_block *tfb; | ||||
struct inpcb *inp = NULL; | struct inpcb *inp = NULL; | ||||
struct socket *so; | struct socket *so; | ||||
struct tcpcb *tp; | struct tcpcb *tp; | ||||
int error; | int error; | ||||
char *s; | char *s; | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
/* | /* | ||||
* Ok, create the full blown connection, and set things up | * Ok, create the full blown connection, and set things up | ||||
* as they would have been set up if we had created the | * as they would have been set up if we had created the | ||||
* connection when the SYN arrived. | * connection when the SYN arrived. | ||||
*/ | */ | ||||
if ((so = solisten_clone(lso)) == NULL) | if ((so = solisten_clone(lso)) == NULL) | ||||
goto allocfail; | goto allocfail; | ||||
#ifdef MAC | #ifdef MAC | ||||
mac_socketpeer_set_from_mbuf(m, so); | mac_socketpeer_set_from_mbuf(m, so); | ||||
#endif | #endif | ||||
error = in_pcballoc(so, &V_tcbinfo); | error = in_pcballoc(so, &V_tcbinfo); | ||||
if (error) { | if (error) { | ||||
sodealloc(so); | sodealloc(so); | ||||
goto allocfail; | goto allocfail; | ||||
} | } | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
if ((tp = tcp_newtcpcb(inp)) == NULL) { | if (V_functions_inherit_listen_socket_stack) | ||||
tfb = tcp_find_and_ref_fb(sototcpcb(lso)->t_fb); | |||||
else | |||||
tfb = tcp_find_and_ref_default_fb(); | |||||
if ((tp = tcp_newtcpcb(inp, tfb)) == NULL) { | |||||
refcount_release(&tfb->tfb_refcnt); | |||||
in_pcbfree(inp); | in_pcbfree(inp); | ||||
sodealloc(so); | sodealloc(so); | ||||
goto allocfail; | goto allocfail; | ||||
} | } | ||||
inp->inp_inc.inc_flags = sc->sc_inc.inc_flags; | inp->inp_inc.inc_flags = sc->sc_inc.inc_flags; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (sc->sc_inc.inc_flags & INC_ISIPV6) { | if (sc->sc_inc.inc_flags & INC_ISIPV6) { | ||||
inp->inp_vflag &= ~INP_IPV4; | inp->inp_vflag &= ~INP_IPV4; | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | if (ipsec_copy_pcbpolicy(sotoinpcb(lso), inp) != 0) | ||||
printf("syncache_socket: could not copy policy\n"); | printf("syncache_socket: could not copy policy\n"); | ||||
#endif | #endif | ||||
tp->t_state = TCPS_SYN_RECEIVED; | tp->t_state = TCPS_SYN_RECEIVED; | ||||
tp->iss = sc->sc_iss; | tp->iss = sc->sc_iss; | ||||
tp->irs = sc->sc_irs; | tp->irs = sc->sc_irs; | ||||
tp->t_port = sc->sc_port; | tp->t_port = sc->sc_port; | ||||
tcp_rcvseqinit(tp); | tcp_rcvseqinit(tp); | ||||
tcp_sendseqinit(tp); | tcp_sendseqinit(tp); | ||||
blk = sototcpcb(lso)->t_fb; | |||||
if (V_functions_inherit_listen_socket_stack && blk != tp->t_fb) { | |||||
/* | |||||
* Our parents t_fb was not the default, | |||||
* we need to release our ref on tp->t_fb and | |||||
* pickup one on the new entry. | |||||
*/ | |||||
struct tcp_function_block *rblk; | |||||
void *ptr = NULL; | |||||
rblk = find_and_ref_tcp_fb(blk); | |||||
KASSERT(rblk != NULL, | |||||
("cannot find blk %p out of syncache?", blk)); | |||||
if (rblk->tfb_tcp_fb_init == NULL || | |||||
(*rblk->tfb_tcp_fb_init)(tp, &ptr) == 0) { | |||||
/* Release the old stack */ | |||||
if (tp->t_fb->tfb_tcp_fb_fini != NULL) | |||||
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 0); | |||||
refcount_release(&tp->t_fb->tfb_refcnt); | |||||
/* Now set in all the pointers */ | |||||
tp->t_fb = rblk; | |||||
tp->t_fb_ptr = ptr; | |||||
} else { | |||||
/* | |||||
* Initialization failed. Release the reference count on | |||||
* the looked up default stack. | |||||
*/ | |||||
refcount_release(&rblk->tfb_refcnt); | |||||
} | |||||
} | |||||
tp->snd_wl1 = sc->sc_irs; | tp->snd_wl1 = sc->sc_irs; | ||||
tp->snd_max = tp->iss + 1; | tp->snd_max = tp->iss + 1; | ||||
tp->snd_nxt = tp->iss + 1; | tp->snd_nxt = tp->iss + 1; | ||||
tp->rcv_up = sc->sc_irs + 1; | tp->rcv_up = sc->sc_irs + 1; | ||||
tp->rcv_wnd = sc->sc_wnd; | tp->rcv_wnd = sc->sc_wnd; | ||||
tp->rcv_adv += tp->rcv_wnd; | tp->rcv_adv += tp->rcv_wnd; | ||||
tp->last_ack_sent = tp->rcv_nxt; | tp->last_ack_sent = tp->rcv_nxt; | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | log(LOG_DEBUG, "%s; %s: Socket create failed " | ||||
"due to limits or memory shortage\n", | "due to limits or memory shortage\n", | ||||
s, __func__); | s, __func__); | ||||
free(s, M_TCPLOG); | free(s, M_TCPLOG); | ||||
} | } | ||||
TCPSTAT_INC(tcps_listendrop); | TCPSTAT_INC(tcps_listendrop); | ||||
return (NULL); | return (NULL); | ||||
abort: | abort: | ||||
refcount_release(&tfb->tfb_refcnt); | |||||
jtl: I don't think this is sufficient. We really need to undo everything done in tcp_newtcpcb()… | |||||
Done Inline ActionsYou are correct, this is a generic issue not related to this patch. So I created D45749 to fix this separately. tuexen: You are correct, this is a generic issue not related to this patch. So I created [[ https… | |||||
Done Inline ActionsAgreed. Thanks for doing that! jtl: Agreed. Thanks for doing that! | |||||
in_pcbfree(inp); | in_pcbfree(inp); | ||||
sodealloc(so); | sodealloc(so); | ||||
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { | if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { | ||||
log(LOG_DEBUG, "%s; %s: in%s_pcbconnect failed with error %i\n", | log(LOG_DEBUG, "%s; %s: in%s_pcbconnect failed with error %i\n", | ||||
s, __func__, (sc->sc_inc.inc_flags & INC_ISIPV6) ? "6" : "", | s, __func__, (sc->sc_inc.inc_flags & INC_ISIPV6) ? "6" : "", | ||||
error); | error); | ||||
free(s, M_TCPLOG); | free(s, M_TCPLOG); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,515 Lines • Show Last 20 Lines |
I don't think this is sufficient. We really need to undo everything done in tcp_newtcpcb(), which includes (among other things) acquiring a refcount on the CC algo, initializing the CC code, and allocating a stats blob. I wonder if we instead should just run tcp_discardcb() here?