Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_usrreq.c
Show First 20 Lines • Show All 372 Lines • ▼ Show 20 Lines | |||||
#ifdef INET | #ifdef INET | ||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { | if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { | ||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr)) | if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr)) | ||||
inp->inp_vflag |= INP_IPV4; | inp->inp_vflag |= INP_IPV4; | ||||
else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { | else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { | ||||
struct sockaddr_in sin; | struct sockaddr_in sin; | ||||
in6_sin6_2_sin(&sin, sin6p); | in6_sin6_2_sin(&sin, sin6p); | ||||
if (IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) { | |||||
error = EAFNOSUPPORT; | |||||
INP_HASH_WUNLOCK(&V_tcbinfo); | |||||
goto out; | |||||
} | |||||
inp->inp_vflag |= INP_IPV4; | inp->inp_vflag |= INP_IPV4; | ||||
inp->inp_vflag &= ~INP_IPV6; | inp->inp_vflag &= ~INP_IPV6; | ||||
error = in_pcbbind(inp, (struct sockaddr *)&sin, | error = in_pcbbind(inp, (struct sockaddr *)&sin, | ||||
td->td_ucred); | td->td_ucred); | ||||
INP_HASH_WUNLOCK(&V_tcbinfo); | INP_HASH_WUNLOCK(&V_tcbinfo); | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 213 Lines • ▼ Show 20 Lines | if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { | ||||
goto out; | goto out; | ||||
} | } | ||||
if ((inp->inp_vflag & INP_IPV4) == 0) { | if ((inp->inp_vflag & INP_IPV4) == 0) { | ||||
error = EAFNOSUPPORT; | error = EAFNOSUPPORT; | ||||
goto out; | goto out; | ||||
} | } | ||||
in6_sin6_2_sin(&sin, sin6p); | in6_sin6_2_sin(&sin, sin6p); | ||||
if (IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) { | |||||
error = EAFNOSUPPORT; | |||||
goto out; | |||||
} | |||||
inp->inp_vflag |= INP_IPV4; | inp->inp_vflag |= INP_IPV4; | ||||
inp->inp_vflag &= ~INP_IPV6; | inp->inp_vflag &= ~INP_IPV6; | ||||
if ((error = prison_remote_ip4(td->td_ucred, | if ((error = prison_remote_ip4(td->td_ucred, | ||||
&sin.sin_addr)) != 0) | &sin.sin_addr)) != 0) | ||||
goto out; | goto out; | ||||
if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0) | if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0) | ||||
goto out; | goto out; | ||||
#ifdef TCP_OFFLOAD | #ifdef TCP_OFFLOAD | ||||
▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
tcp_usr_send(struct socket *so, int flags, struct mbuf *m, | tcp_usr_send(struct socket *so, int flags, struct mbuf *m, | ||||
struct sockaddr *nam, struct mbuf *control, struct thread *td) | struct sockaddr *nam, struct mbuf *control, struct thread *td) | ||||
{ | { | ||||
int error = 0; | int error = 0; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct tcpcb *tp = NULL; | struct tcpcb *tp = NULL; | ||||
struct epoch_tracker net_et; | struct epoch_tracker net_et; | ||||
#ifdef INET | |||||
struct sockaddr_in sin, *sinp; | |||||
#endif | |||||
#ifdef INET6 | #ifdef INET6 | ||||
int isipv6; | int isipv6; | ||||
#endif | #endif | ||||
TCPDEBUG0; | TCPDEBUG0; | ||||
/* | /* | ||||
* We require the pcbinfo lock if we will close the socket as part of | * We require the pcbinfo lock if we will close the socket as part of | ||||
* this call. | * this call. | ||||
Show All 10 Lines | if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { | ||||
* In case of PRUS_NOTREADY, tcp_usr_ready() is responsible | * In case of PRUS_NOTREADY, tcp_usr_ready() is responsible | ||||
* for freeing memory. | * for freeing memory. | ||||
*/ | */ | ||||
if (m && (flags & PRUS_NOTREADY) == 0) | if (m && (flags & PRUS_NOTREADY) == 0) | ||||
m_freem(m); | m_freem(m); | ||||
error = ECONNRESET; | error = ECONNRESET; | ||||
goto out; | goto out; | ||||
} | } | ||||
#ifdef INET6 | |||||
isipv6 = nam && nam->sa_family == AF_INET6; | |||||
#endif /* INET6 */ | |||||
tp = intotcpcb(inp); | tp = intotcpcb(inp); | ||||
TCPDEBUG1(); | TCPDEBUG1(); | ||||
if (nam != NULL && tp->t_state < TCPS_SYN_SENT) { | |||||
switch (nam->sa_family) { | |||||
#ifdef INET | |||||
case AF_INET: | |||||
sinp = (struct sockaddr_in *)nam; | |||||
if (sinp->sin_len != sizeof(struct sockaddr_in)) { | |||||
if (m) | |||||
m_freem(m); | |||||
error = EINVAL; | |||||
goto out; | |||||
} | |||||
if ((inp->inp_vflag & INP_IPV6) != 0) { | |||||
if (m) | |||||
m_freem(m); | |||||
error = EAFNOSUPPORT; | |||||
goto out; | |||||
} | |||||
if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { | |||||
if (m) | |||||
m_freem(m); | |||||
error = EAFNOSUPPORT; | |||||
goto out; | |||||
} | |||||
if ((error = prison_remote_ip4(td->td_ucred, | |||||
&sinp->sin_addr))) { | |||||
if (m) | |||||
m_freem(m); | |||||
goto out; | |||||
} | |||||
#ifdef INET6 | |||||
isipv6 = 0; | |||||
#endif | |||||
break; | |||||
#endif /* INET */ | |||||
#ifdef INET6 | |||||
case AF_INET6: | |||||
{ | |||||
struct sockaddr_in6 *sin6p; | |||||
sin6p = (struct sockaddr_in6 *)nam; | |||||
if (sin6p->sin6_len != sizeof(struct sockaddr_in6)) { | |||||
if (m) | |||||
m_freem(m); | |||||
error = EINVAL; | |||||
goto out; | |||||
} | |||||
if (IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { | |||||
if (m) | |||||
m_freem(m); | |||||
error = EAFNOSUPPORT; | |||||
goto out; | |||||
} | |||||
if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { | |||||
#ifdef INET | |||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { | |||||
error = EINVAL; | |||||
if (m) | |||||
m_freem(m); | |||||
goto out; | |||||
} | |||||
if ((inp->inp_vflag & INP_IPV4) == 0) { | |||||
error = EAFNOSUPPORT; | |||||
if (m) | |||||
m_freem(m); | |||||
goto out; | |||||
} | |||||
inp->inp_vflag &= ~INP_IPV6; | |||||
sinp = &sin; | |||||
in6_sin6_2_sin(sinp, sin6p); | |||||
if (IN_MULTICAST( | |||||
ntohl(sinp->sin_addr.s_addr))) { | |||||
error = EAFNOSUPPORT; | |||||
if (m) | |||||
m_freem(m); | |||||
goto out; | |||||
} | |||||
if ((error = prison_remote_ip4(td->td_ucred, | |||||
&sinp->sin_addr))) { | |||||
if (m) | |||||
m_freem(m); | |||||
goto out; | |||||
} | |||||
isipv6 = 0; | |||||
#else /* INET */ | |||||
error = EAFNOSUPPORT; | |||||
if (m) | |||||
m_freem(m); | |||||
goto out; | |||||
#endif /* INET */ | |||||
} else { | |||||
if ((inp->inp_vflag & INP_IPV6) == 0) { | |||||
if (m) | |||||
m_freem(m); | |||||
error = EAFNOSUPPORT; | |||||
goto out; | |||||
} | |||||
inp->inp_vflag &= ~INP_IPV4; | |||||
inp->inp_inc.inc_flags |= INC_ISIPV6; | |||||
if ((error = prison_remote_ip6(td->td_ucred, | |||||
&sin6p->sin6_addr))) { | |||||
if (m) | |||||
m_freem(m); | |||||
goto out; | |||||
} | |||||
isipv6 = 1; | |||||
} | |||||
break; | |||||
} | |||||
#endif /* INET6 */ | |||||
default: | |||||
if (m) | |||||
m_freem(m); | |||||
error = EAFNOSUPPORT; | |||||
goto out; | |||||
} | |||||
} | |||||
if (control) { | if (control) { | ||||
/* TCP doesn't do control messages (rights, creds, etc) */ | /* TCP doesn't do control messages (rights, creds, etc) */ | ||||
if (control->m_len) { | if (control->m_len) { | ||||
m_freem(control); | m_freem(control); | ||||
if (m) | if (m) | ||||
m_freem(m); | m_freem(m); | ||||
error = EINVAL; | error = EINVAL; | ||||
goto out; | goto out; | ||||
Show All 11 Lines | |||||
#ifdef INET6 | #ifdef INET6 | ||||
if (isipv6) | if (isipv6) | ||||
error = tcp6_connect(tp, nam, td); | error = tcp6_connect(tp, nam, td); | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#if defined(INET6) && defined(INET) | #if defined(INET6) && defined(INET) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
error = tcp_connect(tp, nam, td); | error = tcp_connect(tp, | ||||
(struct sockaddr *)sinp, td); | |||||
#endif | #endif | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
if (IS_FASTOPEN(tp->t_flags)) | if (IS_FASTOPEN(tp->t_flags)) | ||||
tcp_fastopen_connect(tp); | tcp_fastopen_connect(tp); | ||||
else { | else { | ||||
tp->snd_wnd = TTCP_CLIENT_SND_WND; | tp->snd_wnd = TTCP_CLIENT_SND_WND; | ||||
tcp_mss(tp, -1); | tcp_mss(tp, -1); | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
#ifdef INET6 | #ifdef INET6 | ||||
if (isipv6) | if (isipv6) | ||||
error = tcp6_connect(tp, nam, td); | error = tcp6_connect(tp, nam, td); | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#if defined(INET6) && defined(INET) | #if defined(INET6) && defined(INET) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
error = tcp_connect(tp, nam, td); | error = tcp_connect(tp, | ||||
(struct sockaddr *)sinp, td); | |||||
#endif | #endif | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
tp->snd_wnd = TTCP_CLIENT_SND_WND; | tp->snd_wnd = TTCP_CLIENT_SND_WND; | ||||
tcp_mss(tp, -1); | tcp_mss(tp, -1); | ||||
} | } | ||||
tp->snd_up = tp->snd_una + sbavail(&so->so_snd); | tp->snd_up = tp->snd_una + sbavail(&so->so_snd); | ||||
if (!(flags & PRUS_NOTREADY)) { | if (!(flags & PRUS_NOTREADY)) { | ||||
▲ Show 20 Lines • Show All 1,477 Lines • Show Last 20 Lines |