summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_pcb.c
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2003-02-19 22:32:43 +0000
committerjlemon <jlemon@FreeBSD.org>2003-02-19 22:32:43 +0000
commita8bc02dcb257f24a8246bb1c31abe58bf12ebd04 (patch)
tree6317b858b0555a797efb2e5b5bd4c2eebbdc0d10 /sys/netinet/in_pcb.c
parent79a1ebfa6f53d733dc4775c2031ff3d16e53b75c (diff)
downloadFreeBSD-src-a8bc02dcb257f24a8246bb1c31abe58bf12ebd04.zip
FreeBSD-src-a8bc02dcb257f24a8246bb1c31abe58bf12ebd04.tar.gz
Add a TCP TIMEWAIT state which uses less space than a fullblown TCP
control block. Allow the socket and tcpcb structures to be freed earlier than inpcb. Update code to understand an inp w/o a socket. Reviewed by: hsu, silby, jayanth Sponsored by: DARPA, NAI Labs
Diffstat (limited to 'sys/netinet/in_pcb.c')
-rw-r--r--sys/netinet/in_pcb.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 7f83917..46f824d 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -62,6 +62,7 @@
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
+#include <netinet/tcp_var.h>
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
@@ -169,8 +170,11 @@ in_pcballoc(so, pcbinfo, td)
}
#endif /*IPSEC*/
#if defined(INET6)
- if (INP_SOCKAF(so) == AF_INET6 && ip6_v6only)
- inp->inp_flags |= IN6P_IPV6_V6ONLY;
+ if (INP_SOCKAF(so) == AF_INET6) {
+ inp->inp_vflag |= INP_IPV6PROTO;
+ if (ip6_v6only)
+ inp->inp_flags |= IN6P_IPV6_V6ONLY;
+ }
#endif
LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);
pcbinfo->ipi_count++;
@@ -294,6 +298,17 @@ in_pcbbind_setup(inp, nam, laddrp, lportp, td)
t = in_pcblookup_local(inp->inp_pcbinfo,
sin->sin_addr, lport,
prison ? 0 : INPLOOKUP_WILDCARD);
+ /*
+ * XXX
+ * This entire block sorely needs a rewrite.
+ */
+ if (t && (t->inp_vflag & INP_TIMEWAIT)) {
+ if ((ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
+ ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
+ (intotw(t)->tw_so_options & SO_REUSEPORT) == 0) &&
+ (so->so_cred->cr_uid != intotw(t)->tw_cred->cr_uid))
+ return (EADDRINUSE);
+ } else
if (t &&
(ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
@@ -317,6 +332,10 @@ in_pcbbind_setup(inp, nam, laddrp, lportp, td)
return (EADDRNOTAVAIL);
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, prison ? 0 : wild);
+ if (t && (t->inp_vflag & INP_TIMEWAIT)) {
+ if ((reuseport & intotw(t)->tw_so_options) == 0)
+ return (EADDRINUSE);
+ } else
if (t &&
(reuseport & t->inp_socket->so_options) == 0) {
#if defined(INET6)
@@ -640,8 +659,10 @@ in_pcbdetach(inp)
#endif /*IPSEC*/
inp->inp_gencnt = ++ipi->ipi_gencnt;
in_pcbremlists(inp);
- so->so_pcb = 0;
- sotryfree(so);
+ if (so) {
+ so->so_pcb = 0;
+ sotryfree(so);
+ }
if (inp->inp_options)
(void)m_free(inp->inp_options);
if (inp->inp_route.ro_rt)
OpenPOWER on IntegriCloud