xref: /titanic_51/usr/src/cmd/picl/picld/picld.c (revision 24b3ac2ee83543e2e7856433213b6f026a225ac1)
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
5*24b3ac2eSjfrank  * Common Development and Distribution License (the "License").
6*24b3ac2eSjfrank  * 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 /*
23*24b3ac2eSjfrank  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * PICL daemon
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <stdarg.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <libintl.h>
387c478bd9Sstevel@tonic-gate #include <locale.h>
397c478bd9Sstevel@tonic-gate #include <alloca.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <assert.h>
427c478bd9Sstevel@tonic-gate #include <stropts.h>
437c478bd9Sstevel@tonic-gate #include <unistd.h>
447c478bd9Sstevel@tonic-gate #include <signal.h>
457c478bd9Sstevel@tonic-gate #include <pthread.h>
467c478bd9Sstevel@tonic-gate #include <synch.h>
477c478bd9Sstevel@tonic-gate #include <door.h>
487c478bd9Sstevel@tonic-gate #include <sys/door.h>
497c478bd9Sstevel@tonic-gate #include <fcntl.h>
507c478bd9Sstevel@tonic-gate #include <dlfcn.h>
517c478bd9Sstevel@tonic-gate #include <time.h>
527c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
537c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
547c478bd9Sstevel@tonic-gate #include <sys/stat.h>
557c478bd9Sstevel@tonic-gate #include <sys/wait.h>
567c478bd9Sstevel@tonic-gate #include <dirent.h>
577c478bd9Sstevel@tonic-gate #include <syslog.h>
587c478bd9Sstevel@tonic-gate #include <poll.h>
597c478bd9Sstevel@tonic-gate #include <limits.h>
607c478bd9Sstevel@tonic-gate #include <picl.h>
617c478bd9Sstevel@tonic-gate #include "picl2door.h"
627c478bd9Sstevel@tonic-gate #include <picltree.h>
637c478bd9Sstevel@tonic-gate #include "ptree_impl.h"
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * Log text messages
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate #define	MUST_BE_ROOT	gettext("this program must be run as root\n")
697c478bd9Sstevel@tonic-gate #define	CD_ROOT_FAILED	gettext("chdir to root failed\n")
707c478bd9Sstevel@tonic-gate #define	INIT_FAILED	gettext("ptree initialization failed\n")
717c478bd9Sstevel@tonic-gate #define	DAEMON_RUNNING	gettext("PICL daemon already running\n")
727c478bd9Sstevel@tonic-gate #define	DOOR_FAILED	gettext("Failed creating picld door\n")
737c478bd9Sstevel@tonic-gate #define	SIGACT_FAILED	\
747c478bd9Sstevel@tonic-gate 		gettext("Failed to install signal handler for %s: %s\n")
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate  * Constants
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate #define	PICLD				"picld"
807c478bd9Sstevel@tonic-gate #define	DOS_PICL_REQUESTS_LIMIT		10000
817c478bd9Sstevel@tonic-gate #define	SLIDING_INTERVAL_MILLISECONDS	1000
827c478bd9Sstevel@tonic-gate #define	PICLD_MAJOR_REV			0x1
837c478bd9Sstevel@tonic-gate #define	PICLD_MINOR_REV			0x0
847c478bd9Sstevel@tonic-gate #define	DOS_SLEEPTIME_MS		1000
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Macros
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate #define	PICLD_VERSION(x, y)	((x << 8) | y)
907c478bd9Sstevel@tonic-gate #define	PICL_CLIENT_REV(x)	(x & 0xff)
917c478bd9Sstevel@tonic-gate #define	MILLI_TO_NANO(x)	(x * 1000000)
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate extern	char	**environ;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Module Variables
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate static	int		logflag = 1;
997c478bd9Sstevel@tonic-gate static	int		doreinit = 0;
1007c478bd9Sstevel@tonic-gate static	int		door_id = -1;
1017c478bd9Sstevel@tonic-gate static  int 		service_requests = 0;
1027c478bd9Sstevel@tonic-gate static	hrtime_t	orig_time;
1037c478bd9Sstevel@tonic-gate static	hrtime_t	sliding_interval_ms;
1047c478bd9Sstevel@tonic-gate static	uint32_t	dos_req_limit;
1057c478bd9Sstevel@tonic-gate static	uint32_t	dos_ms;
1067c478bd9Sstevel@tonic-gate static	pthread_mutex_t	dos_mutex = PTHREAD_MUTEX_INITIALIZER;
1077c478bd9Sstevel@tonic-gate static	rwlock_t	init_lk;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate  * This returns an error message to libpicl
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate static void
1137c478bd9Sstevel@tonic-gate picld_return_error(picl_callnumber_t cnum, picl_errno_t err)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	picl_reterror_t	ret_error;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	ret_error.cnum = PICL_CNUM_ERROR;
1187c478bd9Sstevel@tonic-gate 	ret_error.in_cnum = cnum;
1197c478bd9Sstevel@tonic-gate 	ret_error.errnum = err;
1207c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1217c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret_error, sizeof (picl_reterror_t), NULL,
1227c478bd9Sstevel@tonic-gate 	    0);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * picld_init is called when a picl_initialize request is received
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate static void
1297c478bd9Sstevel@tonic-gate picld_init(picl_service_t *req)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	picl_retinit_t	ret_init;
1327c478bd9Sstevel@tonic-gate 	int	clmajrev;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	clmajrev = PICL_CLIENT_REV(req->req_init.clrev);
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if (clmajrev < PICL_VERSION_1)
1377c478bd9Sstevel@tonic-gate 		picld_return_error(req->req_init.cnum, PICL_NOTSUPPORTED);
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	ret_init.cnum = req->req_init.cnum;
1407c478bd9Sstevel@tonic-gate 	ret_init.rev = PICLD_VERSION(PICLD_MAJOR_REV, PICLD_MINOR_REV);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1437c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret_init, sizeof (picl_retinit_t), NULL, 0);
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate  * picld_fini is called when a picl_shutdown request is received
1487c478bd9Sstevel@tonic-gate  */
1497c478bd9Sstevel@tonic-gate static void
1507c478bd9Sstevel@tonic-gate picld_fini(picl_service_t *in)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	picl_retfini_t	ret;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_fini.cnum;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1577c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfini_t), NULL, 0);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate static void
1617c478bd9Sstevel@tonic-gate picld_ping(picl_service_t *in)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	picl_retping_t	ret;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_ping.cnum;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1687c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retping_t), NULL, 0);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * picld_wait is called when a picl_wait request is received
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate static void
1757c478bd9Sstevel@tonic-gate picld_wait(picl_service_t *in)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	picl_retwait_t	ret;
1787c478bd9Sstevel@tonic-gate 	int		err;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_wait.cnum;
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	err = xptree_refresh_notify(in->req_wait.secs);
1837c478bd9Sstevel@tonic-gate 	ret.retcode = err;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
1867c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retwait_t), NULL, 0);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * This function returns the handle of the root node of the PICL tree
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate static void
1937c478bd9Sstevel@tonic-gate picld_getroot(picl_service_t *in)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 	picl_retroot_t	ret;
1967c478bd9Sstevel@tonic-gate 	int		err;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETROOT;
1997c478bd9Sstevel@tonic-gate 	err = ptree_get_root(&ret.rnode);
2007c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2017c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2027c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnode);
2037c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
2047c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retroot_t), NULL, 0);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * This function returns the value of the PICL property
2097c478bd9Sstevel@tonic-gate  */
2107c478bd9Sstevel@tonic-gate static void
2117c478bd9Sstevel@tonic-gate picld_get_attrval(picl_service_t *in)
2127c478bd9Sstevel@tonic-gate {
2137c478bd9Sstevel@tonic-gate 	picl_retattrval_t	*ret;
2147c478bd9Sstevel@tonic-gate 	int			err;
2157c478bd9Sstevel@tonic-gate 	size_t			vbufsize;
2167c478bd9Sstevel@tonic-gate 	size_t			len;
2177c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
2187c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
2197c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
2227c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrval.attr, &ptreeh);
2257c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2267c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
2297c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2307c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
2337c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
2367c478bd9Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrval.bufsize, vbufsize);
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	len = sizeof (picl_retattrval_t) + vbufsize;
2397c478bd9Sstevel@tonic-gate 	ret = alloca(len);
2407c478bd9Sstevel@tonic-gate 	if (ret == NULL)
2417c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
2427c478bd9Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVAL;
2437c478bd9Sstevel@tonic-gate 	ret->attr = in->req_attrval.attr;
2447c478bd9Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
2457c478bd9Sstevel@tonic-gate 	err = xptree_get_propval_with_cred(ptreeh, ret->ret_buf, vbufsize,
2467c478bd9Sstevel@tonic-gate 	    cred);
2477c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2487c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	/*
2517c478bd9Sstevel@tonic-gate 	 * adjust returned bytes for charstrings
2527c478bd9Sstevel@tonic-gate 	 */
2537c478bd9Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
2547c478bd9Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	/*
2577c478bd9Sstevel@tonic-gate 	 * convert handle values to picl handles
2587c478bd9Sstevel@tonic-gate 	 */
2597c478bd9Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
2607c478bd9Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
2617c478bd9Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
2627c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
2637c478bd9Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrval_t) +
2647c478bd9Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate  * This function returns the value of the PICL property specified by
2697c478bd9Sstevel@tonic-gate  * its name.
2707c478bd9Sstevel@tonic-gate  */
2717c478bd9Sstevel@tonic-gate static void
2727c478bd9Sstevel@tonic-gate picld_get_attrval_by_name(picl_service_t *in)
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate 	picl_retattrvalbyname_t	*ret;
2757c478bd9Sstevel@tonic-gate 	int			err;
2767c478bd9Sstevel@tonic-gate 	size_t			vbufsize;
2777c478bd9Sstevel@tonic-gate 	size_t			len;
2787c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
2797c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
2807c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
2837c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrvalbyname.nodeh, &ptreeh);
2867c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2877c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
2907c478bd9Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, &pinfo);
2917c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
2927c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
2957c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/*
2987c478bd9Sstevel@tonic-gate 	 * allocate the minimum of piclinfo.size and input bufsize
2997c478bd9Sstevel@tonic-gate 	 */
3007c478bd9Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
3017c478bd9Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrvalbyname.bufsize, vbufsize);
3027c478bd9Sstevel@tonic-gate 	len = sizeof (picl_retattrvalbyname_t) + vbufsize;
3037c478bd9Sstevel@tonic-gate 	ret = alloca(len);
3047c478bd9Sstevel@tonic-gate 	if (ret == NULL)
3057c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3067c478bd9Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVALBYNAME;
3077c478bd9Sstevel@tonic-gate 	ret->nodeh = in->req_attrvalbyname.nodeh;
3087c478bd9Sstevel@tonic-gate 	(void) strcpy(ret->propname, in->req_attrvalbyname.propname);
3097c478bd9Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	err = xptree_get_propval_by_name_with_cred(ptreeh,
3127c478bd9Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, ret->ret_buf, vbufsize,
3137c478bd9Sstevel@tonic-gate 	    cred);
3147c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3157c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3167c478bd9Sstevel@tonic-gate 	/*
3177c478bd9Sstevel@tonic-gate 	 * adjust returned value size for charstrings
3187c478bd9Sstevel@tonic-gate 	 */
3197c478bd9Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
3207c478bd9Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
3237c478bd9Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
3247c478bd9Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
3277c478bd9Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrvalbyname_t) +
3287c478bd9Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate  * This function sets a property value
3337c478bd9Sstevel@tonic-gate  */
3347c478bd9Sstevel@tonic-gate static void
3357c478bd9Sstevel@tonic-gate picld_set_attrval(picl_service_t *in)
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate 	picl_retsetattrval_t	ret;
3387c478bd9Sstevel@tonic-gate 	int			err;
3397c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
3407c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
3417c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
3447c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrval.attr, &ptreeh);
3477c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3487c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
3517c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3527c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
3557c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
3587c478bd9Sstevel@tonic-gate 	 */
3597c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
3607c478bd9Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
3617c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVAL;
3647c478bd9Sstevel@tonic-gate 	ret.attr = in->req_setattrval.attr;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	err = xptree_update_propval_with_cred(ptreeh, in->req_setattrval.valbuf,
3677c478bd9Sstevel@tonic-gate 	    (size_t)in->req_setattrval.bufsize, cred);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3707c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
3737c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrval_t), NULL,
3747c478bd9Sstevel@tonic-gate 	    0);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate  * This function sets the value of a property specified by its name.
3797c478bd9Sstevel@tonic-gate  */
3807c478bd9Sstevel@tonic-gate static void
3817c478bd9Sstevel@tonic-gate picld_set_attrval_by_name(picl_service_t *in)
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	picl_retsetattrvalbyname_t	ret;
3847c478bd9Sstevel@tonic-gate 	int				err;
3857c478bd9Sstevel@tonic-gate 	door_cred_t			cred;
3867c478bd9Sstevel@tonic-gate 	picl_prophdl_t			ptreeh;
3877c478bd9Sstevel@tonic-gate 	ptree_propinfo_t		pinfo;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
3907c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrvalbyname.nodeh, &ptreeh);
3937c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3947c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
3977c478bd9Sstevel@tonic-gate 	    in->req_setattrvalbyname.propname, &pinfo);
3987c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
3997c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
4027c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	/*
4057c478bd9Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
4067c478bd9Sstevel@tonic-gate 	 */
4077c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
4087c478bd9Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
4097c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVALBYNAME;
4127c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_setattrvalbyname.nodeh;
4137c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_setattrvalbyname.propname);
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	err = xptree_update_propval_by_name_with_cred(ptreeh,
4167c478bd9Sstevel@tonic-gate 	    in->req_setattrvalbyname.propname,
4177c478bd9Sstevel@tonic-gate 	    in->req_setattrvalbyname.valbuf,
4187c478bd9Sstevel@tonic-gate 	    (size_t)in->req_setattrvalbyname.bufsize,
4197c478bd9Sstevel@tonic-gate 	    cred);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4227c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
4257c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrvalbyname_t),
4267c478bd9Sstevel@tonic-gate 	    NULL, 0);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate  * This function returns the property information
4317c478bd9Sstevel@tonic-gate  */
4327c478bd9Sstevel@tonic-gate static void
4337c478bd9Sstevel@tonic-gate picld_get_attrinfo(picl_service_t *in)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	picl_retattrinfo_t	ret;
4367c478bd9Sstevel@tonic-gate 	int			err;
4377c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
4387c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrinfo.attr, &ptreeh);
4417c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4427c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRINFO;
4457c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrinfo.attr;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
4487c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4497c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	ret.type = pinfo.piclinfo.type;
4527c478bd9Sstevel@tonic-gate 	ret.accessmode = pinfo.piclinfo.accessmode;
4537c478bd9Sstevel@tonic-gate 	ret.size = (uint32_t)pinfo.piclinfo.size;
4547c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.name, pinfo.piclinfo.name);
4557c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
4567c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrinfo_t), NULL, 0);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate /*
4607c478bd9Sstevel@tonic-gate  * This function returns the node's first property handle
4617c478bd9Sstevel@tonic-gate  */
4627c478bd9Sstevel@tonic-gate static void
4637c478bd9Sstevel@tonic-gate picld_get_first_attr(picl_service_t *in)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate 	picl_retfirstattr_t	ret;
4667c478bd9Sstevel@tonic-gate 	int			err;
4677c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_firstattr.nodeh, &ptreeh);
4707c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4717c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETFIRSTATTR;
4747c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_firstattr.nodeh;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	err = ptree_get_first_prop(ptreeh, &ret.attr);
4777c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4787c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4797c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
4807c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
4817c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfirstattr_t), NULL, 0);
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate /*
4857c478bd9Sstevel@tonic-gate  * This function returns the next property handle in list
4867c478bd9Sstevel@tonic-gate  */
4877c478bd9Sstevel@tonic-gate static void
4887c478bd9Sstevel@tonic-gate picld_get_next_attr(picl_service_t *in)
4897c478bd9Sstevel@tonic-gate {
4907c478bd9Sstevel@tonic-gate 	picl_retnextattr_t	ret;
4917c478bd9Sstevel@tonic-gate 	int			err;
4927c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_nextattr.attr, &ptreeh);
4957c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
4967c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETNEXTATTR;
4997c478bd9Sstevel@tonic-gate 	ret.attr = in->req_nextattr.attr;
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	err = ptree_get_next_prop(ptreeh, &ret.nextattr);
5027c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5037c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nextattr);
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5087c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retnextattr_t), NULL, 0);
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate /*
5127c478bd9Sstevel@tonic-gate  * This function returns the handle of a property specified by its name
5137c478bd9Sstevel@tonic-gate  */
5147c478bd9Sstevel@tonic-gate static void
5157c478bd9Sstevel@tonic-gate picld_get_attr_by_name(picl_service_t *in)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate 	picl_retattrbyname_t	ret;
5187c478bd9Sstevel@tonic-gate 	int			err;
5197c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyname.nodeh, &ptreeh);
5227c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5237c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYNAME;
5267c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_attrbyname.nodeh;
5277c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_attrbyname.propname);
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	err = ptree_get_prop_by_name(ptreeh, ret.propname, &ret.attr);
5307c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5317c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
5347c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5357c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyname_t), NULL,
5367c478bd9Sstevel@tonic-gate 	    0);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate  * This function gets the next property on the same row in the table
5417c478bd9Sstevel@tonic-gate  */
5427c478bd9Sstevel@tonic-gate static void
5437c478bd9Sstevel@tonic-gate picld_get_attr_by_row(picl_service_t *in)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 	picl_retattrbyrow_t	ret;
5467c478bd9Sstevel@tonic-gate 	int			err;
5477c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyrow.attr, &ptreeh);
5507c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5517c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYROW;
5547c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrbyrow.attr;
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	err = ptree_get_next_by_row(ptreeh, &ret.rowattr);
5577c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5587c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5597c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rowattr);
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5627c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyrow_t), NULL, 0);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate /*
5667c478bd9Sstevel@tonic-gate  * This function returns the handle of the next property in the same column
5677c478bd9Sstevel@tonic-gate  * of the table.
5687c478bd9Sstevel@tonic-gate  */
5697c478bd9Sstevel@tonic-gate static void
5707c478bd9Sstevel@tonic-gate picld_get_attr_by_col(picl_service_t *in)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	picl_retattrbycol_t	ret;
5737c478bd9Sstevel@tonic-gate 	int			err;
5747c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbycol.attr, &ptreeh);
5777c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5787c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYCOL;
5817c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrbycol.attr;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	err = ptree_get_next_by_col(ptreeh, &ret.colattr);
5847c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
5857c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.colattr);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
5907c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbycol_t), NULL, 0);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate /*
5947c478bd9Sstevel@tonic-gate  * This function finds the node in the PICLTREE that matches the given
5957c478bd9Sstevel@tonic-gate  * criteria and returns its handle.
5967c478bd9Sstevel@tonic-gate  */
5977c478bd9Sstevel@tonic-gate static void
5987c478bd9Sstevel@tonic-gate picld_find_node(picl_service_t *in)
5997c478bd9Sstevel@tonic-gate {
6007c478bd9Sstevel@tonic-gate 	picl_retfindnode_t	ret;
6017c478bd9Sstevel@tonic-gate 	int			err;
6027c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_findnode.nodeh, &ptreeh);
6057c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6067c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FINDNODE;
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	err = ptree_find_node(ptreeh, in->req_findnode.propname,
6117c478bd9Sstevel@tonic-gate 	    in->req_findnode.ptype, in->req_findnode.valbuf,
6127c478bd9Sstevel@tonic-gate 	    in->req_findnode.valsize, &ret.rnodeh);
6137c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6147c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnodeh);
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6197c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
6207c478bd9Sstevel@tonic-gate }
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate /*
6237c478bd9Sstevel@tonic-gate  * This function finds the property/node that corresponds to the given path
6247c478bd9Sstevel@tonic-gate  * and returns its handle
6257c478bd9Sstevel@tonic-gate  */
6267c478bd9Sstevel@tonic-gate static void
6277c478bd9Sstevel@tonic-gate picld_get_node_by_path(picl_service_t *in)
6287c478bd9Sstevel@tonic-gate {
6297c478bd9Sstevel@tonic-gate 	picl_retnodebypath_t	ret;
6307c478bd9Sstevel@tonic-gate 	int			err;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_NODEBYPATH;
6337c478bd9Sstevel@tonic-gate 	err = ptree_get_node_by_path(in->req_nodebypath.pathbuf, &ret.nodeh);
6347c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6357c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6367c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nodeh);
6377c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6387c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate /*
6427c478bd9Sstevel@tonic-gate  * This function returns finds the frutree parent node for a given node
6437c478bd9Sstevel@tonic-gate  * and returns its handle
6447c478bd9Sstevel@tonic-gate  */
6457c478bd9Sstevel@tonic-gate static void
6467c478bd9Sstevel@tonic-gate picld_get_frutree_parent(picl_service_t *in)
6477c478bd9Sstevel@tonic-gate {
6487c478bd9Sstevel@tonic-gate 	picl_retfruparent_t	ret;
6497c478bd9Sstevel@tonic-gate 	int			err;
6507c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_fruparent.devh, &ptreeh);
6537c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6547c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FRUTREEPARENT;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	err = ptree_get_frutree_parent(ptreeh, &ret.fruh);
6597c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
6607c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
6617c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.fruh);
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
6647c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate /*
6687c478bd9Sstevel@tonic-gate  * This function is called when an unknown client request is received.
6697c478bd9Sstevel@tonic-gate  */
6707c478bd9Sstevel@tonic-gate static void
6717c478bd9Sstevel@tonic-gate picld_unknown_service(picl_service_t *in)
6727c478bd9Sstevel@tonic-gate {
6737c478bd9Sstevel@tonic-gate 	picld_return_error(in->in.cnum, PICL_UNKNOWNSERVICE);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate static void
6777c478bd9Sstevel@tonic-gate check_denial_of_service(int cnum)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate 	hrtime_t	window;
6807c478bd9Sstevel@tonic-gate 	hrtime_t	current;
6817c478bd9Sstevel@tonic-gate 	int		dos_flag;
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	current = gethrtime();
6847c478bd9Sstevel@tonic-gate 	dos_flag = 0;
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	if (pthread_mutex_lock(&dos_mutex) != 0)
6877c478bd9Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	++service_requests;
6907c478bd9Sstevel@tonic-gate 	window = current - orig_time;
6917c478bd9Sstevel@tonic-gate 	if (window > MILLI_TO_NANO(sliding_interval_ms)) {
6927c478bd9Sstevel@tonic-gate 		orig_time = current;
6937c478bd9Sstevel@tonic-gate 		service_requests = 1;
6947c478bd9Sstevel@tonic-gate 	}
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	if (service_requests > dos_req_limit)
6977c478bd9Sstevel@tonic-gate 		dos_flag = 1;
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	if (pthread_mutex_unlock(&dos_mutex) != 0)
7007c478bd9Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	if (dos_flag)
7037c478bd9Sstevel@tonic-gate 		(void) poll(NULL, 0, dos_ms);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate /* ARGSUSED */
7087c478bd9Sstevel@tonic-gate static void
7097c478bd9Sstevel@tonic-gate picld_door_handler(void *cookie, char *argp, size_t asize,
7107c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t n_desc)
7117c478bd9Sstevel@tonic-gate {
7127c478bd9Sstevel@tonic-gate 	picl_service_t  *req;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	/*LINTED*/
7157c478bd9Sstevel@tonic-gate 	req = (picl_service_t *)argp;
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	if (req == NULL)
7187c478bd9Sstevel@tonic-gate 		(void) door_return((char *)req, 0, NULL, 0);
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	check_denial_of_service(req->in.cnum);
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&init_lk);
7237c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {	/* client call number */
7247c478bd9Sstevel@tonic-gate 	case PICL_CNUM_INIT:
7257c478bd9Sstevel@tonic-gate 		/*LINTED*/
7267c478bd9Sstevel@tonic-gate 		picld_init((picl_service_t *)argp);
7277c478bd9Sstevel@tonic-gate 		break;
7287c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FINI:
7297c478bd9Sstevel@tonic-gate 		/*LINTED*/
7307c478bd9Sstevel@tonic-gate 		picld_fini((picl_service_t *)argp);
7317c478bd9Sstevel@tonic-gate 		break;
7327c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETROOT:
7337c478bd9Sstevel@tonic-gate 		/*LINTED*/
7347c478bd9Sstevel@tonic-gate 		picld_getroot((picl_service_t *)argp);
7357c478bd9Sstevel@tonic-gate 		break;
7367c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVAL:
7377c478bd9Sstevel@tonic-gate 		/*LINTED*/
7387c478bd9Sstevel@tonic-gate 		picld_get_attrval((picl_service_t *)argp);
7397c478bd9Sstevel@tonic-gate 		break;
7407c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVALBYNAME:
7417c478bd9Sstevel@tonic-gate 		/*LINTED*/
7427c478bd9Sstevel@tonic-gate 		picld_get_attrval_by_name((picl_service_t *)argp);
7437c478bd9Sstevel@tonic-gate 		break;
7447c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRINFO:
7457c478bd9Sstevel@tonic-gate 		/*LINTED*/
7467c478bd9Sstevel@tonic-gate 		picld_get_attrinfo((picl_service_t *)argp);
7477c478bd9Sstevel@tonic-gate 		break;
7487c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETFIRSTATTR:
7497c478bd9Sstevel@tonic-gate 		/*LINTED*/
7507c478bd9Sstevel@tonic-gate 		picld_get_first_attr((picl_service_t *)argp);
7517c478bd9Sstevel@tonic-gate 		break;
7527c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETNEXTATTR:
7537c478bd9Sstevel@tonic-gate 		/*LINTED*/
7547c478bd9Sstevel@tonic-gate 		picld_get_next_attr((picl_service_t *)argp);
7557c478bd9Sstevel@tonic-gate 		break;
7567c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYNAME:
7577c478bd9Sstevel@tonic-gate 		/*LINTED*/
7587c478bd9Sstevel@tonic-gate 		picld_get_attr_by_name((picl_service_t *)argp);
7597c478bd9Sstevel@tonic-gate 		break;
7607c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYROW:
7617c478bd9Sstevel@tonic-gate 		/*LINTED*/
7627c478bd9Sstevel@tonic-gate 		picld_get_attr_by_row((picl_service_t *)argp);
7637c478bd9Sstevel@tonic-gate 		break;
7647c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYCOL:
7657c478bd9Sstevel@tonic-gate 		/*LINTED*/
7667c478bd9Sstevel@tonic-gate 		picld_get_attr_by_col((picl_service_t *)argp);
7677c478bd9Sstevel@tonic-gate 		break;
7687c478bd9Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVAL:
7697c478bd9Sstevel@tonic-gate 		/*LINTED*/
7707c478bd9Sstevel@tonic-gate 		picld_set_attrval((picl_service_t *)argp);
7717c478bd9Sstevel@tonic-gate 		break;
7727c478bd9Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVALBYNAME:
7737c478bd9Sstevel@tonic-gate 		/*LINTED*/
7747c478bd9Sstevel@tonic-gate 		picld_set_attrval_by_name((picl_service_t *)argp);
7757c478bd9Sstevel@tonic-gate 		break;
7767c478bd9Sstevel@tonic-gate 	case PICL_CNUM_PING:
7777c478bd9Sstevel@tonic-gate 		/*LINTED*/
7787c478bd9Sstevel@tonic-gate 		picld_ping((picl_service_t *)argp);
7797c478bd9Sstevel@tonic-gate 		break;
7807c478bd9Sstevel@tonic-gate 	case PICL_CNUM_WAIT:
7817c478bd9Sstevel@tonic-gate 		/*LINTED*/
7827c478bd9Sstevel@tonic-gate 		picld_wait((picl_service_t *)argp);
7837c478bd9Sstevel@tonic-gate 		break;
7847c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FINDNODE:
7857c478bd9Sstevel@tonic-gate 		/*LINTED*/
7867c478bd9Sstevel@tonic-gate 		picld_find_node((picl_service_t *)argp);
7877c478bd9Sstevel@tonic-gate 		break;
7887c478bd9Sstevel@tonic-gate 	case PICL_CNUM_NODEBYPATH:
7897c478bd9Sstevel@tonic-gate 		/*LINTED*/
7907c478bd9Sstevel@tonic-gate 		picld_get_node_by_path((picl_service_t *)argp);
7917c478bd9Sstevel@tonic-gate 		break;
7927c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FRUTREEPARENT:
7937c478bd9Sstevel@tonic-gate 		/*LINTED*/
7947c478bd9Sstevel@tonic-gate 		picld_get_frutree_parent((picl_service_t *)argp);
7957c478bd9Sstevel@tonic-gate 		break;
7967c478bd9Sstevel@tonic-gate 	default:
7977c478bd9Sstevel@tonic-gate 		/*LINTED*/
7987c478bd9Sstevel@tonic-gate 		picld_unknown_service((picl_service_t *)argp);
7997c478bd9Sstevel@tonic-gate 		break;
8007c478bd9Sstevel@tonic-gate 	};
8017c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate /* ARGSUSED */
8057c478bd9Sstevel@tonic-gate static void
8067c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
8077c478bd9Sstevel@tonic-gate {
8087c478bd9Sstevel@tonic-gate 	doreinit = 1;
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate  * "ping" to see if a daemon is already running
8137c478bd9Sstevel@tonic-gate  */
8147c478bd9Sstevel@tonic-gate static int
8157c478bd9Sstevel@tonic-gate daemon_exists(void)
8167c478bd9Sstevel@tonic-gate {
8177c478bd9Sstevel@tonic-gate 	door_arg_t	darg;
8187c478bd9Sstevel@tonic-gate 	picl_reqping_t	req_ping;
8197c478bd9Sstevel@tonic-gate 	picl_retping_t	ret_ping;
8207c478bd9Sstevel@tonic-gate 	int		doorh;
8217c478bd9Sstevel@tonic-gate 	door_info_t	dinfo;
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	doorh = open(PICLD_DOOR, O_RDONLY);
8247c478bd9Sstevel@tonic-gate 	if (doorh < 0)
8257c478bd9Sstevel@tonic-gate 		return (0);
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
8287c478bd9Sstevel@tonic-gate 		(void) close(doorh);
8297c478bd9Sstevel@tonic-gate 		return (0);
8307c478bd9Sstevel@tonic-gate 	}
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 	if ((dinfo.di_attributes & DOOR_REVOKED) ||
8330ec57554Sraf 	    (dinfo.di_data != (uintptr_t)PICLD_DOOR_COOKIE)) {
8347c478bd9Sstevel@tonic-gate 		(void) close(doorh);
8357c478bd9Sstevel@tonic-gate 		return (0);
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	if (dinfo.di_target != getpid()) {
8397c478bd9Sstevel@tonic-gate 		(void) close(doorh);
8407c478bd9Sstevel@tonic-gate 		return (1);
8417c478bd9Sstevel@tonic-gate 	}
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	req_ping.cnum = PICL_CNUM_PING;
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
8467c478bd9Sstevel@tonic-gate 	darg.data_size = sizeof (picl_reqping_t);
8477c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
8487c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
8497c478bd9Sstevel@tonic-gate 	darg.rbuf = (char *)&ret_ping;
8507c478bd9Sstevel@tonic-gate 	darg.rsize = sizeof (picl_retping_t);
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
8537c478bd9Sstevel@tonic-gate 		(void) close(doorh);
8547c478bd9Sstevel@tonic-gate 		return (0);
8557c478bd9Sstevel@tonic-gate 	}
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 	(void) close(doorh);
8587c478bd9Sstevel@tonic-gate 	return (1);
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate /*
8627c478bd9Sstevel@tonic-gate  * Create the picld door
8637c478bd9Sstevel@tonic-gate  */
8647c478bd9Sstevel@tonic-gate static int
8657c478bd9Sstevel@tonic-gate setup_door(void)
8667c478bd9Sstevel@tonic-gate {
8677c478bd9Sstevel@tonic-gate 	struct stat	stbuf;
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	/*
8707c478bd9Sstevel@tonic-gate 	 * Create the door
8717c478bd9Sstevel@tonic-gate 	 */
8727c478bd9Sstevel@tonic-gate 	door_id = door_create(picld_door_handler, PICLD_DOOR_COOKIE,
873e73e5762Skd93003 	    DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	if (door_id < 0) {
8767c478bd9Sstevel@tonic-gate 		return (-1);
8777c478bd9Sstevel@tonic-gate 	}
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	if (stat(PICLD_DOOR, &stbuf) < 0) {
8807c478bd9Sstevel@tonic-gate 		int newfd;
881*24b3ac2eSjfrank 		mode_t old_mask;
882*24b3ac2eSjfrank 		/* ensure that the door file is world-readable */
883*24b3ac2eSjfrank 		old_mask = umask(0);
884*24b3ac2eSjfrank 		newfd = creat(PICLD_DOOR, 0444);
885*24b3ac2eSjfrank 		/* restore the file mode creation mask */
886*24b3ac2eSjfrank 		(void) umask(old_mask);
887*24b3ac2eSjfrank 		if (newfd < 0)
8887c478bd9Sstevel@tonic-gate 			return (-1);
8897c478bd9Sstevel@tonic-gate 		(void) close(newfd);
8907c478bd9Sstevel@tonic-gate 	}
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	if (fattach(door_id, PICLD_DOOR) < 0) {
8937c478bd9Sstevel@tonic-gate 		if ((errno != EBUSY) ||
8947c478bd9Sstevel@tonic-gate 		    (fdetach(PICLD_DOOR) < 0) ||
8957c478bd9Sstevel@tonic-gate 		    (fattach(door_id, PICLD_DOOR) < 0))
8967c478bd9Sstevel@tonic-gate 			return (-1);
8977c478bd9Sstevel@tonic-gate 	}
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	return (0);
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate /*
9037c478bd9Sstevel@tonic-gate  * Main function of picl daemon
9047c478bd9Sstevel@tonic-gate  */
9057c478bd9Sstevel@tonic-gate int
9067c478bd9Sstevel@tonic-gate main(int argc, char **argv)
9077c478bd9Sstevel@tonic-gate {
9087c478bd9Sstevel@tonic-gate 	struct	sigaction	act;
9097c478bd9Sstevel@tonic-gate 	int			c;
9107c478bd9Sstevel@tonic-gate 	sigset_t		ublk;
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
9147c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	if (getuid() != 0) {
9177c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, MUST_BE_ROOT);
9187c478bd9Sstevel@tonic-gate 		return (0);
9197c478bd9Sstevel@tonic-gate 	}
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&init_lk, USYNC_THREAD, NULL);
9227c478bd9Sstevel@tonic-gate 	doreinit = 0;
9237c478bd9Sstevel@tonic-gate 	logflag = 1;
9247c478bd9Sstevel@tonic-gate 	dos_req_limit = DOS_PICL_REQUESTS_LIMIT;
9257c478bd9Sstevel@tonic-gate 	sliding_interval_ms = SLIDING_INTERVAL_MILLISECONDS;
9267c478bd9Sstevel@tonic-gate 	dos_ms = DOS_SLEEPTIME_MS;
9277c478bd9Sstevel@tonic-gate 	verbose_level = 0;
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	/*
9307c478bd9Sstevel@tonic-gate 	 * parse arguments
9317c478bd9Sstevel@tonic-gate 	 */
9327c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "is:t:l:r:v:d:")) != EOF) {
9337c478bd9Sstevel@tonic-gate 		switch (c) {
9347c478bd9Sstevel@tonic-gate 		case 'd':
9357c478bd9Sstevel@tonic-gate 			dos_ms = strtol(optarg, (char **)NULL, 0);
9367c478bd9Sstevel@tonic-gate 			break;
9377c478bd9Sstevel@tonic-gate 		case 'i':
9387c478bd9Sstevel@tonic-gate 			logflag = 0;
9397c478bd9Sstevel@tonic-gate 			break;
9407c478bd9Sstevel@tonic-gate 		case 's':
9417c478bd9Sstevel@tonic-gate 			sliding_interval_ms = strtoll(optarg, (char **)NULL, 0);
9427c478bd9Sstevel@tonic-gate 			break;
9437c478bd9Sstevel@tonic-gate 		case 't':
9447c478bd9Sstevel@tonic-gate 			dos_req_limit = strtol(optarg, (char **)NULL, 0);
9457c478bd9Sstevel@tonic-gate 			break;
9467c478bd9Sstevel@tonic-gate 		case 'v':
9477c478bd9Sstevel@tonic-gate 			verbose_level = strtol(optarg, (char **)NULL, 0);
9487c478bd9Sstevel@tonic-gate 			logflag = 0;
9497c478bd9Sstevel@tonic-gate 			break;
9507c478bd9Sstevel@tonic-gate 		default:
9517c478bd9Sstevel@tonic-gate 			break;
9527c478bd9Sstevel@tonic-gate 		}
9537c478bd9Sstevel@tonic-gate 	}
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	orig_time = gethrtime();
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 	/*
9587c478bd9Sstevel@tonic-gate 	 * is there a daemon already running?
9597c478bd9Sstevel@tonic-gate 	 */
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	if (daemon_exists()) {
9627c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, DAEMON_RUNNING);
9637c478bd9Sstevel@tonic-gate 		exit(1);
9647c478bd9Sstevel@tonic-gate 	}
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	/*
9677c478bd9Sstevel@tonic-gate 	 * Mask off/block SIGALRM signal so that the environmental plug-in
9687c478bd9Sstevel@tonic-gate 	 * (piclenvd) can use it to simulate sleep() without being affected
9697c478bd9Sstevel@tonic-gate 	 * by time being set back. No other PICL plug-in should use SIGALRM
9707c478bd9Sstevel@tonic-gate 	 * or alarm() for now.
9717c478bd9Sstevel@tonic-gate 	 */
9727c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&ublk);
9737c478bd9Sstevel@tonic-gate 	(void) sigaddset(&ublk, SIGALRM);
9747c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	/*
9777c478bd9Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
9787c478bd9Sstevel@tonic-gate 	 */
9797c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
9807c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
9817c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
9827c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
9837c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
9847c478bd9Sstevel@tonic-gate 		    strerror(errno));
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	if (logflag != 0) {	/* daemonize */
9877c478bd9Sstevel@tonic-gate 		pid_t pid;
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 		pid = fork();
9907c478bd9Sstevel@tonic-gate 		if (pid < 0)
9917c478bd9Sstevel@tonic-gate 			exit(1);
9927c478bd9Sstevel@tonic-gate 		if (pid > 0)
9937c478bd9Sstevel@tonic-gate 			/* parent */
9947c478bd9Sstevel@tonic-gate 			exit(0);
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 		/* child */
9977c478bd9Sstevel@tonic-gate 		if (chdir("/") == -1) {
9987c478bd9Sstevel@tonic-gate 			syslog(LOG_CRIT, CD_ROOT_FAILED);
9997c478bd9Sstevel@tonic-gate 			exit(1);
10007c478bd9Sstevel@tonic-gate 		}
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 		(void) setsid();
10037c478bd9Sstevel@tonic-gate 		(void) close(STDIN_FILENO);
10047c478bd9Sstevel@tonic-gate 		(void) close(STDOUT_FILENO);
10057c478bd9Sstevel@tonic-gate 		(void) close(STDERR_FILENO);
10067c478bd9Sstevel@tonic-gate 		(void) open("/dev/null", O_RDWR, 0);
10077c478bd9Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDOUT_FILENO);
10087c478bd9Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDERR_FILENO);
10097c478bd9Sstevel@tonic-gate 		openlog(PICLD, LOG_PID, LOG_DAEMON);
10107c478bd9Sstevel@tonic-gate 	}
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	/*
10137c478bd9Sstevel@tonic-gate 	 * Initialize the PICL Tree
10147c478bd9Sstevel@tonic-gate 	 */
10157c478bd9Sstevel@tonic-gate 	if (xptree_initialize(NULL) != PICL_SUCCESS) {
10167c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, INIT_FAILED);
10177c478bd9Sstevel@tonic-gate 		exit(1);
10187c478bd9Sstevel@tonic-gate 	}
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	if (setup_door()) {
10217c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, DOOR_FAILED);
10227c478bd9Sstevel@tonic-gate 		exit(1);
10237c478bd9Sstevel@tonic-gate 	}
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	/*
10267c478bd9Sstevel@tonic-gate 	 * setup signal handlers for post-init
10277c478bd9Sstevel@tonic-gate 	 */
10287c478bd9Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
10297c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
10307c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
10317c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
10327c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
10337c478bd9Sstevel@tonic-gate 		    strerror(errno));
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	/*
10367c478bd9Sstevel@tonic-gate 	 * wait for requests
10377c478bd9Sstevel@tonic-gate 	 */
10387c478bd9Sstevel@tonic-gate 	for (;;) {
10397c478bd9Sstevel@tonic-gate 		(void) pause();
10407c478bd9Sstevel@tonic-gate 		if (doreinit) {
10417c478bd9Sstevel@tonic-gate 			/*
10427c478bd9Sstevel@tonic-gate 			 * Block SIGHUP during reinitialization.
10437c478bd9Sstevel@tonic-gate 			 * Also mask off/block SIGALRM signal so that the
10447c478bd9Sstevel@tonic-gate 			 * environmental plug-in (piclenvd) can use it to
10457c478bd9Sstevel@tonic-gate 			 * simulate sleep() without being affected by time
10467c478bd9Sstevel@tonic-gate 			 * being set back. No ohter PICL plug-in should use
10477c478bd9Sstevel@tonic-gate 			 * SIGALRM or alarm() for now.
10487c478bd9Sstevel@tonic-gate 			 */
10497c478bd9Sstevel@tonic-gate 			(void) sigemptyset(&ublk);
10507c478bd9Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGHUP);
10517c478bd9Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGALRM);
10527c478bd9Sstevel@tonic-gate 			(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
10537c478bd9Sstevel@tonic-gate 			(void) sigdelset(&ublk, SIGALRM);
10547c478bd9Sstevel@tonic-gate 			doreinit = 0;
10557c478bd9Sstevel@tonic-gate 			(void) rw_wrlock(&init_lk);
10567c478bd9Sstevel@tonic-gate 			xptree_destroy();
10577c478bd9Sstevel@tonic-gate 			(void) xptree_reinitialize();
10587c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&init_lk);
10597c478bd9Sstevel@tonic-gate 			(void) sigprocmask(SIG_UNBLOCK, &ublk, NULL);
10607c478bd9Sstevel@tonic-gate 		}
10617c478bd9Sstevel@tonic-gate 	}
10627c478bd9Sstevel@tonic-gate }
1063