xref: /illumos-gate/usr/src/cmd/picl/picld/picld.c (revision e9610e3e)
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
524b3ac2eSjfrank  * Common Development and Distribution License (the "License").
624b3ac2eSjfrank  * 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  */
210ec57554Sraf 
227c478bd9Sstevel@tonic-gate /*
23d5da6539SMichael Bergknoff  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * PICL daemon
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <stdarg.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <libintl.h>
367c478bd9Sstevel@tonic-gate #include <locale.h>
377c478bd9Sstevel@tonic-gate #include <alloca.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
397c478bd9Sstevel@tonic-gate #include <assert.h>
407c478bd9Sstevel@tonic-gate #include <stropts.h>
417c478bd9Sstevel@tonic-gate #include <unistd.h>
427c478bd9Sstevel@tonic-gate #include <signal.h>
437c478bd9Sstevel@tonic-gate #include <pthread.h>
447c478bd9Sstevel@tonic-gate #include <synch.h>
457c478bd9Sstevel@tonic-gate #include <door.h>
467c478bd9Sstevel@tonic-gate #include <sys/door.h>
477c478bd9Sstevel@tonic-gate #include <fcntl.h>
487c478bd9Sstevel@tonic-gate #include <dlfcn.h>
497c478bd9Sstevel@tonic-gate #include <time.h>
507c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
517c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
527c478bd9Sstevel@tonic-gate #include <sys/stat.h>
537c478bd9Sstevel@tonic-gate #include <sys/wait.h>
547c478bd9Sstevel@tonic-gate #include <dirent.h>
557c478bd9Sstevel@tonic-gate #include <syslog.h>
567c478bd9Sstevel@tonic-gate #include <poll.h>
577c478bd9Sstevel@tonic-gate #include <limits.h>
587c478bd9Sstevel@tonic-gate #include <picl.h>
597c478bd9Sstevel@tonic-gate #include "picl2door.h"
607c478bd9Sstevel@tonic-gate #include <picltree.h>
617c478bd9Sstevel@tonic-gate #include "ptree_impl.h"
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * Log text messages
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate #define	MUST_BE_ROOT	gettext("this program must be run as root\n")
677c478bd9Sstevel@tonic-gate #define	CD_ROOT_FAILED	gettext("chdir to root failed\n")
687c478bd9Sstevel@tonic-gate #define	INIT_FAILED	gettext("ptree initialization failed\n")
697c478bd9Sstevel@tonic-gate #define	DAEMON_RUNNING	gettext("PICL daemon already running\n")
707c478bd9Sstevel@tonic-gate #define	DOOR_FAILED	gettext("Failed creating picld door\n")
717c478bd9Sstevel@tonic-gate #define	SIGACT_FAILED	\
727c478bd9Sstevel@tonic-gate 		gettext("Failed to install signal handler for %s: %s\n")
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * Constants
767c478bd9Sstevel@tonic-gate  */
777c478bd9Sstevel@tonic-gate #define	PICLD				"picld"
787c478bd9Sstevel@tonic-gate #define	DOS_PICL_REQUESTS_LIMIT		10000
797c478bd9Sstevel@tonic-gate #define	SLIDING_INTERVAL_MILLISECONDS	1000
807c478bd9Sstevel@tonic-gate #define	PICLD_MAJOR_REV			0x1
817c478bd9Sstevel@tonic-gate #define	PICLD_MINOR_REV			0x0
827c478bd9Sstevel@tonic-gate #define	DOS_SLEEPTIME_MS		1000
83980a6e61Sjfrank #define	MAX_POOL_SIZE			_POSIX_THREAD_THREADS_MAX
84980a6e61Sjfrank #define	MAX_CONCURRENT_WAITS	(_POSIX_THREAD_THREADS_MAX - 2)
85980a6e61Sjfrank #define	MAX_USER_WAITS			4
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate  * Macros
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate #define	PICLD_VERSION(x, y)	((x << 8) | y)
917c478bd9Sstevel@tonic-gate #define	PICL_CLIENT_REV(x)	(x & 0xff)
927c478bd9Sstevel@tonic-gate #define	MILLI_TO_NANO(x)	(x * 1000000)
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate extern	char	**environ;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate  * Module Variables
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate static	int		logflag = 1;
1007c478bd9Sstevel@tonic-gate static	int		doreinit = 0;
1017c478bd9Sstevel@tonic-gate static	int		door_id = -1;
102980a6e61Sjfrank static	pthread_mutex_t door_mutex = PTHREAD_MUTEX_INITIALIZER;
103980a6e61Sjfrank static	pthread_cond_t door_cv = PTHREAD_COND_INITIALIZER;
104*e9610e3eSToomas Soome static  int		service_requests = 0;
1057c478bd9Sstevel@tonic-gate static	hrtime_t	orig_time;
1067c478bd9Sstevel@tonic-gate static	hrtime_t	sliding_interval_ms;
1077c478bd9Sstevel@tonic-gate static	uint32_t	dos_req_limit;
1087c478bd9Sstevel@tonic-gate static	uint32_t	dos_ms;
1097c478bd9Sstevel@tonic-gate static	pthread_mutex_t	dos_mutex = PTHREAD_MUTEX_INITIALIZER;
1107c478bd9Sstevel@tonic-gate static	rwlock_t	init_lk;
111980a6e61Sjfrank static	int pool_count = 0;
112980a6e61Sjfrank static	pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
113980a6e61Sjfrank static	pthread_mutex_t	wait_req_mutex = PTHREAD_MUTEX_INITIALIZER;
114980a6e61Sjfrank static	int wait_count = 0;
115980a6e61Sjfrank static	struct {
116980a6e61Sjfrank 	uid_t uid;
117980a6e61Sjfrank 	int count;
118980a6e61Sjfrank } user_count[MAX_CONCURRENT_WAITS];
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate /*
1217c478bd9Sstevel@tonic-gate  * This returns an error message to libpicl
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate static void
picld_return_error(picl_callnumber_t cnum,picl_errno_t err)1247c478bd9Sstevel@tonic-gate picld_return_error(picl_callnumber_t cnum, picl_errno_t err)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	picl_reterror_t	ret_error;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	ret_error.cnum = PICL_CNUM_ERROR;
1297c478bd9Sstevel@tonic-gate 	ret_error.in_cnum = cnum;
1307c478bd9Sstevel@tonic-gate 	ret_error.errnum = err;
1317c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1327c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret_error, sizeof (picl_reterror_t), NULL,
1337c478bd9Sstevel@tonic-gate 	    0);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate  * picld_init is called when a picl_initialize request is received
1387c478bd9Sstevel@tonic-gate  */
1397c478bd9Sstevel@tonic-gate static void
picld_init(picl_service_t * req)1407c478bd9Sstevel@tonic-gate picld_init(picl_service_t *req)
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate 	picl_retinit_t	ret_init;
1437c478bd9Sstevel@tonic-gate 	int	clmajrev;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	clmajrev = PICL_CLIENT_REV(req->req_init.clrev);
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if (clmajrev < PICL_VERSION_1)
1487c478bd9Sstevel@tonic-gate 		picld_return_error(req->req_init.cnum, PICL_NOTSUPPORTED);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	ret_init.cnum = req->req_init.cnum;
1517c478bd9Sstevel@tonic-gate 	ret_init.rev = PICLD_VERSION(PICLD_MAJOR_REV, PICLD_MINOR_REV);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1547c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret_init, sizeof (picl_retinit_t), NULL, 0);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * picld_fini is called when a picl_shutdown request is received
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate static void
picld_fini(picl_service_t * in)1617c478bd9Sstevel@tonic-gate picld_fini(picl_service_t *in)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	picl_retfini_t	ret;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_fini.cnum;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1687c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfini_t), NULL, 0);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate static void
picld_ping(picl_service_t * in)1727c478bd9Sstevel@tonic-gate picld_ping(picl_service_t *in)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate 	picl_retping_t	ret;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_ping.cnum;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1797c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retping_t), NULL, 0);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
182980a6e61Sjfrank static int
check_user(uid_t uid)183980a6e61Sjfrank check_user(uid_t uid)
184980a6e61Sjfrank {
185980a6e61Sjfrank 	int i;
186980a6e61Sjfrank 	uid_t tmp_uid;
187980a6e61Sjfrank 	int free_idx = -1;
188980a6e61Sjfrank 
189980a6e61Sjfrank 	if (uid == 0)
190980a6e61Sjfrank 		return (PICL_SUCCESS);
191980a6e61Sjfrank 	for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
192980a6e61Sjfrank 		if ((tmp_uid = user_count[i].uid) == uid) {
193980a6e61Sjfrank 			if (user_count[i].count == MAX_USER_WAITS)
194980a6e61Sjfrank 				return (PICL_FAILURE);
195980a6e61Sjfrank 			user_count[i].count++;
196980a6e61Sjfrank 			return (PICL_SUCCESS);
197980a6e61Sjfrank 		}
198980a6e61Sjfrank 		if ((free_idx == -1) && (tmp_uid == 0))
199980a6e61Sjfrank 			free_idx = i;
200980a6e61Sjfrank 	}
201980a6e61Sjfrank 	if (free_idx != -1) {
202980a6e61Sjfrank 		user_count[free_idx].uid = uid;
203980a6e61Sjfrank 		user_count[free_idx].count = 1;
204980a6e61Sjfrank 		return (PICL_SUCCESS);
205980a6e61Sjfrank 	}
206980a6e61Sjfrank 	return (PICL_FAILURE);
207980a6e61Sjfrank }
208980a6e61Sjfrank 
209980a6e61Sjfrank static void
done_user(uid_t uid)210980a6e61Sjfrank done_user(uid_t uid)
211980a6e61Sjfrank {
212980a6e61Sjfrank 	int i;
213980a6e61Sjfrank 
214980a6e61Sjfrank 	if (uid == 0)
215980a6e61Sjfrank 		return;
216980a6e61Sjfrank 	for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
217980a6e61Sjfrank 		if (user_count[i].uid == uid) {
218980a6e61Sjfrank 			if (--user_count[i].count == 0)
219980a6e61Sjfrank 				user_count[i].uid = 0;
220980a6e61Sjfrank 			return;
221980a6e61Sjfrank 		}
222980a6e61Sjfrank 	}
223980a6e61Sjfrank }
224980a6e61Sjfrank 
225980a6e61Sjfrank static int
enter_picld_wait(uid_t uid)226980a6e61Sjfrank enter_picld_wait(uid_t uid)
227980a6e61Sjfrank {
228980a6e61Sjfrank 	int	rv;
229980a6e61Sjfrank 
230980a6e61Sjfrank 	if (pthread_mutex_lock(&wait_req_mutex) != 0)
231980a6e61Sjfrank 		return (PICL_FAILURE);
232980a6e61Sjfrank 	if ((wait_count < MAX_CONCURRENT_WAITS) &&
233980a6e61Sjfrank 	    (check_user(uid) == PICL_SUCCESS)) {
234980a6e61Sjfrank 		rv = PICL_SUCCESS;
235980a6e61Sjfrank 		wait_count++;
236980a6e61Sjfrank 	} else {
237980a6e61Sjfrank 		rv = PICL_FAILURE;
238980a6e61Sjfrank 	}
239980a6e61Sjfrank 	(void) pthread_mutex_unlock(&wait_req_mutex);
240980a6e61Sjfrank 	return (rv);
241980a6e61Sjfrank }
242980a6e61Sjfrank 
243980a6e61Sjfrank static void
exit_picld_wait(uid_t uid)244980a6e61Sjfrank exit_picld_wait(uid_t uid)
245980a6e61Sjfrank {
246980a6e61Sjfrank 	(void) pthread_mutex_lock(&wait_req_mutex);
247980a6e61Sjfrank 	done_user(uid);
248980a6e61Sjfrank 	wait_count--;
249980a6e61Sjfrank 	(void) pthread_mutex_unlock(&wait_req_mutex);
250980a6e61Sjfrank }
251980a6e61Sjfrank 
2527c478bd9Sstevel@tonic-gate /*
2537c478bd9Sstevel@tonic-gate  * picld_wait is called when a picl_wait request is received
2547c478bd9Sstevel@tonic-gate  */
2557c478bd9Sstevel@tonic-gate static void
picld_wait(picl_service_t * in)2567c478bd9Sstevel@tonic-gate picld_wait(picl_service_t *in)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate 	picl_retwait_t	ret;
2597c478bd9Sstevel@tonic-gate 	int		err;
260980a6e61Sjfrank 	ucred_t	*puc = NULL;
261980a6e61Sjfrank 	uid_t uid;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_wait.cnum;
264980a6e61Sjfrank 	if (door_ucred(&puc) != 0)
265980a6e61Sjfrank 		ret.retcode = PICL_FAILURE;
266980a6e61Sjfrank 	else {
267980a6e61Sjfrank 		uid = ucred_geteuid(puc);
268980a6e61Sjfrank 		if (enter_picld_wait(uid) == PICL_FAILURE)
269980a6e61Sjfrank 			ret.retcode = PICL_FAILURE;
270980a6e61Sjfrank 		else {
271980a6e61Sjfrank 			err = xptree_refresh_notify(in->req_wait.secs);
272980a6e61Sjfrank 			ret.retcode = err;
273980a6e61Sjfrank 			exit_picld_wait(uid);
274980a6e61Sjfrank 		}
275980a6e61Sjfrank 		ucred_free(puc);
276980a6e61Sjfrank 	}
2777c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
2787c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retwait_t), NULL, 0);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate  * This function returns the handle of the root node of the PICL tree
2837c478bd9Sstevel@tonic-gate  */
2847c478bd9Sstevel@tonic-gate static void
picld_getroot(picl_service_t * in)2857c478bd9Sstevel@tonic-gate picld_getroot(picl_service_t *in)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	picl_retroot_t	ret;
2887c478bd9Sstevel@tonic-gate 	int		err;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETROOT;
2917c478bd9Sstevel@tonic-gate 	err = ptree_get_root(&ret.rnode);
2927c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2937c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2947c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnode);
2957c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
2967c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retroot_t), NULL, 0);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate /*
3007c478bd9Sstevel@tonic-gate  * This function returns the value of the PICL property
3017c478bd9Sstevel@tonic-gate  */
3027c478bd9Sstevel@tonic-gate static void
picld_get_attrval(picl_service_t * in)3037c478bd9Sstevel@tonic-gate picld_get_attrval(picl_service_t *in)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	picl_retattrval_t	*ret;
3067c478bd9Sstevel@tonic-gate 	int			err;
3077c478bd9Sstevel@tonic-gate 	size_t			vbufsize;
3087c478bd9Sstevel@tonic-gate 	size_t			len;
3097c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
3107c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
3117c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
3147c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrval.attr, &ptreeh);
3177c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3187c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
3217c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3227c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
3257c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
3287c478bd9Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrval.bufsize, vbufsize);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	len = sizeof (picl_retattrval_t) + vbufsize;
3317c478bd9Sstevel@tonic-gate 	ret = alloca(len);
3327c478bd9Sstevel@tonic-gate 	if (ret == NULL)
3337c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3347c478bd9Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVAL;
3357c478bd9Sstevel@tonic-gate 	ret->attr = in->req_attrval.attr;
3367c478bd9Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
3377c478bd9Sstevel@tonic-gate 	err = xptree_get_propval_with_cred(ptreeh, ret->ret_buf, vbufsize,
3387c478bd9Sstevel@tonic-gate 	    cred);
3397c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3407c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	/*
3437c478bd9Sstevel@tonic-gate 	 * adjust returned bytes for charstrings
3447c478bd9Sstevel@tonic-gate 	 */
3457c478bd9Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
3467c478bd9Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/*
3497c478bd9Sstevel@tonic-gate 	 * convert handle values to picl handles
3507c478bd9Sstevel@tonic-gate 	 */
3517c478bd9Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
3527c478bd9Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
3537c478bd9Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
3547c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
3557c478bd9Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrval_t) +
3567c478bd9Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate  * This function returns the value of the PICL property specified by
3617c478bd9Sstevel@tonic-gate  * its name.
3627c478bd9Sstevel@tonic-gate  */
3637c478bd9Sstevel@tonic-gate static void
picld_get_attrval_by_name(picl_service_t * in)3647c478bd9Sstevel@tonic-gate picld_get_attrval_by_name(picl_service_t *in)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate 	picl_retattrvalbyname_t	*ret;
3677c478bd9Sstevel@tonic-gate 	int			err;
3687c478bd9Sstevel@tonic-gate 	size_t			vbufsize;
3697c478bd9Sstevel@tonic-gate 	size_t			len;
3707c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
3717c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
3727c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
3757c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrvalbyname.nodeh, &ptreeh);
3787c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3797c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
3827c478bd9Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, &pinfo);
3837c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3847c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
3877c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	/*
3907c478bd9Sstevel@tonic-gate 	 * allocate the minimum of piclinfo.size and input bufsize
3917c478bd9Sstevel@tonic-gate 	 */
3927c478bd9Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
3937c478bd9Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrvalbyname.bufsize, vbufsize);
3947c478bd9Sstevel@tonic-gate 	len = sizeof (picl_retattrvalbyname_t) + vbufsize;
3957c478bd9Sstevel@tonic-gate 	ret = alloca(len);
3967c478bd9Sstevel@tonic-gate 	if (ret == NULL)
3977c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3987c478bd9Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVALBYNAME;
3997c478bd9Sstevel@tonic-gate 	ret->nodeh = in->req_attrvalbyname.nodeh;
4007c478bd9Sstevel@tonic-gate 	(void) strcpy(ret->propname, in->req_attrvalbyname.propname);
4017c478bd9Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	err = xptree_get_propval_by_name_with_cred(ptreeh,
4047c478bd9Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, ret->ret_buf, vbufsize,
4057c478bd9Sstevel@tonic-gate 	    cred);
4067c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4077c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4087c478bd9Sstevel@tonic-gate 	/*
4097c478bd9Sstevel@tonic-gate 	 * adjust returned value size for charstrings
4107c478bd9Sstevel@tonic-gate 	 */
4117c478bd9Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
4127c478bd9Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
4157c478bd9Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
4167c478bd9Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
4197c478bd9Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrvalbyname_t) +
4207c478bd9Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate /*
4247c478bd9Sstevel@tonic-gate  * This function sets a property value
4257c478bd9Sstevel@tonic-gate  */
4267c478bd9Sstevel@tonic-gate static void
picld_set_attrval(picl_service_t * in)4277c478bd9Sstevel@tonic-gate picld_set_attrval(picl_service_t *in)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	picl_retsetattrval_t	ret;
4307c478bd9Sstevel@tonic-gate 	int			err;
4317c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
4327c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
4337c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
4367c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrval.attr, &ptreeh);
4397c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4407c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
4437c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4447c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
4477c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
4487c478bd9Sstevel@tonic-gate 	/*
4497c478bd9Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
4507c478bd9Sstevel@tonic-gate 	 */
4517c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
4527c478bd9Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
4537c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVAL;
4567c478bd9Sstevel@tonic-gate 	ret.attr = in->req_setattrval.attr;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	err = xptree_update_propval_with_cred(ptreeh, in->req_setattrval.valbuf,
4597c478bd9Sstevel@tonic-gate 	    (size_t)in->req_setattrval.bufsize, cred);
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4627c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
4657c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrval_t), NULL,
4667c478bd9Sstevel@tonic-gate 	    0);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate  * This function sets the value of a property specified by its name.
4717c478bd9Sstevel@tonic-gate  */
4727c478bd9Sstevel@tonic-gate static void
picld_set_attrval_by_name(picl_service_t * in)4737c478bd9Sstevel@tonic-gate picld_set_attrval_by_name(picl_service_t *in)
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate 	picl_retsetattrvalbyname_t	ret;
4767c478bd9Sstevel@tonic-gate 	int				err;
4777c478bd9Sstevel@tonic-gate 	door_cred_t			cred;
4787c478bd9Sstevel@tonic-gate 	picl_prophdl_t			ptreeh;
4797c478bd9Sstevel@tonic-gate 	ptree_propinfo_t		pinfo;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
4827c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrvalbyname.nodeh, &ptreeh);
4857c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4867c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
4897c478bd9Sstevel@tonic-gate 	    in->req_setattrvalbyname.propname, &pinfo);
4907c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4917c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
4947c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	/*
4977c478bd9Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
4987c478bd9Sstevel@tonic-gate 	 */
4997c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
5007c478bd9Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
5017c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVALBYNAME;
5047c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_setattrvalbyname.nodeh;
5057c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_setattrvalbyname.propname);
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	err = xptree_update_propval_by_name_with_cred(ptreeh,
50824b3ac2eSjfrank 	    in->req_setattrvalbyname.propname,
50924b3ac2eSjfrank 	    in->req_setattrvalbyname.valbuf,
51024b3ac2eSjfrank 	    (size_t)in->req_setattrvalbyname.bufsize,
51124b3ac2eSjfrank 	    cred);
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5147c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5177c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrvalbyname_t),
5187c478bd9Sstevel@tonic-gate 	    NULL, 0);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate  * This function returns the property information
5237c478bd9Sstevel@tonic-gate  */
5247c478bd9Sstevel@tonic-gate static void
picld_get_attrinfo(picl_service_t * in)5257c478bd9Sstevel@tonic-gate picld_get_attrinfo(picl_service_t *in)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate 	picl_retattrinfo_t	ret;
5287c478bd9Sstevel@tonic-gate 	int			err;
5297c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
5307c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrinfo.attr, &ptreeh);
5337c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5347c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRINFO;
5377c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrinfo.attr;
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
5407c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5417c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	ret.type = pinfo.piclinfo.type;
5447c478bd9Sstevel@tonic-gate 	ret.accessmode = pinfo.piclinfo.accessmode;
5457c478bd9Sstevel@tonic-gate 	ret.size = (uint32_t)pinfo.piclinfo.size;
5467c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.name, pinfo.piclinfo.name);
5477c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5487c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrinfo_t), NULL, 0);
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate  * This function returns the node's first property handle
5537c478bd9Sstevel@tonic-gate  */
5547c478bd9Sstevel@tonic-gate static void
picld_get_first_attr(picl_service_t * in)5557c478bd9Sstevel@tonic-gate picld_get_first_attr(picl_service_t *in)
5567c478bd9Sstevel@tonic-gate {
5577c478bd9Sstevel@tonic-gate 	picl_retfirstattr_t	ret;
5587c478bd9Sstevel@tonic-gate 	int			err;
5597c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_firstattr.nodeh, &ptreeh);
5627c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5637c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETFIRSTATTR;
5667c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_firstattr.nodeh;
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	err = ptree_get_first_prop(ptreeh, &ret.attr);
5697c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5707c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5717c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
5727c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5737c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfirstattr_t), NULL, 0);
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate /*
5777c478bd9Sstevel@tonic-gate  * This function returns the next property handle in list
5787c478bd9Sstevel@tonic-gate  */
5797c478bd9Sstevel@tonic-gate static void
picld_get_next_attr(picl_service_t * in)5807c478bd9Sstevel@tonic-gate picld_get_next_attr(picl_service_t *in)
5817c478bd9Sstevel@tonic-gate {
5827c478bd9Sstevel@tonic-gate 	picl_retnextattr_t	ret;
5837c478bd9Sstevel@tonic-gate 	int			err;
5847c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_nextattr.attr, &ptreeh);
5877c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5887c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETNEXTATTR;
5917c478bd9Sstevel@tonic-gate 	ret.attr = in->req_nextattr.attr;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	err = ptree_get_next_prop(ptreeh, &ret.nextattr);
5947c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5957c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nextattr);
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6007c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retnextattr_t), NULL, 0);
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate /*
6047c478bd9Sstevel@tonic-gate  * This function returns the handle of a property specified by its name
6057c478bd9Sstevel@tonic-gate  */
6067c478bd9Sstevel@tonic-gate static void
picld_get_attr_by_name(picl_service_t * in)6077c478bd9Sstevel@tonic-gate picld_get_attr_by_name(picl_service_t *in)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate 	picl_retattrbyname_t	ret;
6107c478bd9Sstevel@tonic-gate 	int			err;
6117c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyname.nodeh, &ptreeh);
6147c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6157c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYNAME;
6187c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_attrbyname.nodeh;
6197c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_attrbyname.propname);
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	err = ptree_get_prop_by_name(ptreeh, ret.propname, &ret.attr);
6227c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6237c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
6267c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6277c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyname_t), NULL,
6287c478bd9Sstevel@tonic-gate 	    0);
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate /*
6327c478bd9Sstevel@tonic-gate  * This function gets the next property on the same row in the table
6337c478bd9Sstevel@tonic-gate  */
6347c478bd9Sstevel@tonic-gate static void
picld_get_attr_by_row(picl_service_t * in)6357c478bd9Sstevel@tonic-gate picld_get_attr_by_row(picl_service_t *in)
6367c478bd9Sstevel@tonic-gate {
6377c478bd9Sstevel@tonic-gate 	picl_retattrbyrow_t	ret;
6387c478bd9Sstevel@tonic-gate 	int			err;
6397c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyrow.attr, &ptreeh);
6427c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6437c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYROW;
6467c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrbyrow.attr;
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	err = ptree_get_next_by_row(ptreeh, &ret.rowattr);
6497c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6507c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6517c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rowattr);
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6547c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyrow_t), NULL, 0);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate /*
6587c478bd9Sstevel@tonic-gate  * This function returns the handle of the next property in the same column
6597c478bd9Sstevel@tonic-gate  * of the table.
6607c478bd9Sstevel@tonic-gate  */
6617c478bd9Sstevel@tonic-gate static void
picld_get_attr_by_col(picl_service_t * in)6627c478bd9Sstevel@tonic-gate picld_get_attr_by_col(picl_service_t *in)
6637c478bd9Sstevel@tonic-gate {
6647c478bd9Sstevel@tonic-gate 	picl_retattrbycol_t	ret;
6657c478bd9Sstevel@tonic-gate 	int			err;
6667c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbycol.attr, &ptreeh);
6697c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6707c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYCOL;
6737c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrbycol.attr;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	err = ptree_get_next_by_col(ptreeh, &ret.colattr);
6767c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6777c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.colattr);
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6827c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbycol_t), NULL, 0);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate  * This function finds the node in the PICLTREE that matches the given
6877c478bd9Sstevel@tonic-gate  * criteria and returns its handle.
6887c478bd9Sstevel@tonic-gate  */
6897c478bd9Sstevel@tonic-gate static void
picld_find_node(picl_service_t * in)6907c478bd9Sstevel@tonic-gate picld_find_node(picl_service_t *in)
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate 	picl_retfindnode_t	ret;
6937c478bd9Sstevel@tonic-gate 	int			err;
6947c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_findnode.nodeh, &ptreeh);
6977c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6987c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FINDNODE;
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	err = ptree_find_node(ptreeh, in->req_findnode.propname,
7037c478bd9Sstevel@tonic-gate 	    in->req_findnode.ptype, in->req_findnode.valbuf,
7047c478bd9Sstevel@tonic-gate 	    in->req_findnode.valsize, &ret.rnodeh);
7057c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7067c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnodeh);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
7117c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate  * This function finds the property/node that corresponds to the given path
7167c478bd9Sstevel@tonic-gate  * and returns its handle
7177c478bd9Sstevel@tonic-gate  */
7187c478bd9Sstevel@tonic-gate static void
picld_get_node_by_path(picl_service_t * in)7197c478bd9Sstevel@tonic-gate picld_get_node_by_path(picl_service_t *in)
7207c478bd9Sstevel@tonic-gate {
7217c478bd9Sstevel@tonic-gate 	picl_retnodebypath_t	ret;
7227c478bd9Sstevel@tonic-gate 	int			err;
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_NODEBYPATH;
7257c478bd9Sstevel@tonic-gate 	err = ptree_get_node_by_path(in->req_nodebypath.pathbuf, &ret.nodeh);
7267c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7277c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7287c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nodeh);
7297c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
7307c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate /*
7347c478bd9Sstevel@tonic-gate  * This function returns finds the frutree parent node for a given node
7357c478bd9Sstevel@tonic-gate  * and returns its handle
7367c478bd9Sstevel@tonic-gate  */
7377c478bd9Sstevel@tonic-gate static void
picld_get_frutree_parent(picl_service_t * in)7387c478bd9Sstevel@tonic-gate picld_get_frutree_parent(picl_service_t *in)
7397c478bd9Sstevel@tonic-gate {
7407c478bd9Sstevel@tonic-gate 	picl_retfruparent_t	ret;
7417c478bd9Sstevel@tonic-gate 	int			err;
7427c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_fruparent.devh, &ptreeh);
7457c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7467c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FRUTREEPARENT;
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	err = ptree_get_frutree_parent(ptreeh, &ret.fruh);
7517c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7527c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7537c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.fruh);
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
7567c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate /*
7607c478bd9Sstevel@tonic-gate  * This function is called when an unknown client request is received.
7617c478bd9Sstevel@tonic-gate  */
7627c478bd9Sstevel@tonic-gate static void
picld_unknown_service(picl_service_t * in)7637c478bd9Sstevel@tonic-gate picld_unknown_service(picl_service_t *in)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate 	picld_return_error(in->in.cnum, PICL_UNKNOWNSERVICE);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate static void
check_denial_of_service(int cnum)7697c478bd9Sstevel@tonic-gate check_denial_of_service(int cnum)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate 	hrtime_t	window;
7727c478bd9Sstevel@tonic-gate 	hrtime_t	current;
7737c478bd9Sstevel@tonic-gate 	int		dos_flag;
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	current = gethrtime();
7767c478bd9Sstevel@tonic-gate 	dos_flag = 0;
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	if (pthread_mutex_lock(&dos_mutex) != 0)
7797c478bd9Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	++service_requests;
7827c478bd9Sstevel@tonic-gate 	window = current - orig_time;
7837c478bd9Sstevel@tonic-gate 	if (window > MILLI_TO_NANO(sliding_interval_ms)) {
7847c478bd9Sstevel@tonic-gate 		orig_time = current;
7857c478bd9Sstevel@tonic-gate 		service_requests = 1;
7867c478bd9Sstevel@tonic-gate 	}
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	if (service_requests > dos_req_limit)
7897c478bd9Sstevel@tonic-gate 		dos_flag = 1;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	if (pthread_mutex_unlock(&dos_mutex) != 0)
7927c478bd9Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	if (dos_flag)
7957c478bd9Sstevel@tonic-gate 		(void) poll(NULL, 0, dos_ms);
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate /* ARGSUSED */
7997c478bd9Sstevel@tonic-gate static void
picld_door_handler(void * cookie,char * argp,size_t asize,door_desc_t * dp,uint_t n_desc)8007c478bd9Sstevel@tonic-gate picld_door_handler(void *cookie, char *argp, size_t asize,
8017c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t n_desc)
8027c478bd9Sstevel@tonic-gate {
8037c478bd9Sstevel@tonic-gate 	picl_service_t  *req;
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 	/*LINTED*/
8067c478bd9Sstevel@tonic-gate 	req = (picl_service_t *)argp;
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 	if (req == NULL)
8097c478bd9Sstevel@tonic-gate 		(void) door_return((char *)req, 0, NULL, 0);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	check_denial_of_service(req->in.cnum);
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&init_lk);
8147c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {	/* client call number */
8157c478bd9Sstevel@tonic-gate 	case PICL_CNUM_INIT:
8167c478bd9Sstevel@tonic-gate 		/*LINTED*/
8177c478bd9Sstevel@tonic-gate 		picld_init((picl_service_t *)argp);
8187c478bd9Sstevel@tonic-gate 		break;
8197c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FINI:
8207c478bd9Sstevel@tonic-gate 		/*LINTED*/
8217c478bd9Sstevel@tonic-gate 		picld_fini((picl_service_t *)argp);
8227c478bd9Sstevel@tonic-gate 		break;
8237c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETROOT:
8247c478bd9Sstevel@tonic-gate 		/*LINTED*/
8257c478bd9Sstevel@tonic-gate 		picld_getroot((picl_service_t *)argp);
8267c478bd9Sstevel@tonic-gate 		break;
8277c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVAL:
8287c478bd9Sstevel@tonic-gate 		/*LINTED*/
8297c478bd9Sstevel@tonic-gate 		picld_get_attrval((picl_service_t *)argp);
8307c478bd9Sstevel@tonic-gate 		break;
8317c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVALBYNAME:
8327c478bd9Sstevel@tonic-gate 		/*LINTED*/
8337c478bd9Sstevel@tonic-gate 		picld_get_attrval_by_name((picl_service_t *)argp);
8347c478bd9Sstevel@tonic-gate 		break;
8357c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRINFO:
8367c478bd9Sstevel@tonic-gate 		/*LINTED*/
8377c478bd9Sstevel@tonic-gate 		picld_get_attrinfo((picl_service_t *)argp);
8387c478bd9Sstevel@tonic-gate 		break;
8397c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETFIRSTATTR:
8407c478bd9Sstevel@tonic-gate 		/*LINTED*/
8417c478bd9Sstevel@tonic-gate 		picld_get_first_attr((picl_service_t *)argp);
8427c478bd9Sstevel@tonic-gate 		break;
8437c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETNEXTATTR:
8447c478bd9Sstevel@tonic-gate 		/*LINTED*/
8457c478bd9Sstevel@tonic-gate 		picld_get_next_attr((picl_service_t *)argp);
8467c478bd9Sstevel@tonic-gate 		break;
8477c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYNAME:
8487c478bd9Sstevel@tonic-gate 		/*LINTED*/
8497c478bd9Sstevel@tonic-gate 		picld_get_attr_by_name((picl_service_t *)argp);
8507c478bd9Sstevel@tonic-gate 		break;
8517c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYROW:
8527c478bd9Sstevel@tonic-gate 		/*LINTED*/
8537c478bd9Sstevel@tonic-gate 		picld_get_attr_by_row((picl_service_t *)argp);
8547c478bd9Sstevel@tonic-gate 		break;
8557c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYCOL:
8567c478bd9Sstevel@tonic-gate 		/*LINTED*/
8577c478bd9Sstevel@tonic-gate 		picld_get_attr_by_col((picl_service_t *)argp);
8587c478bd9Sstevel@tonic-gate 		break;
8597c478bd9Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVAL:
8607c478bd9Sstevel@tonic-gate 		/*LINTED*/
8617c478bd9Sstevel@tonic-gate 		picld_set_attrval((picl_service_t *)argp);
8627c478bd9Sstevel@tonic-gate 		break;
8637c478bd9Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVALBYNAME:
8647c478bd9Sstevel@tonic-gate 		/*LINTED*/
8657c478bd9Sstevel@tonic-gate 		picld_set_attrval_by_name((picl_service_t *)argp);
8667c478bd9Sstevel@tonic-gate 		break;
8677c478bd9Sstevel@tonic-gate 	case PICL_CNUM_PING:
8687c478bd9Sstevel@tonic-gate 		/*LINTED*/
8697c478bd9Sstevel@tonic-gate 		picld_ping((picl_service_t *)argp);
8707c478bd9Sstevel@tonic-gate 		break;
8717c478bd9Sstevel@tonic-gate 	case PICL_CNUM_WAIT:
8727c478bd9Sstevel@tonic-gate 		/*LINTED*/
8737c478bd9Sstevel@tonic-gate 		picld_wait((picl_service_t *)argp);
8747c478bd9Sstevel@tonic-gate 		break;
8757c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FINDNODE:
8767c478bd9Sstevel@tonic-gate 		/*LINTED*/
8777c478bd9Sstevel@tonic-gate 		picld_find_node((picl_service_t *)argp);
8787c478bd9Sstevel@tonic-gate 		break;
8797c478bd9Sstevel@tonic-gate 	case PICL_CNUM_NODEBYPATH:
8807c478bd9Sstevel@tonic-gate 		/*LINTED*/
8817c478bd9Sstevel@tonic-gate 		picld_get_node_by_path((picl_service_t *)argp);
8827c478bd9Sstevel@tonic-gate 		break;
8837c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FRUTREEPARENT:
8847c478bd9Sstevel@tonic-gate 		/*LINTED*/
8857c478bd9Sstevel@tonic-gate 		picld_get_frutree_parent((picl_service_t *)argp);
8867c478bd9Sstevel@tonic-gate 		break;
8877c478bd9Sstevel@tonic-gate 	default:
8887c478bd9Sstevel@tonic-gate 		/*LINTED*/
8897c478bd9Sstevel@tonic-gate 		picld_unknown_service((picl_service_t *)argp);
8907c478bd9Sstevel@tonic-gate 		break;
8917c478bd9Sstevel@tonic-gate 	};
8927c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate /* ARGSUSED */
8967c478bd9Sstevel@tonic-gate static void
hup_handler(int sig,siginfo_t * siginfo,void * sigctx)8977c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
8987c478bd9Sstevel@tonic-gate {
8997c478bd9Sstevel@tonic-gate 	doreinit = 1;
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate /*
9037c478bd9Sstevel@tonic-gate  * "ping" to see if a daemon is already running
9047c478bd9Sstevel@tonic-gate  */
9057c478bd9Sstevel@tonic-gate static int
daemon_exists(void)9067c478bd9Sstevel@tonic-gate daemon_exists(void)
9077c478bd9Sstevel@tonic-gate {
9087c478bd9Sstevel@tonic-gate 	door_arg_t	darg;
9097c478bd9Sstevel@tonic-gate 	picl_reqping_t	req_ping;
9107c478bd9Sstevel@tonic-gate 	picl_retping_t	ret_ping;
9117c478bd9Sstevel@tonic-gate 	int		doorh;
9127c478bd9Sstevel@tonic-gate 	door_info_t	dinfo;
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	doorh = open(PICLD_DOOR, O_RDONLY);
9157c478bd9Sstevel@tonic-gate 	if (doorh < 0)
9167c478bd9Sstevel@tonic-gate 		return (0);
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
9197c478bd9Sstevel@tonic-gate 		(void) close(doorh);
9207c478bd9Sstevel@tonic-gate 		return (0);
9217c478bd9Sstevel@tonic-gate 	}
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 	if ((dinfo.di_attributes & DOOR_REVOKED) ||
9240ec57554Sraf 	    (dinfo.di_data != (uintptr_t)PICLD_DOOR_COOKIE)) {
9257c478bd9Sstevel@tonic-gate 		(void) close(doorh);
9267c478bd9Sstevel@tonic-gate 		return (0);
9277c478bd9Sstevel@tonic-gate 	}
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	if (dinfo.di_target != getpid()) {
9307c478bd9Sstevel@tonic-gate 		(void) close(doorh);
9317c478bd9Sstevel@tonic-gate 		return (1);
9327c478bd9Sstevel@tonic-gate 	}
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	req_ping.cnum = PICL_CNUM_PING;
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
9377c478bd9Sstevel@tonic-gate 	darg.data_size = sizeof (picl_reqping_t);
9387c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
9397c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
9407c478bd9Sstevel@tonic-gate 	darg.rbuf = (char *)&ret_ping;
9417c478bd9Sstevel@tonic-gate 	darg.rsize = sizeof (picl_retping_t);
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
9447c478bd9Sstevel@tonic-gate 		(void) close(doorh);
9457c478bd9Sstevel@tonic-gate 		return (0);
9467c478bd9Sstevel@tonic-gate 	}
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 	(void) close(doorh);
9497c478bd9Sstevel@tonic-gate 	return (1);
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate 
952980a6e61Sjfrank /*
953980a6e61Sjfrank  * picld_create_server_thread - binds the running thread to the private
954980a6e61Sjfrank  * door pool, and sets the required cancellation state.
955980a6e61Sjfrank  */
956980a6e61Sjfrank /* ARGSUSED */
957980a6e61Sjfrank static void *
picld_create_server_thread(void * arg)958980a6e61Sjfrank picld_create_server_thread(void *arg)
959980a6e61Sjfrank {
960980a6e61Sjfrank 	/*
961980a6e61Sjfrank 	 * wait for door descriptor to be initialized
962980a6e61Sjfrank 	 */
963980a6e61Sjfrank 	(void) pthread_mutex_lock(&door_mutex);
964980a6e61Sjfrank 	while (door_id == -1) {
965980a6e61Sjfrank 		(void) pthread_cond_wait(&door_cv, &door_mutex);
966980a6e61Sjfrank 	}
967980a6e61Sjfrank 	(void) pthread_mutex_unlock(&door_mutex);
968980a6e61Sjfrank 
969980a6e61Sjfrank 	/*
970980a6e61Sjfrank 	 * Bind this thread to the door's private thread pool
971980a6e61Sjfrank 	 */
972980a6e61Sjfrank 	if (door_bind(door_id) < 0) {
973980a6e61Sjfrank 		perror("door_bind");
974980a6e61Sjfrank 	}
975980a6e61Sjfrank 
976980a6e61Sjfrank 	/*
977980a6e61Sjfrank 	 * Disable thread cancellation mechanism
978980a6e61Sjfrank 	 */
979980a6e61Sjfrank 	(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
980980a6e61Sjfrank 	(void) door_return(NULL, 0, NULL, 0); /* wait for door invocation */
981980a6e61Sjfrank 	return (NULL);
982980a6e61Sjfrank }
983980a6e61Sjfrank 
984980a6e61Sjfrank /*
985980a6e61Sjfrank  * picld_server_create_fn - creates threads for the private door pool
986980a6e61Sjfrank  *
987980a6e61Sjfrank  */
988980a6e61Sjfrank /* ARGSUSED */
989980a6e61Sjfrank static void
picld_server_create_fn(door_info_t * dip)990980a6e61Sjfrank picld_server_create_fn(door_info_t *dip)
991980a6e61Sjfrank {
992980a6e61Sjfrank 	pthread_attr_t attr;
993980a6e61Sjfrank 
994d5da6539SMichael Bergknoff 	/*
995d5da6539SMichael Bergknoff 	 * For the non-private pool do nothing. It's used for events which are
996d5da6539SMichael Bergknoff 	 * single threaded anyway. The single thread servicing that pool is
997d5da6539SMichael Bergknoff 	 * created when the event plugin creates its door. Note that the event
998d5da6539SMichael Bergknoff 	 * plugin runs before setup_door instantiates picld_server_create_fn as
999d5da6539SMichael Bergknoff 	 * the new create_proc so the door library default create_proc is used.
1000d5da6539SMichael Bergknoff 	 */
1001d5da6539SMichael Bergknoff 	if (dip == NULL)
1002d5da6539SMichael Bergknoff 		return;
1003d5da6539SMichael Bergknoff 
1004980a6e61Sjfrank 	(void) pthread_mutex_lock(&pool_mutex);
1005980a6e61Sjfrank 	if (pool_count < MAX_POOL_SIZE) {
1006980a6e61Sjfrank 		(void) pthread_attr_init(&attr);
1007980a6e61Sjfrank 		(void) pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
1008980a6e61Sjfrank 		(void) pthread_attr_setdetachstate(&attr,
1009980a6e61Sjfrank 		    PTHREAD_CREATE_DETACHED);
1010980a6e61Sjfrank 		if (pthread_create(NULL, &attr, picld_create_server_thread,
1011980a6e61Sjfrank 		    NULL)) {
1012980a6e61Sjfrank 			perror("pthread_create");
1013980a6e61Sjfrank 		} else {
1014980a6e61Sjfrank 			pool_count++;
1015980a6e61Sjfrank 		}
1016980a6e61Sjfrank 	}
1017980a6e61Sjfrank 	(void) pthread_mutex_unlock(&pool_mutex);
1018980a6e61Sjfrank }
1019980a6e61Sjfrank 
10207c478bd9Sstevel@tonic-gate /*
10217c478bd9Sstevel@tonic-gate  * Create the picld door
10227c478bd9Sstevel@tonic-gate  */
10237c478bd9Sstevel@tonic-gate static int
setup_door(void)10247c478bd9Sstevel@tonic-gate setup_door(void)
10257c478bd9Sstevel@tonic-gate {
10267c478bd9Sstevel@tonic-gate 	struct stat	stbuf;
10277c478bd9Sstevel@tonic-gate 
1028980a6e61Sjfrank 	(void) door_server_create(picld_server_create_fn);
1029980a6e61Sjfrank 	(void) pthread_mutex_lock(&door_mutex);
10307c478bd9Sstevel@tonic-gate 	/*
10317c478bd9Sstevel@tonic-gate 	 * Create the door
10327c478bd9Sstevel@tonic-gate 	 */
10337c478bd9Sstevel@tonic-gate 	door_id = door_create(picld_door_handler, PICLD_DOOR_COOKIE,
1034980a6e61Sjfrank 	    DOOR_REFUSE_DESC | DOOR_NO_CANCEL | DOOR_PRIVATE);
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	if (door_id < 0) {
1037980a6e61Sjfrank 		(void) pthread_mutex_unlock(&door_mutex);
10387c478bd9Sstevel@tonic-gate 		return (-1);
1039980a6e61Sjfrank 	} else {
1040980a6e61Sjfrank 		(void) pthread_cond_signal(&door_cv);
1041980a6e61Sjfrank 		(void) pthread_mutex_unlock(&door_mutex);
10427c478bd9Sstevel@tonic-gate 	}
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 	if (stat(PICLD_DOOR, &stbuf) < 0) {
10457c478bd9Sstevel@tonic-gate 		int newfd;
104624b3ac2eSjfrank 		mode_t old_mask;
104724b3ac2eSjfrank 		/* ensure that the door file is world-readable */
104824b3ac2eSjfrank 		old_mask = umask(0);
104924b3ac2eSjfrank 		newfd = creat(PICLD_DOOR, 0444);
105024b3ac2eSjfrank 		/* restore the file mode creation mask */
105124b3ac2eSjfrank 		(void) umask(old_mask);
105224b3ac2eSjfrank 		if (newfd < 0)
10537c478bd9Sstevel@tonic-gate 			return (-1);
10547c478bd9Sstevel@tonic-gate 		(void) close(newfd);
10557c478bd9Sstevel@tonic-gate 	}
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 	if (fattach(door_id, PICLD_DOOR) < 0) {
10587c478bd9Sstevel@tonic-gate 		if ((errno != EBUSY) ||
10597c478bd9Sstevel@tonic-gate 		    (fdetach(PICLD_DOOR) < 0) ||
10607c478bd9Sstevel@tonic-gate 		    (fattach(door_id, PICLD_DOOR) < 0))
10617c478bd9Sstevel@tonic-gate 			return (-1);
10627c478bd9Sstevel@tonic-gate 	}
10637c478bd9Sstevel@tonic-gate 	return (0);
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate /*
10677c478bd9Sstevel@tonic-gate  * Main function of picl daemon
10687c478bd9Sstevel@tonic-gate  */
10697c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)10707c478bd9Sstevel@tonic-gate main(int argc, char **argv)
10717c478bd9Sstevel@tonic-gate {
10727c478bd9Sstevel@tonic-gate 	struct	sigaction	act;
10737c478bd9Sstevel@tonic-gate 	int			c;
10747c478bd9Sstevel@tonic-gate 	sigset_t		ublk;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
10787c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	if (getuid() != 0) {
10817c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, MUST_BE_ROOT);
10827c478bd9Sstevel@tonic-gate 		return (0);
10837c478bd9Sstevel@tonic-gate 	}
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&init_lk, USYNC_THREAD, NULL);
10867c478bd9Sstevel@tonic-gate 	doreinit = 0;
10877c478bd9Sstevel@tonic-gate 	logflag = 1;
10887c478bd9Sstevel@tonic-gate 	dos_req_limit = DOS_PICL_REQUESTS_LIMIT;
10897c478bd9Sstevel@tonic-gate 	sliding_interval_ms = SLIDING_INTERVAL_MILLISECONDS;
10907c478bd9Sstevel@tonic-gate 	dos_ms = DOS_SLEEPTIME_MS;
10917c478bd9Sstevel@tonic-gate 	verbose_level = 0;
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	/*
10947c478bd9Sstevel@tonic-gate 	 * parse arguments
10957c478bd9Sstevel@tonic-gate 	 */
10967c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "is:t:l:r:v:d:")) != EOF) {
10977c478bd9Sstevel@tonic-gate 		switch (c) {
10987c478bd9Sstevel@tonic-gate 		case 'd':
10997c478bd9Sstevel@tonic-gate 			dos_ms = strtol(optarg, (char **)NULL, 0);
11007c478bd9Sstevel@tonic-gate 			break;
11017c478bd9Sstevel@tonic-gate 		case 'i':
11027c478bd9Sstevel@tonic-gate 			logflag = 0;
11037c478bd9Sstevel@tonic-gate 			break;
11047c478bd9Sstevel@tonic-gate 		case 's':
11057c478bd9Sstevel@tonic-gate 			sliding_interval_ms = strtoll(optarg, (char **)NULL, 0);
11067c478bd9Sstevel@tonic-gate 			break;
11077c478bd9Sstevel@tonic-gate 		case 't':
11087c478bd9Sstevel@tonic-gate 			dos_req_limit = strtol(optarg, (char **)NULL, 0);
11097c478bd9Sstevel@tonic-gate 			break;
11107c478bd9Sstevel@tonic-gate 		case 'v':
11117c478bd9Sstevel@tonic-gate 			verbose_level = strtol(optarg, (char **)NULL, 0);
11127c478bd9Sstevel@tonic-gate 			logflag = 0;
11137c478bd9Sstevel@tonic-gate 			break;
11147c478bd9Sstevel@tonic-gate 		default:
11157c478bd9Sstevel@tonic-gate 			break;
11167c478bd9Sstevel@tonic-gate 		}
11177c478bd9Sstevel@tonic-gate 	}
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	orig_time = gethrtime();
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 	/*
11227c478bd9Sstevel@tonic-gate 	 * is there a daemon already running?
11237c478bd9Sstevel@tonic-gate 	 */
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 	if (daemon_exists()) {
11267c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, DAEMON_RUNNING);
11277c478bd9Sstevel@tonic-gate 		exit(1);
11287c478bd9Sstevel@tonic-gate 	}
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	/*
11317c478bd9Sstevel@tonic-gate 	 * Mask off/block SIGALRM signal so that the environmental plug-in
11327c478bd9Sstevel@tonic-gate 	 * (piclenvd) can use it to simulate sleep() without being affected
11337c478bd9Sstevel@tonic-gate 	 * by time being set back. No other PICL plug-in should use SIGALRM
11347c478bd9Sstevel@tonic-gate 	 * or alarm() for now.
11357c478bd9Sstevel@tonic-gate 	 */
11367c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&ublk);
11377c478bd9Sstevel@tonic-gate 	(void) sigaddset(&ublk, SIGALRM);
11387c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 	/*
11417c478bd9Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
11427c478bd9Sstevel@tonic-gate 	 */
11437c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
11447c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
11457c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
11467c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
11477c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
11487c478bd9Sstevel@tonic-gate 		    strerror(errno));
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 	if (logflag != 0) {	/* daemonize */
11517c478bd9Sstevel@tonic-gate 		pid_t pid;
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 		pid = fork();
11547c478bd9Sstevel@tonic-gate 		if (pid < 0)
11557c478bd9Sstevel@tonic-gate 			exit(1);
11567c478bd9Sstevel@tonic-gate 		if (pid > 0)
11577c478bd9Sstevel@tonic-gate 			/* parent */
11587c478bd9Sstevel@tonic-gate 			exit(0);
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 		/* child */
11617c478bd9Sstevel@tonic-gate 		if (chdir("/") == -1) {
11627c478bd9Sstevel@tonic-gate 			syslog(LOG_CRIT, CD_ROOT_FAILED);
11637c478bd9Sstevel@tonic-gate 			exit(1);
11647c478bd9Sstevel@tonic-gate 		}
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 		(void) setsid();
1167d5da6539SMichael Bergknoff 		closefrom(0);
11687c478bd9Sstevel@tonic-gate 		(void) open("/dev/null", O_RDWR, 0);
11697c478bd9Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDOUT_FILENO);
11707c478bd9Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDERR_FILENO);
11717c478bd9Sstevel@tonic-gate 		openlog(PICLD, LOG_PID, LOG_DAEMON);
11727c478bd9Sstevel@tonic-gate 	}
11737c478bd9Sstevel@tonic-gate 
11747c478bd9Sstevel@tonic-gate 	/*
11757c478bd9Sstevel@tonic-gate 	 * Initialize the PICL Tree
11767c478bd9Sstevel@tonic-gate 	 */
1177*e9610e3eSToomas Soome 	if (xptree_initialize(0) != PICL_SUCCESS) {
11787c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, INIT_FAILED);
11797c478bd9Sstevel@tonic-gate 		exit(1);
11807c478bd9Sstevel@tonic-gate 	}
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 	if (setup_door()) {
11837c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, DOOR_FAILED);
11847c478bd9Sstevel@tonic-gate 		exit(1);
11857c478bd9Sstevel@tonic-gate 	}
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 	/*
11887c478bd9Sstevel@tonic-gate 	 * setup signal handlers for post-init
11897c478bd9Sstevel@tonic-gate 	 */
11907c478bd9Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
11917c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
11927c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
11937c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
11947c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
11957c478bd9Sstevel@tonic-gate 		    strerror(errno));
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 	/*
11987c478bd9Sstevel@tonic-gate 	 * wait for requests
11997c478bd9Sstevel@tonic-gate 	 */
12007c478bd9Sstevel@tonic-gate 	for (;;) {
12017c478bd9Sstevel@tonic-gate 		(void) pause();
12027c478bd9Sstevel@tonic-gate 		if (doreinit) {
12037c478bd9Sstevel@tonic-gate 			/*
12047c478bd9Sstevel@tonic-gate 			 * Block SIGHUP during reinitialization.
12057c478bd9Sstevel@tonic-gate 			 * Also mask off/block SIGALRM signal so that the
12067c478bd9Sstevel@tonic-gate 			 * environmental plug-in (piclenvd) can use it to
12077c478bd9Sstevel@tonic-gate 			 * simulate sleep() without being affected by time
12087c478bd9Sstevel@tonic-gate 			 * being set back. No ohter PICL plug-in should use
12097c478bd9Sstevel@tonic-gate 			 * SIGALRM or alarm() for now.
12107c478bd9Sstevel@tonic-gate 			 */
12117c478bd9Sstevel@tonic-gate 			(void) sigemptyset(&ublk);
12127c478bd9Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGHUP);
12137c478bd9Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGALRM);
12147c478bd9Sstevel@tonic-gate 			(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
12157c478bd9Sstevel@tonic-gate 			(void) sigdelset(&ublk, SIGALRM);
12167c478bd9Sstevel@tonic-gate 			doreinit = 0;
12177c478bd9Sstevel@tonic-gate 			(void) rw_wrlock(&init_lk);
12187c478bd9Sstevel@tonic-gate 			xptree_destroy();
12197c478bd9Sstevel@tonic-gate 			(void) xptree_reinitialize();
12207c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&init_lk);
12217c478bd9Sstevel@tonic-gate 			(void) sigprocmask(SIG_UNBLOCK, &ublk, NULL);
12227c478bd9Sstevel@tonic-gate 		}
12237c478bd9Sstevel@tonic-gate 	}
12247c478bd9Sstevel@tonic-gate }
1225