diff options
| author | Robert Watson <rwatson@FreeBSD.org> | 2006-07-21 17:11:15 +0000 | 
|---|---|---|
| committer | Robert Watson <rwatson@FreeBSD.org> | 2006-07-21 17:11:15 +0000 | 
| commit | a152f8a36128ce99cc252941396d7db06ec7084e (patch) | |
| tree | c584d49beb0289bc5110816075b0f48383df5bfd | |
| parent | 05a7329cbad79bc2d72b63eee9badbdb4deff62d (diff) | |
Notes
28 files changed, 438 insertions, 189 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 4d5936a7c4d9..6e203d1d3e60 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 2c7222398cb6..02b641a89725 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 4f2f006757e2..b584860e3d62 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 76913a57085d..8ab39e49377f 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 1421c8d02a43..187685611ae1 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 f21ad7980b56..a0534b7d0d26 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 8facb95994bc..ad14e84a366f 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 0f2837770cb1..b8e98b31e694 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 a8523ab44f6b..deea5b3db0df 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 1939964bbc76..a1fdb2717a13 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 16b9a208e3d8..3029ffd4c187 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 922184a25bf0..6513757181e1 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 21d3766eb742..f6d6fb2b8456 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 85700f981c68..1bac6d916d55 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 982705fbf7f0..4e599cf03281 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 72bff98f6da4..622973929cae 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 f635c8959c34..dfe1c6831a36 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 676b22e15d94..64574cf9f1f7 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 676b22e15d94..64574cf9f1f7 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 111a9830f809..549627bf7992 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 7fff2b62507e..695a7e1569de 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 86ff948f7902..cab78ebcef86 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 f031b9690eb4..005c2d597633 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 a590f1ef43d0..b93d6d69d1e3 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 489014a0d5c1..84de6294594d 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 d9a56397e8f0..9400df276175 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 6a1cb111c584..abf59d3f27c3 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 df4ac2ff14b3..249642076da4 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,  };  /*  | 
