2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A/*
2N/A * svc_door.c, Server side for doors IPC based RPC.
2N/A */
2N/A
2N/A#include "mt.h"
2N/A#include "rpc_mt.h"
2N/A#include <stdio.h>
2N/A#include <unistd.h>
2N/A#include <sys/types.h>
2N/A#include <rpc/rpc.h>
2N/A#include <errno.h>
2N/A#include <syslog.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <sys/stat.h>
2N/A#include <door.h>
2N/A#include <alloca.h>
2N/A#include <dlfcn.h>
2N/A#include <limits.h>
2N/A#include <rpc/svc_mt.h>
2N/A
2N/Astatic void svc_door_destroy_pvt();
2N/Astatic int return_xprt_copy();
2N/A
2N/Aint __rpc_default_door_buf_size = 16000;
2N/Aint __rpc_min_door_buf_size = 1000;
2N/A
2N/Astatic struct xp_ops *svc_door_ops();
2N/A
2N/Amutex_t svc_door_mutex = DEFAULTMUTEX;
2N/Acond_t svc_door_waitcv = DEFAULTCV;
2N/Aint svc_ndoorfds = 0;
2N/A
2N/A/*
2N/A * Dispatch information for door calls.
2N/A */
2N/Atypedef struct {
2N/A rpcprog_t prognum;
2N/A rpcvers_t versnum;
2N/A void (*dispatch)();
2N/A} call_info_t;
2N/A
2N/A/*
2N/A * kept in xprt->xp_p2
2N/A */
2N/Astruct svc_door_data {
2N/A uint_t su_iosz; /* size of send/recv buffer */
2N/A uint32_t su_xid; /* transaction id */
2N/A XDR su_xdrs; /* XDR handle */
2N/A char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
2N/A call_info_t call_info; /* dispatch info */
2N/A char *argbuf; /* argument buffer */
2N/A size_t arglen; /* argument length */
2N/A char *buf; /* result buffer */
2N/A int len; /* result length */
2N/A};
2N/A#define su_data(xprt) ((struct svc_door_data *)(xprt->xp_p2))
2N/A
2N/Astatic SVCXPRT *get_xprt_copy();
2N/Astatic bool_t svc_door_recv();
2N/Astatic void svc_door_destroy();
2N/A
2N/Astatic SVCXPRT_LIST *dxlist; /* list of door based service handles */
2N/A
2N/A/*
2N/A * List management routines.
2N/A */
2N/Abool_t
2N/A__svc_add_to_xlist(SVCXPRT_LIST **list, SVCXPRT *xprt, mutex_t *lockp)
2N/A{
2N/A SVCXPRT_LIST *l;
2N/A
2N/A if ((l = malloc(sizeof (*l))) == NULL)
2N/A return (FALSE);
2N/A l->xprt = xprt;
2N/A if (lockp != NULL)
2N/A (void) mutex_lock(lockp);
2N/A l->next = *list;
2N/A *list = l;
2N/A if (lockp != NULL)
2N/A (void) mutex_unlock(lockp);
2N/A return (TRUE);
2N/A}
2N/A
2N/Avoid
2N/A__svc_rm_from_xlist(SVCXPRT_LIST **list, SVCXPRT *xprt, mutex_t *lockp)
2N/A{
2N/A SVCXPRT_LIST **l, *tmp;
2N/A
2N/A if (lockp != NULL)
2N/A (void) mutex_lock(lockp);
2N/A for (l = list; *l != NULL; l = &(*l)->next) {
2N/A if ((*l)->xprt == xprt) {
2N/A tmp = (*l)->next;
2N/A free(*l);
2N/A *l = tmp;
2N/A break;
2N/A }
2N/A }
2N/A if (lockp != NULL)
2N/A (void) mutex_unlock(lockp);
2N/A}
2N/A
2N/Avoid
2N/A__svc_free_xlist(SVCXPRT_LIST **list, mutex_t *lockp)
2N/A{
2N/A SVCXPRT_LIST *tmp;
2N/A
2N/A if (lockp != NULL)
2N/A (void) mutex_lock(lockp);
2N/A while (*list != NULL) {
2N/A tmp = (*list)->next;
2N/A free(*list);
2N/A *list = tmp;
2N/A }
2N/A if (lockp != NULL)
2N/A (void) mutex_unlock(lockp);
2N/A}
2N/A
2N/A/*
2N/A * Destroy all door based service handles.
2N/A */
2N/Avoid
2N/A__svc_cleanup_door_xprts(void)
2N/A{
2N/A SVCXPRT_LIST *l, *tmp = NULL;
2N/A
2N/A (void) mutex_lock(&svc_door_mutex);
2N/A for (l = dxlist; l != NULL; l = tmp) {
2N/A tmp = l->next;
2N/A svc_door_destroy_pvt(l->xprt);
2N/A }
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A}
2N/A
2N/Astatic bool_t
2N/Amake_tmp_dir(void)
2N/A{
2N/A struct stat statbuf;
2N/A
2N/A if (stat(RPC_DOOR_DIR, &statbuf) < 0) {
2N/A (void) mkdir(RPC_DOOR_DIR, (mode_t)0755);
2N/A (void) chmod(RPC_DOOR_DIR, (mode_t)01777);
2N/A if (stat(RPC_DOOR_DIR, &statbuf) < 0)
2N/A return (FALSE);
2N/A }
2N/A return ((statbuf.st_mode & S_IFMT) == S_IFDIR &&
2N/A (statbuf.st_mode & 01777) == 01777);
2N/A}
2N/A
2N/Astatic void
2N/Asvc_door_dispatch(SVCXPRT *xprt, struct rpc_msg *msg, struct svc_req *r)
2N/A{
2N/A enum auth_stat why;
2N/A/* LINTED pointer alignment */
2N/A struct svc_door_data *su = su_data(xprt);
2N/A bool_t nd;
2N/A
2N/A r->rq_xprt = xprt;
2N/A r->rq_prog = msg->rm_call.cb_prog;
2N/A r->rq_vers = msg->rm_call.cb_vers;
2N/A r->rq_proc = msg->rm_call.cb_proc;
2N/A r->rq_cred = msg->rm_call.cb_cred;
2N/A
2N/A if (msg->rm_call.cb_cred.oa_flavor == AUTH_NULL) {
2N/A r->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
2N/A r->rq_xprt->xp_verf.oa_length = 0;
2N/A
2N/A } else if ((why = __gss_authenticate(r, msg, &nd)) != AUTH_OK) {
2N/A svcerr_auth(xprt, why);
2N/A return;
2N/A }
2N/A
2N/A if (su->call_info.prognum == r->rq_prog && su->call_info.versnum ==
2N/A r->rq_vers) {
2N/A (*su->call_info.dispatch)(r, xprt);
2N/A return;
2N/A }
2N/A
2N/A /*
2N/A * if we got here, the program or version
2N/A * is not served ...
2N/A */
2N/A if (su->call_info.prognum == r->rq_prog)
2N/A svcerr_progvers(xprt, su->call_info.versnum,
2N/A su->call_info.versnum);
2N/A else
2N/A svcerr_noprog(xprt);
2N/A}
2N/A
2N/A/*
2N/A * This is the door server procedure.
2N/A */
2N/A/* ARGSUSED */
2N/Astatic void
2N/Adoor_server(void *cookie, char *argp, size_t arg_size,
2N/A door_desc_t *dp, uint_t n_did)
2N/A{
2N/A SVCXPRT *parent = (SVCXPRT *)cookie;
2N/A SVCXPRT *xprt;
2N/A struct rpc_msg *msg;
2N/A struct svc_req *r;
2N/A char *cred_area;
2N/A char *result_buf;
2N/A int len;
2N/A struct svc_door_data *su;
2N/A
2N/A /*
2N/A * allocate result buffer
2N/A */
2N/A/* LINTED pointer alignment */
2N/A result_buf = alloca(su_data(parent)->su_iosz);
2N/A if (result_buf == NULL) {
2N/A (void) syslog(LOG_ERR, "door_server: alloca failed");
2N/A (void) door_return(NULL, 0, NULL, 0);
2N/A /*NOTREACHED*/
2N/A }
2N/A
2N/A (void) mutex_lock(&svc_door_mutex);
2N/A if ((xprt = get_xprt_copy(parent, result_buf)) == NULL) {
2N/A (void) syslog(LOG_ERR,
2N/A "door_server: memory allocation failure");
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A (void) door_return(NULL, 0, NULL, 0);
2N/A /*NOTREACHED*/
2N/A }
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A
2N/A/* LINTED pointer alignment */
2N/A msg = SVCEXT(xprt)->msg;
2N/A/* LINTED pointer alignment */
2N/A r = SVCEXT(xprt)->req;
2N/A/* LINTED pointer alignment */
2N/A cred_area = SVCEXT(xprt)->cred_area;
2N/A
2N/A msg->rm_call.cb_cred.oa_base = cred_area;
2N/A msg->rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
2N/A r->rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
2N/A
2N/A/* LINTED pointer alignment */
2N/A su = su_data(xprt);
2N/A su->argbuf = argp;
2N/A su->arglen = arg_size;
2N/A
2N/A if (svc_door_recv(xprt, msg))
2N/A svc_door_dispatch(xprt, msg, r);
2N/A
2N/A if ((len = return_xprt_copy(xprt)) > 0) {
2N/A (void) door_return(result_buf, (size_t)len, NULL, 0);
2N/A /*NOTREACHED*/
2N/A } else {
2N/A (void) door_return(NULL, 0, NULL, 0);
2N/A /*NOTREACHED*/
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Usage:
2N/A * xprt = svc_door_create(dispatch, prognum, versnum, sendsize);
2N/A * Once *xprt is initialized, it is registered.
2N/A * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
2N/A * system defaults are chosen.
2N/A * The routines returns NULL if a problem occurred.
2N/A */
2N/A
2N/Avoid
2N/Asvc_door_xprtfree(SVCXPRT *xprt)
2N/A{
2N/A/* LINTED pointer alignment */
2N/A struct svc_door_data *su = xprt ? su_data(xprt) : NULL;
2N/A
2N/A if (xprt == NULL)
2N/A return;
2N/A if (xprt->xp_netid)
2N/A free(xprt->xp_netid);
2N/A if (xprt->xp_tp)
2N/A free(xprt->xp_tp);
2N/A if (su != NULL)
2N/A free(su);
2N/A svc_xprt_free(xprt);
2N/A}
2N/A
2N/ASVCXPRT *
2N/Asvc_door_create(void (*dispatch)(), const rpcprog_t prognum,
2N/A const rpcvers_t versnum, const uint_t sendsize)
2N/A{
2N/A SVCXPRT *xprt;
2N/A struct svc_door_data *su = NULL;
2N/A char rendezvous[128] = "";
2N/A int fd;
2N/A int did = -1;
2N/A mode_t mask;
2N/A uint_t ssize;
2N/A
2N/A (void) mutex_lock(&svc_door_mutex);
2N/A
2N/A if (!make_tmp_dir()) {
2N/A (void) syslog(LOG_ERR, "svc_door_create: cannot open %s",
2N/A RPC_DOOR_DIR);
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A return (NULL);
2N/A }
2N/A
2N/A if ((xprt = svc_xprt_alloc()) == NULL) {
2N/A (void) syslog(LOG_ERR, "svc_door_create: out of memory");
2N/A goto freedata;
2N/A }
2N/A/* LINTED pointer alignment */
2N/A svc_flags(xprt) |= SVC_DOOR;
2N/A
2N/A (void) sprintf(rendezvous, RPC_DOOR_RENDEZVOUS, (int)prognum,
2N/A (int)versnum);
2N/A mask = umask(0);
2N/A fd = open(rendezvous, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0644);
2N/A (void) umask(mask);
2N/A if (fd < 0) {
2N/A if (errno == EEXIST) {
2N/A if (unlink(rendezvous) < 0) {
2N/A (void) syslog(LOG_ERR,
2N/A "svc_door_create: %s %s:%m", rendezvous,
2N/A "exists and could not be removed");
2N/A goto freedata;
2N/A }
2N/A mask = umask(0);
2N/A fd = open(rendezvous, O_WRONLY|O_CREAT|O_EXCL|
2N/A O_TRUNC, 0644);
2N/A (void) umask(mask);
2N/A if (fd < 0) {
2N/A (void) syslog(LOG_ERR,
2N/A "svc_door_create: %s %s:%m",
2N/A "could not create", rendezvous);
2N/A goto freedata;
2N/A }
2N/A } else {
2N/A (void) syslog(LOG_ERR,
2N/A "svc_door_create: could not create %s:%m",
2N/A rendezvous);
2N/A goto freedata;
2N/A }
2N/A }
2N/A (void) close(fd);
2N/A did = door_create(door_server, (void *)xprt, DOOR_REFUSE_DESC);
2N/A if (did < 0) {
2N/A (void) syslog(LOG_ERR,
2N/A "svc_door_create: door_create failed: %m");
2N/A goto freedata;
2N/A }
2N/A
2N/A if (fattach(did, rendezvous) < 0) {
2N/A if (errno != EBUSY || fdetach(rendezvous) < 0 ||
2N/A fattach(did, rendezvous) < 0) {
2N/A (void) syslog(LOG_ERR,
2N/A "svc_door_create: fattach failed: %m");
2N/A goto freedata;
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * Determine send size
2N/A */
2N/A if (sendsize < __rpc_min_door_buf_size)
2N/A ssize = __rpc_default_door_buf_size;
2N/A else
2N/A ssize = RNDUP(sendsize);
2N/A
2N/A su = malloc(sizeof (*su));
2N/A if (su == NULL) {
2N/A (void) syslog(LOG_ERR, "svc_door_create: out of memory");
2N/A goto freedata;
2N/A }
2N/A su->su_iosz = ssize;
2N/A su->call_info.prognum = prognum;
2N/A su->call_info.versnum = versnum;
2N/A su->call_info.dispatch = dispatch;
2N/A
2N/A xprt->xp_p2 = (caddr_t)su;
2N/A xprt->xp_verf.oa_base = su->su_verfbody;
2N/A xprt->xp_ops = svc_door_ops();
2N/A xprt->xp_netid = strdup("door");
2N/A if (xprt->xp_netid == NULL) {
2N/A syslog(LOG_ERR, "svc_door_create: strdup failed");
2N/A goto freedata;
2N/A }
2N/A xprt->xp_tp = strdup(rendezvous);
2N/A if (xprt->xp_tp == NULL) {
2N/A syslog(LOG_ERR, "svc_door_create: strdup failed");
2N/A goto freedata;
2N/A }
2N/A xprt->xp_fd = did;
2N/A
2N/A svc_ndoorfds++;
2N/A if (!__svc_add_to_xlist(&dxlist, xprt, NULL)) {
2N/A
2N/A (void) syslog(LOG_ERR, "svc_door_create: out of memory");
2N/A goto freedata;
2N/A }
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A return (xprt);
2N/Afreedata:
2N/A (void) fdetach(rendezvous);
2N/A (void) unlink(rendezvous);
2N/A if (did >= 0)
2N/A (void) door_revoke(did);
2N/A if (xprt)
2N/A svc_door_xprtfree(xprt);
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A return (NULL);
2N/A}
2N/A
2N/A
2N/Astatic SVCXPRT *
2N/Asvc_door_xprtcopy(SVCXPRT *parent)
2N/A{
2N/A SVCXPRT *xprt;
2N/A struct svc_door_data *su;
2N/A
2N/A if ((xprt = svc_xprt_alloc()) == NULL)
2N/A return (NULL);
2N/A
2N/A/* LINTED pointer alignment */
2N/A SVCEXT(xprt)->parent = parent;
2N/A/* LINTED pointer alignment */
2N/A SVCEXT(xprt)->flags = SVCEXT(parent)->flags;
2N/A
2N/A xprt->xp_fd = parent->xp_fd;
2N/A xprt->xp_port = parent->xp_port;
2N/A xprt->xp_ops = svc_door_ops();
2N/A if (parent->xp_tp) {
2N/A xprt->xp_tp = (char *)strdup(parent->xp_tp);
2N/A if (xprt->xp_tp == NULL) {
2N/A syslog(LOG_ERR, "svc_door_xprtcopy: strdup failed");
2N/A svc_door_xprtfree(xprt);
2N/A return (NULL);
2N/A }
2N/A }
2N/A if (parent->xp_netid) {
2N/A xprt->xp_netid = (char *)strdup(parent->xp_netid);
2N/A if (xprt->xp_netid == NULL) {
2N/A syslog(LOG_ERR, "svc_door_xprtcopy: strdup failed");
2N/A if (parent->xp_tp)
2N/A free(parent->xp_tp);
2N/A svc_door_xprtfree(xprt);
2N/A return (NULL);
2N/A }
2N/A }
2N/A xprt->xp_type = parent->xp_type;
2N/A
2N/A if ((su = malloc(sizeof (struct svc_door_data))) == NULL) {
2N/A svc_door_xprtfree(xprt);
2N/A return (NULL);
2N/A }
2N/A/* LINTED pointer alignment */
2N/A su->su_iosz = su_data(parent)->su_iosz;
2N/A/* LINTED pointer alignment */
2N/A su->call_info = su_data(parent)->call_info;
2N/A
2N/A xprt->xp_p2 = (caddr_t)su; /* su_data(xprt) = su */
2N/A xprt->xp_verf.oa_base = su->su_verfbody;
2N/A
2N/A return (xprt);
2N/A}
2N/A
2N/A
2N/Astatic SVCXPRT *
2N/Aget_xprt_copy(SVCXPRT *parent, char *buf)
2N/A{
2N/A/* LINTED pointer alignment */
2N/A SVCXPRT_LIST *xlist = SVCEXT(parent)->my_xlist;
2N/A SVCXPRT_LIST *xret;
2N/A SVCXPRT *xprt;
2N/A struct svc_door_data *su;
2N/A
2N/A xret = xlist->next;
2N/A if (xret) {
2N/A xlist->next = xret->next;
2N/A xret->next = NULL;
2N/A xprt = xret->xprt;
2N/A/* LINTED pointer alignment */
2N/A svc_flags(xprt) = svc_flags(parent);
2N/A } else
2N/A xprt = svc_door_xprtcopy(parent);
2N/A
2N/A if (xprt) {
2N/A/* LINTED pointer alignment */
2N/A SVCEXT(parent)->refcnt++;
2N/A/* LINTED pointer alignment */
2N/A su = su_data(xprt);
2N/A su->buf = buf;
2N/A su->len = 0;
2N/A }
2N/A return (xprt);
2N/A}
2N/A
2N/Aint
2N/Areturn_xprt_copy(SVCXPRT *xprt)
2N/A{
2N/A SVCXPRT *parent;
2N/A SVCXPRT_LIST *xhead, *xlist;
2N/A/* LINTED pointer alignment */
2N/A int len = su_data(xprt)->len;
2N/A
2N/A (void) mutex_lock(&svc_door_mutex);
2N/A/* LINTED pointer alignment */
2N/A if ((parent = SVCEXT(xprt)->parent) == NULL) {
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A return (0);
2N/A }
2N/A/* LINTED pointer alignment */
2N/A xhead = SVCEXT(parent)->my_xlist;
2N/A/* LINTED pointer alignment */
2N/A xlist = SVCEXT(xprt)->my_xlist;
2N/A xlist->next = xhead->next;
2N/A xhead->next = xlist;
2N/A/* LINTED pointer alignment */
2N/A SVCEXT(parent)->refcnt--;
2N/A
2N/A /*
2N/A * Propagate any error flags. This is done in both directions to
2N/A * ensure that if one child gets an error, everyone will see it
2N/A * (even if there are multiple outstanding children) and the
2N/A * door will get closed.
2N/A */
2N/A/* LINTED pointer alignment */
2N/A svc_flags(xprt) |= svc_flags(parent);
2N/A/* LINTED pointer alignment */
2N/A if (svc_defunct(xprt)) {
2N/A/* LINTED pointer alignment */
2N/A svc_flags(parent) |= SVC_DEFUNCT;
2N/A /* LINTED pointer cast */
2N/A if (SVCEXT(parent)->refcnt == 0)
2N/A svc_door_destroy(xprt);
2N/A }
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A return (len);
2N/A}
2N/A
2N/A/* ARGSUSED */
2N/Astatic enum xprt_stat
2N/Asvc_door_stat(SVCXPRT *xprt)
2N/A{
2N/A return (XPRT_IDLE);
2N/A}
2N/A
2N/Astatic bool_t
2N/Asvc_door_recv(SVCXPRT *xprt, struct rpc_msg *msg)
2N/A{
2N/A/* LINTED pointer alignment */
2N/A struct svc_door_data *su = su_data(xprt);
2N/A XDR *xdrs = &(su->su_xdrs);
2N/A
2N/A xdrmem_create(xdrs, su->argbuf, su->arglen, XDR_DECODE);
2N/A if (!xdr_callmsg(xdrs, msg))
2N/A return (FALSE);
2N/A su->su_xid = msg->rm_xid;
2N/A return (TRUE);
2N/A}
2N/A
2N/Astatic bool_t
2N/Asvc_door_reply(SVCXPRT *xprt, struct rpc_msg *msg)
2N/A{
2N/A/* LINTED pointer alignment */
2N/A struct svc_door_data *su = su_data(xprt);
2N/A XDR *xdrs = &(su->su_xdrs);
2N/A
2N/A xdrmem_create(xdrs, su->buf, su->su_iosz, XDR_ENCODE);
2N/A msg->rm_xid = su->su_xid;
2N/A if (xdr_replymsg(xdrs, msg)) {
2N/A su->len = (int)XDR_GETPOS(xdrs);
2N/A return (TRUE);
2N/A }
2N/A return (FALSE);
2N/A}
2N/A
2N/Astatic bool_t
2N/Asvc_door_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
2N/A{
2N/A/* LINTED pointer alignment */
2N/A return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
2N/A}
2N/A
2N/Astatic bool_t
2N/Asvc_door_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
2N/A{
2N/A/* LINTED pointer alignment */
2N/A XDR *xdrs = &(su_data(xprt)->su_xdrs);
2N/A
2N/A xdrs->x_op = XDR_FREE;
2N/A return ((*xdr_args)(xdrs, args_ptr));
2N/A}
2N/A
2N/Astatic void
2N/Asvc_door_destroy(SVCXPRT *xprt)
2N/A{
2N/A (void) mutex_lock(&svc_door_mutex);
2N/A svc_door_destroy_pvt(xprt);
2N/A (void) mutex_unlock(&svc_door_mutex);
2N/A}
2N/A
2N/Astatic void
2N/Asvc_door_destroy_pvt(SVCXPRT *xprt)
2N/A{
2N/A/* LINTED pointer alignment */
2N/A if (SVCEXT(xprt)->parent)
2N/A/* LINTED pointer alignment */
2N/A xprt = SVCEXT(xprt)->parent;
2N/A/* LINTED pointer alignment */
2N/A svc_flags(xprt) |= SVC_DEFUNCT;
2N/A/* LINTED pointer alignment */
2N/A if (SVCEXT(xprt)->refcnt > 0)
2N/A return;
2N/A
2N/A __svc_rm_from_xlist(&dxlist, xprt, NULL);
2N/A
2N/A if (xprt->xp_tp) {
2N/A (void) fdetach(xprt->xp_tp);
2N/A (void) unlink(xprt->xp_tp);
2N/A }
2N/A (void) door_revoke(xprt->xp_fd);
2N/A
2N/A svc_xprt_destroy(xprt);
2N/A if (--svc_ndoorfds == 0)
2N/A /* wake up door dispatching */
2N/A (void) cond_signal(&svc_door_waitcv);
2N/A}
2N/A
2N/A/* ARGSUSED */
2N/Astatic bool_t
2N/Asvc_door_control(SVCXPRT *xprt, const uint_t rq, void *in)
2N/A{
2N/A extern int __rpc_legal_connmaxrec(int);
2N/A
2N/A size_t door_param;
2N/A int tmp;
2N/A
2N/A switch (rq) {
2N/A case SVCSET_CONNMAXREC:
2N/A tmp = __rpc_legal_connmaxrec(*(int *)in);
2N/A if (tmp >= 0) {
2N/A door_param = (tmp == 0)? SIZE_MAX :
2N/A (size_t)(ssize_t)tmp;
2N/A if (door_setparam(xprt->xp_fd, DOOR_PARAM_DATA_MAX,
2N/A door_param) == 0)
2N/A return (TRUE);
2N/A return (FALSE);
2N/A }
2N/A return (FALSE);
2N/A case SVCGET_CONNMAXREC:
2N/A if (door_getparam(xprt->xp_fd, DOOR_PARAM_DATA_MAX,
2N/A &door_param) == 0) {
2N/A if (door_param == SIZE_MAX)
2N/A tmp = 0;
2N/A else if (door_param > INT_MAX)
2N/A tmp = INT_MAX;
2N/A else if (door_param > 0)
2N/A tmp = (int)door_param;
2N/A else
2N/A return (FALSE);
2N/A
2N/A *(int *)in = tmp;
2N/A return (TRUE);
2N/A }
2N/A return (FALSE);
2N/A }
2N/A return (FALSE);
2N/A}
2N/A
2N/Astatic struct xp_ops *
2N/Asvc_door_ops(void)
2N/A{
2N/A static struct xp_ops ops;
2N/A extern mutex_t ops_lock;
2N/A
2N/A (void) mutex_lock(&ops_lock);
2N/A if (ops.xp_recv == NULL) {
2N/A ops.xp_recv = svc_door_recv;
2N/A ops.xp_stat = svc_door_stat;
2N/A ops.xp_getargs = svc_door_getargs;
2N/A ops.xp_reply = svc_door_reply;
2N/A ops.xp_freeargs = svc_door_freeargs;
2N/A ops.xp_destroy = svc_door_destroy;
2N/A ops.xp_control = svc_door_control;
2N/A }
2N/A (void) mutex_unlock(&ops_lock);
2N/A return (&ops);
2N/A}
2N/A
2N/A/*
2N/A * Return door credentials.
2N/A */
2N/A/* ARGSUSED */
2N/Abool_t
2N/A__svc_get_door_cred(SVCXPRT *xprt, svc_local_cred_t *lcred)
2N/A{
2N/A door_cred_t dc;
2N/A
2N/A if (door_cred(&dc) < 0)
2N/A return (FALSE);
2N/A lcred->euid = dc.dc_euid;
2N/A lcred->egid = dc.dc_egid;
2N/A lcred->ruid = dc.dc_ruid;
2N/A lcred->rgid = dc.dc_rgid;
2N/A lcred->pid = dc.dc_pid;
2N/A return (TRUE);
2N/A}
2N/A
2N/A/* ARGSUSED */
2N/Abool_t
2N/A__svc_get_door_ucred(const SVCXPRT *xprt, ucred_t *ucp)
2N/A{
2N/A return (door_ucred(&ucp) == 0);
2N/A}