summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/uipc_socket.c11
-rw-r--r--sys/kern/uipc_usrreq.c19
-rw-r--r--sys/net/raw_usrreq.c12
-rw-r--r--sys/net/rtsock.c8
-rw-r--r--sys/netatalk/ddp_usrreq.c23
-rw-r--r--sys/netatm/atm_aal5.c15
-rw-r--r--sys/netatm/atm_usrreq.c1
-rw-r--r--sys/netgraph/bluetooth/include/ng_btsocket_hci_raw.h1
-rw-r--r--sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h2
-rw-r--r--sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h1
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket.c4
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c6
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c9
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c10
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c11
-rw-r--r--sys/netgraph/ng_socket.c4
-rw-r--r--sys/netinet/raw_ip.c49
-rw-r--r--sys/netinet/tcp_subr.c49
-rw-r--r--sys/netinet/tcp_timewait.c49
-rw-r--r--sys/netinet/tcp_usrreq.c147
-rw-r--r--sys/netinet/udp_usrreq.c32
-rw-r--r--sys/netinet6/raw_ip6.c24
-rw-r--r--sys/netinet6/udp6_usrreq.c50
-rw-r--r--sys/netipsec/keysock.c12
-rw-r--r--sys/netipx/ipx_usrreq.c21
-rw-r--r--sys/netipx/spx_usrreq.c37
-rw-r--r--sys/netkey/keysock.c12
-rw-r--r--sys/netnatm/natm.c8
28 files changed, 438 insertions, 189 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 4d5936a..6e203d1 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -589,6 +589,8 @@ sofree(so)
sorflush(so);
knlist_destroy(&so->so_rcv.sb_sel.si_note);
knlist_destroy(&so->so_snd.sb_sel.si_note);
+ if (so->so_proto->pr_usrreqs->pru_detach != NULL)
+ (*so->so_proto->pr_usrreqs->pru_detach)(so);
sodealloc(so);
}
@@ -653,8 +655,8 @@ soclose(so)
}
drop:
- if (*so->so_proto->pr_usrreqs->pru_detach != NULL)
- (*so->so_proto->pr_usrreqs->pru_detach)(so);
+ if (so->so_proto->pr_usrreqs->pru_close != NULL)
+ (*so->so_proto->pr_usrreqs->pru_close)(so);
ACCEPT_LOCK();
SOCK_LOCK(so);
KASSERT((so->so_state & SS_NOFDREF) == 0, ("soclose: NOFDREF"));
@@ -676,9 +678,6 @@ drop:
* with any socket locks held. Protocols do call it while holding their own
* recursible protocol mutexes, but this is something that should be subject
* to review in the future.
- *
- * XXXRW: Why do we maintain a distinction between pru_abort() and
- * pru_detach()?
*/
void
soabort(so)
@@ -697,7 +696,7 @@ soabort(so)
KASSERT((so->so_state & SQ_COMP) == 0, ("soabort: SQ_COMP"));
KASSERT((so->so_state & SQ_INCOMP) == 0, ("soabort: SQ_INCOMP"));
- if (*so->so_proto->pr_usrreqs->pru_abort != NULL)
+ if (so->so_proto->pr_usrreqs->pru_abort != NULL)
(*so->so_proto->pr_usrreqs->pru_abort)(so);
ACCEPT_LOCK();
SOCK_LOCK(so);
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 2c72223..02b641a 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -149,8 +149,7 @@ uipc_abort(struct socket *so)
KASSERT(unp != NULL, ("uipc_abort: unp == NULL"));
UNP_LOCK();
unp_drop(unp, ECONNABORTED);
- unp_detach(unp);
- UNP_UNLOCK_ASSERT();
+ UNP_UNLOCK();
}
static int
@@ -210,6 +209,21 @@ uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
return (error);
}
+/*
+ * XXXRW: Should also unbind?
+ */
+static void
+uipc_close(struct socket *so)
+{
+ struct unpcb *unp;
+
+ unp = sotounpcb(so);
+ KASSERT(unp != NULL, ("uipc_close: unp == NULL"));
+ UNP_LOCK();
+ unp_disconnect(unp);
+ UNP_UNLOCK();
+}
+
int
uipc_connect2(struct socket *so1, struct socket *so2)
{
@@ -565,6 +579,7 @@ struct pr_usrreqs uipc_usrreqs = {
.pru_sosend = sosend,
.pru_soreceive = soreceive,
.pru_sopoll = sopoll,
+ .pru_close = uipc_close,
};
int
diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c
index 4f2f006..b584860 100644
--- a/sys/net/raw_usrreq.c
+++ b/sys/net/raw_usrreq.c
@@ -146,7 +146,16 @@ raw_uabort(struct socket *so)
KASSERT(rp != NULL, ("raw_uabort: rp == NULL"));
raw_disconnect(rp);
soisdisconnected(so);
- raw_detach(rp);
+}
+
+static void
+raw_uclose(struct socket *so)
+{
+ struct rawcb *rp = sotorawcb(so);
+
+ KASSERT(rp != NULL, ("raw_uabort: rp == NULL"));
+ raw_disconnect(rp);
+ soisdisconnected(so);
}
/* pru_accept is EOPNOTSUPP */
@@ -295,4 +304,5 @@ struct pr_usrreqs raw_usrreqs = {
.pru_send = raw_usend,
.pru_shutdown = raw_ushutdown,
.pru_sockaddr = raw_usockaddr,
+ .pru_close = raw_uclose,
};
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 76913a5..8ab39e4 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -144,6 +144,13 @@ rts_abort(struct socket *so)
raw_usrreqs.pru_abort(so);
}
+static void
+rts_close(struct socket *so)
+{
+
+ raw_usrreqs.pru_close(so);
+}
+
/* pru_accept is EOPNOTSUPP */
static int
@@ -292,6 +299,7 @@ static struct pr_usrreqs route_usrreqs = {
.pru_send = rts_send,
.pru_shutdown = rts_shutdown,
.pru_sockaddr = rts_sockaddr,
+ .pru_close = rts_close,
};
/*ARGSUSED*/
diff --git a/sys/netatalk/ddp_usrreq.c b/sys/netatalk/ddp_usrreq.c
index 1421c8d..1876856 100644
--- a/sys/netatalk/ddp_usrreq.c
+++ b/sys/netatalk/ddp_usrreq.c
@@ -202,6 +202,10 @@ out:
return (error);
}
+/*
+ * XXXRW: This is never called because we only invoke abort on stream
+ * protocols.
+ */
static void
ddp_abort(struct socket *so)
{
@@ -210,10 +214,22 @@ ddp_abort(struct socket *so)
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_abort: ddp == NULL"));
- DDP_LIST_XLOCK();
DDP_LOCK(ddp);
- at_pcbdetach(so, ddp);
- DDP_LIST_XUNLOCK();
+ at_pcbdisconnect(ddp);
+ DDP_UNLOCK(ddp);
+}
+
+static void
+ddp_close(struct socket *so)
+{
+ struct ddpcb *ddp;
+
+ ddp = sotoddpcb(so);
+ KASSERT(ddp != NULL, ("ddp_close: ddp == NULL"));
+
+ DDP_LOCK(ddp);
+ at_pcbdisconnect(ddp);
+ DDP_UNLOCK(ddp);
}
void
@@ -276,4 +292,5 @@ struct pr_usrreqs ddp_usrreqs = {
.pru_send = ddp_send,
.pru_shutdown = ddp_shutdown,
.pru_sockaddr = at_setsockaddr,
+ .pru_close = ddp_close,
};
diff --git a/sys/netatm/atm_aal5.c b/sys/netatm/atm_aal5.c
index f21ad798..a0534b7 100644
--- a/sys/netatm/atm_aal5.c
+++ b/sys/netatm/atm_aal5.c
@@ -88,6 +88,7 @@ static int atm_aal5_incoming(void *, Atm_connection *,
Atm_attributes *, void **);
static void atm_aal5_cpcs_data(void *, KBuffer *);
static caddr_t atm_aal5_getname(void *);
+static void atm_aal5_close(struct socket *);
/*
@@ -108,6 +109,7 @@ struct pr_usrreqs atm_aal5_usrreqs = {
.pru_sense = atm_aal5_sense,
.pru_shutdown = atm_aal5_shutdown,
.pru_sockaddr = atm_aal5_sockaddr,
+ .pru_close = atm_aal5_close,
};
/*
@@ -565,8 +567,19 @@ atm_aal5_abort(so)
{
ATM_INTRO_NOERR("abort");
+ (void)atm_sock_disconnect(so);
so->so_error = ECONNABORTED;
- atm_sock_detach(so);
+
+ ATM_OUTRO_NOERR();
+}
+
+static void
+atm_aal5_close(so)
+ struct socket *so;
+{
+ ATM_INTRO_NOERR("close");
+
+ (void)atm_sock_disconnect(so);
ATM_OUTRO_NOERR();
}
diff --git a/sys/netatm/atm_usrreq.c b/sys/netatm/atm_usrreq.c
index 8facb95..ad14e84 100644
--- a/sys/netatm/atm_usrreq.c
+++ b/sys/netatm/atm_usrreq.c
@@ -79,6 +79,7 @@ struct pr_usrreqs atm_dgram_usrreqs = {
.pru_sosend = NULL,
.pru_soreceive = NULL,
.pru_sopoll = NULL,
+ .pru_close = atm_proto_notsupp5,
};
diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_hci_raw.h b/sys/netgraph/bluetooth/include/ng_btsocket_hci_raw.h
index 0f28377..b8e98b3 100644
--- a/sys/netgraph/bluetooth/include/ng_btsocket_hci_raw.h
+++ b/sys/netgraph/bluetooth/include/ng_btsocket_hci_raw.h
@@ -67,6 +67,7 @@ typedef struct ng_btsocket_hci_raw_pcb * ng_btsocket_hci_raw_pcb_p;
void ng_btsocket_hci_raw_init (void);
void ng_btsocket_hci_raw_abort (struct socket *);
+void ng_btsocket_hci_raw_close (struct socket *);
int ng_btsocket_hci_raw_attach (struct socket *, int, struct thread *);
int ng_btsocket_hci_raw_bind (struct socket *, struct sockaddr *,
struct thread *);
diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
index a8523ab..deea5b3 100644
--- a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
+++ b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
@@ -93,6 +93,7 @@ typedef struct ng_btsocket_l2cap_raw_pcb * ng_btsocket_l2cap_raw_pcb_p;
void ng_btsocket_l2cap_raw_init (void);
void ng_btsocket_l2cap_raw_abort (struct socket *);
+void ng_btsocket_l2cap_raw_close (struct socket *);
int ng_btsocket_l2cap_raw_attach (struct socket *, int, struct thread *);
int ng_btsocket_l2cap_raw_bind (struct socket *, struct sockaddr *,
struct thread *);
@@ -184,6 +185,7 @@ typedef struct ng_btsocket_l2cap_pcb * ng_btsocket_l2cap_pcb_p;
void ng_btsocket_l2cap_init (void);
void ng_btsocket_l2cap_abort (struct socket *);
+void ng_btsocket_l2cap_close (struct socket *);
int ng_btsocket_l2cap_accept (struct socket *, struct sockaddr **);
int ng_btsocket_l2cap_attach (struct socket *, int, struct thread *);
int ng_btsocket_l2cap_bind (struct socket *, struct sockaddr *,
diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
index 1939964..a1fdb27 100644
--- a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
+++ b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
@@ -315,6 +315,7 @@ typedef struct ng_btsocket_rfcomm_pcb * ng_btsocket_rfcomm_pcb_p;
void ng_btsocket_rfcomm_init (void);
void ng_btsocket_rfcomm_abort (struct socket *);
+void ng_btsocket_rfcomm_close (struct socket *);
int ng_btsocket_rfcomm_accept (struct socket *, struct sockaddr **);
int ng_btsocket_rfcomm_attach (struct socket *, int, struct thread *);
int ng_btsocket_rfcomm_bind (struct socket *, struct sockaddr *,
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket.c b/sys/netgraph/bluetooth/socket/ng_btsocket.c
index 16b9a20..3029ffd 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket.c
@@ -74,6 +74,7 @@ static struct pr_usrreqs ng_btsocket_hci_raw_usrreqs = {
.pru_send = ng_btsocket_hci_raw_send,
.pru_shutdown = NULL,
.pru_sockaddr = ng_btsocket_hci_raw_sockaddr,
+ .pru_close = ng_btsocket_hci_raw_close,
};
/*
@@ -92,6 +93,7 @@ static struct pr_usrreqs ng_btsocket_l2cap_raw_usrreqs = {
.pru_send = ng_btsocket_l2cap_raw_send,
.pru_shutdown = NULL,
.pru_sockaddr = ng_btsocket_l2cap_raw_sockaddr,
+ .pru_close = ng_btsocket_l2cap_raw_close,
};
/*
@@ -112,6 +114,7 @@ static struct pr_usrreqs ng_btsocket_l2cap_usrreqs = {
.pru_send = ng_btsocket_l2cap_send,
.pru_shutdown = NULL,
.pru_sockaddr = ng_btsocket_l2cap_sockaddr,
+ .pru_close = ng_btsocket_l2cap_close,
};
/*
@@ -132,6 +135,7 @@ static struct pr_usrreqs ng_btsocket_rfcomm_usrreqs = {
.pru_send = ng_btsocket_rfcomm_send,
.pru_shutdown = NULL,
.pru_sockaddr = ng_btsocket_rfcomm_sockaddr,
+ .pru_close = ng_btsocket_rfcomm_close,
};
/*
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
index 922184a..6513757 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
@@ -876,9 +876,13 @@ ng_btsocket_hci_raw_init(void)
void
ng_btsocket_hci_raw_abort(struct socket *so)
{
- ng_btsocket_hci_raw_detach(so);
} /* ng_btsocket_hci_raw_abort */
+void
+ng_btsocket_hci_raw_close(struct socket *so)
+{
+} /* ng_btsocket_hci_raw_close */
+
/*
* Create new raw HCI socket
*/
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
index 21d3766..f6d6fb2 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
@@ -1917,9 +1917,16 @@ ng_btsocket_l2cap_abort(struct socket *so)
{
so->so_error = ECONNABORTED;
- ng_btsocket_l2cap_detach(so);
+ (void)ng_btsocket_l2cap_disconnect(so);
} /* ng_btsocket_l2cap_abort */
+void
+ng_btsocket_l2cap_close(struct socket *so)
+{
+
+ (void)ng_btsocket_l2cap_disconnect(so);
+} /* ng_btsocket_l2cap_close */
+
/*
* Accept connection on socket. Nothing to do here, socket must be connected
* and ready, so just return peer address and be done with it.
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c
index 85700f9..1bac6d9 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c
@@ -575,9 +575,17 @@ ng_btsocket_l2cap_raw_init(void)
void
ng_btsocket_l2cap_raw_abort(struct socket *so)
{
- ng_btsocket_l2cap_raw_detach(so);
+
+ (void)ng_btsocket_l2cap_raw_disconnect(so);
} /* ng_btsocket_l2cap_raw_abort */
+void
+ng_btsocket_l2cap_raw_close(struct socket *so)
+{
+
+ (void)ng_btsocket_l2cap_raw_disconnect(so);
+} /* ng_btsocket_l2cap_raw_close */
+
/*
* Create and attach new socket
*/
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
index 982705f..4e599cf 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
@@ -346,11 +346,18 @@ ng_btsocket_rfcomm_init(void)
void
ng_btsocket_rfcomm_abort(struct socket *so)
{
- so->so_error = ECONNABORTED;
- ng_btsocket_rfcomm_detach(so);
+ so->so_error = ECONNABORTED;
+ (void)ng_btsocket_rfcomm_disconnect(so);
} /* ng_btsocket_rfcomm_abort */
+void
+ng_btsocket_rfcomm_close(struct socket *so)
+{
+
+ (void)ng_btsocket_rfcomm_disconnect(so);
+} /* ng_btsocket_rfcomm_close */
+
/*
* Accept connection on socket. Nothing to do here, socket must be connected
* and ready, so just return peer address and be done with it.
diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c
index 72bff98..6229739 100644
--- a/sys/netgraph/ng_socket.c
+++ b/sys/netgraph/ng_socket.c
@@ -1087,6 +1087,8 @@ dummy_disconnect(struct socket *so)
}
/*
* Control and data socket type descriptors
+ *
+ * XXXRW: Perhaps _close should do something?
*/
static struct pr_usrreqs ngc_usrreqs = {
@@ -1100,6 +1102,7 @@ static struct pr_usrreqs ngc_usrreqs = {
.pru_send = ngc_send,
.pru_shutdown = NULL,
.pru_sockaddr = ng_setsockaddr,
+ .pru_close = NULL,
};
static struct pr_usrreqs ngd_usrreqs = {
@@ -1113,6 +1116,7 @@ static struct pr_usrreqs ngd_usrreqs = {
.pru_send = ngd_send,
.pru_shutdown = NULL,
.pru_sockaddr = ng_setsockaddr,
+ .pru_close = NULL,
};
/*
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index f635c89..dfe1c68 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -622,12 +622,17 @@ rip_attach(struct socket *so, int proto, struct thread *td)
}
static void
-rip_pcbdetach(struct socket *so, struct inpcb *inp)
+rip_detach(struct socket *so)
{
+ struct inpcb *inp;
- INP_INFO_WLOCK_ASSERT(&ripcbinfo);
- INP_LOCK_ASSERT(inp);
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("rip_detach: inp == NULL"));
+ KASSERT(inp->inp_faddr.s_addr == INADDR_ANY,
+ ("rip_detach: not closed"));
+ INP_INFO_WLOCK(&ripcbinfo);
+ INP_LOCK(inp);
if (so == ip_mrouter && ip_mrouter_done)
ip_mrouter_done();
if (ip_rsvp_force_done)
@@ -636,32 +641,48 @@ rip_pcbdetach(struct socket *so, struct inpcb *inp)
ip_rsvp_done();
in_pcbdetach(inp);
in_pcbfree(inp);
+ INP_INFO_WUNLOCK(&ripcbinfo);
}
static void
-rip_detach(struct socket *so)
+rip_dodisconnect(struct socket *so, struct inpcb *inp)
+{
+
+ INP_LOCK_ASSERT(inp);
+
+ inp->inp_faddr.s_addr = INADDR_ANY;
+ SOCK_LOCK(so);
+ so->so_state &= ~SS_ISCONNECTED;
+ SOCK_UNLOCK(so);
+}
+
+static void
+rip_abort(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
- KASSERT(inp != NULL, ("rip_detach: inp == NULL"));
+ KASSERT(inp != NULL, ("rip_abort: inp == NULL"));
+
INP_INFO_WLOCK(&ripcbinfo);
INP_LOCK(inp);
- rip_pcbdetach(so, inp);
+ rip_dodisconnect(so, inp);
+ INP_UNLOCK(inp);
INP_INFO_WUNLOCK(&ripcbinfo);
}
static void
-rip_abort(struct socket *so)
+rip_close(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
- KASSERT(inp != NULL, ("rip_abort: inp == NULL"));
+ KASSERT(inp != NULL, ("rip_close: inp == NULL"));
+
INP_INFO_WLOCK(&ripcbinfo);
INP_LOCK(inp);
- soisdisconnected(so);
- rip_pcbdetach(so, inp);
+ rip_dodisconnect(so, inp);
+ INP_UNLOCK(inp);
INP_INFO_WUNLOCK(&ripcbinfo);
}
@@ -677,10 +698,7 @@ rip_disconnect(struct socket *so)
KASSERT(inp != NULL, ("rip_disconnect: inp == NULL"));
INP_INFO_WLOCK(&ripcbinfo);
INP_LOCK(inp);
- inp->inp_faddr.s_addr = INADDR_ANY;
- SOCK_LOCK(so);
- so->so_state &= ~SS_ISCONNECTED;
- SOCK_UNLOCK(so);
+ rip_dodisconnect(so, inp);
INP_UNLOCK(inp);
INP_INFO_WUNLOCK(&ripcbinfo);
return (0);
@@ -912,5 +930,6 @@ struct pr_usrreqs rip_usrreqs = {
.pru_send = rip_send,
.pru_shutdown = rip_shutdown,
.pru_sockaddr = rip_sockaddr,
- .pru_sosetlabel = in_pcbsosetlabel
+ .pru_sosetlabel = in_pcbsosetlabel,
+ .pru_close = rip_close,
};
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 676b22e..64574cf 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -808,18 +808,7 @@ tcp_close(struct tcpcb *tp)
KASSERT(so->so_state & SS_PROTOREF,
("tcp_close: !SS_PROTOREF"));
inp->inp_vflag &= ~INP_SOCKREF;
- tcp_discardcb(tp);
-#ifdef INET6
- if (inp->inp_vflag & INP_IPV6PROTO) {
- in6_pcbdetach(inp);
- in6_pcbfree(inp);
- } else {
-#endif
- in_pcbdetach(inp);
- in_pcbfree(inp);
-#ifdef INET6
- }
-#endif
+ INP_UNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
so->so_state &= ~SS_PROTOREF;
@@ -1789,12 +1778,6 @@ tcp_twstart(struct tcpcb *tp)
KASSERT(so->so_state & SS_PROTOREF,
("tcp_twstart: !SS_PROTOREF"));
inp->inp_vflag &= ~INP_SOCKREF;
-#ifdef INET6
- if (inp->inp_vflag & INP_IPV6PROTO)
- in6_pcbdetach(inp);
- else
-#endif
- in_pcbdetach(inp);
INP_UNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
@@ -1847,12 +1830,11 @@ tcp_twclose(struct tcptw *tw, int reuse)
/*
* At this point, we are in one of two situations:
*
- * (1) We have no socket, just an inpcb<->twtcp pair. Release it all
- * after validating.
+ * (1) We have no socket, just an inpcb<->twtcp pair. We can free
+ * all state.
*
- * (2) We have a socket, which we may or may now own the reference
- * for. If we own the reference, release all the state after
- * validating. If not, leave it for the socket close to clean up.
+ * (2) We have a socket -- if we own a reference, release it and
+ * notify the socket layer.
*/
inp = tw->tw_inpcb;
KASSERT((inp->inp_vflag & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
@@ -1867,22 +1849,15 @@ tcp_twclose(struct tcptw *tw, int reuse)
so = inp->inp_socket;
if (so != NULL) {
+ /*
+ * If there's a socket, handle two cases: first, we own a
+ * strong reference, which we will now release, or we don't
+ * in which case another reference exists (XXXRW: think
+ * about this more), and we don't need to take action.
+ */
if (inp->inp_vflag & INP_SOCKREF) {
- /*
- * If a socket is present, and we own the only
- * reference, we need to tear down the socket and the
- * inpcb.
- */
inp->inp_vflag &= ~INP_SOCKREF;
-#ifdef INET6
- if (inp->inp_vflag & INP_IPV6PROTO) {
- in6_pcbdetach(inp);
- in6_pcbfree(inp);
- } else {
- in_pcbdetach(inp);
- in_pcbfree(inp);
- }
-#endif
+ INP_UNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
KASSERT(so->so_state & SS_PROTOREF,
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 676b22e..64574cf 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -808,18 +808,7 @@ tcp_close(struct tcpcb *tp)
KASSERT(so->so_state & SS_PROTOREF,
("tcp_close: !SS_PROTOREF"));
inp->inp_vflag &= ~INP_SOCKREF;
- tcp_discardcb(tp);
-#ifdef INET6
- if (inp->inp_vflag & INP_IPV6PROTO) {
- in6_pcbdetach(inp);
- in6_pcbfree(inp);
- } else {
-#endif
- in_pcbdetach(inp);
- in_pcbfree(inp);
-#ifdef INET6
- }
-#endif
+ INP_UNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
so->so_state &= ~SS_PROTOREF;
@@ -1789,12 +1778,6 @@ tcp_twstart(struct tcpcb *tp)
KASSERT(so->so_state & SS_PROTOREF,
("tcp_twstart: !SS_PROTOREF"));
inp->inp_vflag &= ~INP_SOCKREF;
-#ifdef INET6
- if (inp->inp_vflag & INP_IPV6PROTO)
- in6_pcbdetach(inp);
- else
-#endif
- in_pcbdetach(inp);
INP_UNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
@@ -1847,12 +1830,11 @@ tcp_twclose(struct tcptw *tw, int reuse)
/*
* At this point, we are in one of two situations:
*
- * (1) We have no socket, just an inpcb<->twtcp pair. Release it all
- * after validating.
+ * (1) We have no socket, just an inpcb<->twtcp pair. We can free
+ * all state.
*
- * (2) We have a socket, which we may or may now own the reference
- * for. If we own the reference, release all the state after
- * validating. If not, leave it for the socket close to clean up.
+ * (2) We have a socket -- if we own a reference, release it and
+ * notify the socket layer.
*/
inp = tw->tw_inpcb;
KASSERT((inp->inp_vflag & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
@@ -1867,22 +1849,15 @@ tcp_twclose(struct tcptw *tw, int reuse)
so = inp->inp_socket;
if (so != NULL) {
+ /*
+ * If there's a socket, handle two cases: first, we own a
+ * strong reference, which we will now release, or we don't
+ * in which case another reference exists (XXXRW: think
+ * about this more), and we don't need to take action.
+ */
if (inp->inp_vflag & INP_SOCKREF) {
- /*
- * If a socket is present, and we own the only
- * reference, we need to tear down the socket and the
- * inpcb.
- */
inp->inp_vflag &= ~INP_SOCKREF;
-#ifdef INET6
- if (inp->inp_vflag & INP_IPV6PROTO) {
- in6_pcbdetach(inp);
- in6_pcbfree(inp);
- } else {
- in_pcbdetach(inp);
- in_pcbfree(inp);
- }
-#endif
+ INP_UNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
KASSERT(so->so_state & SS_PROTOREF,
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 111a983..549627b 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -137,12 +137,13 @@ out:
}
/*
- * tcp_detach() releases any protocol state that can be reasonably released
- * when a socket shutdown is requested, and is a shared code path for
- * tcp_usr_detach() and tcp_usr_abort(), the two socket close entry points.
+ * tcp_detach is called when the socket layer loses its final reference
+ * to the socket, be it a file descriptor reference, a reference from TCP,
+ * etc. At this point, there is only one case in which we will keep around
+ * inpcb state: time wait.
*
- * Accepts pcbinfo, inpcb locked, will unlock the inpcb (if needed) on
- * return.
+ * This function can probably be re-absorbed back into tcp_usr_detach() now
+ * that there is a single detach path.
*/
static void
tcp_detach(struct socket *so, struct inpcb *inp)
@@ -158,19 +159,24 @@ tcp_detach(struct socket *so, struct inpcb *inp)
KASSERT(so->so_pcb == inp, ("tcp_detach: so_pcb != inp"));
KASSERT(inp->inp_socket == so, ("tcp_detach: inp_socket != so"));
+ tp = intotcpcb(inp);
+
if (inp->inp_vflag & INP_TIMEWAIT) {
+ /*
+ * There are two cases to handle: one in which the time wait
+ * state is being discarded (INP_DROPPED), and one in which
+ * this connection will remain in timewait. In the former,
+ * it is time to discard all state (except tcptw, which has
+ * already been discarded by the timewait close code, which
+ * should be further up the call stack somewhere). In the
+ * latter case, we detach from the socket, but leave the pcb
+ * present until timewait ends.
+ *
+ * XXXRW: Would it be cleaner to free the tcptw here?
+ */
if (inp->inp_vflag & INP_DROPPED) {
- /*
- * Connection was in time wait and has been dropped;
- * the calling path is either via tcp_twclose(), or
- * as a result of an eventual soclose() after
- * tcp_twclose() has been called. In either case,
- * tcp_twclose() has detached the tcptw from the
- * inpcb, so we just detach and free the inpcb.
- *
- * XXXRW: Would it be cleaner to free the tcptw
- * here?
- */
+ KASSERT(tp == NULL, ("tcp_detach: INP_TIMEWAIT && "
+ "INP_DROPPED && tp != NULL"));
#ifdef INET6
if (isipv6) {
in6_pcbdetach(inp);
@@ -183,11 +189,6 @@ tcp_detach(struct socket *so, struct inpcb *inp)
}
#endif
} else {
- /*
- * Connection is in time wait and has not yet been
- * dropped; allow the socket to be discarded, but
- * need to keep inpcb until end of time wait.
- */
#ifdef INET6
if (isipv6)
in6_pcbdetach(inp);
@@ -198,20 +199,21 @@ tcp_detach(struct socket *so, struct inpcb *inp)
}
} else {
/*
- * If not in timewait, there are two possible paths. First,
- * the TCP connection is either embryonic or done, in which
- * case we tear down all state. Second, it may still be
- * active, in which case we acquire a reference to the socket
- * and will free it later when TCP is done.
+ * If the connection is not in timewait, we consider two
+ * two conditions: one in which no further processing is
+ * necessary (dropped || embryonic), and one in which TCP is
+ * not yet done, but no longer requires the socket, so the
+ * pcb will persist for the time being.
+ *
+ * XXXRW: Does the second case still occur?
*/
- tp = intotcpcb(inp);
if (inp->inp_vflag & INP_DROPPED ||
tp->t_state < TCPS_SYN_SENT) {
tcp_discardcb(tp);
#ifdef INET6
if (isipv6) {
- in_pcbdetach(inp);
- in_pcbfree(inp);
+ in6_pcbdetach(inp);
+ in6_pcbfree(inp);
} else {
#endif
in_pcbdetach(inp);
@@ -220,11 +222,12 @@ tcp_detach(struct socket *so, struct inpcb *inp)
}
#endif
} else {
- SOCK_LOCK(so);
- so->so_state |= SS_PROTOREF;
- SOCK_UNLOCK(so);
- inp->inp_vflag |= INP_SOCKREF;
- INP_UNLOCK(inp);
+#ifdef INET6
+ if (isipv6)
+ in6_pcbdetach(inp);
+ else
+#endif
+ in_pcbdetach(inp);
}
}
}
@@ -251,15 +254,6 @@ tcp_usr_detach(struct socket *so)
("tcp_usr_detach: inp_socket == NULL"));
TCPDEBUG1();
- /*
- * First, if we still have full TCP state, and we're not dropped,
- * initiate a disconnect.
- */
- if (!(inp->inp_vflag & INP_TIMEWAIT) &&
- !(inp->inp_vflag & INP_DROPPED)) {
- tp = intotcpcb(inp);
- tcp_disconnect(tp);
- }
tcp_detach(so, inp);
tp = NULL;
TCPDEBUG2(PRU_DETACH);
@@ -926,15 +920,13 @@ out:
}
/*
- * Abort the TCP.
- *
- * First, drop the connection. Then collect state if possible.
+ * Abort the TCP. Drop the connection abruptly.
*/
static void
tcp_usr_abort(struct socket *so)
{
struct inpcb *inp;
- struct tcpcb *tp;
+ struct tcpcb *tp = NULL;
TCPDEBUG0;
inp = sotoinpcb(so);
@@ -944,20 +936,63 @@ tcp_usr_abort(struct socket *so)
INP_LOCK(inp);
KASSERT(inp->inp_socket != NULL,
("tcp_usr_abort: inp_socket == NULL"));
- TCPDEBUG1();
/*
- * First, if we still have full TCP state, and we're not dropped,
- * drop.
+ * If we still have full TCP state, and we're not dropped, drop.
*/
if (!(inp->inp_vflag & INP_TIMEWAIT) &&
!(inp->inp_vflag & INP_DROPPED)) {
tp = intotcpcb(inp);
+ TCPDEBUG1();
tcp_drop(tp, ECONNABORTED);
+ TCPDEBUG2(PRU_ABORT);
}
- tcp_detach(so, inp);
- tp = NULL;
- TCPDEBUG2(PRU_DETACH);
+ if (!(inp->inp_vflag & INP_DROPPED)) {
+ SOCK_LOCK(so);
+ so->so_state |= SS_PROTOREF;
+ SOCK_UNLOCK(so);
+ inp->inp_vflag |= INP_SOCKREF;
+ }
+ INP_UNLOCK(inp);
+ INP_INFO_WUNLOCK(&tcbinfo);
+}
+
+/*
+ * TCP socket is closed. Start friendly disconnect.
+ */
+static void
+tcp_usr_close(struct socket *so)
+{
+ struct inpcb *inp;
+ struct tcpcb *tp = NULL;
+ TCPDEBUG0;
+
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("tcp_usr_close: inp == NULL"));
+
+ INP_INFO_WLOCK(&tcbinfo);
+ INP_LOCK(inp);
+ KASSERT(inp->inp_socket != NULL,
+ ("tcp_usr_close: inp_socket == NULL"));
+
+ /*
+ * If we still have full TCP state, and we're not dropped, initiate
+ * a disconnect.
+ */
+ if (!(inp->inp_vflag & INP_TIMEWAIT) &&
+ !(inp->inp_vflag & INP_DROPPED)) {
+ tp = intotcpcb(inp);
+ TCPDEBUG1();
+ tcp_disconnect(tp);
+ TCPDEBUG2(PRU_CLOSE);
+ }
+ if (!(inp->inp_vflag & INP_DROPPED)) {
+ SOCK_LOCK(so);
+ so->so_state |= SS_PROTOREF;
+ SOCK_UNLOCK(so);
+ inp->inp_vflag |= INP_SOCKREF;
+ }
+ INP_UNLOCK(inp);
INP_INFO_WUNLOCK(&tcbinfo);
}
@@ -1019,7 +1054,8 @@ struct pr_usrreqs tcp_usrreqs = {
.pru_send = tcp_usr_send,
.pru_shutdown = tcp_usr_shutdown,
.pru_sockaddr = tcp_sockaddr,
- .pru_sosetlabel = in_pcbsosetlabel
+ .pru_sosetlabel = in_pcbsosetlabel,
+ .pru_close = tcp_usr_close,
};
#ifdef INET6
@@ -1039,7 +1075,8 @@ struct pr_usrreqs tcp6_usrreqs = {
.pru_send = tcp_usr_send,
.pru_shutdown = tcp_usr_shutdown,
.pru_sockaddr = in6_mapped_sockaddr,
- .pru_sosetlabel = in_pcbsosetlabel
+ .pru_sosetlabel = in_pcbsosetlabel,
+ .pru_close = tcp_usr_close,
};
#endif /* INET6 */
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 7fff2b6..695a7e1 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -959,9 +959,12 @@ udp_abort(struct socket *so)
KASSERT(inp != NULL, ("udp_abort: inp == NULL"));
INP_INFO_WLOCK(&udbinfo);
INP_LOCK(inp);
- soisdisconnected(so);
- in_pcbdetach(inp);
- in_pcbfree(inp);
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ in_pcbdisconnect(inp);
+ inp->inp_laddr.s_addr = INADDR_ANY;
+ soisdisconnected(so);
+ }
+ INP_UNLOCK(inp);
INP_INFO_WUNLOCK(&udbinfo);
}
@@ -1007,6 +1010,24 @@ udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
return error;
}
+static void
+udp_close(struct socket *so)
+{
+ struct inpcb *inp;
+
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("udp_close: inp == NULL"));
+ INP_INFO_WLOCK(&udbinfo);
+ INP_LOCK(inp);
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ in_pcbdisconnect(inp);
+ inp->inp_laddr.s_addr = INADDR_ANY;
+ soisdisconnected(so);
+ }
+ INP_UNLOCK(inp);
+ INP_INFO_WUNLOCK(&udbinfo);
+}
+
static int
udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
@@ -1041,6 +1062,8 @@ udp_detach(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp_detach: inp == NULL"));
+ KASSERT(inp->inp_faddr.s_addr == INADDR_ANY,
+ ("udp_detach: not disconnected"));
INP_INFO_WLOCK(&udbinfo);
INP_LOCK(inp);
in_pcbdetach(inp);
@@ -1131,5 +1154,6 @@ struct pr_usrreqs udp_usrreqs = {
.pru_sosend = sosend_dgram,
.pru_shutdown = udp_shutdown,
.pru_sockaddr = udp_sockaddr,
- .pru_sosetlabel = in_pcbsosetlabel
+ .pru_sosetlabel = in_pcbsosetlabel,
+ .pru_close = udp_close,
};
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 86ff948..cab78eb 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -586,25 +586,42 @@ rip6_detach(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
+
/* xxx: RSVP */
if (so == ip6_mrouter)
ip6_mrouter_done();
+ INP_INFO_WLOCK(&ripcbinfo);
+ INP_LOCK(inp);
if (inp->in6p_icmp6filt) {
FREE(inp->in6p_icmp6filt, M_PCB);
inp->in6p_icmp6filt = NULL;
}
- INP_INFO_WLOCK(&ripcbinfo);
- INP_LOCK(inp);
in6_pcbdetach(inp);
in6_pcbfree(inp);
INP_INFO_WUNLOCK(&ripcbinfo);
}
+/* XXXRW: This can't ever be called. */
static void
rip6_abort(struct socket *so)
{
+ struct inpcb *inp;
+
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("rip6_abort: inp == NULL"));
+
+ soisdisconnected(so);
+}
+
+static void
+rip6_close(struct socket *so)
+{
+ struct inpcb *inp;
+
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("rip6_close: inp == NULL"));
+
soisdisconnected(so);
- rip6_detach(so);
}
static int
@@ -794,4 +811,5 @@ struct pr_usrreqs rip6_usrreqs = {
.pru_send = rip6_send,
.pru_shutdown = rip6_shutdown,
.pru_sockaddr = in6_setsockaddr,
+ .pru_close = rip6_close,
};
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index f031b96..005c2d5 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -480,11 +480,24 @@ udp6_abort(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_abort: inp == NULL"));
+#ifdef INET
+ if (inp->inp_vflag & INP_IPV4) {
+ struct pr_usrreqs *pru;
+
+ pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
+ (*pru->pru_abort)(so);
+ return;
+ }
+#endif
+
INP_INFO_WLOCK(&udbinfo);
INP_LOCK(inp);
- soisdisconnected(so);
- in6_pcbdetach(inp);
- in6_pcbfree(inp);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
+ in6_pcbdisconnect(inp);
+ inp->in6p_laddr = in6addr_any;
+ soisdisconnected(so);
+ }
+ INP_UNLOCK(inp);
INP_INFO_WUNLOCK(&udbinfo);
}
@@ -565,6 +578,34 @@ out:
return error;
}
+static void
+udp6_close(struct socket *so)
+{
+ struct inpcb *inp;
+
+ inp = sotoinpcb(so);
+ KASSERT(inp != NULL, ("udp6_close: inp == NULL"));
+
+#ifdef INET
+ if (inp->inp_vflag & INP_IPV4) {
+ struct pr_usrreqs *pru;
+
+ pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
+ (*pru->pru_disconnect)(so);
+ return;
+ }
+#endif
+ INP_INFO_WLOCK(&udbinfo);
+ INP_LOCK(inp);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
+ in6_pcbdisconnect(inp);
+ inp->in6p_laddr = in6addr_any;
+ soisdisconnected(so);
+ }
+ INP_UNLOCK(inp);
+ INP_INFO_WUNLOCK(&udbinfo);
+}
+
static int
udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
@@ -755,5 +796,6 @@ struct pr_usrreqs udp6_usrreqs = {
.pru_send = udp6_send,
.pru_shutdown = udp_shutdown,
.pru_sockaddr = in6_mapped_sockaddr,
- .pru_sosetlabel = in_pcbsosetlabel
+ .pru_sosetlabel = in_pcbsosetlabel,
+ .pru_close = udp6_close
};
diff --git a/sys/netipsec/keysock.c b/sys/netipsec/keysock.c
index a590f1e..b93d6d6 100644
--- a/sys/netipsec/keysock.c
+++ b/sys/netipsec/keysock.c
@@ -439,6 +439,17 @@ key_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
}
/*
+ * key_close()
+ * derived from net/rtsock.c:rts_close().
+ */
+static void
+key_abort(struct socket *so)
+{
+
+ raw_usrreqs.pru_close(so);
+}
+
+/*
* key_connect()
* derived from net/rtsock.c:rts_connect()
*/
@@ -553,6 +564,7 @@ struct pr_usrreqs key_usrreqs = {
.pru_send = key_send,
.pru_shutdown = key_shutdown,
.pru_sockaddr = key_sockaddr,
+ .pru_close = key_close,
};
/* sysctl */
diff --git a/sys/netipx/ipx_usrreq.c b/sys/netipx/ipx_usrreq.c
index 489014a..84de629 100644
--- a/sys/netipx/ipx_usrreq.c
+++ b/sys/netipx/ipx_usrreq.c
@@ -88,6 +88,7 @@ static int ipx_send(struct socket *so, int flags, struct mbuf *m,
static int ipx_shutdown(struct socket *so);
static int ripx_attach(struct socket *so, int proto, struct thread *td);
static int ipx_output(struct ipxpcb *ipxp, struct mbuf *m0);
+static void ipx_usr_close(struct socket *so);
struct pr_usrreqs ipx_usrreqs = {
.pru_abort = ipx_usr_abort,
@@ -101,6 +102,7 @@ struct pr_usrreqs ipx_usrreqs = {
.pru_send = ipx_send,
.pru_shutdown = ipx_shutdown,
.pru_sockaddr = ipx_sockaddr,
+ .pru_close = ipx_usr_close,
};
struct pr_usrreqs ripx_usrreqs = {
@@ -115,6 +117,7 @@ struct pr_usrreqs ripx_usrreqs = {
.pru_send = ipx_send,
.pru_shutdown = ipx_shutdown,
.pru_sockaddr = ipx_sockaddr,
+ .pru_close = ipx_usr_close,
};
/*
@@ -432,14 +435,8 @@ static void
ipx_usr_abort(so)
struct socket *so;
{
- struct ipxpcb *ipxp = sotoipxpcb(so);
- KASSERT(ipxp != NULL, ("ipx_usr_abort: ipxp == NULL"));
- IPX_LIST_LOCK();
- IPX_LOCK(ipxp);
- ipx_pcbdetach(ipxp);
- ipx_pcbfree(ipxp);
- IPX_LIST_UNLOCK();
+ /* XXXRW: Possibly ipx_disconnect() here? */
soisdisconnected(so);
}
@@ -482,6 +479,15 @@ ipx_bind(so, nam, td)
return (error);
}
+static void
+ipx_usr_close(so)
+ struct socket *so;
+{
+
+ /* XXXRW: Possibly ipx_disconnect() here? */
+ soisdisconnected(so);
+}
+
static int
ipx_connect(so, nam, td)
struct socket *so;
@@ -513,6 +519,7 @@ ipx_detach(so)
{
struct ipxpcb *ipxp = sotoipxpcb(so);
+ /* XXXRW: Should assert detached. */
KASSERT(ipxp != NULL, ("ipx_detach: ipxp == NULL"));
IPX_LIST_LOCK();
IPX_LOCK(ipxp);
diff --git a/sys/netipx/spx_usrreq.c b/sys/netipx/spx_usrreq.c
index d9a5639..9400df2 100644
--- a/sys/netipx/spx_usrreq.c
+++ b/sys/netipx/spx_usrreq.c
@@ -101,6 +101,7 @@ static void spx_usr_abort(struct socket *so);
static int spx_accept(struct socket *so, struct sockaddr **nam);
static int spx_attach(struct socket *so, int proto, struct thread *td);
static int spx_bind(struct socket *so, struct sockaddr *nam, struct thread *td);
+static void spx_usr_close(struct socket *so);
static int spx_connect(struct socket *so, struct sockaddr *nam,
struct thread *td);
static void spx_detach(struct socket *so);
@@ -131,6 +132,7 @@ struct pr_usrreqs spx_usrreqs = {
.pru_send = spx_send,
.pru_shutdown = spx_shutdown,
.pru_sockaddr = ipx_sockaddr,
+ .pru_close = spx_usr_close,
};
struct pr_usrreqs spx_usrreq_sps = {
@@ -149,6 +151,7 @@ struct pr_usrreqs spx_usrreq_sps = {
.pru_send = spx_send,
.pru_shutdown = spx_shutdown,
.pru_sockaddr = ipx_sockaddr,
+ .pru_close = spx_usr_close,
};
void
@@ -1320,9 +1323,7 @@ spx_usr_abort(struct socket *so)
IPX_LIST_LOCK();
IPX_LOCK(ipxp);
spx_drop(cb, ECONNABORTED);
- spx_pcbdetach(ipxp);
- ipx_pcbdetach(ipxp);
- ipx_pcbfree(ipxp);
+ IPX_UNLOCK(ipxp);
IPX_LIST_UNLOCK();
}
@@ -1459,6 +1460,28 @@ out:
return (error);
}
+static void
+spx_usr_close(struct socket *so)
+{
+ struct ipxpcb *ipxp;
+ struct spxpcb *cb;
+
+ ipxp = sotoipxpcb(so);
+ KASSERT(ipxp != NULL, ("spx_usr_close: ipxp == NULL"));
+
+ cb = ipxtospxpcb(ipxp);
+ KASSERT(cb != NULL, ("spx_usr_close: cb == NULL"));
+
+ IPX_LIST_LOCK();
+ IPX_LOCK(ipxp);
+ if (cb->s_state > TCPS_LISTEN)
+ spx_disconnect(cb);
+ else
+ spx_close(cb);
+ IPX_UNLOCK(ipxp);
+ IPX_LIST_UNLOCK();
+}
+
/*
* Initiate connection to peer. Enter SYN_SENT state, and mark socket as
* connecting. Start keep-alive timer, setup prototype header, send initial
@@ -1518,6 +1541,9 @@ spx_detach(struct socket *so)
struct ipxpcb *ipxp;
struct spxpcb *cb;
+ /*
+ * XXXRW: Should assert appropriately detached.
+ */
ipxp = sotoipxpcb(so);
KASSERT(ipxp != NULL, ("spx_detach: ipxp == NULL"));
@@ -1526,12 +1552,7 @@ spx_detach(struct socket *so)
IPX_LIST_LOCK();
IPX_LOCK(ipxp);
- if (cb->s_state > TCPS_LISTEN)
- spx_disconnect(cb);
- else
- spx_close(cb);
spx_pcbdetach(ipxp);
- ipx_pcbdetach(ipxp);
ipx_pcbfree(ipxp);
IPX_LIST_UNLOCK();
}
diff --git a/sys/netkey/keysock.c b/sys/netkey/keysock.c
index 6a1cb11..abf59d3 100644
--- a/sys/netkey/keysock.c
+++ b/sys/netkey/keysock.c
@@ -348,6 +348,17 @@ key_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
}
/*
+ * key_close()
+ * derived from net/rtsock.c:rts_close()
+ */
+static void
+key_close(struct socket *so)
+{
+
+ raw_usrreqs.pru_close(so);
+}
+
+/*
* key_connect()
* derived from net/rtsock.c:rts_connect()
*/
@@ -460,6 +471,7 @@ struct pr_usrreqs key_usrreqs = {
.pru_send = key_send,
.pru_shutdown = key_shutdown,
.pru_sockaddr = key_sockaddr,
+ .pru_close = key_close,
};
/* sysctl */
diff --git a/sys/netnatm/natm.c b/sys/netnatm/natm.c
index df4ac2f..2496420 100644
--- a/sys/netnatm/natm.c
+++ b/sys/netnatm/natm.c
@@ -336,7 +336,12 @@ static void
natm_usr_abort(struct socket *so)
{
- natm_usr_detach(so);
+}
+
+static void
+natm_usr_close(struct socket *so)
+{
+
}
static int
@@ -366,6 +371,7 @@ struct pr_usrreqs natm_usrreqs = {
.pru_send = natm_usr_send,
.pru_shutdown = natm_usr_shutdown,
.pru_sockaddr = natm_usr_sockaddr,
+ .pru_close = natm_usr_close,
};
/*
OpenPOWER on IntegriCloud