Change semantics of socket close and detach. Add a new protocol switch
function, pru_close, to notify protocols that the file descriptor or other consumer of a socket is closing the socket. pru_abort is now a notification of close also, and no longer detaches. pru_detach is no longer used to notify of close, and will be called during socket tear-down by sofree() when all references to a socket evaporate after an earlier call to abort or close the socket. This means detach is now an unconditional teardown of a socket, whereas previously sockets could persist after detach of the protocol retained a reference. This faciliates sharing mutexes between layers of the network stack as the mutex is required during the checking and removal of references at the head of sofree(). With this change, pru_detach can now assume that the mutex will no longer be required by the socket layer after completion, whereas before this was not necessarily true. Reviewed by: gnn
This commit is contained in:
parent
05a7329cba
commit
a152f8a361
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=160549
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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*/
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ struct pr_usrreqs atm_dgram_usrreqs = {
|
||||
.pru_sosend = NULL,
|
||||
.pru_soreceive = NULL,
|
||||
.pru_sopoll = NULL,
|
||||
.pru_close = atm_proto_notsupp5,
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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 *,
|
||||
|
@ -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 *,
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user