xref: /onnv-gate/usr/src/cmd/picl/picld/picld.c (revision 7162)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56325Sjfrank  * Common Development and Distribution License (the "License").
66325Sjfrank  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211016Sraf 
220Sstevel@tonic-gate /*
236325Sjfrank  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * PICL daemon
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <stdlib.h>
350Sstevel@tonic-gate #include <stdarg.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <libintl.h>
380Sstevel@tonic-gate #include <locale.h>
390Sstevel@tonic-gate #include <alloca.h>
400Sstevel@tonic-gate #include <errno.h>
410Sstevel@tonic-gate #include <assert.h>
420Sstevel@tonic-gate #include <stropts.h>
430Sstevel@tonic-gate #include <unistd.h>
440Sstevel@tonic-gate #include <signal.h>
450Sstevel@tonic-gate #include <pthread.h>
460Sstevel@tonic-gate #include <synch.h>
470Sstevel@tonic-gate #include <door.h>
480Sstevel@tonic-gate #include <sys/door.h>
490Sstevel@tonic-gate #include <fcntl.h>
500Sstevel@tonic-gate #include <dlfcn.h>
510Sstevel@tonic-gate #include <time.h>
520Sstevel@tonic-gate #include <sys/utsname.h>
530Sstevel@tonic-gate #include <sys/systeminfo.h>
540Sstevel@tonic-gate #include <sys/stat.h>
550Sstevel@tonic-gate #include <sys/wait.h>
560Sstevel@tonic-gate #include <dirent.h>
570Sstevel@tonic-gate #include <syslog.h>
580Sstevel@tonic-gate #include <poll.h>
590Sstevel@tonic-gate #include <limits.h>
600Sstevel@tonic-gate #include <picl.h>
610Sstevel@tonic-gate #include "picl2door.h"
620Sstevel@tonic-gate #include <picltree.h>
630Sstevel@tonic-gate #include "ptree_impl.h"
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  * Log text messages
670Sstevel@tonic-gate  */
680Sstevel@tonic-gate #define	MUST_BE_ROOT	gettext("this program must be run as root\n")
690Sstevel@tonic-gate #define	CD_ROOT_FAILED	gettext("chdir to root failed\n")
700Sstevel@tonic-gate #define	INIT_FAILED	gettext("ptree initialization failed\n")
710Sstevel@tonic-gate #define	DAEMON_RUNNING	gettext("PICL daemon already running\n")
720Sstevel@tonic-gate #define	DOOR_FAILED	gettext("Failed creating picld door\n")
730Sstevel@tonic-gate #define	SIGACT_FAILED	\
740Sstevel@tonic-gate 		gettext("Failed to install signal handler for %s: %s\n")
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * Constants
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate #define	PICLD				"picld"
800Sstevel@tonic-gate #define	DOS_PICL_REQUESTS_LIMIT		10000
810Sstevel@tonic-gate #define	SLIDING_INTERVAL_MILLISECONDS	1000
820Sstevel@tonic-gate #define	PICLD_MAJOR_REV			0x1
830Sstevel@tonic-gate #define	PICLD_MINOR_REV			0x0
840Sstevel@tonic-gate #define	DOS_SLEEPTIME_MS		1000
85*7162Sjfrank #define	MAX_POOL_SIZE			_POSIX_THREAD_THREADS_MAX
86*7162Sjfrank #define	MAX_CONCURRENT_WAITS	(_POSIX_THREAD_THREADS_MAX - 2)
87*7162Sjfrank #define	MAX_USER_WAITS			4
880Sstevel@tonic-gate 
890Sstevel@tonic-gate /*
900Sstevel@tonic-gate  * Macros
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate #define	PICLD_VERSION(x, y)	((x << 8) | y)
930Sstevel@tonic-gate #define	PICL_CLIENT_REV(x)	(x & 0xff)
940Sstevel@tonic-gate #define	MILLI_TO_NANO(x)	(x * 1000000)
950Sstevel@tonic-gate 
960Sstevel@tonic-gate extern	char	**environ;
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate  * Module Variables
1000Sstevel@tonic-gate  */
1010Sstevel@tonic-gate static	int		logflag = 1;
1020Sstevel@tonic-gate static	int		doreinit = 0;
1030Sstevel@tonic-gate static	int		door_id = -1;
104*7162Sjfrank static	pthread_mutex_t door_mutex = PTHREAD_MUTEX_INITIALIZER;
105*7162Sjfrank static	pthread_cond_t door_cv = PTHREAD_COND_INITIALIZER;
1060Sstevel@tonic-gate static  int 		service_requests = 0;
1070Sstevel@tonic-gate static	hrtime_t	orig_time;
1080Sstevel@tonic-gate static	hrtime_t	sliding_interval_ms;
1090Sstevel@tonic-gate static	uint32_t	dos_req_limit;
1100Sstevel@tonic-gate static	uint32_t	dos_ms;
1110Sstevel@tonic-gate static	pthread_mutex_t	dos_mutex = PTHREAD_MUTEX_INITIALIZER;
1120Sstevel@tonic-gate static	rwlock_t	init_lk;
113*7162Sjfrank static	int pool_count = 0;
114*7162Sjfrank static	pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
115*7162Sjfrank static	pthread_mutex_t	wait_req_mutex = PTHREAD_MUTEX_INITIALIZER;
116*7162Sjfrank static	int wait_count = 0;
117*7162Sjfrank static	struct {
118*7162Sjfrank 	uid_t uid;
119*7162Sjfrank 	int count;
120*7162Sjfrank } user_count[MAX_CONCURRENT_WAITS];
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate /*
1230Sstevel@tonic-gate  * This returns an error message to libpicl
1240Sstevel@tonic-gate  */
1250Sstevel@tonic-gate static void
1260Sstevel@tonic-gate picld_return_error(picl_callnumber_t cnum, picl_errno_t err)
1270Sstevel@tonic-gate {
1280Sstevel@tonic-gate 	picl_reterror_t	ret_error;
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	ret_error.cnum = PICL_CNUM_ERROR;
1310Sstevel@tonic-gate 	ret_error.in_cnum = cnum;
1320Sstevel@tonic-gate 	ret_error.errnum = err;
1330Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1340Sstevel@tonic-gate 	(void) door_return((char *)&ret_error, sizeof (picl_reterror_t), NULL,
1350Sstevel@tonic-gate 	    0);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate /*
1390Sstevel@tonic-gate  * picld_init is called when a picl_initialize request is received
1400Sstevel@tonic-gate  */
1410Sstevel@tonic-gate static void
1420Sstevel@tonic-gate picld_init(picl_service_t *req)
1430Sstevel@tonic-gate {
1440Sstevel@tonic-gate 	picl_retinit_t	ret_init;
1450Sstevel@tonic-gate 	int	clmajrev;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	clmajrev = PICL_CLIENT_REV(req->req_init.clrev);
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	if (clmajrev < PICL_VERSION_1)
1500Sstevel@tonic-gate 		picld_return_error(req->req_init.cnum, PICL_NOTSUPPORTED);
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	ret_init.cnum = req->req_init.cnum;
1530Sstevel@tonic-gate 	ret_init.rev = PICLD_VERSION(PICLD_MAJOR_REV, PICLD_MINOR_REV);
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1560Sstevel@tonic-gate 	(void) door_return((char *)&ret_init, sizeof (picl_retinit_t), NULL, 0);
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate  * picld_fini is called when a picl_shutdown request is received
1610Sstevel@tonic-gate  */
1620Sstevel@tonic-gate static void
1630Sstevel@tonic-gate picld_fini(picl_service_t *in)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 	picl_retfini_t	ret;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	ret.cnum = in->req_fini.cnum;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1700Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfini_t), NULL, 0);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate static void
1740Sstevel@tonic-gate picld_ping(picl_service_t *in)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate 	picl_retping_t	ret;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	ret.cnum = in->req_ping.cnum;
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1810Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retping_t), NULL, 0);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate 
184*7162Sjfrank static int
185*7162Sjfrank check_user(uid_t uid)
186*7162Sjfrank {
187*7162Sjfrank 	int i;
188*7162Sjfrank 	uid_t tmp_uid;
189*7162Sjfrank 	int free_idx = -1;
190*7162Sjfrank 
191*7162Sjfrank 	if (uid == 0)
192*7162Sjfrank 		return (PICL_SUCCESS);
193*7162Sjfrank 	for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
194*7162Sjfrank 		if ((tmp_uid = user_count[i].uid) == uid) {
195*7162Sjfrank 			if (user_count[i].count == MAX_USER_WAITS)
196*7162Sjfrank 				return (PICL_FAILURE);
197*7162Sjfrank 			user_count[i].count++;
198*7162Sjfrank 			return (PICL_SUCCESS);
199*7162Sjfrank 		}
200*7162Sjfrank 		if ((free_idx == -1) && (tmp_uid == 0))
201*7162Sjfrank 			free_idx = i;
202*7162Sjfrank 	}
203*7162Sjfrank 	if (free_idx != -1) {
204*7162Sjfrank 		user_count[free_idx].uid = uid;
205*7162Sjfrank 		user_count[free_idx].count = 1;
206*7162Sjfrank 		return (PICL_SUCCESS);
207*7162Sjfrank 	}
208*7162Sjfrank 	return (PICL_FAILURE);
209*7162Sjfrank }
210*7162Sjfrank 
211*7162Sjfrank static void
212*7162Sjfrank done_user(uid_t uid)
213*7162Sjfrank {
214*7162Sjfrank 	int i;
215*7162Sjfrank 
216*7162Sjfrank 	if (uid == 0)
217*7162Sjfrank 		return;
218*7162Sjfrank 	for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
219*7162Sjfrank 		if (user_count[i].uid == uid) {
220*7162Sjfrank 			if (--user_count[i].count == 0)
221*7162Sjfrank 				user_count[i].uid = 0;
222*7162Sjfrank 			return;
223*7162Sjfrank 		}
224*7162Sjfrank 	}
225*7162Sjfrank }
226*7162Sjfrank 
227*7162Sjfrank static int
228*7162Sjfrank enter_picld_wait(uid_t uid)
229*7162Sjfrank {
230*7162Sjfrank 	int	rv;
231*7162Sjfrank 
232*7162Sjfrank 	if (pthread_mutex_lock(&wait_req_mutex) != 0)
233*7162Sjfrank 		return (PICL_FAILURE);
234*7162Sjfrank 	if ((wait_count < MAX_CONCURRENT_WAITS) &&
235*7162Sjfrank 	    (check_user(uid) == PICL_SUCCESS)) {
236*7162Sjfrank 		rv = PICL_SUCCESS;
237*7162Sjfrank 		wait_count++;
238*7162Sjfrank 	} else {
239*7162Sjfrank 		rv = PICL_FAILURE;
240*7162Sjfrank 	}
241*7162Sjfrank 	(void) pthread_mutex_unlock(&wait_req_mutex);
242*7162Sjfrank 	return (rv);
243*7162Sjfrank }
244*7162Sjfrank 
245*7162Sjfrank static void
246*7162Sjfrank exit_picld_wait(uid_t uid)
247*7162Sjfrank {
248*7162Sjfrank 	(void) pthread_mutex_lock(&wait_req_mutex);
249*7162Sjfrank 	done_user(uid);
250*7162Sjfrank 	wait_count--;
251*7162Sjfrank 	(void) pthread_mutex_unlock(&wait_req_mutex);
252*7162Sjfrank }
253*7162Sjfrank 
2540Sstevel@tonic-gate /*
2550Sstevel@tonic-gate  * picld_wait is called when a picl_wait request is received
2560Sstevel@tonic-gate  */
2570Sstevel@tonic-gate static void
2580Sstevel@tonic-gate picld_wait(picl_service_t *in)
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate 	picl_retwait_t	ret;
2610Sstevel@tonic-gate 	int		err;
262*7162Sjfrank 	ucred_t	*puc = NULL;
263*7162Sjfrank 	uid_t uid;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	ret.cnum = in->req_wait.cnum;
266*7162Sjfrank 	if (door_ucred(&puc) != 0)
267*7162Sjfrank 		ret.retcode = PICL_FAILURE;
268*7162Sjfrank 	else {
269*7162Sjfrank 		uid = ucred_geteuid(puc);
270*7162Sjfrank 		if (enter_picld_wait(uid) == PICL_FAILURE)
271*7162Sjfrank 			ret.retcode = PICL_FAILURE;
272*7162Sjfrank 		else {
273*7162Sjfrank 			err = xptree_refresh_notify(in->req_wait.secs);
274*7162Sjfrank 			ret.retcode = err;
275*7162Sjfrank 			exit_picld_wait(uid);
276*7162Sjfrank 		}
277*7162Sjfrank 		ucred_free(puc);
278*7162Sjfrank 	}
2790Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
2800Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retwait_t), NULL, 0);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate  * This function returns the handle of the root node of the PICL tree
2850Sstevel@tonic-gate  */
2860Sstevel@tonic-gate static void
2870Sstevel@tonic-gate picld_getroot(picl_service_t *in)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate 	picl_retroot_t	ret;
2900Sstevel@tonic-gate 	int		err;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETROOT;
2930Sstevel@tonic-gate 	err = ptree_get_root(&ret.rnode);
2940Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2950Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2960Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnode);
2970Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
2980Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retroot_t), NULL, 0);
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate /*
3020Sstevel@tonic-gate  * This function returns the value of the PICL property
3030Sstevel@tonic-gate  */
3040Sstevel@tonic-gate static void
3050Sstevel@tonic-gate picld_get_attrval(picl_service_t *in)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate 	picl_retattrval_t	*ret;
3080Sstevel@tonic-gate 	int			err;
3090Sstevel@tonic-gate 	size_t			vbufsize;
3100Sstevel@tonic-gate 	size_t			len;
3110Sstevel@tonic-gate 	door_cred_t		cred;
3120Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
3130Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
3160Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrval.attr, &ptreeh);
3190Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3200Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
3230Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3240Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
3270Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
3300Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrval.bufsize, vbufsize);
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	len = sizeof (picl_retattrval_t) + vbufsize;
3330Sstevel@tonic-gate 	ret = alloca(len);
3340Sstevel@tonic-gate 	if (ret == NULL)
3350Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3360Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVAL;
3370Sstevel@tonic-gate 	ret->attr = in->req_attrval.attr;
3380Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
3390Sstevel@tonic-gate 	err = xptree_get_propval_with_cred(ptreeh, ret->ret_buf, vbufsize,
3400Sstevel@tonic-gate 	    cred);
3410Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3420Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	/*
3450Sstevel@tonic-gate 	 * adjust returned bytes for charstrings
3460Sstevel@tonic-gate 	 */
3470Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
3480Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	/*
3510Sstevel@tonic-gate 	 * convert handle values to picl handles
3520Sstevel@tonic-gate 	 */
3530Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
3540Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
3550Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
3560Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
3570Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrval_t) +
3580Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate /*
3620Sstevel@tonic-gate  * This function returns the value of the PICL property specified by
3630Sstevel@tonic-gate  * its name.
3640Sstevel@tonic-gate  */
3650Sstevel@tonic-gate static void
3660Sstevel@tonic-gate picld_get_attrval_by_name(picl_service_t *in)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate 	picl_retattrvalbyname_t	*ret;
3690Sstevel@tonic-gate 	int			err;
3700Sstevel@tonic-gate 	size_t			vbufsize;
3710Sstevel@tonic-gate 	size_t			len;
3720Sstevel@tonic-gate 	door_cred_t		cred;
3730Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
3740Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
3770Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrvalbyname.nodeh, &ptreeh);
3800Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3810Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
3840Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, &pinfo);
3850Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3860Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
3890Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	/*
3920Sstevel@tonic-gate 	 * allocate the minimum of piclinfo.size and input bufsize
3930Sstevel@tonic-gate 	 */
3940Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
3950Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrvalbyname.bufsize, vbufsize);
3960Sstevel@tonic-gate 	len = sizeof (picl_retattrvalbyname_t) + vbufsize;
3970Sstevel@tonic-gate 	ret = alloca(len);
3980Sstevel@tonic-gate 	if (ret == NULL)
3990Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
4000Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVALBYNAME;
4010Sstevel@tonic-gate 	ret->nodeh = in->req_attrvalbyname.nodeh;
4020Sstevel@tonic-gate 	(void) strcpy(ret->propname, in->req_attrvalbyname.propname);
4030Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	err = xptree_get_propval_by_name_with_cred(ptreeh,
4060Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, ret->ret_buf, vbufsize,
4070Sstevel@tonic-gate 	    cred);
4080Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4090Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4100Sstevel@tonic-gate 	/*
4110Sstevel@tonic-gate 	 * adjust returned value size for charstrings
4120Sstevel@tonic-gate 	 */
4130Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
4140Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
4170Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
4180Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
4210Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrvalbyname_t) +
4220Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate /*
4260Sstevel@tonic-gate  * This function sets a property value
4270Sstevel@tonic-gate  */
4280Sstevel@tonic-gate static void
4290Sstevel@tonic-gate picld_set_attrval(picl_service_t *in)
4300Sstevel@tonic-gate {
4310Sstevel@tonic-gate 	picl_retsetattrval_t	ret;
4320Sstevel@tonic-gate 	int			err;
4330Sstevel@tonic-gate 	door_cred_t		cred;
4340Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
4350Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
4380Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrval.attr, &ptreeh);
4410Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4420Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
4450Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4460Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
4490Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
4500Sstevel@tonic-gate 	/*
4510Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
4520Sstevel@tonic-gate 	 */
4530Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
4540Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
4550Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVAL;
4580Sstevel@tonic-gate 	ret.attr = in->req_setattrval.attr;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	err = xptree_update_propval_with_cred(ptreeh, in->req_setattrval.valbuf,
4610Sstevel@tonic-gate 	    (size_t)in->req_setattrval.bufsize, cred);
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4640Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
4670Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrval_t), NULL,
4680Sstevel@tonic-gate 	    0);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate /*
4720Sstevel@tonic-gate  * This function sets the value of a property specified by its name.
4730Sstevel@tonic-gate  */
4740Sstevel@tonic-gate static void
4750Sstevel@tonic-gate picld_set_attrval_by_name(picl_service_t *in)
4760Sstevel@tonic-gate {
4770Sstevel@tonic-gate 	picl_retsetattrvalbyname_t	ret;
4780Sstevel@tonic-gate 	int				err;
4790Sstevel@tonic-gate 	door_cred_t			cred;
4800Sstevel@tonic-gate 	picl_prophdl_t			ptreeh;
4810Sstevel@tonic-gate 	ptree_propinfo_t		pinfo;
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
4840Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrvalbyname.nodeh, &ptreeh);
4870Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4880Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
4910Sstevel@tonic-gate 	    in->req_setattrvalbyname.propname, &pinfo);
4920Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4930Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
4960Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	/*
4990Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
5000Sstevel@tonic-gate 	 */
5010Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
5020Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
5030Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVALBYNAME;
5060Sstevel@tonic-gate 	ret.nodeh = in->req_setattrvalbyname.nodeh;
5070Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_setattrvalbyname.propname);
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	err = xptree_update_propval_by_name_with_cred(ptreeh,
5106325Sjfrank 	    in->req_setattrvalbyname.propname,
5116325Sjfrank 	    in->req_setattrvalbyname.valbuf,
5126325Sjfrank 	    (size_t)in->req_setattrvalbyname.bufsize,
5136325Sjfrank 	    cred);
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5160Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5190Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrvalbyname_t),
5200Sstevel@tonic-gate 	    NULL, 0);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate /*
5240Sstevel@tonic-gate  * This function returns the property information
5250Sstevel@tonic-gate  */
5260Sstevel@tonic-gate static void
5270Sstevel@tonic-gate picld_get_attrinfo(picl_service_t *in)
5280Sstevel@tonic-gate {
5290Sstevel@tonic-gate 	picl_retattrinfo_t	ret;
5300Sstevel@tonic-gate 	int			err;
5310Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
5320Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrinfo.attr, &ptreeh);
5350Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5360Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRINFO;
5390Sstevel@tonic-gate 	ret.attr = in->req_attrinfo.attr;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
5420Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5430Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	ret.type = pinfo.piclinfo.type;
5460Sstevel@tonic-gate 	ret.accessmode = pinfo.piclinfo.accessmode;
5470Sstevel@tonic-gate 	ret.size = (uint32_t)pinfo.piclinfo.size;
5480Sstevel@tonic-gate 	(void) strcpy(ret.name, pinfo.piclinfo.name);
5490Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5500Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrinfo_t), NULL, 0);
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate /*
5540Sstevel@tonic-gate  * This function returns the node's first property handle
5550Sstevel@tonic-gate  */
5560Sstevel@tonic-gate static void
5570Sstevel@tonic-gate picld_get_first_attr(picl_service_t *in)
5580Sstevel@tonic-gate {
5590Sstevel@tonic-gate 	picl_retfirstattr_t	ret;
5600Sstevel@tonic-gate 	int			err;
5610Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_firstattr.nodeh, &ptreeh);
5640Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5650Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETFIRSTATTR;
5680Sstevel@tonic-gate 	ret.nodeh = in->req_firstattr.nodeh;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	err = ptree_get_first_prop(ptreeh, &ret.attr);
5710Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5720Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5730Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
5740Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5750Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfirstattr_t), NULL, 0);
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate /*
5790Sstevel@tonic-gate  * This function returns the next property handle in list
5800Sstevel@tonic-gate  */
5810Sstevel@tonic-gate static void
5820Sstevel@tonic-gate picld_get_next_attr(picl_service_t *in)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate 	picl_retnextattr_t	ret;
5850Sstevel@tonic-gate 	int			err;
5860Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_nextattr.attr, &ptreeh);
5890Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5900Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETNEXTATTR;
5930Sstevel@tonic-gate 	ret.attr = in->req_nextattr.attr;
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	err = ptree_get_next_prop(ptreeh, &ret.nextattr);
5960Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5970Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nextattr);
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6020Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retnextattr_t), NULL, 0);
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate /*
6060Sstevel@tonic-gate  * This function returns the handle of a property specified by its name
6070Sstevel@tonic-gate  */
6080Sstevel@tonic-gate static void
6090Sstevel@tonic-gate picld_get_attr_by_name(picl_service_t *in)
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate 	picl_retattrbyname_t	ret;
6120Sstevel@tonic-gate 	int			err;
6130Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyname.nodeh, &ptreeh);
6160Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6170Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYNAME;
6200Sstevel@tonic-gate 	ret.nodeh = in->req_attrbyname.nodeh;
6210Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_attrbyname.propname);
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	err = ptree_get_prop_by_name(ptreeh, ret.propname, &ret.attr);
6240Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6250Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
6280Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6290Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyname_t), NULL,
6300Sstevel@tonic-gate 	    0);
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate /*
6340Sstevel@tonic-gate  * This function gets the next property on the same row in the table
6350Sstevel@tonic-gate  */
6360Sstevel@tonic-gate static void
6370Sstevel@tonic-gate picld_get_attr_by_row(picl_service_t *in)
6380Sstevel@tonic-gate {
6390Sstevel@tonic-gate 	picl_retattrbyrow_t	ret;
6400Sstevel@tonic-gate 	int			err;
6410Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyrow.attr, &ptreeh);
6440Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6450Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYROW;
6480Sstevel@tonic-gate 	ret.attr = in->req_attrbyrow.attr;
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	err = ptree_get_next_by_row(ptreeh, &ret.rowattr);
6510Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6520Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6530Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rowattr);
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6560Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyrow_t), NULL, 0);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate  * This function returns the handle of the next property in the same column
6610Sstevel@tonic-gate  * of the table.
6620Sstevel@tonic-gate  */
6630Sstevel@tonic-gate static void
6640Sstevel@tonic-gate picld_get_attr_by_col(picl_service_t *in)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate 	picl_retattrbycol_t	ret;
6670Sstevel@tonic-gate 	int			err;
6680Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbycol.attr, &ptreeh);
6710Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6720Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYCOL;
6750Sstevel@tonic-gate 	ret.attr = in->req_attrbycol.attr;
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 	err = ptree_get_next_by_col(ptreeh, &ret.colattr);
6780Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6790Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	cvt_ptree2picl(&ret.colattr);
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6840Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbycol_t), NULL, 0);
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate /*
6880Sstevel@tonic-gate  * This function finds the node in the PICLTREE that matches the given
6890Sstevel@tonic-gate  * criteria and returns its handle.
6900Sstevel@tonic-gate  */
6910Sstevel@tonic-gate static void
6920Sstevel@tonic-gate picld_find_node(picl_service_t *in)
6930Sstevel@tonic-gate {
6940Sstevel@tonic-gate 	picl_retfindnode_t	ret;
6950Sstevel@tonic-gate 	int			err;
6960Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_findnode.nodeh, &ptreeh);
6990Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7000Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FINDNODE;
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 	err = ptree_find_node(ptreeh, in->req_findnode.propname,
7050Sstevel@tonic-gate 	    in->req_findnode.ptype, in->req_findnode.valbuf,
7060Sstevel@tonic-gate 	    in->req_findnode.valsize, &ret.rnodeh);
7070Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7080Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnodeh);
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
7130Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7140Sstevel@tonic-gate }
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate /*
7170Sstevel@tonic-gate  * This function finds the property/node that corresponds to the given path
7180Sstevel@tonic-gate  * and returns its handle
7190Sstevel@tonic-gate  */
7200Sstevel@tonic-gate static void
7210Sstevel@tonic-gate picld_get_node_by_path(picl_service_t *in)
7220Sstevel@tonic-gate {
7230Sstevel@tonic-gate 	picl_retnodebypath_t	ret;
7240Sstevel@tonic-gate 	int			err;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_NODEBYPATH;
7270Sstevel@tonic-gate 	err = ptree_get_node_by_path(in->req_nodebypath.pathbuf, &ret.nodeh);
7280Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7290Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7300Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nodeh);
7310Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
7320Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate /*
7360Sstevel@tonic-gate  * This function returns finds the frutree parent node for a given node
7370Sstevel@tonic-gate  * and returns its handle
7380Sstevel@tonic-gate  */
7390Sstevel@tonic-gate static void
7400Sstevel@tonic-gate picld_get_frutree_parent(picl_service_t *in)
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate 	picl_retfruparent_t	ret;
7430Sstevel@tonic-gate 	int			err;
7440Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_fruparent.devh, &ptreeh);
7470Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7480Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FRUTREEPARENT;
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	err = ptree_get_frutree_parent(ptreeh, &ret.fruh);
7530Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
7540Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
7550Sstevel@tonic-gate 	cvt_ptree2picl(&ret.fruh);
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
7580Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate /*
7620Sstevel@tonic-gate  * This function is called when an unknown client request is received.
7630Sstevel@tonic-gate  */
7640Sstevel@tonic-gate static void
7650Sstevel@tonic-gate picld_unknown_service(picl_service_t *in)
7660Sstevel@tonic-gate {
7670Sstevel@tonic-gate 	picld_return_error(in->in.cnum, PICL_UNKNOWNSERVICE);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate static void
7710Sstevel@tonic-gate check_denial_of_service(int cnum)
7720Sstevel@tonic-gate {
7730Sstevel@tonic-gate 	hrtime_t	window;
7740Sstevel@tonic-gate 	hrtime_t	current;
7750Sstevel@tonic-gate 	int		dos_flag;
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	current = gethrtime();
7780Sstevel@tonic-gate 	dos_flag = 0;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	if (pthread_mutex_lock(&dos_mutex) != 0)
7810Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 	++service_requests;
7840Sstevel@tonic-gate 	window = current - orig_time;
7850Sstevel@tonic-gate 	if (window > MILLI_TO_NANO(sliding_interval_ms)) {
7860Sstevel@tonic-gate 		orig_time = current;
7870Sstevel@tonic-gate 		service_requests = 1;
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	if (service_requests > dos_req_limit)
7910Sstevel@tonic-gate 		dos_flag = 1;
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	if (pthread_mutex_unlock(&dos_mutex) != 0)
7940Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	if (dos_flag)
7970Sstevel@tonic-gate 		(void) poll(NULL, 0, dos_ms);
7980Sstevel@tonic-gate }
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate /* ARGSUSED */
8010Sstevel@tonic-gate static void
8020Sstevel@tonic-gate picld_door_handler(void *cookie, char *argp, size_t asize,
8030Sstevel@tonic-gate     door_desc_t *dp, uint_t n_desc)
8040Sstevel@tonic-gate {
8050Sstevel@tonic-gate 	picl_service_t  *req;
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	/*LINTED*/
8080Sstevel@tonic-gate 	req = (picl_service_t *)argp;
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	if (req == NULL)
8110Sstevel@tonic-gate 		(void) door_return((char *)req, 0, NULL, 0);
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	check_denial_of_service(req->in.cnum);
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	(void) rw_rdlock(&init_lk);
8160Sstevel@tonic-gate 	switch (req->in.cnum) {	/* client call number */
8170Sstevel@tonic-gate 	case PICL_CNUM_INIT:
8180Sstevel@tonic-gate 		/*LINTED*/
8190Sstevel@tonic-gate 		picld_init((picl_service_t *)argp);
8200Sstevel@tonic-gate 		break;
8210Sstevel@tonic-gate 	case PICL_CNUM_FINI:
8220Sstevel@tonic-gate 		/*LINTED*/
8230Sstevel@tonic-gate 		picld_fini((picl_service_t *)argp);
8240Sstevel@tonic-gate 		break;
8250Sstevel@tonic-gate 	case PICL_CNUM_GETROOT:
8260Sstevel@tonic-gate 		/*LINTED*/
8270Sstevel@tonic-gate 		picld_getroot((picl_service_t *)argp);
8280Sstevel@tonic-gate 		break;
8290Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVAL:
8300Sstevel@tonic-gate 		/*LINTED*/
8310Sstevel@tonic-gate 		picld_get_attrval((picl_service_t *)argp);
8320Sstevel@tonic-gate 		break;
8330Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVALBYNAME:
8340Sstevel@tonic-gate 		/*LINTED*/
8350Sstevel@tonic-gate 		picld_get_attrval_by_name((picl_service_t *)argp);
8360Sstevel@tonic-gate 		break;
8370Sstevel@tonic-gate 	case PICL_CNUM_GETATTRINFO:
8380Sstevel@tonic-gate 		/*LINTED*/
8390Sstevel@tonic-gate 		picld_get_attrinfo((picl_service_t *)argp);
8400Sstevel@tonic-gate 		break;
8410Sstevel@tonic-gate 	case PICL_CNUM_GETFIRSTATTR:
8420Sstevel@tonic-gate 		/*LINTED*/
8430Sstevel@tonic-gate 		picld_get_first_attr((picl_service_t *)argp);
8440Sstevel@tonic-gate 		break;
8450Sstevel@tonic-gate 	case PICL_CNUM_GETNEXTATTR:
8460Sstevel@tonic-gate 		/*LINTED*/
8470Sstevel@tonic-gate 		picld_get_next_attr((picl_service_t *)argp);
8480Sstevel@tonic-gate 		break;
8490Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYNAME:
8500Sstevel@tonic-gate 		/*LINTED*/
8510Sstevel@tonic-gate 		picld_get_attr_by_name((picl_service_t *)argp);
8520Sstevel@tonic-gate 		break;
8530Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYROW:
8540Sstevel@tonic-gate 		/*LINTED*/
8550Sstevel@tonic-gate 		picld_get_attr_by_row((picl_service_t *)argp);
8560Sstevel@tonic-gate 		break;
8570Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYCOL:
8580Sstevel@tonic-gate 		/*LINTED*/
8590Sstevel@tonic-gate 		picld_get_attr_by_col((picl_service_t *)argp);
8600Sstevel@tonic-gate 		break;
8610Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVAL:
8620Sstevel@tonic-gate 		/*LINTED*/
8630Sstevel@tonic-gate 		picld_set_attrval((picl_service_t *)argp);
8640Sstevel@tonic-gate 		break;
8650Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVALBYNAME:
8660Sstevel@tonic-gate 		/*LINTED*/
8670Sstevel@tonic-gate 		picld_set_attrval_by_name((picl_service_t *)argp);
8680Sstevel@tonic-gate 		break;
8690Sstevel@tonic-gate 	case PICL_CNUM_PING:
8700Sstevel@tonic-gate 		/*LINTED*/
8710Sstevel@tonic-gate 		picld_ping((picl_service_t *)argp);
8720Sstevel@tonic-gate 		break;
8730Sstevel@tonic-gate 	case PICL_CNUM_WAIT:
8740Sstevel@tonic-gate 		/*LINTED*/
8750Sstevel@tonic-gate 		picld_wait((picl_service_t *)argp);
8760Sstevel@tonic-gate 		break;
8770Sstevel@tonic-gate 	case PICL_CNUM_FINDNODE:
8780Sstevel@tonic-gate 		/*LINTED*/
8790Sstevel@tonic-gate 		picld_find_node((picl_service_t *)argp);
8800Sstevel@tonic-gate 		break;
8810Sstevel@tonic-gate 	case PICL_CNUM_NODEBYPATH:
8820Sstevel@tonic-gate 		/*LINTED*/
8830Sstevel@tonic-gate 		picld_get_node_by_path((picl_service_t *)argp);
8840Sstevel@tonic-gate 		break;
8850Sstevel@tonic-gate 	case PICL_CNUM_FRUTREEPARENT:
8860Sstevel@tonic-gate 		/*LINTED*/
8870Sstevel@tonic-gate 		picld_get_frutree_parent((picl_service_t *)argp);
8880Sstevel@tonic-gate 		break;
8890Sstevel@tonic-gate 	default:
8900Sstevel@tonic-gate 		/*LINTED*/
8910Sstevel@tonic-gate 		picld_unknown_service((picl_service_t *)argp);
8920Sstevel@tonic-gate 		break;
8930Sstevel@tonic-gate 	};
8940Sstevel@tonic-gate 	/*NOTREACHED*/
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate /* ARGSUSED */
8980Sstevel@tonic-gate static void
8990Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
9000Sstevel@tonic-gate {
9010Sstevel@tonic-gate 	doreinit = 1;
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate /*
9050Sstevel@tonic-gate  * "ping" to see if a daemon is already running
9060Sstevel@tonic-gate  */
9070Sstevel@tonic-gate static int
9080Sstevel@tonic-gate daemon_exists(void)
9090Sstevel@tonic-gate {
9100Sstevel@tonic-gate 	door_arg_t	darg;
9110Sstevel@tonic-gate 	picl_reqping_t	req_ping;
9120Sstevel@tonic-gate 	picl_retping_t	ret_ping;
9130Sstevel@tonic-gate 	int		doorh;
9140Sstevel@tonic-gate 	door_info_t	dinfo;
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	doorh = open(PICLD_DOOR, O_RDONLY);
9170Sstevel@tonic-gate 	if (doorh < 0)
9180Sstevel@tonic-gate 		return (0);
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
9210Sstevel@tonic-gate 		(void) close(doorh);
9220Sstevel@tonic-gate 		return (0);
9230Sstevel@tonic-gate 	}
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	if ((dinfo.di_attributes & DOOR_REVOKED) ||
9261016Sraf 	    (dinfo.di_data != (uintptr_t)PICLD_DOOR_COOKIE)) {
9270Sstevel@tonic-gate 		(void) close(doorh);
9280Sstevel@tonic-gate 		return (0);
9290Sstevel@tonic-gate 	}
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	if (dinfo.di_target != getpid()) {
9320Sstevel@tonic-gate 		(void) close(doorh);
9330Sstevel@tonic-gate 		return (1);
9340Sstevel@tonic-gate 	}
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	req_ping.cnum = PICL_CNUM_PING;
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
9390Sstevel@tonic-gate 	darg.data_size = sizeof (picl_reqping_t);
9400Sstevel@tonic-gate 	darg.desc_ptr = NULL;
9410Sstevel@tonic-gate 	darg.desc_num = 0;
9420Sstevel@tonic-gate 	darg.rbuf = (char *)&ret_ping;
9430Sstevel@tonic-gate 	darg.rsize = sizeof (picl_retping_t);
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
9460Sstevel@tonic-gate 		(void) close(doorh);
9470Sstevel@tonic-gate 		return (0);
9480Sstevel@tonic-gate 	}
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	(void) close(doorh);
9510Sstevel@tonic-gate 	return (1);
9520Sstevel@tonic-gate }
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate /*
955*7162Sjfrank  * picld_create_server_thread - binds the running thread to the private
956*7162Sjfrank  * door pool, and sets the required cancellation state.
957*7162Sjfrank  */
958*7162Sjfrank /* ARGSUSED */
959*7162Sjfrank static void *
960*7162Sjfrank picld_create_server_thread(void *arg)
961*7162Sjfrank {
962*7162Sjfrank 	/*
963*7162Sjfrank 	 * wait for door descriptor to be initialized
964*7162Sjfrank 	 */
965*7162Sjfrank 	(void) pthread_mutex_lock(&door_mutex);
966*7162Sjfrank 	while (door_id == -1) {
967*7162Sjfrank 		(void) pthread_cond_wait(&door_cv, &door_mutex);
968*7162Sjfrank 	}
969*7162Sjfrank 	(void) pthread_mutex_unlock(&door_mutex);
970*7162Sjfrank 
971*7162Sjfrank 	/*
972*7162Sjfrank 	 * Bind this thread to the door's private thread pool
973*7162Sjfrank 	 */
974*7162Sjfrank 	if (door_bind(door_id) < 0) {
975*7162Sjfrank 		perror("door_bind");
976*7162Sjfrank 	}
977*7162Sjfrank 
978*7162Sjfrank 	/*
979*7162Sjfrank 	 * Disable thread cancellation mechanism
980*7162Sjfrank 	 */
981*7162Sjfrank 	(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
982*7162Sjfrank 	(void) door_return(NULL, 0, NULL, 0); /* wait for door invocation */
983*7162Sjfrank 	return (NULL);
984*7162Sjfrank }
985*7162Sjfrank 
986*7162Sjfrank /*
987*7162Sjfrank  * picld_server_create_fn - creates threads for the private door pool
988*7162Sjfrank  *
989*7162Sjfrank  */
990*7162Sjfrank /* ARGSUSED */
991*7162Sjfrank static void
992*7162Sjfrank picld_server_create_fn(door_info_t *dip)
993*7162Sjfrank {
994*7162Sjfrank 	pthread_attr_t attr;
995*7162Sjfrank 
996*7162Sjfrank 	(void) pthread_mutex_lock(&pool_mutex);
997*7162Sjfrank 	if (pool_count < MAX_POOL_SIZE) {
998*7162Sjfrank 		(void) pthread_attr_init(&attr);
999*7162Sjfrank 		(void) pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
1000*7162Sjfrank 		(void) pthread_attr_setdetachstate(&attr,
1001*7162Sjfrank 		    PTHREAD_CREATE_DETACHED);
1002*7162Sjfrank 		if (pthread_create(NULL, &attr, picld_create_server_thread,
1003*7162Sjfrank 		    NULL)) {
1004*7162Sjfrank 			perror("pthread_create");
1005*7162Sjfrank 		} else {
1006*7162Sjfrank 			pool_count++;
1007*7162Sjfrank 		}
1008*7162Sjfrank 	}
1009*7162Sjfrank 	(void) pthread_mutex_unlock(&pool_mutex);
1010*7162Sjfrank }
1011*7162Sjfrank 
1012*7162Sjfrank /*
10130Sstevel@tonic-gate  * Create the picld door
10140Sstevel@tonic-gate  */
10150Sstevel@tonic-gate static int
10160Sstevel@tonic-gate setup_door(void)
10170Sstevel@tonic-gate {
10180Sstevel@tonic-gate 	struct stat	stbuf;
10190Sstevel@tonic-gate 
1020*7162Sjfrank 	(void) door_server_create(picld_server_create_fn);
1021*7162Sjfrank 	(void) pthread_mutex_lock(&door_mutex);
10220Sstevel@tonic-gate 	/*
10230Sstevel@tonic-gate 	 * Create the door
10240Sstevel@tonic-gate 	 */
10250Sstevel@tonic-gate 	door_id = door_create(picld_door_handler, PICLD_DOOR_COOKIE,
1026*7162Sjfrank 	    DOOR_REFUSE_DESC | DOOR_NO_CANCEL | DOOR_PRIVATE);
10270Sstevel@tonic-gate 
10280Sstevel@tonic-gate 	if (door_id < 0) {
1029*7162Sjfrank 		(void) pthread_mutex_unlock(&door_mutex);
10300Sstevel@tonic-gate 		return (-1);
1031*7162Sjfrank 	} else {
1032*7162Sjfrank 		(void) pthread_cond_signal(&door_cv);
1033*7162Sjfrank 		(void) pthread_mutex_unlock(&door_mutex);
10340Sstevel@tonic-gate 	}
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 	if (stat(PICLD_DOOR, &stbuf) < 0) {
10370Sstevel@tonic-gate 		int newfd;
10386325Sjfrank 		mode_t old_mask;
10396325Sjfrank 		/* ensure that the door file is world-readable */
10406325Sjfrank 		old_mask = umask(0);
10416325Sjfrank 		newfd = creat(PICLD_DOOR, 0444);
10426325Sjfrank 		/* restore the file mode creation mask */
10436325Sjfrank 		(void) umask(old_mask);
10446325Sjfrank 		if (newfd < 0)
10450Sstevel@tonic-gate 			return (-1);
10460Sstevel@tonic-gate 		(void) close(newfd);
10470Sstevel@tonic-gate 	}
10480Sstevel@tonic-gate 
10490Sstevel@tonic-gate 	if (fattach(door_id, PICLD_DOOR) < 0) {
10500Sstevel@tonic-gate 		if ((errno != EBUSY) ||
10510Sstevel@tonic-gate 		    (fdetach(PICLD_DOOR) < 0) ||
10520Sstevel@tonic-gate 		    (fattach(door_id, PICLD_DOOR) < 0))
10530Sstevel@tonic-gate 			return (-1);
10540Sstevel@tonic-gate 	}
10550Sstevel@tonic-gate 	return (0);
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate /*
10590Sstevel@tonic-gate  * Main function of picl daemon
10600Sstevel@tonic-gate  */
10610Sstevel@tonic-gate int
10620Sstevel@tonic-gate main(int argc, char **argv)
10630Sstevel@tonic-gate {
10640Sstevel@tonic-gate 	struct	sigaction	act;
10650Sstevel@tonic-gate 	int			c;
10660Sstevel@tonic-gate 	sigset_t		ublk;
10670Sstevel@tonic-gate 
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
10700Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
10710Sstevel@tonic-gate 
10720Sstevel@tonic-gate 	if (getuid() != 0) {
10730Sstevel@tonic-gate 		syslog(LOG_CRIT, MUST_BE_ROOT);
10740Sstevel@tonic-gate 		return (0);
10750Sstevel@tonic-gate 	}
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	(void) rwlock_init(&init_lk, USYNC_THREAD, NULL);
10780Sstevel@tonic-gate 	doreinit = 0;
10790Sstevel@tonic-gate 	logflag = 1;
10800Sstevel@tonic-gate 	dos_req_limit = DOS_PICL_REQUESTS_LIMIT;
10810Sstevel@tonic-gate 	sliding_interval_ms = SLIDING_INTERVAL_MILLISECONDS;
10820Sstevel@tonic-gate 	dos_ms = DOS_SLEEPTIME_MS;
10830Sstevel@tonic-gate 	verbose_level = 0;
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate 	/*
10860Sstevel@tonic-gate 	 * parse arguments
10870Sstevel@tonic-gate 	 */
10880Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "is:t:l:r:v:d:")) != EOF) {
10890Sstevel@tonic-gate 		switch (c) {
10900Sstevel@tonic-gate 		case 'd':
10910Sstevel@tonic-gate 			dos_ms = strtol(optarg, (char **)NULL, 0);
10920Sstevel@tonic-gate 			break;
10930Sstevel@tonic-gate 		case 'i':
10940Sstevel@tonic-gate 			logflag = 0;
10950Sstevel@tonic-gate 			break;
10960Sstevel@tonic-gate 		case 's':
10970Sstevel@tonic-gate 			sliding_interval_ms = strtoll(optarg, (char **)NULL, 0);
10980Sstevel@tonic-gate 			break;
10990Sstevel@tonic-gate 		case 't':
11000Sstevel@tonic-gate 			dos_req_limit = strtol(optarg, (char **)NULL, 0);
11010Sstevel@tonic-gate 			break;
11020Sstevel@tonic-gate 		case 'v':
11030Sstevel@tonic-gate 			verbose_level = strtol(optarg, (char **)NULL, 0);
11040Sstevel@tonic-gate 			logflag = 0;
11050Sstevel@tonic-gate 			break;
11060Sstevel@tonic-gate 		default:
11070Sstevel@tonic-gate 			break;
11080Sstevel@tonic-gate 		}
11090Sstevel@tonic-gate 	}
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate 	orig_time = gethrtime();
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate 	/*
11140Sstevel@tonic-gate 	 * is there a daemon already running?
11150Sstevel@tonic-gate 	 */
11160Sstevel@tonic-gate 
11170Sstevel@tonic-gate 	if (daemon_exists()) {
11180Sstevel@tonic-gate 		syslog(LOG_CRIT, DAEMON_RUNNING);
11190Sstevel@tonic-gate 		exit(1);
11200Sstevel@tonic-gate 	}
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	/*
11230Sstevel@tonic-gate 	 * Mask off/block SIGALRM signal so that the environmental plug-in
11240Sstevel@tonic-gate 	 * (piclenvd) can use it to simulate sleep() without being affected
11250Sstevel@tonic-gate 	 * by time being set back. No other PICL plug-in should use SIGALRM
11260Sstevel@tonic-gate 	 * or alarm() for now.
11270Sstevel@tonic-gate 	 */
11280Sstevel@tonic-gate 	(void) sigemptyset(&ublk);
11290Sstevel@tonic-gate 	(void) sigaddset(&ublk, SIGALRM);
11300Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 	/*
11330Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
11340Sstevel@tonic-gate 	 */
11350Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
11360Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
11370Sstevel@tonic-gate 	act.sa_flags = 0;
11380Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
11390Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
11400Sstevel@tonic-gate 		    strerror(errno));
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	if (logflag != 0) {	/* daemonize */
11430Sstevel@tonic-gate 		pid_t pid;
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 		pid = fork();
11460Sstevel@tonic-gate 		if (pid < 0)
11470Sstevel@tonic-gate 			exit(1);
11480Sstevel@tonic-gate 		if (pid > 0)
11490Sstevel@tonic-gate 			/* parent */
11500Sstevel@tonic-gate 			exit(0);
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 		/* child */
11530Sstevel@tonic-gate 		if (chdir("/") == -1) {
11540Sstevel@tonic-gate 			syslog(LOG_CRIT, CD_ROOT_FAILED);
11550Sstevel@tonic-gate 			exit(1);
11560Sstevel@tonic-gate 		}
11570Sstevel@tonic-gate 
11580Sstevel@tonic-gate 		(void) setsid();
11590Sstevel@tonic-gate 		(void) close(STDIN_FILENO);
11600Sstevel@tonic-gate 		(void) close(STDOUT_FILENO);
11610Sstevel@tonic-gate 		(void) close(STDERR_FILENO);
11620Sstevel@tonic-gate 		(void) open("/dev/null", O_RDWR, 0);
11630Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDOUT_FILENO);
11640Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDERR_FILENO);
11650Sstevel@tonic-gate 		openlog(PICLD, LOG_PID, LOG_DAEMON);
11660Sstevel@tonic-gate 	}
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 	/*
11690Sstevel@tonic-gate 	 * Initialize the PICL Tree
11700Sstevel@tonic-gate 	 */
11710Sstevel@tonic-gate 	if (xptree_initialize(NULL) != PICL_SUCCESS) {
11720Sstevel@tonic-gate 		syslog(LOG_CRIT, INIT_FAILED);
11730Sstevel@tonic-gate 		exit(1);
11740Sstevel@tonic-gate 	}
11750Sstevel@tonic-gate 
11760Sstevel@tonic-gate 	if (setup_door()) {
11770Sstevel@tonic-gate 		syslog(LOG_CRIT, DOOR_FAILED);
11780Sstevel@tonic-gate 		exit(1);
11790Sstevel@tonic-gate 	}
11800Sstevel@tonic-gate 
11810Sstevel@tonic-gate 	/*
11820Sstevel@tonic-gate 	 * setup signal handlers for post-init
11830Sstevel@tonic-gate 	 */
11840Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
11850Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
11860Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
11870Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
11880Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
11890Sstevel@tonic-gate 		    strerror(errno));
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	/*
11920Sstevel@tonic-gate 	 * wait for requests
11930Sstevel@tonic-gate 	 */
11940Sstevel@tonic-gate 	for (;;) {
11950Sstevel@tonic-gate 		(void) pause();
11960Sstevel@tonic-gate 		if (doreinit) {
11970Sstevel@tonic-gate 			/*
11980Sstevel@tonic-gate 			 * Block SIGHUP during reinitialization.
11990Sstevel@tonic-gate 			 * Also mask off/block SIGALRM signal so that the
12000Sstevel@tonic-gate 			 * environmental plug-in (piclenvd) can use it to
12010Sstevel@tonic-gate 			 * simulate sleep() without being affected by time
12020Sstevel@tonic-gate 			 * being set back. No ohter PICL plug-in should use
12030Sstevel@tonic-gate 			 * SIGALRM or alarm() for now.
12040Sstevel@tonic-gate 			 */
12050Sstevel@tonic-gate 			(void) sigemptyset(&ublk);
12060Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGHUP);
12070Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGALRM);
12080Sstevel@tonic-gate 			(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
12090Sstevel@tonic-gate 			(void) sigdelset(&ublk, SIGALRM);
12100Sstevel@tonic-gate 			doreinit = 0;
12110Sstevel@tonic-gate 			(void) rw_wrlock(&init_lk);
12120Sstevel@tonic-gate 			xptree_destroy();
12130Sstevel@tonic-gate 			(void) xptree_reinitialize();
12140Sstevel@tonic-gate 			(void) rw_unlock(&init_lk);
12150Sstevel@tonic-gate 			(void) sigprocmask(SIG_UNBLOCK, &ublk, NULL);
12160Sstevel@tonic-gate 		}
12170Sstevel@tonic-gate 	}
12180Sstevel@tonic-gate }
1219