Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6_pcb.c
Show First 20 Lines • Show All 236 Lines • ▼ Show 20 Lines | if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { | ||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) { | (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) { | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
return (EADDRNOTAVAIL); | return (EADDRNOTAVAIL); | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
} | } | ||||
if (lport) { | if (lport) { | ||||
struct inpcb *t; | struct inpcb *t; | ||||
struct tcptw *tw; | |||||
/* GROSS */ | /* GROSS */ | ||||
if (ntohs(lport) <= V_ipport_reservedhigh && | if (ntohs(lport) <= V_ipport_reservedhigh && | ||||
ntohs(lport) >= V_ipport_reservedlow && | ntohs(lport) >= V_ipport_reservedlow && | ||||
priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT)) | priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT)) | ||||
return (EACCES); | return (EACCES); | ||||
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && | if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && | ||||
priv_check_cred(inp->inp_cred, PRIV_NETINET_REUSEPORT) != 0) { | priv_check_cred(inp->inp_cred, PRIV_NETINET_REUSEPORT) != 0) { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | #ifdef INET | ||||
if (t && (! in_pcbbind_check_bindmulti(inp, t))) | if (t && (! in_pcbbind_check_bindmulti(inp, t))) | ||||
return (EADDRINUSE); | return (EADDRINUSE); | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, | t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, | ||||
lport, lookupflags, cred); | lport, lookupflags, cred); | ||||
if (t && (t->inp_flags & INP_TIMEWAIT)) { | if (t && (reuseport & inp_so_options(t)) == 0 && | ||||
/* | |||||
* XXXRW: If an incpb has had its timewait | |||||
* state recycled, we treat the address as | |||||
* being in use (for now). This is better | |||||
* than a panic, but not desirable. | |||||
*/ | |||||
tw = intotw(t); | |||||
if (tw == NULL || | |||||
((reuseport & tw->tw_so_options) == 0 && | |||||
(reuseport_lb & tw->tw_so_options) == 0)) | |||||
return (EADDRINUSE); | |||||
} else if (t && (reuseport & inp_so_options(t)) == 0 && | |||||
(reuseport_lb & inp_so_options(t)) == 0) { | (reuseport_lb & inp_so_options(t)) == 0) { | ||||
return (EADDRINUSE); | return (EADDRINUSE); | ||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && | if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && | ||||
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | ||||
struct sockaddr_in sin; | struct sockaddr_in sin; | ||||
in6_sin6_2_sin(&sin, sin6); | in6_sin6_2_sin(&sin, sin6); | ||||
t = in_pcblookup_local(pcbinfo, sin.sin_addr, | t = in_pcblookup_local(pcbinfo, sin.sin_addr, | ||||
lport, lookupflags, cred); | lport, lookupflags, cred); | ||||
if (t && t->inp_flags & INP_TIMEWAIT) { | if (t && | ||||
tw = intotw(t); | |||||
if (tw == NULL) | |||||
return (EADDRINUSE); | |||||
if ((reuseport & tw->tw_so_options) == 0 | |||||
&& (reuseport_lb & tw->tw_so_options) == 0 | |||||
&& (ntohl(t->inp_laddr.s_addr) != | |||||
INADDR_ANY || ((inp->inp_vflag & | |||||
INP_IPV6PROTO) == | |||||
(t->inp_vflag & INP_IPV6PROTO)))) | |||||
return (EADDRINUSE); | |||||
} else if (t && | |||||
(reuseport & inp_so_options(t)) == 0 && | (reuseport & inp_so_options(t)) == 0 && | ||||
(reuseport_lb & inp_so_options(t)) == 0 && | (reuseport_lb & inp_so_options(t)) == 0 && | ||||
(ntohl(t->inp_laddr.s_addr) != INADDR_ANY || | (ntohl(t->inp_laddr.s_addr) != INADDR_ANY || | ||||
(t->inp_vflag & INP_IPV6PROTO) != 0)) { | (t->inp_vflag & INP_IPV6PROTO) != 0)) { | ||||
return (EADDRINUSE); | return (EADDRINUSE); | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 817 Lines • Show Last 20 Lines |