Changeset View
Changeset View
Standalone View
Standalone View
head/sys/rpc/svc_vc.c
Show First 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | |||||
static bool_t svc_vc_backchannel_reply(SVCXPRT *, struct rpc_msg *, | static bool_t svc_vc_backchannel_reply(SVCXPRT *, struct rpc_msg *, | ||||
struct sockaddr *, struct mbuf *, uint32_t *); | struct sockaddr *, struct mbuf *, uint32_t *); | ||||
static bool_t svc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, | static bool_t svc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, | ||||
void *in); | void *in); | ||||
static SVCXPRT *svc_vc_create_conn(SVCPOOL *pool, struct socket *so, | static SVCXPRT *svc_vc_create_conn(SVCPOOL *pool, struct socket *so, | ||||
struct sockaddr *raddr); | struct sockaddr *raddr); | ||||
static int svc_vc_accept(struct socket *head, struct socket **sop); | static int svc_vc_accept(struct socket *head, struct socket **sop); | ||||
static int svc_vc_soupcall(struct socket *so, void *arg, int waitflag); | static int svc_vc_soupcall(struct socket *so, void *arg, int waitflag); | ||||
static int svc_vc_rendezvous_soupcall(struct socket *, void *, int); | |||||
static struct xp_ops svc_vc_rendezvous_ops = { | static struct xp_ops svc_vc_rendezvous_ops = { | ||||
.xp_recv = svc_vc_rendezvous_recv, | .xp_recv = svc_vc_rendezvous_recv, | ||||
.xp_stat = svc_vc_rendezvous_stat, | .xp_stat = svc_vc_rendezvous_stat, | ||||
.xp_reply = (bool_t (*)(SVCXPRT *, struct rpc_msg *, | .xp_reply = (bool_t (*)(SVCXPRT *, struct rpc_msg *, | ||||
struct sockaddr *, struct mbuf *, uint32_t *))svc_vc_null, | struct sockaddr *, struct mbuf *, uint32_t *))svc_vc_null, | ||||
.xp_destroy = svc_vc_rendezvous_destroy, | .xp_destroy = svc_vc_rendezvous_destroy, | ||||
.xp_control = svc_vc_rendezvous_control | .xp_control = svc_vc_rendezvous_control | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, | ||||
memcpy(&xprt->xp_ltaddr, sa, sa->sa_len); | memcpy(&xprt->xp_ltaddr, sa, sa->sa_len); | ||||
free(sa, M_SONAME); | free(sa, M_SONAME); | ||||
xprt_register(xprt); | xprt_register(xprt); | ||||
solisten(so, -1, curthread); | solisten(so, -1, curthread); | ||||
SOCKBUF_LOCK(&so->so_rcv); | SOLISTEN_LOCK(so); | ||||
xprt->xp_upcallset = 1; | xprt->xp_upcallset = 1; | ||||
soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); | solisten_upcall_set(so, svc_vc_rendezvous_soupcall, xprt); | ||||
SOCKBUF_UNLOCK(&so->so_rcv); | SOLISTEN_UNLOCK(so); | ||||
return (xprt); | return (xprt); | ||||
cleanup_svc_vc_create: | cleanup_svc_vc_create: | ||||
sx_destroy(&xprt->xp_lock); | sx_destroy(&xprt->xp_lock); | ||||
svc_xprt_free(xprt); | svc_xprt_free(xprt); | ||||
return (NULL); | return (NULL); | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* This does all of the accept except the final call to soaccept. The | * This does all of the accept except the final call to soaccept. The | ||||
* caller will call soaccept after dropping its locks (soaccept may | * caller will call soaccept after dropping its locks (soaccept may | ||||
* call malloc). | * call malloc). | ||||
*/ | */ | ||||
int | int | ||||
svc_vc_accept(struct socket *head, struct socket **sop) | svc_vc_accept(struct socket *head, struct socket **sop) | ||||
{ | { | ||||
int error = 0; | |||||
struct socket *so; | struct socket *so; | ||||
int error = 0; | |||||
short nbio; | |||||
/* XXXGL: shouldn't that be an assertion? */ | |||||
if ((head->so_options & SO_ACCEPTCONN) == 0) { | if ((head->so_options & SO_ACCEPTCONN) == 0) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto done; | goto done; | ||||
} | } | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_socket_check_accept(curthread->td_ucred, head); | error = mac_socket_check_accept(curthread->td_ucred, head); | ||||
if (error != 0) | if (error != 0) | ||||
goto done; | goto done; | ||||
#endif | #endif | ||||
ACCEPT_LOCK(); | |||||
if (TAILQ_EMPTY(&head->so_comp)) { | |||||
ACCEPT_UNLOCK(); | |||||
error = EWOULDBLOCK; | |||||
goto done; | |||||
} | |||||
so = TAILQ_FIRST(&head->so_comp); | |||||
KASSERT(!(so->so_qstate & SQ_INCOMP), ("svc_vc_accept: so SQ_INCOMP")); | |||||
KASSERT(so->so_qstate & SQ_COMP, ("svc_vc_accept: so not SQ_COMP")); | |||||
/* | /* | ||||
* Before changing the flags on the socket, we have to bump the | * XXXGL: we want non-blocking semantics. The socket could be a | ||||
* reference count. Otherwise, if the protocol calls sofree(), | * socket created by kernel as well as socket shared with userland, | ||||
* the socket will be released due to a zero refcount. | * so we can't be sure about presense of SS_NBIO. We also shall not | ||||
* XXX might not need soref() since this is simpler than kern_accept. | * toggle it on the socket, since that may surprise userland. So we | ||||
* set SS_NBIO only temporarily. | |||||
*/ | */ | ||||
SOCK_LOCK(so); /* soref() and so_state update */ | SOLISTEN_LOCK(head); | ||||
soref(so); /* file descriptor reference */ | nbio = head->so_state & SS_NBIO; | ||||
head->so_state |= SS_NBIO; | |||||
error = solisten_dequeue(head, &so, 0); | |||||
head->so_state &= (nbio & ~SS_NBIO); | |||||
if (error) | |||||
goto done; | |||||
TAILQ_REMOVE(&head->so_comp, so, so_list); | so->so_state |= nbio; | ||||
head->so_qlen--; | |||||
so->so_state |= (head->so_state & SS_NBIO); | |||||
so->so_qstate &= ~SQ_COMP; | |||||
so->so_head = NULL; | |||||
SOCK_UNLOCK(so); | |||||
ACCEPT_UNLOCK(); | |||||
*sop = so; | *sop = so; | ||||
/* connection has been removed from the listen queue */ | /* connection has been removed from the listen queue */ | ||||
KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0); | KNOTE_UNLOCKED(&head->so_rdsel.si_note, 0); | ||||
done: | done: | ||||
return (error); | return (error); | ||||
} | } | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
static bool_t | static bool_t | ||||
svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, | svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, | ||||
struct sockaddr **addrp, struct mbuf **mp) | struct sockaddr **addrp, struct mbuf **mp) | ||||
Show All 16 Lines | svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, | ||||
if (error == EWOULDBLOCK) { | if (error == EWOULDBLOCK) { | ||||
/* | /* | ||||
* We must re-test for new connections after taking | * We must re-test for new connections after taking | ||||
* the lock to protect us in the case where a new | * the lock to protect us in the case where a new | ||||
* connection arrives after our call to accept fails | * connection arrives after our call to accept fails | ||||
* with EWOULDBLOCK. | * with EWOULDBLOCK. | ||||
*/ | */ | ||||
ACCEPT_LOCK(); | SOLISTEN_LOCK(xprt->xp_socket); | ||||
if (TAILQ_EMPTY(&xprt->xp_socket->so_comp)) | if (TAILQ_EMPTY(&xprt->xp_socket->sol_comp)) | ||||
xprt_inactive_self(xprt); | xprt_inactive_self(xprt); | ||||
ACCEPT_UNLOCK(); | SOLISTEN_UNLOCK(xprt->xp_socket); | ||||
sx_xunlock(&xprt->xp_lock); | sx_xunlock(&xprt->xp_lock); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
if (error) { | if (error) { | ||||
SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); | SOLISTEN_LOCK(xprt->xp_socket); | ||||
if (xprt->xp_upcallset) { | if (xprt->xp_upcallset) { | ||||
xprt->xp_upcallset = 0; | xprt->xp_upcallset = 0; | ||||
soupcall_clear(xprt->xp_socket, SO_RCV); | soupcall_clear(xprt->xp_socket, SO_RCV); | ||||
} | } | ||||
SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); | SOLISTEN_UNLOCK(xprt->xp_socket); | ||||
xprt_inactive_self(xprt); | xprt_inactive_self(xprt); | ||||
sx_xunlock(&xprt->xp_lock); | sx_xunlock(&xprt->xp_lock); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
sx_xunlock(&xprt->xp_lock); | sx_xunlock(&xprt->xp_lock); | ||||
sa = NULL; | sa = NULL; | ||||
Show All 30 Lines | |||||
{ | { | ||||
return (XPRT_IDLE); | return (XPRT_IDLE); | ||||
} | } | ||||
static void | static void | ||||
svc_vc_destroy_common(SVCXPRT *xprt) | svc_vc_destroy_common(SVCXPRT *xprt) | ||||
{ | { | ||||
SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); | |||||
if (xprt->xp_upcallset) { | |||||
xprt->xp_upcallset = 0; | |||||
soupcall_clear(xprt->xp_socket, SO_RCV); | |||||
} | |||||
SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); | |||||
if (xprt->xp_socket) | if (xprt->xp_socket) | ||||
(void)soclose(xprt->xp_socket); | (void)soclose(xprt->xp_socket); | ||||
if (xprt->xp_netid) | if (xprt->xp_netid) | ||||
(void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1); | (void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1); | ||||
svc_xprt_free(xprt); | svc_xprt_free(xprt); | ||||
} | } | ||||
static void | static void | ||||
svc_vc_rendezvous_destroy(SVCXPRT *xprt) | svc_vc_rendezvous_destroy(SVCXPRT *xprt) | ||||
{ | { | ||||
SOLISTEN_LOCK(xprt->xp_socket); | |||||
if (xprt->xp_upcallset) { | |||||
xprt->xp_upcallset = 0; | |||||
solisten_upcall_set(xprt->xp_socket, NULL, NULL); | |||||
} | |||||
SOLISTEN_UNLOCK(xprt->xp_socket); | |||||
svc_vc_destroy_common(xprt); | svc_vc_destroy_common(xprt); | ||||
} | } | ||||
static void | static void | ||||
svc_vc_destroy(SVCXPRT *xprt) | svc_vc_destroy(SVCXPRT *xprt) | ||||
{ | { | ||||
struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1; | struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1; | ||||
SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); | |||||
if (xprt->xp_upcallset) { | |||||
xprt->xp_upcallset = 0; | |||||
soupcall_clear(xprt->xp_socket, SO_RCV); | |||||
} | |||||
SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); | |||||
svc_vc_destroy_common(xprt); | svc_vc_destroy_common(xprt); | ||||
if (cd->mreq) | if (cd->mreq) | ||||
m_freem(cd->mreq); | m_freem(cd->mreq); | ||||
if (cd->mpending) | if (cd->mpending) | ||||
m_freem(cd->mpending); | m_freem(cd->mpending); | ||||
mem_free(cd, sizeof(*cd)); | mem_free(cd, sizeof(*cd)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 458 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
svc_vc_soupcall(struct socket *so, void *arg, int waitflag) | svc_vc_soupcall(struct socket *so, void *arg, int waitflag) | ||||
{ | { | ||||
SVCXPRT *xprt = (SVCXPRT *) arg; | SVCXPRT *xprt = (SVCXPRT *) arg; | ||||
if (soreadable(xprt->xp_socket)) | if (soreadable(xprt->xp_socket)) | ||||
xprt_active(xprt); | |||||
return (SU_OK); | |||||
} | |||||
static int | |||||
svc_vc_rendezvous_soupcall(struct socket *head, void *arg, int waitflag) | |||||
{ | |||||
SVCXPRT *xprt = (SVCXPRT *) arg; | |||||
if (!TAILQ_EMPTY(&head->sol_comp)) | |||||
xprt_active(xprt); | xprt_active(xprt); | ||||
return (SU_OK); | return (SU_OK); | ||||
} | } | ||||
#if 0 | #if 0 | ||||
/* | /* | ||||
* Get the effective UID of the sending process. Used by rpcbind, keyserv | * Get the effective UID of the sending process. Used by rpcbind, keyserv | ||||
* and rpc.yppasswdd on AF_LOCAL. | * and rpc.yppasswdd on AF_LOCAL. | ||||
Show All 19 Lines |