Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_usrreq.c
Show First 20 Lines • Show All 1,707 Lines • ▼ Show 20 Lines | if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { \ | ||||
INP_WUNLOCK(inp); \ | INP_WUNLOCK(inp); \ | ||||
cleanup; \ | cleanup; \ | ||||
return (ECONNRESET); \ | return (ECONNRESET); \ | ||||
} \ | } \ | ||||
tp = intotcpcb(inp); \ | tp = intotcpcb(inp); \ | ||||
} while(0) | } while(0) | ||||
#define INP_WLOCK_RECHECK(inp) INP_WLOCK_RECHECK_CLEANUP((inp), /* noop */) | #define INP_WLOCK_RECHECK(inp) INP_WLOCK_RECHECK_CLEANUP((inp), /* noop */) | ||||
static int | int | ||||
tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt) | tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt) | ||||
{ | { | ||||
struct socket *so = inp->inp_socket; | |||||
struct tcpcb *tp = intotcpcb(inp); | struct tcpcb *tp = intotcpcb(inp); | ||||
int error = 0; | int error = 0; | ||||
MPASS(sopt->sopt_dir == SOPT_SET); | MPASS(sopt->sopt_dir == SOPT_SET); | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
KASSERT((inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) == 0, | |||||
("inp_flags == %x", inp->inp_flags)); | |||||
KASSERT(so != NULL, ("inp_socket == NULL")); | |||||
if (sopt->sopt_level != IPPROTO_TCP) { | if (sopt->sopt_level != IPPROTO_TCP) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (inp->inp_vflag & INP_IPV6PROTO) | if (inp->inp_vflag & INP_IPV6PROTO) | ||||
error = ip6_ctloutput(inp->inp_socket, sopt); | error = ip6_ctloutput(so, sopt); | ||||
#endif | #endif | ||||
#if defined(INET6) && defined(INET) | #if defined(INET6) && defined(INET) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
error = ip_ctloutput(inp->inp_socket, sopt); | error = ip_ctloutput(so, sopt); | ||||
#endif | #endif | ||||
/* | /* | ||||
* When an IP-level socket option affects TCP, pass control | * When an IP-level socket option affects TCP, pass control | ||||
* down to stack tfb_tcp_ctloutput, otherwise return what | * down to stack tfb_tcp_ctloutput, otherwise return what | ||||
* IP level returned. | * IP level returned. | ||||
*/ | */ | ||||
switch (sopt->sopt_level) { | switch (sopt->sopt_level) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | #endif | ||||
if (blk->tfb_tcp_fb_init) { | if (blk->tfb_tcp_fb_init) { | ||||
error = (*blk->tfb_tcp_fb_init)(tp); | error = (*blk->tfb_tcp_fb_init)(tp); | ||||
if (error) { | if (error) { | ||||
refcount_release(&blk->tfb_refcnt); | refcount_release(&blk->tfb_refcnt); | ||||
if (tp->t_fb->tfb_tcp_fb_init) { | if (tp->t_fb->tfb_tcp_fb_init) { | ||||
if((*tp->t_fb->tfb_tcp_fb_init)(tp) != 0) { | if((*tp->t_fb->tfb_tcp_fb_init)(tp) != 0) { | ||||
/* Fall back failed, drop the connection */ | /* Fall back failed, drop the connection */ | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
soabort(inp->inp_socket); | soabort(so); | ||||
return(error); | return (error); | ||||
} | } | ||||
} | } | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
} | } | ||||
refcount_release(&tp->t_fb->tfb_refcnt); | refcount_release(&tp->t_fb->tfb_refcnt); | ||||
tp->t_fb = blk; | tp->t_fb = blk; | ||||
#ifdef TCP_OFFLOAD | #ifdef TCP_OFFLOAD | ||||
if (tp->t_flags & TF_TOE) { | if (tp->t_flags & TF_TOE) { | ||||
tcp_offload_ctloutput(tp, sopt->sopt_dir, | tcp_offload_ctloutput(tp, sopt->sopt_dir, | ||||
sopt->sopt_name); | sopt->sopt_name); | ||||
} | } | ||||
#endif | #endif | ||||
err_out: | err_out: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
return (error); | return (error); | ||||
} | } | ||||
tp = intotcpcb(inp); | |||||
/* Pass in the INP locked, callee must unlock it. */ | /* Pass in the INP locked, callee must unlock it. */ | ||||
return (tp->t_fb->tfb_tcp_ctloutput(inp, sopt)); | return (tp->t_fb->tfb_tcp_ctloutput(inp, sopt)); | ||||
} | } | ||||
static int | static int | ||||
tcp_ctloutput_get(struct inpcb *inp, struct sockopt *sopt) | tcp_ctloutput_get(struct inpcb *inp, struct sockopt *sopt) | ||||
{ | { | ||||
struct socket *so = inp->inp_socket; | |||||
struct tcpcb *tp = intotcpcb(inp); | |||||
int error = 0; | int error = 0; | ||||
struct tcpcb *tp; | |||||
MPASS(sopt->sopt_dir == SOPT_GET); | MPASS(sopt->sopt_dir == SOPT_GET); | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
KASSERT((inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) == 0, | |||||
("inp_flags == %x", inp->inp_flags)); | |||||
KASSERT(so != NULL, ("inp_socket == NULL")); | |||||
if (sopt->sopt_level != IPPROTO_TCP) { | if (sopt->sopt_level != IPPROTO_TCP) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (inp->inp_vflag & INP_IPV6PROTO) | if (inp->inp_vflag & INP_IPV6PROTO) | ||||
error = ip6_ctloutput(inp->inp_socket, sopt); | error = ip6_ctloutput(so, sopt); | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#if defined(INET6) && defined(INET) | #if defined(INET6) && defined(INET) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
error = ip_ctloutput(inp->inp_socket, sopt); | error = ip_ctloutput(so, sopt); | ||||
#endif | #endif | ||||
return (error); | return (error); | ||||
} | } | ||||
tp = intotcpcb(inp); | |||||
if (((sopt->sopt_name == TCP_FUNCTION_BLK) || | if (((sopt->sopt_name == TCP_FUNCTION_BLK) || | ||||
(sopt->sopt_name == TCP_FUNCTION_ALIAS))) { | (sopt->sopt_name == TCP_FUNCTION_ALIAS))) { | ||||
struct tcp_function_set fsn; | struct tcp_function_set fsn; | ||||
if (sopt->sopt_name == TCP_FUNCTION_ALIAS) { | if (sopt->sopt_name == TCP_FUNCTION_ALIAS) { | ||||
memset(&fsn, 0, sizeof(fsn)); | memset(&fsn, 0, sizeof(fsn)); | ||||
find_tcp_function_alias(tp->t_fb, &fsn); | find_tcp_function_alias(tp->t_fb, &fsn); | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | if (error == 0) { | ||||
free(ptr, M_CC_MEM); | free(ptr, M_CC_MEM); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
tcp_default_ctloutput(struct inpcb *inp, struct sockopt *sopt) | tcp_default_ctloutput(struct inpcb *inp, struct sockopt *sopt) | ||||
{ | { | ||||
struct tcpcb *tp; | struct socket *so = inp->inp_socket; | ||||
struct tcpcb *tp = intotcpcb(inp); | |||||
int error, opt, optval; | int error, opt, optval; | ||||
u_int ui; | u_int ui; | ||||
struct tcp_info ti; | struct tcp_info ti; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
struct tls_enable tls; | struct tls_enable tls; | ||||
#endif | #endif | ||||
char *pbuf, buf[TCP_LOG_ID_LEN]; | char *pbuf, buf[TCP_LOG_ID_LEN]; | ||||
#ifdef STATS | #ifdef STATS | ||||
struct statsblob *sbp; | struct statsblob *sbp; | ||||
#endif | #endif | ||||
size_t len; | size_t len; | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
KASSERT((inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) == 0, | |||||
("inp_flags == %x", inp->inp_flags)); | |||||
KASSERT(so != NULL, ("inp_socket == NULL")); | |||||
tp = intotcpcb(inp); | |||||
switch (sopt->sopt_level) { | switch (sopt->sopt_level) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case IPPROTO_IPV6: | case IPPROTO_IPV6: | ||||
MPASS(inp->inp_vflag & INP_IPV6PROTO); | MPASS(inp->inp_vflag & INP_IPV6PROTO); | ||||
switch (sopt->sopt_name) { | switch (sopt->sopt_name) { | ||||
case IPV6_USE_MIN_MTU: | case IPV6_USE_MIN_MTU: | ||||
tcp6_use_min_mtu(tp); | tcp6_use_min_mtu(tp); | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | case TCP_REUSPORT_LB_NUMA: | ||||
break; | break; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
case TCP_TXTLS_ENABLE: | case TCP_TXTLS_ENABLE: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
error = copyin_tls_enable(sopt, &tls); | error = copyin_tls_enable(sopt, &tls); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
error = ktls_enable_tx(inp->inp_socket, &tls); | error = ktls_enable_tx(so, &tls); | ||||
break; | break; | ||||
case TCP_TXTLS_MODE: | case TCP_TXTLS_MODE: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
error = sooptcopyin(sopt, &ui, sizeof(ui), sizeof(ui)); | error = sooptcopyin(sopt, &ui, sizeof(ui), sizeof(ui)); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
INP_WLOCK_RECHECK(inp); | INP_WLOCK_RECHECK(inp); | ||||
error = ktls_set_tx_mode(inp->inp_socket, ui); | error = ktls_set_tx_mode(so, ui); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
break; | break; | ||||
case TCP_RXTLS_ENABLE: | case TCP_RXTLS_ENABLE: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
error = sooptcopyin(sopt, &tls, sizeof(tls), | error = sooptcopyin(sopt, &tls, sizeof(tls), | ||||
sizeof(tls)); | sizeof(tls)); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
error = ktls_enable_rx(inp->inp_socket, &tls); | error = ktls_enable_rx(so, &tls); | ||||
break; | break; | ||||
#endif | #endif | ||||
case TCP_KEEPIDLE: | case TCP_KEEPIDLE: | ||||
case TCP_KEEPINTVL: | case TCP_KEEPINTVL: | ||||
case TCP_KEEPINIT: | case TCP_KEEPINIT: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
error = sooptcopyin(sopt, &ui, sizeof(ui), sizeof(ui)); | error = sooptcopyin(sopt, &ui, sizeof(ui), sizeof(ui)); | ||||
▲ Show 20 Lines • Show All 328 Lines • ▼ Show 20 Lines | #ifdef TCP_BLACKBOX | ||||
case TCP_LOGDUMP: | case TCP_LOGDUMP: | ||||
case TCP_LOGDUMPID: | case TCP_LOGDUMPID: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
case TCP_TXTLS_MODE: | case TCP_TXTLS_MODE: | ||||
error = ktls_get_tx_mode(inp->inp_socket, &optval); | error = ktls_get_tx_mode(so, &optval); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
if (error == 0) | if (error == 0) | ||||
error = sooptcopyout(sopt, &optval, | error = sooptcopyout(sopt, &optval, | ||||
sizeof(optval)); | sizeof(optval)); | ||||
break; | break; | ||||
case TCP_RXTLS_MODE: | case TCP_RXTLS_MODE: | ||||
error = ktls_get_rx_mode(inp->inp_socket, &optval); | error = ktls_get_rx_mode(so, &optval); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
if (error == 0) | if (error == 0) | ||||
error = sooptcopyout(sopt, &optval, | error = sooptcopyout(sopt, &optval, | ||||
sizeof(optval)); | sizeof(optval)); | ||||
break; | break; | ||||
#endif | #endif | ||||
case TCP_LRD: | case TCP_LRD: | ||||
optval = tp->t_flags & TF_LRD; | optval = tp->t_flags & TF_LRD; | ||||
▲ Show 20 Lines • Show All 443 Lines • Show Last 20 Lines |