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 @@ soclose(so) * 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 @@ ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 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,19 +641,19 @@ 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) { - struct inpcb *inp; - inp = sotoinpcb(so); - KASSERT(inp != NULL, ("rip_detach: inp == NULL")); - INP_INFO_WLOCK(&ripcbinfo); - INP_LOCK(inp); - rip_pcbdetach(so, inp); - INP_INFO_WUNLOCK(&ripcbinfo); + INP_LOCK_ASSERT(inp); + + inp->inp_faddr.s_addr = INADDR_ANY; + SOCK_LOCK(so); + so->so_state &= ~SS_ISCONNECTED; + SOCK_UNLOCK(so); } static void @@ -658,10 +663,26 @@ rip_abort(struct socket *so) inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip_abort: 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); +} + +static void +rip_close(struct socket *so) +{ + struct inpcb *inp; + + inp = sotoinpcb(so); + KASSERT(inp != NULL, ("rip_close: inp == NULL")); + + INP_INFO_WLOCK(&ripcbinfo); + INP_LOCK(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 @@ tcp_usr_attach(struct socket *so, int proto, struct thread *td) } /* - * 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 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m, } /* - * 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 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 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 @@ -438,6 +438,17 @@ key_bind(struct socket *so, struct sockaddr *nam, struct thread *td) return error; } +/* + * 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 @@ spx_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 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 @@ -347,6 +347,17 @@ key_bind(struct socket *so, struct sockaddr *nam, struct thread *p) return error; } +/* + * 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, }; /*