summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_pcb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/in_pcb.c')
-rw-r--r--sys/netinet/in_pcb.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 9dac3ec..4fa5c6f 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -728,6 +728,34 @@ in_pcbfree(struct inpcb *inp)
uma_zfree(ipi->ipi_zone, inp);
}
+/*
+ * TCP needs to maintain its inpcb structure after the TCP connection has
+ * been torn down. However, it must be disconnected from the inpcb hashes as
+ * it must not prevent binding of future connections to the same port/ip
+ * combination by other inpcbs.
+ */
+void
+in_pcbdrop(struct inpcb *inp)
+{
+ struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
+
+ INP_INFO_WLOCK_ASSERT(pcbinfo);
+ INP_LOCK_ASSERT(inp);
+
+ inp->inp_vflag |= INP_DROPPED;
+ if (inp->inp_lport) {
+ struct inpcbport *phd = inp->inp_phd;
+
+ LIST_REMOVE(inp, inp_hash);
+ LIST_REMOVE(inp, inp_portlist);
+ if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
+ LIST_REMOVE(phd, phd_hash);
+ free(phd, M_PCB);
+ }
+ inp->inp_lport = 0;
+ }
+}
+
struct sockaddr *
in_sockaddr(in_port_t port, struct in_addr *addr_p)
{
OpenPOWER on IntegriCloud