xref: /titanic_51/usr/src/cmd/picl/picld/picld.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * PICL daemon
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <libintl.h>
38*7c478bd9Sstevel@tonic-gate #include <locale.h>
39*7c478bd9Sstevel@tonic-gate #include <alloca.h>
40*7c478bd9Sstevel@tonic-gate #include <errno.h>
41*7c478bd9Sstevel@tonic-gate #include <assert.h>
42*7c478bd9Sstevel@tonic-gate #include <stropts.h>
43*7c478bd9Sstevel@tonic-gate #include <unistd.h>
44*7c478bd9Sstevel@tonic-gate #include <signal.h>
45*7c478bd9Sstevel@tonic-gate #include <pthread.h>
46*7c478bd9Sstevel@tonic-gate #include <synch.h>
47*7c478bd9Sstevel@tonic-gate #include <door.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/door.h>
49*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
50*7c478bd9Sstevel@tonic-gate #include <dlfcn.h>
51*7c478bd9Sstevel@tonic-gate #include <time.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
56*7c478bd9Sstevel@tonic-gate #include <dirent.h>
57*7c478bd9Sstevel@tonic-gate #include <syslog.h>
58*7c478bd9Sstevel@tonic-gate #include <poll.h>
59*7c478bd9Sstevel@tonic-gate #include <limits.h>
60*7c478bd9Sstevel@tonic-gate #include <picl.h>
61*7c478bd9Sstevel@tonic-gate #include "picl2door.h"
62*7c478bd9Sstevel@tonic-gate #include <picltree.h>
63*7c478bd9Sstevel@tonic-gate #include "ptree_impl.h"
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate /*
66*7c478bd9Sstevel@tonic-gate  * Log text messages
67*7c478bd9Sstevel@tonic-gate  */
68*7c478bd9Sstevel@tonic-gate #define	MUST_BE_ROOT	gettext("this program must be run as root\n")
69*7c478bd9Sstevel@tonic-gate #define	CD_ROOT_FAILED	gettext("chdir to root failed\n")
70*7c478bd9Sstevel@tonic-gate #define	INIT_FAILED	gettext("ptree initialization failed\n")
71*7c478bd9Sstevel@tonic-gate #define	DAEMON_RUNNING	gettext("PICL daemon already running\n")
72*7c478bd9Sstevel@tonic-gate #define	DOOR_FAILED	gettext("Failed creating picld door\n")
73*7c478bd9Sstevel@tonic-gate #define	SIGACT_FAILED	\
74*7c478bd9Sstevel@tonic-gate 		gettext("Failed to install signal handler for %s: %s\n")
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /*
77*7c478bd9Sstevel@tonic-gate  * Constants
78*7c478bd9Sstevel@tonic-gate  */
79*7c478bd9Sstevel@tonic-gate #define	PICLD				"picld"
80*7c478bd9Sstevel@tonic-gate #define	DOS_PICL_REQUESTS_LIMIT		10000
81*7c478bd9Sstevel@tonic-gate #define	SLIDING_INTERVAL_MILLISECONDS	1000
82*7c478bd9Sstevel@tonic-gate #define	PICLD_MAJOR_REV			0x1
83*7c478bd9Sstevel@tonic-gate #define	PICLD_MINOR_REV			0x0
84*7c478bd9Sstevel@tonic-gate #define	DOS_SLEEPTIME_MS		1000
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /*
87*7c478bd9Sstevel@tonic-gate  * Macros
88*7c478bd9Sstevel@tonic-gate  */
89*7c478bd9Sstevel@tonic-gate #define	PICLD_VERSION(x, y)	((x << 8) | y)
90*7c478bd9Sstevel@tonic-gate #define	PICL_CLIENT_REV(x)	(x & 0xff)
91*7c478bd9Sstevel@tonic-gate #define	MILLI_TO_NANO(x)	(x * 1000000)
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate extern	char	**environ;
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate /*
96*7c478bd9Sstevel@tonic-gate  * Module Variables
97*7c478bd9Sstevel@tonic-gate  */
98*7c478bd9Sstevel@tonic-gate static	int		logflag = 1;
99*7c478bd9Sstevel@tonic-gate static	int		doreinit = 0;
100*7c478bd9Sstevel@tonic-gate static	int		door_id = -1;
101*7c478bd9Sstevel@tonic-gate static  int 		service_requests = 0;
102*7c478bd9Sstevel@tonic-gate static	hrtime_t	orig_time;
103*7c478bd9Sstevel@tonic-gate static	hrtime_t	sliding_interval_ms;
104*7c478bd9Sstevel@tonic-gate static	uint32_t	dos_req_limit;
105*7c478bd9Sstevel@tonic-gate static	uint32_t	dos_ms;
106*7c478bd9Sstevel@tonic-gate static	pthread_mutex_t	dos_mutex = PTHREAD_MUTEX_INITIALIZER;
107*7c478bd9Sstevel@tonic-gate static	rwlock_t	init_lk;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate /*
110*7c478bd9Sstevel@tonic-gate  * This returns an error message to libpicl
111*7c478bd9Sstevel@tonic-gate  */
112*7c478bd9Sstevel@tonic-gate static void
113*7c478bd9Sstevel@tonic-gate picld_return_error(picl_callnumber_t cnum, picl_errno_t err)
114*7c478bd9Sstevel@tonic-gate {
115*7c478bd9Sstevel@tonic-gate 	picl_reterror_t	ret_error;
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	ret_error.cnum = PICL_CNUM_ERROR;
118*7c478bd9Sstevel@tonic-gate 	ret_error.in_cnum = cnum;
119*7c478bd9Sstevel@tonic-gate 	ret_error.errnum = err;
120*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
121*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret_error, sizeof (picl_reterror_t), NULL,
122*7c478bd9Sstevel@tonic-gate 	    0);
123*7c478bd9Sstevel@tonic-gate }
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate /*
126*7c478bd9Sstevel@tonic-gate  * picld_init is called when a picl_initialize request is received
127*7c478bd9Sstevel@tonic-gate  */
128*7c478bd9Sstevel@tonic-gate static void
129*7c478bd9Sstevel@tonic-gate picld_init(picl_service_t *req)
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate 	picl_retinit_t	ret_init;
132*7c478bd9Sstevel@tonic-gate 	int	clmajrev;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	clmajrev = PICL_CLIENT_REV(req->req_init.clrev);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	if (clmajrev < PICL_VERSION_1)
137*7c478bd9Sstevel@tonic-gate 		picld_return_error(req->req_init.cnum, PICL_NOTSUPPORTED);
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	ret_init.cnum = req->req_init.cnum;
140*7c478bd9Sstevel@tonic-gate 	ret_init.rev = PICLD_VERSION(PICLD_MAJOR_REV, PICLD_MINOR_REV);
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
143*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret_init, sizeof (picl_retinit_t), NULL, 0);
144*7c478bd9Sstevel@tonic-gate }
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate /*
147*7c478bd9Sstevel@tonic-gate  * picld_fini is called when a picl_shutdown request is received
148*7c478bd9Sstevel@tonic-gate  */
149*7c478bd9Sstevel@tonic-gate static void
150*7c478bd9Sstevel@tonic-gate picld_fini(picl_service_t *in)
151*7c478bd9Sstevel@tonic-gate {
152*7c478bd9Sstevel@tonic-gate 	picl_retfini_t	ret;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_fini.cnum;
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
157*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfini_t), NULL, 0);
158*7c478bd9Sstevel@tonic-gate }
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate static void
161*7c478bd9Sstevel@tonic-gate picld_ping(picl_service_t *in)
162*7c478bd9Sstevel@tonic-gate {
163*7c478bd9Sstevel@tonic-gate 	picl_retping_t	ret;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_ping.cnum;
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
168*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retping_t), NULL, 0);
169*7c478bd9Sstevel@tonic-gate }
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate /*
172*7c478bd9Sstevel@tonic-gate  * picld_wait is called when a picl_wait request is received
173*7c478bd9Sstevel@tonic-gate  */
174*7c478bd9Sstevel@tonic-gate static void
175*7c478bd9Sstevel@tonic-gate picld_wait(picl_service_t *in)
176*7c478bd9Sstevel@tonic-gate {
177*7c478bd9Sstevel@tonic-gate 	picl_retwait_t	ret;
178*7c478bd9Sstevel@tonic-gate 	int		err;
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	ret.cnum = in->req_wait.cnum;
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	err = xptree_refresh_notify(in->req_wait.secs);
183*7c478bd9Sstevel@tonic-gate 	ret.retcode = err;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
186*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retwait_t), NULL, 0);
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate /*
190*7c478bd9Sstevel@tonic-gate  * This function returns the handle of the root node of the PICL tree
191*7c478bd9Sstevel@tonic-gate  */
192*7c478bd9Sstevel@tonic-gate static void
193*7c478bd9Sstevel@tonic-gate picld_getroot(picl_service_t *in)
194*7c478bd9Sstevel@tonic-gate {
195*7c478bd9Sstevel@tonic-gate 	picl_retroot_t	ret;
196*7c478bd9Sstevel@tonic-gate 	int		err;
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETROOT;
199*7c478bd9Sstevel@tonic-gate 	err = ptree_get_root(&ret.rnode);
200*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
201*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
202*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnode);
203*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
204*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retroot_t), NULL, 0);
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate /*
208*7c478bd9Sstevel@tonic-gate  * This function returns the value of the PICL property
209*7c478bd9Sstevel@tonic-gate  */
210*7c478bd9Sstevel@tonic-gate static void
211*7c478bd9Sstevel@tonic-gate picld_get_attrval(picl_service_t *in)
212*7c478bd9Sstevel@tonic-gate {
213*7c478bd9Sstevel@tonic-gate 	picl_retattrval_t	*ret;
214*7c478bd9Sstevel@tonic-gate 	int			err;
215*7c478bd9Sstevel@tonic-gate 	size_t			vbufsize;
216*7c478bd9Sstevel@tonic-gate 	size_t			len;
217*7c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
218*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
219*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
222*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrval.attr, &ptreeh);
225*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
226*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
229*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
230*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
233*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
236*7c478bd9Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrval.bufsize, vbufsize);
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	len = sizeof (picl_retattrval_t) + vbufsize;
239*7c478bd9Sstevel@tonic-gate 	ret = alloca(len);
240*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
241*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
242*7c478bd9Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVAL;
243*7c478bd9Sstevel@tonic-gate 	ret->attr = in->req_attrval.attr;
244*7c478bd9Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
245*7c478bd9Sstevel@tonic-gate 	err = xptree_get_propval_with_cred(ptreeh, ret->ret_buf, vbufsize,
246*7c478bd9Sstevel@tonic-gate 	    cred);
247*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
248*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	/*
251*7c478bd9Sstevel@tonic-gate 	 * adjust returned bytes for charstrings
252*7c478bd9Sstevel@tonic-gate 	 */
253*7c478bd9Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
254*7c478bd9Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	/*
257*7c478bd9Sstevel@tonic-gate 	 * convert handle values to picl handles
258*7c478bd9Sstevel@tonic-gate 	 */
259*7c478bd9Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
260*7c478bd9Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
261*7c478bd9Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
262*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
263*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrval_t) +
264*7c478bd9Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
265*7c478bd9Sstevel@tonic-gate }
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate /*
268*7c478bd9Sstevel@tonic-gate  * This function returns the value of the PICL property specified by
269*7c478bd9Sstevel@tonic-gate  * its name.
270*7c478bd9Sstevel@tonic-gate  */
271*7c478bd9Sstevel@tonic-gate static void
272*7c478bd9Sstevel@tonic-gate picld_get_attrval_by_name(picl_service_t *in)
273*7c478bd9Sstevel@tonic-gate {
274*7c478bd9Sstevel@tonic-gate 	picl_retattrvalbyname_t	*ret;
275*7c478bd9Sstevel@tonic-gate 	int			err;
276*7c478bd9Sstevel@tonic-gate 	size_t			vbufsize;
277*7c478bd9Sstevel@tonic-gate 	size_t			len;
278*7c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
279*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
280*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
283*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrvalbyname.nodeh, &ptreeh);
286*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
287*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
290*7c478bd9Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, &pinfo);
291*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
292*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_READ))
295*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTREADABLE);
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	/*
298*7c478bd9Sstevel@tonic-gate 	 * allocate the minimum of piclinfo.size and input bufsize
299*7c478bd9Sstevel@tonic-gate 	 */
300*7c478bd9Sstevel@tonic-gate 	vbufsize = pinfo.piclinfo.size;
301*7c478bd9Sstevel@tonic-gate 	vbufsize = MIN((size_t)in->req_attrvalbyname.bufsize, vbufsize);
302*7c478bd9Sstevel@tonic-gate 	len = sizeof (picl_retattrvalbyname_t) + vbufsize;
303*7c478bd9Sstevel@tonic-gate 	ret = alloca(len);
304*7c478bd9Sstevel@tonic-gate 	if (ret == NULL)
305*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
306*7c478bd9Sstevel@tonic-gate 	ret->cnum = PICL_CNUM_GETATTRVALBYNAME;
307*7c478bd9Sstevel@tonic-gate 	ret->nodeh = in->req_attrvalbyname.nodeh;
308*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ret->propname, in->req_attrvalbyname.propname);
309*7c478bd9Sstevel@tonic-gate 	ret->nbytes = (uint32_t)vbufsize;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	err = xptree_get_propval_by_name_with_cred(ptreeh,
312*7c478bd9Sstevel@tonic-gate 	    in->req_attrvalbyname.propname, ret->ret_buf, vbufsize,
313*7c478bd9Sstevel@tonic-gate 	    cred);
314*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
315*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
316*7c478bd9Sstevel@tonic-gate 	/*
317*7c478bd9Sstevel@tonic-gate 	 * adjust returned value size for charstrings
318*7c478bd9Sstevel@tonic-gate 	 */
319*7c478bd9Sstevel@tonic-gate 	if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
320*7c478bd9Sstevel@tonic-gate 		ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
323*7c478bd9Sstevel@tonic-gate 	    (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
324*7c478bd9Sstevel@tonic-gate 		cvt_ptree2picl(&ret->ret_nodeh);
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
327*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)ret, sizeof (picl_retattrvalbyname_t) +
328*7c478bd9Sstevel@tonic-gate 	    (size_t)ret->nbytes, NULL, 0);
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate /*
332*7c478bd9Sstevel@tonic-gate  * This function sets a property value
333*7c478bd9Sstevel@tonic-gate  */
334*7c478bd9Sstevel@tonic-gate static void
335*7c478bd9Sstevel@tonic-gate picld_set_attrval(picl_service_t *in)
336*7c478bd9Sstevel@tonic-gate {
337*7c478bd9Sstevel@tonic-gate 	picl_retsetattrval_t	ret;
338*7c478bd9Sstevel@tonic-gate 	int			err;
339*7c478bd9Sstevel@tonic-gate 	door_cred_t		cred;
340*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
341*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
344*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrval.attr, &ptreeh);
347*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
348*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
351*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
352*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
355*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
356*7c478bd9Sstevel@tonic-gate 	/*
357*7c478bd9Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
358*7c478bd9Sstevel@tonic-gate 	 */
359*7c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
360*7c478bd9Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
361*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVAL;
364*7c478bd9Sstevel@tonic-gate 	ret.attr = in->req_setattrval.attr;
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	err = xptree_update_propval_with_cred(ptreeh, in->req_setattrval.valbuf,
367*7c478bd9Sstevel@tonic-gate 	    (size_t)in->req_setattrval.bufsize, cred);
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
370*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
373*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrval_t), NULL,
374*7c478bd9Sstevel@tonic-gate 	    0);
375*7c478bd9Sstevel@tonic-gate }
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate /*
378*7c478bd9Sstevel@tonic-gate  * This function sets the value of a property specified by its name.
379*7c478bd9Sstevel@tonic-gate  */
380*7c478bd9Sstevel@tonic-gate static void
381*7c478bd9Sstevel@tonic-gate picld_set_attrval_by_name(picl_service_t *in)
382*7c478bd9Sstevel@tonic-gate {
383*7c478bd9Sstevel@tonic-gate 	picl_retsetattrvalbyname_t	ret;
384*7c478bd9Sstevel@tonic-gate 	int				err;
385*7c478bd9Sstevel@tonic-gate 	door_cred_t			cred;
386*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t			ptreeh;
387*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t		pinfo;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	if (door_cred(&cred) < 0)
390*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_FAILURE);
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_setattrvalbyname.nodeh, &ptreeh);
393*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
394*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	err = xptree_get_propinfo_by_name(ptreeh,
397*7c478bd9Sstevel@tonic-gate 	    in->req_setattrvalbyname.propname, &pinfo);
398*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
399*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
402*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 	/*
405*7c478bd9Sstevel@tonic-gate 	 * For non-volatile prop, only super user can set its value.
406*7c478bd9Sstevel@tonic-gate 	 */
407*7c478bd9Sstevel@tonic-gate 	if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
408*7c478bd9Sstevel@tonic-gate 	    (cred.dc_euid != SUPER_USER))
409*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, PICL_PERMDENIED);
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_SETATTRVALBYNAME;
412*7c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_setattrvalbyname.nodeh;
413*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_setattrvalbyname.propname);
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	err = xptree_update_propval_by_name_with_cred(ptreeh,
416*7c478bd9Sstevel@tonic-gate 		in->req_setattrvalbyname.propname,
417*7c478bd9Sstevel@tonic-gate 		in->req_setattrvalbyname.valbuf,
418*7c478bd9Sstevel@tonic-gate 		(size_t)in->req_setattrvalbyname.bufsize,
419*7c478bd9Sstevel@tonic-gate 		cred);
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
422*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
425*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retsetattrvalbyname_t),
426*7c478bd9Sstevel@tonic-gate 	    NULL, 0);
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate /*
430*7c478bd9Sstevel@tonic-gate  * This function returns the property information
431*7c478bd9Sstevel@tonic-gate  */
432*7c478bd9Sstevel@tonic-gate static void
433*7c478bd9Sstevel@tonic-gate picld_get_attrinfo(picl_service_t *in)
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate 	picl_retattrinfo_t	ret;
436*7c478bd9Sstevel@tonic-gate 	int			err;
437*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	pinfo;
438*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrinfo.attr, &ptreeh);
441*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
442*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRINFO;
445*7c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrinfo.attr;
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(ptreeh, &pinfo);
448*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
449*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	ret.type = pinfo.piclinfo.type;
452*7c478bd9Sstevel@tonic-gate 	ret.accessmode = pinfo.piclinfo.accessmode;
453*7c478bd9Sstevel@tonic-gate 	ret.size = (uint32_t)pinfo.piclinfo.size;
454*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.name, pinfo.piclinfo.name);
455*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
456*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrinfo_t), NULL, 0);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate /*
460*7c478bd9Sstevel@tonic-gate  * This function returns the node's first property handle
461*7c478bd9Sstevel@tonic-gate  */
462*7c478bd9Sstevel@tonic-gate static void
463*7c478bd9Sstevel@tonic-gate picld_get_first_attr(picl_service_t *in)
464*7c478bd9Sstevel@tonic-gate {
465*7c478bd9Sstevel@tonic-gate 	picl_retfirstattr_t	ret;
466*7c478bd9Sstevel@tonic-gate 	int			err;
467*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_firstattr.nodeh, &ptreeh);
470*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
471*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETFIRSTATTR;
474*7c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_firstattr.nodeh;
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	err = ptree_get_first_prop(ptreeh, &ret.attr);
477*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
478*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
479*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
480*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
481*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retfirstattr_t), NULL, 0);
482*7c478bd9Sstevel@tonic-gate }
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate /*
485*7c478bd9Sstevel@tonic-gate  * This function returns the next property handle in list
486*7c478bd9Sstevel@tonic-gate  */
487*7c478bd9Sstevel@tonic-gate static void
488*7c478bd9Sstevel@tonic-gate picld_get_next_attr(picl_service_t *in)
489*7c478bd9Sstevel@tonic-gate {
490*7c478bd9Sstevel@tonic-gate 	picl_retnextattr_t	ret;
491*7c478bd9Sstevel@tonic-gate 	int			err;
492*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_nextattr.attr, &ptreeh);
495*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
496*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETNEXTATTR;
499*7c478bd9Sstevel@tonic-gate 	ret.attr = in->req_nextattr.attr;
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	err = ptree_get_next_prop(ptreeh, &ret.nextattr);
502*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
503*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nextattr);
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
508*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retnextattr_t), NULL, 0);
509*7c478bd9Sstevel@tonic-gate }
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate /*
512*7c478bd9Sstevel@tonic-gate  * This function returns the handle of a property specified by its name
513*7c478bd9Sstevel@tonic-gate  */
514*7c478bd9Sstevel@tonic-gate static void
515*7c478bd9Sstevel@tonic-gate picld_get_attr_by_name(picl_service_t *in)
516*7c478bd9Sstevel@tonic-gate {
517*7c478bd9Sstevel@tonic-gate 	picl_retattrbyname_t	ret;
518*7c478bd9Sstevel@tonic-gate 	int			err;
519*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyname.nodeh, &ptreeh);
522*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
523*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYNAME;
526*7c478bd9Sstevel@tonic-gate 	ret.nodeh = in->req_attrbyname.nodeh;
527*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ret.propname, in->req_attrbyname.propname);
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 	err = ptree_get_prop_by_name(ptreeh, ret.propname, &ret.attr);
530*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
531*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.attr);
534*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
535*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyname_t), NULL,
536*7c478bd9Sstevel@tonic-gate 	    0);
537*7c478bd9Sstevel@tonic-gate }
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate /*
540*7c478bd9Sstevel@tonic-gate  * This function gets the next property on the same row in the table
541*7c478bd9Sstevel@tonic-gate  */
542*7c478bd9Sstevel@tonic-gate static void
543*7c478bd9Sstevel@tonic-gate picld_get_attr_by_row(picl_service_t *in)
544*7c478bd9Sstevel@tonic-gate {
545*7c478bd9Sstevel@tonic-gate 	picl_retattrbyrow_t	ret;
546*7c478bd9Sstevel@tonic-gate 	int			err;
547*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbyrow.attr, &ptreeh);
550*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
551*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYROW;
554*7c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrbyrow.attr;
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 	err = ptree_get_next_by_row(ptreeh, &ret.rowattr);
557*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
558*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
559*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rowattr);
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
562*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbyrow_t), NULL, 0);
563*7c478bd9Sstevel@tonic-gate }
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate /*
566*7c478bd9Sstevel@tonic-gate  * This function returns the handle of the next property in the same column
567*7c478bd9Sstevel@tonic-gate  * of the table.
568*7c478bd9Sstevel@tonic-gate  */
569*7c478bd9Sstevel@tonic-gate static void
570*7c478bd9Sstevel@tonic-gate picld_get_attr_by_col(picl_service_t *in)
571*7c478bd9Sstevel@tonic-gate {
572*7c478bd9Sstevel@tonic-gate 	picl_retattrbycol_t	ret;
573*7c478bd9Sstevel@tonic-gate 	int			err;
574*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		ptreeh;
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_attrbycol.attr, &ptreeh);
577*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
578*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_GETATTRBYCOL;
581*7c478bd9Sstevel@tonic-gate 	ret.attr = in->req_attrbycol.attr;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	err = ptree_get_next_by_col(ptreeh, &ret.colattr);
584*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
585*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.colattr);
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
590*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (picl_retattrbycol_t), NULL, 0);
591*7c478bd9Sstevel@tonic-gate }
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate /*
594*7c478bd9Sstevel@tonic-gate  * This function finds the node in the PICLTREE that matches the given
595*7c478bd9Sstevel@tonic-gate  * criteria and returns its handle.
596*7c478bd9Sstevel@tonic-gate  */
597*7c478bd9Sstevel@tonic-gate static void
598*7c478bd9Sstevel@tonic-gate picld_find_node(picl_service_t *in)
599*7c478bd9Sstevel@tonic-gate {
600*7c478bd9Sstevel@tonic-gate 	picl_retfindnode_t	ret;
601*7c478bd9Sstevel@tonic-gate 	int			err;
602*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_findnode.nodeh, &ptreeh);
605*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
606*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FINDNODE;
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	err = ptree_find_node(ptreeh, in->req_findnode.propname,
611*7c478bd9Sstevel@tonic-gate 	    in->req_findnode.ptype, in->req_findnode.valbuf,
612*7c478bd9Sstevel@tonic-gate 	    in->req_findnode.valsize, &ret.rnodeh);
613*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
614*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.rnodeh);
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
619*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
620*7c478bd9Sstevel@tonic-gate }
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate /*
623*7c478bd9Sstevel@tonic-gate  * This function finds the property/node that corresponds to the given path
624*7c478bd9Sstevel@tonic-gate  * and returns its handle
625*7c478bd9Sstevel@tonic-gate  */
626*7c478bd9Sstevel@tonic-gate static void
627*7c478bd9Sstevel@tonic-gate picld_get_node_by_path(picl_service_t *in)
628*7c478bd9Sstevel@tonic-gate {
629*7c478bd9Sstevel@tonic-gate 	picl_retnodebypath_t	ret;
630*7c478bd9Sstevel@tonic-gate 	int			err;
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_NODEBYPATH;
633*7c478bd9Sstevel@tonic-gate 	err = ptree_get_node_by_path(in->req_nodebypath.pathbuf, &ret.nodeh);
634*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
635*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
636*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.nodeh);
637*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
638*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
639*7c478bd9Sstevel@tonic-gate }
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate /*
642*7c478bd9Sstevel@tonic-gate  * This function returns finds the frutree parent node for a given node
643*7c478bd9Sstevel@tonic-gate  * and returns its handle
644*7c478bd9Sstevel@tonic-gate  */
645*7c478bd9Sstevel@tonic-gate static void
646*7c478bd9Sstevel@tonic-gate picld_get_frutree_parent(picl_service_t *in)
647*7c478bd9Sstevel@tonic-gate {
648*7c478bd9Sstevel@tonic-gate 	picl_retfruparent_t	ret;
649*7c478bd9Sstevel@tonic-gate 	int			err;
650*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		ptreeh;
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	err = cvt_picl2ptree(in->req_fruparent.devh, &ptreeh);
653*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
654*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	ret.cnum = PICL_CNUM_FRUTREEPARENT;
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	err = ptree_get_frutree_parent(ptreeh, &ret.fruh);
659*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
660*7c478bd9Sstevel@tonic-gate 		picld_return_error(in->in.cnum, err);
661*7c478bd9Sstevel@tonic-gate 	cvt_ptree2picl(&ret.fruh);
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&init_lk);
664*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&ret, sizeof (ret), NULL, 0);
665*7c478bd9Sstevel@tonic-gate }
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate /*
668*7c478bd9Sstevel@tonic-gate  * This function is called when an unknown client request is received.
669*7c478bd9Sstevel@tonic-gate  */
670*7c478bd9Sstevel@tonic-gate static void
671*7c478bd9Sstevel@tonic-gate picld_unknown_service(picl_service_t *in)
672*7c478bd9Sstevel@tonic-gate {
673*7c478bd9Sstevel@tonic-gate 	picld_return_error(in->in.cnum, PICL_UNKNOWNSERVICE);
674*7c478bd9Sstevel@tonic-gate }
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate static void
677*7c478bd9Sstevel@tonic-gate check_denial_of_service(int cnum)
678*7c478bd9Sstevel@tonic-gate {
679*7c478bd9Sstevel@tonic-gate 	hrtime_t	window;
680*7c478bd9Sstevel@tonic-gate 	hrtime_t	current;
681*7c478bd9Sstevel@tonic-gate 	int		dos_flag;
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	current = gethrtime();
684*7c478bd9Sstevel@tonic-gate 	dos_flag = 0;
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	if (pthread_mutex_lock(&dos_mutex) != 0)
687*7c478bd9Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	++service_requests;
690*7c478bd9Sstevel@tonic-gate 	window = current - orig_time;
691*7c478bd9Sstevel@tonic-gate 	if (window > MILLI_TO_NANO(sliding_interval_ms)) {
692*7c478bd9Sstevel@tonic-gate 		orig_time = current;
693*7c478bd9Sstevel@tonic-gate 		service_requests = 1;
694*7c478bd9Sstevel@tonic-gate 	}
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	if (service_requests > dos_req_limit)
697*7c478bd9Sstevel@tonic-gate 		dos_flag = 1;
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 	if (pthread_mutex_unlock(&dos_mutex) != 0)
700*7c478bd9Sstevel@tonic-gate 		picld_return_error(cnum, PICL_FAILURE);
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate 	if (dos_flag)
703*7c478bd9Sstevel@tonic-gate 		(void) poll(NULL, 0, dos_ms);
704*7c478bd9Sstevel@tonic-gate }
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
708*7c478bd9Sstevel@tonic-gate static void
709*7c478bd9Sstevel@tonic-gate picld_door_handler(void *cookie, char *argp, size_t asize,
710*7c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t n_desc)
711*7c478bd9Sstevel@tonic-gate {
712*7c478bd9Sstevel@tonic-gate 	picl_service_t  *req;
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 	/*LINTED*/
715*7c478bd9Sstevel@tonic-gate 	req = (picl_service_t *)argp;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	if (req == NULL)
718*7c478bd9Sstevel@tonic-gate 		(void) door_return((char *)req, 0, NULL, 0);
719*7c478bd9Sstevel@tonic-gate 
720*7c478bd9Sstevel@tonic-gate 	check_denial_of_service(req->in.cnum);
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&init_lk);
723*7c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {	/* client call number */
724*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_INIT:
725*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
726*7c478bd9Sstevel@tonic-gate 		picld_init((picl_service_t *)argp);
727*7c478bd9Sstevel@tonic-gate 		break;
728*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FINI:
729*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
730*7c478bd9Sstevel@tonic-gate 		picld_fini((picl_service_t *)argp);
731*7c478bd9Sstevel@tonic-gate 		break;
732*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETROOT:
733*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
734*7c478bd9Sstevel@tonic-gate 		picld_getroot((picl_service_t *)argp);
735*7c478bd9Sstevel@tonic-gate 		break;
736*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVAL:
737*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
738*7c478bd9Sstevel@tonic-gate 		picld_get_attrval((picl_service_t *)argp);
739*7c478bd9Sstevel@tonic-gate 		break;
740*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRVALBYNAME:
741*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
742*7c478bd9Sstevel@tonic-gate 		picld_get_attrval_by_name((picl_service_t *)argp);
743*7c478bd9Sstevel@tonic-gate 		break;
744*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRINFO:
745*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
746*7c478bd9Sstevel@tonic-gate 		picld_get_attrinfo((picl_service_t *)argp);
747*7c478bd9Sstevel@tonic-gate 		break;
748*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETFIRSTATTR:
749*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
750*7c478bd9Sstevel@tonic-gate 		picld_get_first_attr((picl_service_t *)argp);
751*7c478bd9Sstevel@tonic-gate 		break;
752*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETNEXTATTR:
753*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
754*7c478bd9Sstevel@tonic-gate 		picld_get_next_attr((picl_service_t *)argp);
755*7c478bd9Sstevel@tonic-gate 		break;
756*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYNAME:
757*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
758*7c478bd9Sstevel@tonic-gate 		picld_get_attr_by_name((picl_service_t *)argp);
759*7c478bd9Sstevel@tonic-gate 		break;
760*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYROW:
761*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
762*7c478bd9Sstevel@tonic-gate 		picld_get_attr_by_row((picl_service_t *)argp);
763*7c478bd9Sstevel@tonic-gate 		break;
764*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_GETATTRBYCOL:
765*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
766*7c478bd9Sstevel@tonic-gate 		picld_get_attr_by_col((picl_service_t *)argp);
767*7c478bd9Sstevel@tonic-gate 		break;
768*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVAL:
769*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
770*7c478bd9Sstevel@tonic-gate 		picld_set_attrval((picl_service_t *)argp);
771*7c478bd9Sstevel@tonic-gate 		break;
772*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_SETATTRVALBYNAME:
773*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
774*7c478bd9Sstevel@tonic-gate 		picld_set_attrval_by_name((picl_service_t *)argp);
775*7c478bd9Sstevel@tonic-gate 		break;
776*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_PING:
777*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
778*7c478bd9Sstevel@tonic-gate 		picld_ping((picl_service_t *)argp);
779*7c478bd9Sstevel@tonic-gate 		break;
780*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_WAIT:
781*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
782*7c478bd9Sstevel@tonic-gate 		picld_wait((picl_service_t *)argp);
783*7c478bd9Sstevel@tonic-gate 		break;
784*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FINDNODE:
785*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
786*7c478bd9Sstevel@tonic-gate 		picld_find_node((picl_service_t *)argp);
787*7c478bd9Sstevel@tonic-gate 		break;
788*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_NODEBYPATH:
789*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
790*7c478bd9Sstevel@tonic-gate 		picld_get_node_by_path((picl_service_t *)argp);
791*7c478bd9Sstevel@tonic-gate 		break;
792*7c478bd9Sstevel@tonic-gate 	case PICL_CNUM_FRUTREEPARENT:
793*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
794*7c478bd9Sstevel@tonic-gate 		picld_get_frutree_parent((picl_service_t *)argp);
795*7c478bd9Sstevel@tonic-gate 		break;
796*7c478bd9Sstevel@tonic-gate 	default:
797*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
798*7c478bd9Sstevel@tonic-gate 		picld_unknown_service((picl_service_t *)argp);
799*7c478bd9Sstevel@tonic-gate 		break;
800*7c478bd9Sstevel@tonic-gate 	};
801*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
802*7c478bd9Sstevel@tonic-gate }
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
805*7c478bd9Sstevel@tonic-gate static void
806*7c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
807*7c478bd9Sstevel@tonic-gate {
808*7c478bd9Sstevel@tonic-gate 	doreinit = 1;
809*7c478bd9Sstevel@tonic-gate }
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate /*
812*7c478bd9Sstevel@tonic-gate  * "ping" to see if a daemon is already running
813*7c478bd9Sstevel@tonic-gate  */
814*7c478bd9Sstevel@tonic-gate static int
815*7c478bd9Sstevel@tonic-gate daemon_exists(void)
816*7c478bd9Sstevel@tonic-gate {
817*7c478bd9Sstevel@tonic-gate 	door_arg_t	darg;
818*7c478bd9Sstevel@tonic-gate 	picl_reqping_t	req_ping;
819*7c478bd9Sstevel@tonic-gate 	picl_retping_t	ret_ping;
820*7c478bd9Sstevel@tonic-gate 	int		doorh;
821*7c478bd9Sstevel@tonic-gate 	door_info_t	dinfo;
822*7c478bd9Sstevel@tonic-gate 
823*7c478bd9Sstevel@tonic-gate 	doorh = open(PICLD_DOOR, O_RDONLY);
824*7c478bd9Sstevel@tonic-gate 	if (doorh < 0)
825*7c478bd9Sstevel@tonic-gate 		return (0);
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
828*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
829*7c478bd9Sstevel@tonic-gate 		return (0);
830*7c478bd9Sstevel@tonic-gate 	}
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate 	if ((dinfo.di_attributes & DOOR_REVOKED) ||
833*7c478bd9Sstevel@tonic-gate 	    (dinfo.di_data != (door_ptr_t)PICLD_DOOR_COOKIE)) {
834*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
835*7c478bd9Sstevel@tonic-gate 		return (0);
836*7c478bd9Sstevel@tonic-gate 	}
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	if (dinfo.di_target != getpid()) {
839*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
840*7c478bd9Sstevel@tonic-gate 		return (1);
841*7c478bd9Sstevel@tonic-gate 	}
842*7c478bd9Sstevel@tonic-gate 
843*7c478bd9Sstevel@tonic-gate 	req_ping.cnum = PICL_CNUM_PING;
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
846*7c478bd9Sstevel@tonic-gate 	darg.data_size = sizeof (picl_reqping_t);
847*7c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
848*7c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
849*7c478bd9Sstevel@tonic-gate 	darg.rbuf = (char *)&ret_ping;
850*7c478bd9Sstevel@tonic-gate 	darg.rsize = sizeof (picl_retping_t);
851*7c478bd9Sstevel@tonic-gate 
852*7c478bd9Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
853*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
854*7c478bd9Sstevel@tonic-gate 		return (0);
855*7c478bd9Sstevel@tonic-gate 	}
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate 	(void) close(doorh);
858*7c478bd9Sstevel@tonic-gate 	return (1);
859*7c478bd9Sstevel@tonic-gate }
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate /*
862*7c478bd9Sstevel@tonic-gate  * Create the picld door
863*7c478bd9Sstevel@tonic-gate  */
864*7c478bd9Sstevel@tonic-gate static int
865*7c478bd9Sstevel@tonic-gate setup_door(void)
866*7c478bd9Sstevel@tonic-gate {
867*7c478bd9Sstevel@tonic-gate 	struct stat	stbuf;
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate 	/*
870*7c478bd9Sstevel@tonic-gate 	 * Create the door
871*7c478bd9Sstevel@tonic-gate 	 */
872*7c478bd9Sstevel@tonic-gate 	door_id = door_create(picld_door_handler, PICLD_DOOR_COOKIE,
873*7c478bd9Sstevel@tonic-gate 	    DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 	if (door_id < 0) {
876*7c478bd9Sstevel@tonic-gate 		return (-1);
877*7c478bd9Sstevel@tonic-gate 	}
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate 	if (stat(PICLD_DOOR, &stbuf) < 0) {
880*7c478bd9Sstevel@tonic-gate 		int newfd;
881*7c478bd9Sstevel@tonic-gate 		if ((newfd = creat(PICLD_DOOR, 0444)) < 0)
882*7c478bd9Sstevel@tonic-gate 			return (-1);
883*7c478bd9Sstevel@tonic-gate 		(void) close(newfd);
884*7c478bd9Sstevel@tonic-gate 	}
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 	if (fattach(door_id, PICLD_DOOR) < 0) {
887*7c478bd9Sstevel@tonic-gate 		if ((errno != EBUSY) ||
888*7c478bd9Sstevel@tonic-gate 		    (fdetach(PICLD_DOOR) < 0) ||
889*7c478bd9Sstevel@tonic-gate 		    (fattach(door_id, PICLD_DOOR) < 0))
890*7c478bd9Sstevel@tonic-gate 			return (-1);
891*7c478bd9Sstevel@tonic-gate 	}
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate 	return (0);
894*7c478bd9Sstevel@tonic-gate }
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate /*
897*7c478bd9Sstevel@tonic-gate  * Main function of picl daemon
898*7c478bd9Sstevel@tonic-gate  */
899*7c478bd9Sstevel@tonic-gate int
900*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
901*7c478bd9Sstevel@tonic-gate {
902*7c478bd9Sstevel@tonic-gate 	struct	sigaction	act;
903*7c478bd9Sstevel@tonic-gate 	int			c;
904*7c478bd9Sstevel@tonic-gate 	sigset_t		ublk;
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 
907*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
908*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
909*7c478bd9Sstevel@tonic-gate 
910*7c478bd9Sstevel@tonic-gate 	if (getuid() != 0) {
911*7c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, MUST_BE_ROOT);
912*7c478bd9Sstevel@tonic-gate 		return (0);
913*7c478bd9Sstevel@tonic-gate 	}
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&init_lk, USYNC_THREAD, NULL);
916*7c478bd9Sstevel@tonic-gate 	doreinit = 0;
917*7c478bd9Sstevel@tonic-gate 	logflag = 1;
918*7c478bd9Sstevel@tonic-gate 	dos_req_limit = DOS_PICL_REQUESTS_LIMIT;
919*7c478bd9Sstevel@tonic-gate 	sliding_interval_ms = SLIDING_INTERVAL_MILLISECONDS;
920*7c478bd9Sstevel@tonic-gate 	dos_ms = DOS_SLEEPTIME_MS;
921*7c478bd9Sstevel@tonic-gate 	verbose_level = 0;
922*7c478bd9Sstevel@tonic-gate 
923*7c478bd9Sstevel@tonic-gate 	/*
924*7c478bd9Sstevel@tonic-gate 	 * parse arguments
925*7c478bd9Sstevel@tonic-gate 	 */
926*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "is:t:l:r:v:d:")) != EOF) {
927*7c478bd9Sstevel@tonic-gate 		switch (c) {
928*7c478bd9Sstevel@tonic-gate 		case 'd':
929*7c478bd9Sstevel@tonic-gate 			dos_ms = strtol(optarg, (char **)NULL, 0);
930*7c478bd9Sstevel@tonic-gate 			break;
931*7c478bd9Sstevel@tonic-gate 		case 'i':
932*7c478bd9Sstevel@tonic-gate 			logflag = 0;
933*7c478bd9Sstevel@tonic-gate 			break;
934*7c478bd9Sstevel@tonic-gate 		case 's':
935*7c478bd9Sstevel@tonic-gate 			sliding_interval_ms = strtoll(optarg, (char **)NULL, 0);
936*7c478bd9Sstevel@tonic-gate 			break;
937*7c478bd9Sstevel@tonic-gate 		case 't':
938*7c478bd9Sstevel@tonic-gate 			dos_req_limit = strtol(optarg, (char **)NULL, 0);
939*7c478bd9Sstevel@tonic-gate 			break;
940*7c478bd9Sstevel@tonic-gate 		case 'v':
941*7c478bd9Sstevel@tonic-gate 			verbose_level = strtol(optarg, (char **)NULL, 0);
942*7c478bd9Sstevel@tonic-gate 			logflag = 0;
943*7c478bd9Sstevel@tonic-gate 			break;
944*7c478bd9Sstevel@tonic-gate 		default:
945*7c478bd9Sstevel@tonic-gate 			break;
946*7c478bd9Sstevel@tonic-gate 		}
947*7c478bd9Sstevel@tonic-gate 	}
948*7c478bd9Sstevel@tonic-gate 
949*7c478bd9Sstevel@tonic-gate 	orig_time = gethrtime();
950*7c478bd9Sstevel@tonic-gate 
951*7c478bd9Sstevel@tonic-gate 	/*
952*7c478bd9Sstevel@tonic-gate 	 * is there a daemon already running?
953*7c478bd9Sstevel@tonic-gate 	 */
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate 	if (daemon_exists()) {
956*7c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, DAEMON_RUNNING);
957*7c478bd9Sstevel@tonic-gate 		exit(1);
958*7c478bd9Sstevel@tonic-gate 	}
959*7c478bd9Sstevel@tonic-gate 
960*7c478bd9Sstevel@tonic-gate 	/*
961*7c478bd9Sstevel@tonic-gate 	 * Mask off/block SIGALRM signal so that the environmental plug-in
962*7c478bd9Sstevel@tonic-gate 	 * (piclenvd) can use it to simulate sleep() without being affected
963*7c478bd9Sstevel@tonic-gate 	 * by time being set back. No other PICL plug-in should use SIGALRM
964*7c478bd9Sstevel@tonic-gate 	 * or alarm() for now.
965*7c478bd9Sstevel@tonic-gate 	 */
966*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&ublk);
967*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&ublk, SIGALRM);
968*7c478bd9Sstevel@tonic-gate 	(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate 	/*
971*7c478bd9Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
972*7c478bd9Sstevel@tonic-gate 	 */
973*7c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
974*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
975*7c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
976*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
977*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
978*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 	if (logflag != 0) {	/* daemonize */
981*7c478bd9Sstevel@tonic-gate 		pid_t pid;
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate 		pid = fork();
984*7c478bd9Sstevel@tonic-gate 		if (pid < 0)
985*7c478bd9Sstevel@tonic-gate 			exit(1);
986*7c478bd9Sstevel@tonic-gate 		if (pid > 0)
987*7c478bd9Sstevel@tonic-gate 			/* parent */
988*7c478bd9Sstevel@tonic-gate 			exit(0);
989*7c478bd9Sstevel@tonic-gate 
990*7c478bd9Sstevel@tonic-gate 		/* child */
991*7c478bd9Sstevel@tonic-gate 		if (chdir("/") == -1) {
992*7c478bd9Sstevel@tonic-gate 			syslog(LOG_CRIT, CD_ROOT_FAILED);
993*7c478bd9Sstevel@tonic-gate 			exit(1);
994*7c478bd9Sstevel@tonic-gate 		}
995*7c478bd9Sstevel@tonic-gate 
996*7c478bd9Sstevel@tonic-gate 		(void) setsid();
997*7c478bd9Sstevel@tonic-gate 		(void) close(STDIN_FILENO);
998*7c478bd9Sstevel@tonic-gate 		(void) close(STDOUT_FILENO);
999*7c478bd9Sstevel@tonic-gate 		(void) close(STDERR_FILENO);
1000*7c478bd9Sstevel@tonic-gate 		(void) open("/dev/null", O_RDWR, 0);
1001*7c478bd9Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDOUT_FILENO);
1002*7c478bd9Sstevel@tonic-gate 		(void) dup2(STDIN_FILENO, STDERR_FILENO);
1003*7c478bd9Sstevel@tonic-gate 		openlog(PICLD, LOG_PID, LOG_DAEMON);
1004*7c478bd9Sstevel@tonic-gate 	}
1005*7c478bd9Sstevel@tonic-gate 
1006*7c478bd9Sstevel@tonic-gate 	/*
1007*7c478bd9Sstevel@tonic-gate 	 * Initialize the PICL Tree
1008*7c478bd9Sstevel@tonic-gate 	 */
1009*7c478bd9Sstevel@tonic-gate 	if (xptree_initialize(NULL) != PICL_SUCCESS) {
1010*7c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, INIT_FAILED);
1011*7c478bd9Sstevel@tonic-gate 		exit(1);
1012*7c478bd9Sstevel@tonic-gate 	}
1013*7c478bd9Sstevel@tonic-gate 
1014*7c478bd9Sstevel@tonic-gate 	if (setup_door()) {
1015*7c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, DOOR_FAILED);
1016*7c478bd9Sstevel@tonic-gate 		exit(1);
1017*7c478bd9Sstevel@tonic-gate 	}
1018*7c478bd9Sstevel@tonic-gate 
1019*7c478bd9Sstevel@tonic-gate 	/*
1020*7c478bd9Sstevel@tonic-gate 	 * setup signal handlers for post-init
1021*7c478bd9Sstevel@tonic-gate 	 */
1022*7c478bd9Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
1023*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
1024*7c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
1025*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
1026*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
1027*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 	/*
1030*7c478bd9Sstevel@tonic-gate 	 * wait for requests
1031*7c478bd9Sstevel@tonic-gate 	 */
1032*7c478bd9Sstevel@tonic-gate 	for (;;) {
1033*7c478bd9Sstevel@tonic-gate 		(void) pause();
1034*7c478bd9Sstevel@tonic-gate 		if (doreinit) {
1035*7c478bd9Sstevel@tonic-gate 			/*
1036*7c478bd9Sstevel@tonic-gate 			 * Block SIGHUP during reinitialization.
1037*7c478bd9Sstevel@tonic-gate 			 * Also mask off/block SIGALRM signal so that the
1038*7c478bd9Sstevel@tonic-gate 			 * environmental plug-in (piclenvd) can use it to
1039*7c478bd9Sstevel@tonic-gate 			 * simulate sleep() without being affected by time
1040*7c478bd9Sstevel@tonic-gate 			 * being set back. No ohter PICL plug-in should use
1041*7c478bd9Sstevel@tonic-gate 			 * SIGALRM or alarm() for now.
1042*7c478bd9Sstevel@tonic-gate 			 */
1043*7c478bd9Sstevel@tonic-gate 			(void) sigemptyset(&ublk);
1044*7c478bd9Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGHUP);
1045*7c478bd9Sstevel@tonic-gate 			(void) sigaddset(&ublk, SIGALRM);
1046*7c478bd9Sstevel@tonic-gate 			(void) sigprocmask(SIG_BLOCK, &ublk, NULL);
1047*7c478bd9Sstevel@tonic-gate 			(void) sigdelset(&ublk, SIGALRM);
1048*7c478bd9Sstevel@tonic-gate 			doreinit = 0;
1049*7c478bd9Sstevel@tonic-gate 			(void) rw_wrlock(&init_lk);
1050*7c478bd9Sstevel@tonic-gate 			xptree_destroy();
1051*7c478bd9Sstevel@tonic-gate 			(void) xptree_reinitialize();
1052*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&init_lk);
1053*7c478bd9Sstevel@tonic-gate 			(void) sigprocmask(SIG_UNBLOCK, &ublk, NULL);
1054*7c478bd9Sstevel@tonic-gate 		}
1055*7c478bd9Sstevel@tonic-gate 	}
1056*7c478bd9Sstevel@tonic-gate }
1057