summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/in6_pcb.c
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2003-06-17 00:31:30 +0000
committercognet <cognet@FreeBSD.org>2003-06-17 00:31:30 +0000
commit74ee61c2bbc5044cd0c47d4e33abab739855286f (patch)
treef0827383c4c0a21900e79e2d828010faf18222c6 /sys/netinet6/in6_pcb.c
parent91eb81dd0ca9affe6de206f1624486f3dd7f458e (diff)
downloadFreeBSD-src-74ee61c2bbc5044cd0c47d4e33abab739855286f.zip
FreeBSD-src-74ee61c2bbc5044cd0c47d4e33abab739855286f.tar.gz
Do not attempt to access to inp_socket fields if the socket is in the TIME_WAIT
state, as inp_socket will then be NULL. This fixes a panic that occurs when one tries to bind a port that was previously binded with remaining TIME_WAIT sockets.
Diffstat (limited to 'sys/netinet6/in6_pcb.c')
-rw-r--r--sys/netinet6/in6_pcb.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index b328d32..84ea6a9 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -198,12 +198,18 @@ in6_pcbbind(inp, nam, td)
t = in6_pcblookup_local(pcbinfo,
&sin6->sin6_addr, lport,
INPLOOKUP_WILDCARD);
- if (t &&
+ if (t && (t->inp_vflag & INP_TIMEWAIT)) {
+ if ((!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+ !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
+ !(intotw(t)->tw_so_options & SO_REUSEPORT))
+ && so->so_cred->cr_uid !=
+ intotw(t)->tw_cred->cr_uid)
+ return (EADDRINUSE);
+ } else if (t &&
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
- !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
- (t->inp_socket->so_options &
- SO_REUSEPORT) == 0) &&
- (so->so_cred->cr_uid !=
+ !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
+ (t->inp_socket->so_options & SO_REUSEPORT)
+ == 0) && (so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid))
return (EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
@@ -214,7 +220,17 @@ in6_pcbbind(inp, nam, td)
t = in_pcblookup_local(pcbinfo,
sin.sin_addr, lport,
INPLOOKUP_WILDCARD);
- if (t &&
+ if (t && (t->inp_vflag & INP_TIMEWAIT)) {
+ if (so->so_cred->cr_uid !=
+ intotw(t)->tw_cred->cr_uid &&
+ (ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY ||
+ ((inp->inp_vflag &
+ INP_IPV6PROTO) ==
+ (t->inp_vflag &
+ INP_IPV6PROTO))))
+ return (EADDRINUSE);
+ } else if (t &&
(so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid) &&
(ntohl(t->inp_laddr.s_addr) !=
@@ -226,7 +242,9 @@ in6_pcbbind(inp, nam, td)
}
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
lport, wild);
- if (t && (reuseport & t->inp_socket->so_options) == 0)
+ if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ?
+ intotw(t)->tw_so_options :
+ t->inp_socket->so_options)) == 0)
return(EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
@@ -235,12 +253,19 @@ in6_pcbbind(inp, nam, td)
in6_sin6_2_sin(&sin, sin6);
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
lport, wild);
- if (t &&
- (reuseport & t->inp_socket->so_options)
- == 0 &&
- (ntohl(t->inp_laddr.s_addr)
- != INADDR_ANY ||
- INP_SOCKAF(so) ==
+ if (t && t->inp_vflag & INP_TIMEWAIT) {
+ if ((reuseport &
+ intotw(t)->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 & t->inp_socket->so_options)
+ == 0 && (ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY || INP_SOCKAF(so) ==
INP_SOCKAF(t->inp_socket)))
return (EADDRINUSE);
}
OpenPOWER on IntegriCloud