xref: /illumos-gate/usr/src/lib/libnsl/rpc/svc_door.c (revision 0900f4f20e4cdeb8e5af4ba32aca32d28aeba2f9)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
567dbe2beSCasper H.S. Dik  * Common Development and Distribution License (the "License").
667dbe2beSCasper H.S. Dik  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2161961e0fSrobinson 
227c478bd9Sstevel@tonic-gate /*
2367dbe2beSCasper H.S. Dik  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
26*0900f4f2SMarcel Telka /*
27*0900f4f2SMarcel Telka  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
28*0900f4f2SMarcel Telka  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * svc_door.c, Server side for doors IPC based RPC.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include "mt.h"
357c478bd9Sstevel@tonic-gate #include "rpc_mt.h"
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <syslog.h>
427c478bd9Sstevel@tonic-gate #include <stdlib.h>
437c478bd9Sstevel@tonic-gate #include <string.h>
447c478bd9Sstevel@tonic-gate #include <sys/stat.h>
457c478bd9Sstevel@tonic-gate #include <door.h>
467c478bd9Sstevel@tonic-gate #include <alloca.h>
477c478bd9Sstevel@tonic-gate #include <dlfcn.h>
487c478bd9Sstevel@tonic-gate #include <limits.h>
497c478bd9Sstevel@tonic-gate #include <rpc/svc_mt.h>
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static void svc_door_destroy_pvt();
527c478bd9Sstevel@tonic-gate static int return_xprt_copy();
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate int __rpc_default_door_buf_size = 16000;
557c478bd9Sstevel@tonic-gate int __rpc_min_door_buf_size = 1000;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate static struct xp_ops *svc_door_ops();
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate mutex_t	svc_door_mutex = DEFAULTMUTEX;
607c478bd9Sstevel@tonic-gate cond_t	svc_door_waitcv = DEFAULTCV;
617c478bd9Sstevel@tonic-gate int	svc_ndoorfds = 0;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * Dispatch information for door calls.
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate typedef struct {
677c478bd9Sstevel@tonic-gate 	rpcprog_t		prognum;
687c478bd9Sstevel@tonic-gate 	rpcvers_t		versnum;
697c478bd9Sstevel@tonic-gate 	void			(*dispatch)();
707c478bd9Sstevel@tonic-gate } call_info_t;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /*
737c478bd9Sstevel@tonic-gate  * kept in xprt->xp_p2
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate struct svc_door_data {
767c478bd9Sstevel@tonic-gate 	uint_t   	su_iosz;		/* size of send/recv buffer */
777c478bd9Sstevel@tonic-gate 	uint32_t	su_xid;			/* transaction id */
787c478bd9Sstevel@tonic-gate 	XDR		su_xdrs;		/* XDR handle */
797c478bd9Sstevel@tonic-gate 	char		su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
807c478bd9Sstevel@tonic-gate 	call_info_t	call_info;		/* dispatch info */
817c478bd9Sstevel@tonic-gate 	char		*argbuf;		/* argument buffer */
827c478bd9Sstevel@tonic-gate 	size_t		arglen;			/* argument length */
837c478bd9Sstevel@tonic-gate 	char		*buf;			/* result buffer */
847c478bd9Sstevel@tonic-gate 	int		len;			/* result length */
857c478bd9Sstevel@tonic-gate };
867c478bd9Sstevel@tonic-gate #define	su_data(xprt)	((struct svc_door_data *)(xprt->xp_p2))
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static SVCXPRT *get_xprt_copy();
897c478bd9Sstevel@tonic-gate static bool_t svc_door_recv();
907c478bd9Sstevel@tonic-gate static void svc_door_destroy();
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate static SVCXPRT_LIST *dxlist;	/* list of door based service handles */
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * List management routines.
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate bool_t
__svc_add_to_xlist(SVCXPRT_LIST ** list,SVCXPRT * xprt,mutex_t * lockp)9861961e0fSrobinson __svc_add_to_xlist(SVCXPRT_LIST **list, SVCXPRT *xprt, mutex_t *lockp)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	SVCXPRT_LIST	*l;
1017c478bd9Sstevel@tonic-gate 
10261961e0fSrobinson 	if ((l = malloc(sizeof (*l))) == NULL)
1037c478bd9Sstevel@tonic-gate 		return (FALSE);
1047c478bd9Sstevel@tonic-gate 	l->xprt = xprt;
1057c478bd9Sstevel@tonic-gate 	if (lockp != NULL)
10661961e0fSrobinson 		(void) mutex_lock(lockp);
1077c478bd9Sstevel@tonic-gate 	l->next = *list;
1087c478bd9Sstevel@tonic-gate 	*list = l;
1097c478bd9Sstevel@tonic-gate 	if (lockp != NULL)
11061961e0fSrobinson 		(void) mutex_unlock(lockp);
1117c478bd9Sstevel@tonic-gate 	return (TRUE);
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate void
__svc_rm_from_xlist(SVCXPRT_LIST ** list,SVCXPRT * xprt,mutex_t * lockp)11561961e0fSrobinson __svc_rm_from_xlist(SVCXPRT_LIST **list, SVCXPRT *xprt, mutex_t *lockp)
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate 	SVCXPRT_LIST	**l, *tmp;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	if (lockp != NULL)
12061961e0fSrobinson 		(void) mutex_lock(lockp);
1217c478bd9Sstevel@tonic-gate 	for (l = list; *l != NULL; l = &(*l)->next) {
1227c478bd9Sstevel@tonic-gate 		if ((*l)->xprt == xprt) {
1237c478bd9Sstevel@tonic-gate 			tmp = (*l)->next;
12461961e0fSrobinson 			free(*l);
1257c478bd9Sstevel@tonic-gate 			*l = tmp;
1267c478bd9Sstevel@tonic-gate 			break;
1277c478bd9Sstevel@tonic-gate 		}
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 	if (lockp != NULL)
13061961e0fSrobinson 		(void) mutex_unlock(lockp);
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate void
__svc_free_xlist(SVCXPRT_LIST ** list,mutex_t * lockp)13461961e0fSrobinson __svc_free_xlist(SVCXPRT_LIST **list, mutex_t *lockp)
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	SVCXPRT_LIST	*tmp;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	if (lockp != NULL)
13961961e0fSrobinson 		(void) mutex_lock(lockp);
1407c478bd9Sstevel@tonic-gate 	while (*list != NULL) {
1417c478bd9Sstevel@tonic-gate 		tmp = (*list)->next;
1427c478bd9Sstevel@tonic-gate 		free(*list);
1437c478bd9Sstevel@tonic-gate 		*list = tmp;
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 	if (lockp != NULL)
14661961e0fSrobinson 		(void) mutex_unlock(lockp);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * Destroy all door based service handles.
1517c478bd9Sstevel@tonic-gate  */
1527c478bd9Sstevel@tonic-gate void
__svc_cleanup_door_xprts(void)15361961e0fSrobinson __svc_cleanup_door_xprts(void)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	SVCXPRT_LIST	*l, *tmp = NULL;
1567c478bd9Sstevel@tonic-gate 
15761961e0fSrobinson 	(void) mutex_lock(&svc_door_mutex);
1587c478bd9Sstevel@tonic-gate 	for (l = dxlist; l != NULL; l = tmp) {
1597c478bd9Sstevel@tonic-gate 		tmp = l->next;
1607c478bd9Sstevel@tonic-gate 		svc_door_destroy_pvt(l->xprt);
1617c478bd9Sstevel@tonic-gate 	}
16261961e0fSrobinson 	(void) mutex_unlock(&svc_door_mutex);
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate static bool_t
make_tmp_dir(void)16661961e0fSrobinson make_tmp_dir(void)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	struct stat statbuf;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (stat(RPC_DOOR_DIR, &statbuf) < 0) {
1717c478bd9Sstevel@tonic-gate 		(void) mkdir(RPC_DOOR_DIR, (mode_t)0755);
1727c478bd9Sstevel@tonic-gate 		(void) chmod(RPC_DOOR_DIR, (mode_t)01777);
1737c478bd9Sstevel@tonic-gate 		if (stat(RPC_DOOR_DIR, &statbuf) < 0)
1747c478bd9Sstevel@tonic-gate 			return (FALSE);
1757c478bd9Sstevel@tonic-gate 	}
1767c478bd9Sstevel@tonic-gate 	return ((statbuf.st_mode & S_IFMT) == S_IFDIR &&
1777c478bd9Sstevel@tonic-gate 	    (statbuf.st_mode & 01777) == 01777);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate static void
svc_door_dispatch(SVCXPRT * xprt,struct rpc_msg * msg,struct svc_req * r)18161961e0fSrobinson svc_door_dispatch(SVCXPRT *xprt, struct rpc_msg *msg, struct svc_req *r)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate 	enum auth_stat		why;
1847c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
1857c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su = su_data(xprt);
1867c478bd9Sstevel@tonic-gate 	bool_t nd;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	r->rq_xprt = xprt;
1897c478bd9Sstevel@tonic-gate 	r->rq_prog = msg->rm_call.cb_prog;
1907c478bd9Sstevel@tonic-gate 	r->rq_vers = msg->rm_call.cb_vers;
1917c478bd9Sstevel@tonic-gate 	r->rq_proc = msg->rm_call.cb_proc;
1927c478bd9Sstevel@tonic-gate 	r->rq_cred = msg->rm_call.cb_cred;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (msg->rm_call.cb_cred.oa_flavor == AUTH_NULL) {
1957c478bd9Sstevel@tonic-gate 		r->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
1967c478bd9Sstevel@tonic-gate 		r->rq_xprt->xp_verf.oa_length = 0;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	} else if ((why = __gss_authenticate(r, msg, &nd)) != AUTH_OK) {
1997c478bd9Sstevel@tonic-gate 		svcerr_auth(xprt, why);
2007c478bd9Sstevel@tonic-gate 		return;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	if (su->call_info.prognum == r->rq_prog && su->call_info.versnum ==
2047c478bd9Sstevel@tonic-gate 	    r->rq_vers) {
2057c478bd9Sstevel@tonic-gate 		(*su->call_info.dispatch)(r, xprt);
2067c478bd9Sstevel@tonic-gate 		return;
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	/*
2107c478bd9Sstevel@tonic-gate 	 * if we got here, the program or version
2117c478bd9Sstevel@tonic-gate 	 * is not served ...
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 	if (su->call_info.prognum == r->rq_prog)
2147c478bd9Sstevel@tonic-gate 		svcerr_progvers(xprt, su->call_info.versnum,
2157c478bd9Sstevel@tonic-gate 		    su->call_info.versnum);
2167c478bd9Sstevel@tonic-gate 	else
2177c478bd9Sstevel@tonic-gate 		svcerr_noprog(xprt);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate  * This is the door server procedure.
2227c478bd9Sstevel@tonic-gate  */
2237c478bd9Sstevel@tonic-gate /* ARGSUSED */
2247c478bd9Sstevel@tonic-gate static void
door_server(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_did)2257c478bd9Sstevel@tonic-gate door_server(void *cookie, char *argp, size_t arg_size,
2267c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t n_did)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 	SVCXPRT			*parent = (SVCXPRT *)cookie;
2297c478bd9Sstevel@tonic-gate 	SVCXPRT			*xprt;
2307c478bd9Sstevel@tonic-gate 	struct rpc_msg		*msg;
2317c478bd9Sstevel@tonic-gate 	struct svc_req		*r;
2327c478bd9Sstevel@tonic-gate 	char			*cred_area;
2337c478bd9Sstevel@tonic-gate 	char			*result_buf;
2347c478bd9Sstevel@tonic-gate 	int			len;
2357c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/*
2387c478bd9Sstevel@tonic-gate 	 * allocate result buffer
2397c478bd9Sstevel@tonic-gate 	 */
2407c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
24161961e0fSrobinson 	result_buf = alloca(su_data(parent)->su_iosz);
2427c478bd9Sstevel@tonic-gate 	if (result_buf == NULL) {
2437c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR, "door_server: alloca failed");
2447c478bd9Sstevel@tonic-gate 		(void) door_return(NULL, 0, NULL, 0);
2457c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate 
24861961e0fSrobinson 	(void) mutex_lock(&svc_door_mutex);
2497c478bd9Sstevel@tonic-gate 	if ((xprt = get_xprt_copy(parent, result_buf)) == NULL) {
2507c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR,
2517c478bd9Sstevel@tonic-gate 		    "door_server: memory allocation failure");
25261961e0fSrobinson 		(void) mutex_unlock(&svc_door_mutex);
2537c478bd9Sstevel@tonic-gate 		(void) door_return(NULL, 0, NULL, 0);
2547c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
2557c478bd9Sstevel@tonic-gate 	}
25661961e0fSrobinson 	(void) mutex_unlock(&svc_door_mutex);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
2597c478bd9Sstevel@tonic-gate 	msg = SVCEXT(xprt)->msg;
2607c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
2617c478bd9Sstevel@tonic-gate 	r = SVCEXT(xprt)->req;
2627c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
2637c478bd9Sstevel@tonic-gate 	cred_area = SVCEXT(xprt)->cred_area;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	msg->rm_call.cb_cred.oa_base = cred_area;
2667c478bd9Sstevel@tonic-gate 	msg->rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
2677c478bd9Sstevel@tonic-gate 	r->rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
2707c478bd9Sstevel@tonic-gate 	su = su_data(xprt);
2717c478bd9Sstevel@tonic-gate 	su->argbuf = argp;
2727c478bd9Sstevel@tonic-gate 	su->arglen = arg_size;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	if (svc_door_recv(xprt, msg))
2757c478bd9Sstevel@tonic-gate 		svc_door_dispatch(xprt, msg, r);
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	if ((len = return_xprt_copy(xprt)) > 0) {
2787c478bd9Sstevel@tonic-gate 		(void) door_return(result_buf, (size_t)len, NULL, 0);
2797c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
2807c478bd9Sstevel@tonic-gate 	} else {
2817c478bd9Sstevel@tonic-gate 		(void) door_return(NULL, 0, NULL, 0);
2827c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate  * Usage:
2887c478bd9Sstevel@tonic-gate  *	xprt = svc_door_create(dispatch, prognum, versnum, sendsize);
2897c478bd9Sstevel@tonic-gate  * Once *xprt is initialized, it is registered.
2907c478bd9Sstevel@tonic-gate  * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
2917c478bd9Sstevel@tonic-gate  * system defaults are chosen.
2927c478bd9Sstevel@tonic-gate  * The routines returns NULL if a problem occurred.
2937c478bd9Sstevel@tonic-gate  */
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate void
svc_door_xprtfree(SVCXPRT * xprt)29661961e0fSrobinson svc_door_xprtfree(SVCXPRT *xprt)
2977c478bd9Sstevel@tonic-gate {
2987c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
2997c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su = xprt ? su_data(xprt) : NULL;
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	if (xprt == NULL)
3027c478bd9Sstevel@tonic-gate 		return;
3037c478bd9Sstevel@tonic-gate 	if (xprt->xp_netid)
30461961e0fSrobinson 		free(xprt->xp_netid);
3057c478bd9Sstevel@tonic-gate 	if (xprt->xp_tp)
30661961e0fSrobinson 		free(xprt->xp_tp);
3077c478bd9Sstevel@tonic-gate 	if (su != NULL)
30861961e0fSrobinson 		free(su);
3097c478bd9Sstevel@tonic-gate 	svc_xprt_free(xprt);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate SVCXPRT *
svc_door_create(void (* dispatch)(),const rpcprog_t prognum,const rpcvers_t versnum,const uint_t sendsize)31361961e0fSrobinson svc_door_create(void (*dispatch)(), const rpcprog_t prognum,
31461961e0fSrobinson 				const rpcvers_t versnum, const uint_t sendsize)
3157c478bd9Sstevel@tonic-gate {
3167c478bd9Sstevel@tonic-gate 	SVCXPRT			*xprt;
3177c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su = NULL;
3187c478bd9Sstevel@tonic-gate 	char			rendezvous[128] = "";
3197c478bd9Sstevel@tonic-gate 	int			fd;
3207c478bd9Sstevel@tonic-gate 	int			did = -1;
3217c478bd9Sstevel@tonic-gate 	mode_t			mask;
32261961e0fSrobinson 	uint_t			ssize;
3237c478bd9Sstevel@tonic-gate 
32461961e0fSrobinson 	(void) mutex_lock(&svc_door_mutex);
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	if (!make_tmp_dir()) {
3277c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR, "svc_door_create: cannot open %s",
3287c478bd9Sstevel@tonic-gate 		    RPC_DOOR_DIR);
32961961e0fSrobinson 		(void) mutex_unlock(&svc_door_mutex);
33061961e0fSrobinson 		return (NULL);
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	if ((xprt = svc_xprt_alloc()) == NULL) {
3347c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR, "svc_door_create: out of memory");
3357c478bd9Sstevel@tonic-gate 		goto freedata;
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
3387c478bd9Sstevel@tonic-gate 	svc_flags(xprt) |= SVC_DOOR;
3397c478bd9Sstevel@tonic-gate 
34061961e0fSrobinson 	(void) sprintf(rendezvous, RPC_DOOR_RENDEZVOUS, (int)prognum,
34161961e0fSrobinson 	    (int)versnum);
3427c478bd9Sstevel@tonic-gate 	mask = umask(0);
3437c478bd9Sstevel@tonic-gate 	fd =  open(rendezvous, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0644);
3447c478bd9Sstevel@tonic-gate 	(void) umask(mask);
3457c478bd9Sstevel@tonic-gate 	if (fd < 0) {
3467c478bd9Sstevel@tonic-gate 		if (errno == EEXIST) {
3477c478bd9Sstevel@tonic-gate 			if (unlink(rendezvous) < 0) {
3487c478bd9Sstevel@tonic-gate 				(void) syslog(LOG_ERR,
3497c478bd9Sstevel@tonic-gate 				    "svc_door_create: %s %s:%m", rendezvous,
3507c478bd9Sstevel@tonic-gate 				    "exists and could not be removed");
3517c478bd9Sstevel@tonic-gate 				goto freedata;
3527c478bd9Sstevel@tonic-gate 			}
3537c478bd9Sstevel@tonic-gate 			mask = umask(0);
3547c478bd9Sstevel@tonic-gate 			fd =  open(rendezvous, O_WRONLY | O_CREAT | O_EXCL |
3557c478bd9Sstevel@tonic-gate 			    O_TRUNC, 0644);
3567c478bd9Sstevel@tonic-gate 			(void) umask(mask);
3577c478bd9Sstevel@tonic-gate 			if (fd < 0) {
3587c478bd9Sstevel@tonic-gate 				(void) syslog(LOG_ERR,
3597c478bd9Sstevel@tonic-gate 				    "svc_door_create: %s %s:%m",
3607c478bd9Sstevel@tonic-gate 				    "could not create", rendezvous);
3617c478bd9Sstevel@tonic-gate 				goto freedata;
3627c478bd9Sstevel@tonic-gate 			}
3637c478bd9Sstevel@tonic-gate 		} else {
3647c478bd9Sstevel@tonic-gate 			(void) syslog(LOG_ERR,
3657c478bd9Sstevel@tonic-gate 			    "svc_door_create: could not create %s:%m",
3667c478bd9Sstevel@tonic-gate 			    rendezvous);
3677c478bd9Sstevel@tonic-gate 			goto freedata;
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 	}
37061961e0fSrobinson 	(void) close(fd);
3717c478bd9Sstevel@tonic-gate 	did = door_create(door_server, (void *)xprt, DOOR_REFUSE_DESC);
3727c478bd9Sstevel@tonic-gate 	if (did < 0) {
3737c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR,
3747c478bd9Sstevel@tonic-gate 		    "svc_door_create: door_create failed: %m");
3757c478bd9Sstevel@tonic-gate 		goto freedata;
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	if (fattach(did, rendezvous) < 0) {
3797c478bd9Sstevel@tonic-gate 		if (errno != EBUSY || fdetach(rendezvous) < 0 ||
3807c478bd9Sstevel@tonic-gate 		    fattach(did, rendezvous) < 0) {
3817c478bd9Sstevel@tonic-gate 			(void) syslog(LOG_ERR,
3827c478bd9Sstevel@tonic-gate 			    "svc_door_create: fattach failed: %m");
3837c478bd9Sstevel@tonic-gate 			goto freedata;
3847c478bd9Sstevel@tonic-gate 		}
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/*
3887c478bd9Sstevel@tonic-gate 	 * Determine send size
3897c478bd9Sstevel@tonic-gate 	 */
3907c478bd9Sstevel@tonic-gate 	if (sendsize < __rpc_min_door_buf_size)
39161961e0fSrobinson 		ssize = __rpc_default_door_buf_size;
3927c478bd9Sstevel@tonic-gate 	else
39361961e0fSrobinson 		ssize = RNDUP(sendsize);
3947c478bd9Sstevel@tonic-gate 
39561961e0fSrobinson 	su = malloc(sizeof (*su));
3967c478bd9Sstevel@tonic-gate 	if (su == NULL) {
3977c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR, "svc_door_create: out of memory");
3987c478bd9Sstevel@tonic-gate 		goto freedata;
3997c478bd9Sstevel@tonic-gate 	}
40061961e0fSrobinson 	su->su_iosz = ssize;
4017c478bd9Sstevel@tonic-gate 	su->call_info.prognum = prognum;
4027c478bd9Sstevel@tonic-gate 	su->call_info.versnum = versnum;
4037c478bd9Sstevel@tonic-gate 	su->call_info.dispatch = dispatch;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	xprt->xp_p2 = (caddr_t)su;
4067c478bd9Sstevel@tonic-gate 	xprt->xp_verf.oa_base = su->su_verfbody;
4077c478bd9Sstevel@tonic-gate 	xprt->xp_ops = svc_door_ops();
4087c478bd9Sstevel@tonic-gate 	xprt->xp_netid = strdup("door");
4097c478bd9Sstevel@tonic-gate 	if (xprt->xp_netid == NULL) {
4107c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "svc_door_create: strdup failed");
4117c478bd9Sstevel@tonic-gate 		goto freedata;
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 	xprt->xp_tp = strdup(rendezvous);
4147c478bd9Sstevel@tonic-gate 	if (xprt->xp_tp == NULL) {
4157c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "svc_door_create: strdup failed");
4167c478bd9Sstevel@tonic-gate 		goto freedata;
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate 	xprt->xp_fd = did;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	svc_ndoorfds++;
42161961e0fSrobinson 	if (!__svc_add_to_xlist(&dxlist, xprt, NULL)) {
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_ERR, "svc_door_create: out of memory");
4247c478bd9Sstevel@tonic-gate 		goto freedata;
4257c478bd9Sstevel@tonic-gate 	}
42661961e0fSrobinson 	(void) mutex_unlock(&svc_door_mutex);
4277c478bd9Sstevel@tonic-gate 	return (xprt);
4287c478bd9Sstevel@tonic-gate freedata:
4297c478bd9Sstevel@tonic-gate 	(void) fdetach(rendezvous);
4307c478bd9Sstevel@tonic-gate 	(void) unlink(rendezvous);
4317c478bd9Sstevel@tonic-gate 	if (did >= 0)
4327c478bd9Sstevel@tonic-gate 		(void) door_revoke(did);
4337c478bd9Sstevel@tonic-gate 	if (xprt)
4347c478bd9Sstevel@tonic-gate 		svc_door_xprtfree(xprt);
43561961e0fSrobinson 	(void) mutex_unlock(&svc_door_mutex);
43661961e0fSrobinson 	return (NULL);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate static SVCXPRT *
svc_door_xprtcopy(SVCXPRT * parent)44161961e0fSrobinson svc_door_xprtcopy(SVCXPRT *parent)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	SVCXPRT			*xprt;
4447c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if ((xprt = svc_xprt_alloc()) == NULL)
4477c478bd9Sstevel@tonic-gate 		return (NULL);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
4507c478bd9Sstevel@tonic-gate 	SVCEXT(xprt)->parent = parent;
4517c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
4527c478bd9Sstevel@tonic-gate 	SVCEXT(xprt)->flags = SVCEXT(parent)->flags;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	xprt->xp_fd = parent->xp_fd;
4557c478bd9Sstevel@tonic-gate 	xprt->xp_port = parent->xp_port;
4567c478bd9Sstevel@tonic-gate 	xprt->xp_ops = svc_door_ops();
4577c478bd9Sstevel@tonic-gate 	if (parent->xp_tp) {
4587c478bd9Sstevel@tonic-gate 		xprt->xp_tp = (char *)strdup(parent->xp_tp);
4597c478bd9Sstevel@tonic-gate 		if (xprt->xp_tp == NULL) {
4607c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "svc_door_xprtcopy: strdup failed");
4617c478bd9Sstevel@tonic-gate 			svc_door_xprtfree(xprt);
4627c478bd9Sstevel@tonic-gate 			return (NULL);
4637c478bd9Sstevel@tonic-gate 		}
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 	if (parent->xp_netid) {
4667c478bd9Sstevel@tonic-gate 		xprt->xp_netid = (char *)strdup(parent->xp_netid);
4677c478bd9Sstevel@tonic-gate 		if (xprt->xp_netid == NULL) {
4687c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "svc_door_xprtcopy: strdup failed");
4697c478bd9Sstevel@tonic-gate 			if (parent->xp_tp)
47061961e0fSrobinson 				free(parent->xp_tp);
4717c478bd9Sstevel@tonic-gate 			svc_door_xprtfree(xprt);
4727c478bd9Sstevel@tonic-gate 			return (NULL);
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 	xprt->xp_type = parent->xp_type;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	if ((su = malloc(sizeof (struct svc_door_data))) == NULL) {
4787c478bd9Sstevel@tonic-gate 		svc_door_xprtfree(xprt);
4797c478bd9Sstevel@tonic-gate 		return (NULL);
4807c478bd9Sstevel@tonic-gate 	}
4817c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
4827c478bd9Sstevel@tonic-gate 	su->su_iosz = su_data(parent)->su_iosz;
4837c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
4847c478bd9Sstevel@tonic-gate 	su->call_info = su_data(parent)->call_info;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	xprt->xp_p2 = (caddr_t)su;	/* su_data(xprt) = su */
4877c478bd9Sstevel@tonic-gate 	xprt->xp_verf.oa_base = su->su_verfbody;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	return (xprt);
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate static SVCXPRT *
get_xprt_copy(SVCXPRT * parent,char * buf)49461961e0fSrobinson get_xprt_copy(SVCXPRT *parent, char *buf)
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
4977c478bd9Sstevel@tonic-gate 	SVCXPRT_LIST		*xlist = SVCEXT(parent)->my_xlist;
4987c478bd9Sstevel@tonic-gate 	SVCXPRT_LIST		*xret;
4997c478bd9Sstevel@tonic-gate 	SVCXPRT			*xprt;
5007c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	xret = xlist->next;
5037c478bd9Sstevel@tonic-gate 	if (xret) {
5047c478bd9Sstevel@tonic-gate 		xlist->next = xret->next;
5057c478bd9Sstevel@tonic-gate 		xret->next = NULL;
5067c478bd9Sstevel@tonic-gate 		xprt = xret->xprt;
5077c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5087c478bd9Sstevel@tonic-gate 		svc_flags(xprt) = svc_flags(parent);
5097c478bd9Sstevel@tonic-gate 	} else
5107c478bd9Sstevel@tonic-gate 		xprt = svc_door_xprtcopy(parent);
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	if (xprt) {
5137c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5147c478bd9Sstevel@tonic-gate 		SVCEXT(parent)->refcnt++;
5157c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5167c478bd9Sstevel@tonic-gate 		su = su_data(xprt);
5177c478bd9Sstevel@tonic-gate 		su->buf = buf;
5187c478bd9Sstevel@tonic-gate 		su->len = 0;
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 	return (xprt);
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate int
return_xprt_copy(SVCXPRT * xprt)52461961e0fSrobinson return_xprt_copy(SVCXPRT *xprt)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate 	SVCXPRT		*parent;
5277c478bd9Sstevel@tonic-gate 	SVCXPRT_LIST	*xhead, *xlist;
5287c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5297c478bd9Sstevel@tonic-gate 	int		len = su_data(xprt)->len;
5307c478bd9Sstevel@tonic-gate 
53161961e0fSrobinson 	(void) mutex_lock(&svc_door_mutex);
5327c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5337c478bd9Sstevel@tonic-gate 	if ((parent = SVCEXT(xprt)->parent) == NULL) {
53461961e0fSrobinson 		(void) mutex_unlock(&svc_door_mutex);
5357c478bd9Sstevel@tonic-gate 		return (0);
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5387c478bd9Sstevel@tonic-gate 	xhead = SVCEXT(parent)->my_xlist;
5397c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5407c478bd9Sstevel@tonic-gate 	xlist = SVCEXT(xprt)->my_xlist;
5417c478bd9Sstevel@tonic-gate 	xlist->next = xhead->next;
5427c478bd9Sstevel@tonic-gate 	xhead->next = xlist;
5437c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5447c478bd9Sstevel@tonic-gate 	SVCEXT(parent)->refcnt--;
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	/*
5477c478bd9Sstevel@tonic-gate 	 * Propagate any error flags.  This is done in both directions to
5487c478bd9Sstevel@tonic-gate 	 * ensure that if one child gets an error, everyone will see it
5497c478bd9Sstevel@tonic-gate 	 * (even if there are multiple outstanding children) and the
5507c478bd9Sstevel@tonic-gate 	 * door will get closed.
5517c478bd9Sstevel@tonic-gate 	 */
5527c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5537c478bd9Sstevel@tonic-gate 	svc_flags(xprt) |= svc_flags(parent);
5547c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5557c478bd9Sstevel@tonic-gate 	if (svc_defunct(xprt)) {
5567c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5577c478bd9Sstevel@tonic-gate 		svc_flags(parent) |= SVC_DEFUNCT;
55861961e0fSrobinson 		/* LINTED pointer cast */
5597c478bd9Sstevel@tonic-gate 		if (SVCEXT(parent)->refcnt == 0)
560*0900f4f2SMarcel Telka 			svc_door_destroy_pvt(xprt);
5617c478bd9Sstevel@tonic-gate 	}
56261961e0fSrobinson 	(void) mutex_unlock(&svc_door_mutex);
5637c478bd9Sstevel@tonic-gate 	return (len);
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate /* ARGSUSED */
5677c478bd9Sstevel@tonic-gate static enum xprt_stat
svc_door_stat(SVCXPRT * xprt)56861961e0fSrobinson svc_door_stat(SVCXPRT *xprt)
5697c478bd9Sstevel@tonic-gate {
5707c478bd9Sstevel@tonic-gate 	return (XPRT_IDLE);
5717c478bd9Sstevel@tonic-gate }
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate static bool_t
svc_door_recv(SVCXPRT * xprt,struct rpc_msg * msg)57461961e0fSrobinson svc_door_recv(SVCXPRT *xprt, struct rpc_msg *msg)
5757c478bd9Sstevel@tonic-gate {
5767c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5777c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su = su_data(xprt);
5787c478bd9Sstevel@tonic-gate 	XDR			*xdrs = &(su->su_xdrs);
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	xdrmem_create(xdrs, su->argbuf, su->arglen, XDR_DECODE);
5817c478bd9Sstevel@tonic-gate 	if (!xdr_callmsg(xdrs, msg))
5827c478bd9Sstevel@tonic-gate 		return (FALSE);
5837c478bd9Sstevel@tonic-gate 	su->su_xid = msg->rm_xid;
5847c478bd9Sstevel@tonic-gate 	return (TRUE);
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate static bool_t
svc_door_reply(SVCXPRT * xprt,struct rpc_msg * msg)58861961e0fSrobinson svc_door_reply(SVCXPRT *xprt, struct rpc_msg *msg)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
5917c478bd9Sstevel@tonic-gate 	struct svc_door_data	*su = su_data(xprt);
5927c478bd9Sstevel@tonic-gate 	XDR			*xdrs = &(su->su_xdrs);
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	xdrmem_create(xdrs, su->buf, su->su_iosz, XDR_ENCODE);
5957c478bd9Sstevel@tonic-gate 	msg->rm_xid = su->su_xid;
5967c478bd9Sstevel@tonic-gate 	if (xdr_replymsg(xdrs, msg)) {
5977c478bd9Sstevel@tonic-gate 		su->len = (int)XDR_GETPOS(xdrs);
5987c478bd9Sstevel@tonic-gate 		return (TRUE);
5997c478bd9Sstevel@tonic-gate 	}
6007c478bd9Sstevel@tonic-gate 	return (FALSE);
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate static bool_t
svc_door_getargs(SVCXPRT * xprt,xdrproc_t xdr_args,caddr_t args_ptr)60461961e0fSrobinson svc_door_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
6077c478bd9Sstevel@tonic-gate 	return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate static bool_t
svc_door_freeargs(SVCXPRT * xprt,xdrproc_t xdr_args,caddr_t args_ptr)61161961e0fSrobinson svc_door_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
6127c478bd9Sstevel@tonic-gate {
6137c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
6147c478bd9Sstevel@tonic-gate 	XDR		*xdrs = &(su_data(xprt)->su_xdrs);
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	xdrs->x_op = XDR_FREE;
6177c478bd9Sstevel@tonic-gate 	return ((*xdr_args)(xdrs, args_ptr));
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate static void
svc_door_destroy(SVCXPRT * xprt)62161961e0fSrobinson svc_door_destroy(SVCXPRT *xprt)
6227c478bd9Sstevel@tonic-gate {
62361961e0fSrobinson 	(void) mutex_lock(&svc_door_mutex);
6247c478bd9Sstevel@tonic-gate 	svc_door_destroy_pvt(xprt);
62561961e0fSrobinson 	(void) mutex_unlock(&svc_door_mutex);
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate static void
svc_door_destroy_pvt(SVCXPRT * xprt)62961961e0fSrobinson svc_door_destroy_pvt(SVCXPRT *xprt)
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
6327c478bd9Sstevel@tonic-gate 	if (SVCEXT(xprt)->parent)
6337c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
6347c478bd9Sstevel@tonic-gate 		xprt = SVCEXT(xprt)->parent;
6357c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
6367c478bd9Sstevel@tonic-gate 	svc_flags(xprt) |= SVC_DEFUNCT;
6377c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
6387c478bd9Sstevel@tonic-gate 	if (SVCEXT(xprt)->refcnt > 0)
6397c478bd9Sstevel@tonic-gate 		return;
6407c478bd9Sstevel@tonic-gate 
64161961e0fSrobinson 	__svc_rm_from_xlist(&dxlist, xprt, NULL);
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	if (xprt->xp_tp) {
6447c478bd9Sstevel@tonic-gate 		(void) fdetach(xprt->xp_tp);
6457c478bd9Sstevel@tonic-gate 		(void) unlink(xprt->xp_tp);
6467c478bd9Sstevel@tonic-gate 	}
6477c478bd9Sstevel@tonic-gate 	(void) door_revoke(xprt->xp_fd);
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	svc_xprt_destroy(xprt);
6507c478bd9Sstevel@tonic-gate 	if (--svc_ndoorfds == 0)
65161961e0fSrobinson 		/* wake up door dispatching */
65261961e0fSrobinson 		(void) cond_signal(&svc_door_waitcv);
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate /* ARGSUSED */
6567c478bd9Sstevel@tonic-gate static bool_t
svc_door_control(SVCXPRT * xprt,const uint_t rq,void * in)65761961e0fSrobinson svc_door_control(SVCXPRT *xprt, const uint_t rq, void *in)
6587c478bd9Sstevel@tonic-gate {
6597c478bd9Sstevel@tonic-gate 	extern int __rpc_legal_connmaxrec(int);
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	size_t door_param;
6627c478bd9Sstevel@tonic-gate 	int tmp;
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	switch (rq) {
6657c478bd9Sstevel@tonic-gate 	case SVCSET_CONNMAXREC:
6667c478bd9Sstevel@tonic-gate 		tmp = __rpc_legal_connmaxrec(*(int *)in);
6677c478bd9Sstevel@tonic-gate 		if (tmp >= 0) {
6687c478bd9Sstevel@tonic-gate 			door_param = (tmp == 0)? SIZE_MAX :
6697c478bd9Sstevel@tonic-gate 			    (size_t)(ssize_t)tmp;
6707c478bd9Sstevel@tonic-gate 			if (door_setparam(xprt->xp_fd, DOOR_PARAM_DATA_MAX,
6717c478bd9Sstevel@tonic-gate 			    door_param) == 0)
6727c478bd9Sstevel@tonic-gate 				return (TRUE);
6737c478bd9Sstevel@tonic-gate 			return (FALSE);
6747c478bd9Sstevel@tonic-gate 		}
67561961e0fSrobinson 		return (FALSE);
6767c478bd9Sstevel@tonic-gate 	case SVCGET_CONNMAXREC:
6777c478bd9Sstevel@tonic-gate 		if (door_getparam(xprt->xp_fd, DOOR_PARAM_DATA_MAX,
6787c478bd9Sstevel@tonic-gate 		    &door_param) == 0) {
6797c478bd9Sstevel@tonic-gate 			if (door_param == SIZE_MAX)
6807c478bd9Sstevel@tonic-gate 				tmp = 0;
6817c478bd9Sstevel@tonic-gate 			else if (door_param > INT_MAX)
6827c478bd9Sstevel@tonic-gate 				tmp = INT_MAX;
6837c478bd9Sstevel@tonic-gate 			else if (door_param > 0)
6847c478bd9Sstevel@tonic-gate 				tmp = (int)door_param;
6857c478bd9Sstevel@tonic-gate 			else
6867c478bd9Sstevel@tonic-gate 				return (FALSE);
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 			*(int *)in = tmp;
6897c478bd9Sstevel@tonic-gate 			return (TRUE);
69061961e0fSrobinson 		}
6917c478bd9Sstevel@tonic-gate 		return (FALSE);
6927c478bd9Sstevel@tonic-gate 	}
6937c478bd9Sstevel@tonic-gate 	return (FALSE);
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate static struct xp_ops *
svc_door_ops(void)69761961e0fSrobinson svc_door_ops(void)
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate 	static struct xp_ops	ops;
7007c478bd9Sstevel@tonic-gate 	extern mutex_t		ops_lock;
7017c478bd9Sstevel@tonic-gate 
70261961e0fSrobinson 	(void) mutex_lock(&ops_lock);
7037c478bd9Sstevel@tonic-gate 	if (ops.xp_recv == NULL) {
7047c478bd9Sstevel@tonic-gate 		ops.xp_recv = svc_door_recv;
7057c478bd9Sstevel@tonic-gate 		ops.xp_stat = svc_door_stat;
7067c478bd9Sstevel@tonic-gate 		ops.xp_getargs = svc_door_getargs;
7077c478bd9Sstevel@tonic-gate 		ops.xp_reply = svc_door_reply;
7087c478bd9Sstevel@tonic-gate 		ops.xp_freeargs = svc_door_freeargs;
7097c478bd9Sstevel@tonic-gate 		ops.xp_destroy = svc_door_destroy;
7107c478bd9Sstevel@tonic-gate 		ops.xp_control = svc_door_control;
7117c478bd9Sstevel@tonic-gate 	}
71261961e0fSrobinson 	(void) mutex_unlock(&ops_lock);
7137c478bd9Sstevel@tonic-gate 	return (&ops);
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate /*
7177c478bd9Sstevel@tonic-gate  * Return door credentials.
7187c478bd9Sstevel@tonic-gate  */
7197c478bd9Sstevel@tonic-gate /* ARGSUSED */
7207c478bd9Sstevel@tonic-gate bool_t
__svc_get_door_cred(SVCXPRT * xprt,svc_local_cred_t * lcred)7217c478bd9Sstevel@tonic-gate __svc_get_door_cred(SVCXPRT *xprt, svc_local_cred_t *lcred)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate 	door_cred_t		dc;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	if (door_cred(&dc) < 0)
7267c478bd9Sstevel@tonic-gate 		return (FALSE);
7277c478bd9Sstevel@tonic-gate 	lcred->euid = dc.dc_euid;
7287c478bd9Sstevel@tonic-gate 	lcred->egid = dc.dc_egid;
7297c478bd9Sstevel@tonic-gate 	lcred->ruid = dc.dc_ruid;
7307c478bd9Sstevel@tonic-gate 	lcred->rgid = dc.dc_rgid;
7317c478bd9Sstevel@tonic-gate 	lcred->pid = dc.dc_pid;
7327c478bd9Sstevel@tonic-gate 	return (TRUE);
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate /* ARGSUSED */
7367c478bd9Sstevel@tonic-gate bool_t
__svc_get_door_ucred(const SVCXPRT * xprt,ucred_t * ucp)7377c478bd9Sstevel@tonic-gate __svc_get_door_ucred(const SVCXPRT *xprt, ucred_t *ucp)
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate 	return (door_ucred(&ucp) == 0);
7407c478bd9Sstevel@tonic-gate }
741