10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56325Sjfrank * Common Development and Distribution License (the "License").
66325Sjfrank * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
211016Sraf
220Sstevel@tonic-gate /*
23*8775SMichael.Bergknoff@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * PICL daemon
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <stdarg.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <libintl.h>
360Sstevel@tonic-gate #include <locale.h>
370Sstevel@tonic-gate #include <alloca.h>
380Sstevel@tonic-gate #include <errno.h>
390Sstevel@tonic-gate #include <assert.h>
400Sstevel@tonic-gate #include <stropts.h>
410Sstevel@tonic-gate #include <unistd.h>
420Sstevel@tonic-gate #include <signal.h>
430Sstevel@tonic-gate #include <pthread.h>
440Sstevel@tonic-gate #include <synch.h>
450Sstevel@tonic-gate #include <door.h>
460Sstevel@tonic-gate #include <sys/door.h>
470Sstevel@tonic-gate #include <fcntl.h>
480Sstevel@tonic-gate #include <dlfcn.h>
490Sstevel@tonic-gate #include <time.h>
500Sstevel@tonic-gate #include <sys/utsname.h>
510Sstevel@tonic-gate #include <sys/systeminfo.h>
520Sstevel@tonic-gate #include <sys/stat.h>
530Sstevel@tonic-gate #include <sys/wait.h>
540Sstevel@tonic-gate #include <dirent.h>
550Sstevel@tonic-gate #include <syslog.h>
560Sstevel@tonic-gate #include <poll.h>
570Sstevel@tonic-gate #include <limits.h>
580Sstevel@tonic-gate #include <picl.h>
590Sstevel@tonic-gate #include "picl2door.h"
600Sstevel@tonic-gate #include <picltree.h>
610Sstevel@tonic-gate #include "ptree_impl.h"
620Sstevel@tonic-gate
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate * Log text messages
650Sstevel@tonic-gate */
660Sstevel@tonic-gate #define MUST_BE_ROOT gettext("this program must be run as root\n")
670Sstevel@tonic-gate #define CD_ROOT_FAILED gettext("chdir to root failed\n")
680Sstevel@tonic-gate #define INIT_FAILED gettext("ptree initialization failed\n")
690Sstevel@tonic-gate #define DAEMON_RUNNING gettext("PICL daemon already running\n")
700Sstevel@tonic-gate #define DOOR_FAILED gettext("Failed creating picld door\n")
710Sstevel@tonic-gate #define SIGACT_FAILED \
720Sstevel@tonic-gate gettext("Failed to install signal handler for %s: %s\n")
730Sstevel@tonic-gate
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate * Constants
760Sstevel@tonic-gate */
770Sstevel@tonic-gate #define PICLD "picld"
780Sstevel@tonic-gate #define DOS_PICL_REQUESTS_LIMIT 10000
790Sstevel@tonic-gate #define SLIDING_INTERVAL_MILLISECONDS 1000
800Sstevel@tonic-gate #define PICLD_MAJOR_REV 0x1
810Sstevel@tonic-gate #define PICLD_MINOR_REV 0x0
820Sstevel@tonic-gate #define DOS_SLEEPTIME_MS 1000
837162Sjfrank #define MAX_POOL_SIZE _POSIX_THREAD_THREADS_MAX
847162Sjfrank #define MAX_CONCURRENT_WAITS (_POSIX_THREAD_THREADS_MAX - 2)
857162Sjfrank #define MAX_USER_WAITS 4
860Sstevel@tonic-gate
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate * Macros
890Sstevel@tonic-gate */
900Sstevel@tonic-gate #define PICLD_VERSION(x, y) ((x << 8) | y)
910Sstevel@tonic-gate #define PICL_CLIENT_REV(x) (x & 0xff)
920Sstevel@tonic-gate #define MILLI_TO_NANO(x) (x * 1000000)
930Sstevel@tonic-gate
940Sstevel@tonic-gate extern char **environ;
950Sstevel@tonic-gate
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate * Module Variables
980Sstevel@tonic-gate */
990Sstevel@tonic-gate static int logflag = 1;
1000Sstevel@tonic-gate static int doreinit = 0;
1010Sstevel@tonic-gate static int door_id = -1;
1027162Sjfrank static pthread_mutex_t door_mutex = PTHREAD_MUTEX_INITIALIZER;
1037162Sjfrank static pthread_cond_t door_cv = PTHREAD_COND_INITIALIZER;
1040Sstevel@tonic-gate static int service_requests = 0;
1050Sstevel@tonic-gate static hrtime_t orig_time;
1060Sstevel@tonic-gate static hrtime_t sliding_interval_ms;
1070Sstevel@tonic-gate static uint32_t dos_req_limit;
1080Sstevel@tonic-gate static uint32_t dos_ms;
1090Sstevel@tonic-gate static pthread_mutex_t dos_mutex = PTHREAD_MUTEX_INITIALIZER;
1100Sstevel@tonic-gate static rwlock_t init_lk;
1117162Sjfrank static int pool_count = 0;
1127162Sjfrank static pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
1137162Sjfrank static pthread_mutex_t wait_req_mutex = PTHREAD_MUTEX_INITIALIZER;
1147162Sjfrank static int wait_count = 0;
1157162Sjfrank static struct {
1167162Sjfrank uid_t uid;
1177162Sjfrank int count;
1187162Sjfrank } user_count[MAX_CONCURRENT_WAITS];
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate /*
1210Sstevel@tonic-gate * This returns an error message to libpicl
1220Sstevel@tonic-gate */
1230Sstevel@tonic-gate static void
picld_return_error(picl_callnumber_t cnum,picl_errno_t err)1240Sstevel@tonic-gate picld_return_error(picl_callnumber_t cnum, picl_errno_t err)
1250Sstevel@tonic-gate {
1260Sstevel@tonic-gate picl_reterror_t ret_error;
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate ret_error.cnum = PICL_CNUM_ERROR;
1290Sstevel@tonic-gate ret_error.in_cnum = cnum;
1300Sstevel@tonic-gate ret_error.errnum = err;
1310Sstevel@tonic-gate (void) rw_unlock(&init_lk);
1320Sstevel@tonic-gate (void) door_return((char *)&ret_error, sizeof (picl_reterror_t), NULL,
1330Sstevel@tonic-gate 0);
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate /*
1370Sstevel@tonic-gate * picld_init is called when a picl_initialize request is received
1380Sstevel@tonic-gate */
1390Sstevel@tonic-gate static void
picld_init(picl_service_t * req)1400Sstevel@tonic-gate picld_init(picl_service_t *req)
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate picl_retinit_t ret_init;
1430Sstevel@tonic-gate int clmajrev;
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate clmajrev = PICL_CLIENT_REV(req->req_init.clrev);
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate if (clmajrev < PICL_VERSION_1)
1480Sstevel@tonic-gate picld_return_error(req->req_init.cnum, PICL_NOTSUPPORTED);
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate ret_init.cnum = req->req_init.cnum;
1510Sstevel@tonic-gate ret_init.rev = PICLD_VERSION(PICLD_MAJOR_REV, PICLD_MINOR_REV);
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate (void) rw_unlock(&init_lk);
1540Sstevel@tonic-gate (void) door_return((char *)&ret_init, sizeof (picl_retinit_t), NULL, 0);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate /*
1580Sstevel@tonic-gate * picld_fini is called when a picl_shutdown request is received
1590Sstevel@tonic-gate */
1600Sstevel@tonic-gate static void
picld_fini(picl_service_t * in)1610Sstevel@tonic-gate picld_fini(picl_service_t *in)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate picl_retfini_t ret;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate ret.cnum = in->req_fini.cnum;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate (void) rw_unlock(&init_lk);
1680Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retfini_t), NULL, 0);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate static void
picld_ping(picl_service_t * in)1720Sstevel@tonic-gate picld_ping(picl_service_t *in)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate picl_retping_t ret;
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate ret.cnum = in->req_ping.cnum;
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate (void) rw_unlock(&init_lk);
1790Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retping_t), NULL, 0);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1827162Sjfrank static int
check_user(uid_t uid)1837162Sjfrank check_user(uid_t uid)
1847162Sjfrank {
1857162Sjfrank int i;
1867162Sjfrank uid_t tmp_uid;
1877162Sjfrank int free_idx = -1;
1887162Sjfrank
1897162Sjfrank if (uid == 0)
1907162Sjfrank return (PICL_SUCCESS);
1917162Sjfrank for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
1927162Sjfrank if ((tmp_uid = user_count[i].uid) == uid) {
1937162Sjfrank if (user_count[i].count == MAX_USER_WAITS)
1947162Sjfrank return (PICL_FAILURE);
1957162Sjfrank user_count[i].count++;
1967162Sjfrank return (PICL_SUCCESS);
1977162Sjfrank }
1987162Sjfrank if ((free_idx == -1) && (tmp_uid == 0))
1997162Sjfrank free_idx = i;
2007162Sjfrank }
2017162Sjfrank if (free_idx != -1) {
2027162Sjfrank user_count[free_idx].uid = uid;
2037162Sjfrank user_count[free_idx].count = 1;
2047162Sjfrank return (PICL_SUCCESS);
2057162Sjfrank }
2067162Sjfrank return (PICL_FAILURE);
2077162Sjfrank }
2087162Sjfrank
2097162Sjfrank static void
done_user(uid_t uid)2107162Sjfrank done_user(uid_t uid)
2117162Sjfrank {
2127162Sjfrank int i;
2137162Sjfrank
2147162Sjfrank if (uid == 0)
2157162Sjfrank return;
2167162Sjfrank for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
2177162Sjfrank if (user_count[i].uid == uid) {
2187162Sjfrank if (--user_count[i].count == 0)
2197162Sjfrank user_count[i].uid = 0;
2207162Sjfrank return;
2217162Sjfrank }
2227162Sjfrank }
2237162Sjfrank }
2247162Sjfrank
2257162Sjfrank static int
enter_picld_wait(uid_t uid)2267162Sjfrank enter_picld_wait(uid_t uid)
2277162Sjfrank {
2287162Sjfrank int rv;
2297162Sjfrank
2307162Sjfrank if (pthread_mutex_lock(&wait_req_mutex) != 0)
2317162Sjfrank return (PICL_FAILURE);
2327162Sjfrank if ((wait_count < MAX_CONCURRENT_WAITS) &&
2337162Sjfrank (check_user(uid) == PICL_SUCCESS)) {
2347162Sjfrank rv = PICL_SUCCESS;
2357162Sjfrank wait_count++;
2367162Sjfrank } else {
2377162Sjfrank rv = PICL_FAILURE;
2387162Sjfrank }
2397162Sjfrank (void) pthread_mutex_unlock(&wait_req_mutex);
2407162Sjfrank return (rv);
2417162Sjfrank }
2427162Sjfrank
2437162Sjfrank static void
exit_picld_wait(uid_t uid)2447162Sjfrank exit_picld_wait(uid_t uid)
2457162Sjfrank {
2467162Sjfrank (void) pthread_mutex_lock(&wait_req_mutex);
2477162Sjfrank done_user(uid);
2487162Sjfrank wait_count--;
2497162Sjfrank (void) pthread_mutex_unlock(&wait_req_mutex);
2507162Sjfrank }
2517162Sjfrank
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate * picld_wait is called when a picl_wait request is received
2540Sstevel@tonic-gate */
2550Sstevel@tonic-gate static void
picld_wait(picl_service_t * in)2560Sstevel@tonic-gate picld_wait(picl_service_t *in)
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate picl_retwait_t ret;
2590Sstevel@tonic-gate int err;
2607162Sjfrank ucred_t *puc = NULL;
2617162Sjfrank uid_t uid;
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate ret.cnum = in->req_wait.cnum;
2647162Sjfrank if (door_ucred(&puc) != 0)
2657162Sjfrank ret.retcode = PICL_FAILURE;
2667162Sjfrank else {
2677162Sjfrank uid = ucred_geteuid(puc);
2687162Sjfrank if (enter_picld_wait(uid) == PICL_FAILURE)
2697162Sjfrank ret.retcode = PICL_FAILURE;
2707162Sjfrank else {
2717162Sjfrank err = xptree_refresh_notify(in->req_wait.secs);
2727162Sjfrank ret.retcode = err;
2737162Sjfrank exit_picld_wait(uid);
2747162Sjfrank }
2757162Sjfrank ucred_free(puc);
2767162Sjfrank }
2770Sstevel@tonic-gate (void) rw_unlock(&init_lk);
2780Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retwait_t), NULL, 0);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate /*
2820Sstevel@tonic-gate * This function returns the handle of the root node of the PICL tree
2830Sstevel@tonic-gate */
2840Sstevel@tonic-gate static void
picld_getroot(picl_service_t * in)2850Sstevel@tonic-gate picld_getroot(picl_service_t *in)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate picl_retroot_t ret;
2880Sstevel@tonic-gate int err;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate ret.cnum = PICL_CNUM_GETROOT;
2910Sstevel@tonic-gate err = ptree_get_root(&ret.rnode);
2920Sstevel@tonic-gate if (err != PICL_SUCCESS)
2930Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
2940Sstevel@tonic-gate cvt_ptree2picl(&ret.rnode);
2950Sstevel@tonic-gate (void) rw_unlock(&init_lk);
2960Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retroot_t), NULL, 0);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate * This function returns the value of the PICL property
3010Sstevel@tonic-gate */
3020Sstevel@tonic-gate static void
picld_get_attrval(picl_service_t * in)3030Sstevel@tonic-gate picld_get_attrval(picl_service_t *in)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate picl_retattrval_t *ret;
3060Sstevel@tonic-gate int err;
3070Sstevel@tonic-gate size_t vbufsize;
3080Sstevel@tonic-gate size_t len;
3090Sstevel@tonic-gate door_cred_t cred;
3100Sstevel@tonic-gate picl_prophdl_t ptreeh;
3110Sstevel@tonic-gate ptree_propinfo_t pinfo;
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate if (door_cred(&cred) < 0)
3140Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_FAILURE);
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate err = cvt_picl2ptree(in->req_attrval.attr, &ptreeh);
3170Sstevel@tonic-gate if (err != PICL_SUCCESS)
3180Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate err = ptree_get_propinfo(ptreeh, &pinfo);
3210Sstevel@tonic-gate if (err != PICL_SUCCESS)
3220Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate if (!(pinfo.piclinfo.accessmode & PICL_READ))
3250Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_NOTREADABLE);
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate vbufsize = pinfo.piclinfo.size;
3280Sstevel@tonic-gate vbufsize = MIN((size_t)in->req_attrval.bufsize, vbufsize);
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate len = sizeof (picl_retattrval_t) + vbufsize;
3310Sstevel@tonic-gate ret = alloca(len);
3320Sstevel@tonic-gate if (ret == NULL)
3330Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_FAILURE);
3340Sstevel@tonic-gate ret->cnum = PICL_CNUM_GETATTRVAL;
3350Sstevel@tonic-gate ret->attr = in->req_attrval.attr;
3360Sstevel@tonic-gate ret->nbytes = (uint32_t)vbufsize;
3370Sstevel@tonic-gate err = xptree_get_propval_with_cred(ptreeh, ret->ret_buf, vbufsize,
3380Sstevel@tonic-gate cred);
3390Sstevel@tonic-gate if (err != PICL_SUCCESS)
3400Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate /*
3430Sstevel@tonic-gate * adjust returned bytes for charstrings
3440Sstevel@tonic-gate */
3450Sstevel@tonic-gate if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
3460Sstevel@tonic-gate ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate /*
3490Sstevel@tonic-gate * convert handle values to picl handles
3500Sstevel@tonic-gate */
3510Sstevel@tonic-gate if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
3520Sstevel@tonic-gate (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
3530Sstevel@tonic-gate cvt_ptree2picl(&ret->ret_nodeh);
3540Sstevel@tonic-gate (void) rw_unlock(&init_lk);
3550Sstevel@tonic-gate (void) door_return((char *)ret, sizeof (picl_retattrval_t) +
3560Sstevel@tonic-gate (size_t)ret->nbytes, NULL, 0);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate /*
3600Sstevel@tonic-gate * This function returns the value of the PICL property specified by
3610Sstevel@tonic-gate * its name.
3620Sstevel@tonic-gate */
3630Sstevel@tonic-gate static void
picld_get_attrval_by_name(picl_service_t * in)3640Sstevel@tonic-gate picld_get_attrval_by_name(picl_service_t *in)
3650Sstevel@tonic-gate {
3660Sstevel@tonic-gate picl_retattrvalbyname_t *ret;
3670Sstevel@tonic-gate int err;
3680Sstevel@tonic-gate size_t vbufsize;
3690Sstevel@tonic-gate size_t len;
3700Sstevel@tonic-gate door_cred_t cred;
3710Sstevel@tonic-gate picl_nodehdl_t ptreeh;
3720Sstevel@tonic-gate ptree_propinfo_t pinfo;
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate if (door_cred(&cred) < 0)
3750Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_FAILURE);
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate err = cvt_picl2ptree(in->req_attrvalbyname.nodeh, &ptreeh);
3780Sstevel@tonic-gate if (err != PICL_SUCCESS)
3790Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate err = xptree_get_propinfo_by_name(ptreeh,
3820Sstevel@tonic-gate in->req_attrvalbyname.propname, &pinfo);
3830Sstevel@tonic-gate if (err != PICL_SUCCESS)
3840Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate if (!(pinfo.piclinfo.accessmode & PICL_READ))
3870Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_NOTREADABLE);
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate * allocate the minimum of piclinfo.size and input bufsize
3910Sstevel@tonic-gate */
3920Sstevel@tonic-gate vbufsize = pinfo.piclinfo.size;
3930Sstevel@tonic-gate vbufsize = MIN((size_t)in->req_attrvalbyname.bufsize, vbufsize);
3940Sstevel@tonic-gate len = sizeof (picl_retattrvalbyname_t) + vbufsize;
3950Sstevel@tonic-gate ret = alloca(len);
3960Sstevel@tonic-gate if (ret == NULL)
3970Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_FAILURE);
3980Sstevel@tonic-gate ret->cnum = PICL_CNUM_GETATTRVALBYNAME;
3990Sstevel@tonic-gate ret->nodeh = in->req_attrvalbyname.nodeh;
4000Sstevel@tonic-gate (void) strcpy(ret->propname, in->req_attrvalbyname.propname);
4010Sstevel@tonic-gate ret->nbytes = (uint32_t)vbufsize;
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate err = xptree_get_propval_by_name_with_cred(ptreeh,
4040Sstevel@tonic-gate in->req_attrvalbyname.propname, ret->ret_buf, vbufsize,
4050Sstevel@tonic-gate cred);
4060Sstevel@tonic-gate if (err != PICL_SUCCESS)
4070Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
4080Sstevel@tonic-gate /*
4090Sstevel@tonic-gate * adjust returned value size for charstrings
4100Sstevel@tonic-gate */
4110Sstevel@tonic-gate if (pinfo.piclinfo.type == PICL_PTYPE_CHARSTRING)
4120Sstevel@tonic-gate ret->nbytes = (uint32_t)strlen(ret->ret_buf) + 1;
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate if ((pinfo.piclinfo.type == PICL_PTYPE_TABLE) ||
4150Sstevel@tonic-gate (pinfo.piclinfo.type == PICL_PTYPE_REFERENCE))
4160Sstevel@tonic-gate cvt_ptree2picl(&ret->ret_nodeh);
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate (void) rw_unlock(&init_lk);
4190Sstevel@tonic-gate (void) door_return((char *)ret, sizeof (picl_retattrvalbyname_t) +
4200Sstevel@tonic-gate (size_t)ret->nbytes, NULL, 0);
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate /*
4240Sstevel@tonic-gate * This function sets a property value
4250Sstevel@tonic-gate */
4260Sstevel@tonic-gate static void
picld_set_attrval(picl_service_t * in)4270Sstevel@tonic-gate picld_set_attrval(picl_service_t *in)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate picl_retsetattrval_t ret;
4300Sstevel@tonic-gate int err;
4310Sstevel@tonic-gate door_cred_t cred;
4320Sstevel@tonic-gate picl_prophdl_t ptreeh;
4330Sstevel@tonic-gate ptree_propinfo_t pinfo;
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate if (door_cred(&cred) < 0)
4360Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_FAILURE);
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate err = cvt_picl2ptree(in->req_setattrval.attr, &ptreeh);
4390Sstevel@tonic-gate if (err != PICL_SUCCESS)
4400Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate err = ptree_get_propinfo(ptreeh, &pinfo);
4430Sstevel@tonic-gate if (err != PICL_SUCCESS)
4440Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
4470Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
4480Sstevel@tonic-gate /*
4490Sstevel@tonic-gate * For non-volatile prop, only super user can set its value.
4500Sstevel@tonic-gate */
4510Sstevel@tonic-gate if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
4520Sstevel@tonic-gate (cred.dc_euid != SUPER_USER))
4530Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_PERMDENIED);
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate ret.cnum = PICL_CNUM_SETATTRVAL;
4560Sstevel@tonic-gate ret.attr = in->req_setattrval.attr;
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate err = xptree_update_propval_with_cred(ptreeh, in->req_setattrval.valbuf,
4590Sstevel@tonic-gate (size_t)in->req_setattrval.bufsize, cred);
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate if (err != PICL_SUCCESS)
4620Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate (void) rw_unlock(&init_lk);
4650Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retsetattrval_t), NULL,
4660Sstevel@tonic-gate 0);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate /*
4700Sstevel@tonic-gate * This function sets the value of a property specified by its name.
4710Sstevel@tonic-gate */
4720Sstevel@tonic-gate static void
picld_set_attrval_by_name(picl_service_t * in)4730Sstevel@tonic-gate picld_set_attrval_by_name(picl_service_t *in)
4740Sstevel@tonic-gate {
4750Sstevel@tonic-gate picl_retsetattrvalbyname_t ret;
4760Sstevel@tonic-gate int err;
4770Sstevel@tonic-gate door_cred_t cred;
4780Sstevel@tonic-gate picl_prophdl_t ptreeh;
4790Sstevel@tonic-gate ptree_propinfo_t pinfo;
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate if (door_cred(&cred) < 0)
4820Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_FAILURE);
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate err = cvt_picl2ptree(in->req_setattrvalbyname.nodeh, &ptreeh);
4850Sstevel@tonic-gate if (err != PICL_SUCCESS)
4860Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate err = xptree_get_propinfo_by_name(ptreeh,
4890Sstevel@tonic-gate in->req_setattrvalbyname.propname, &pinfo);
4900Sstevel@tonic-gate if (err != PICL_SUCCESS)
4910Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate if (!(pinfo.piclinfo.accessmode & PICL_WRITE))
4940Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_NOTWRITABLE);
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /*
4970Sstevel@tonic-gate * For non-volatile prop, only super user can set its value.
4980Sstevel@tonic-gate */
4990Sstevel@tonic-gate if (!(pinfo.piclinfo.accessmode & PICL_VOLATILE) &&
5000Sstevel@tonic-gate (cred.dc_euid != SUPER_USER))
5010Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_PERMDENIED);
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate ret.cnum = PICL_CNUM_SETATTRVALBYNAME;
5040Sstevel@tonic-gate ret.nodeh = in->req_setattrvalbyname.nodeh;
5050Sstevel@tonic-gate (void) strcpy(ret.propname, in->req_setattrvalbyname.propname);
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate err = xptree_update_propval_by_name_with_cred(ptreeh,
5086325Sjfrank in->req_setattrvalbyname.propname,
5096325Sjfrank in->req_setattrvalbyname.valbuf,
5106325Sjfrank (size_t)in->req_setattrvalbyname.bufsize,
5116325Sjfrank cred);
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate if (err != PICL_SUCCESS)
5140Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate (void) rw_unlock(&init_lk);
5170Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retsetattrvalbyname_t),
5180Sstevel@tonic-gate NULL, 0);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate * This function returns the property information
5230Sstevel@tonic-gate */
5240Sstevel@tonic-gate static void
picld_get_attrinfo(picl_service_t * in)5250Sstevel@tonic-gate picld_get_attrinfo(picl_service_t *in)
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate picl_retattrinfo_t ret;
5280Sstevel@tonic-gate int err;
5290Sstevel@tonic-gate ptree_propinfo_t pinfo;
5300Sstevel@tonic-gate picl_prophdl_t ptreeh;
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate err = cvt_picl2ptree(in->req_attrinfo.attr, &ptreeh);
5330Sstevel@tonic-gate if (err != PICL_SUCCESS)
5340Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate ret.cnum = PICL_CNUM_GETATTRINFO;
5370Sstevel@tonic-gate ret.attr = in->req_attrinfo.attr;
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate err = ptree_get_propinfo(ptreeh, &pinfo);
5400Sstevel@tonic-gate if (err != PICL_SUCCESS)
5410Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate ret.type = pinfo.piclinfo.type;
5440Sstevel@tonic-gate ret.accessmode = pinfo.piclinfo.accessmode;
5450Sstevel@tonic-gate ret.size = (uint32_t)pinfo.piclinfo.size;
5460Sstevel@tonic-gate (void) strcpy(ret.name, pinfo.piclinfo.name);
5470Sstevel@tonic-gate (void) rw_unlock(&init_lk);
5480Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retattrinfo_t), NULL, 0);
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate /*
5520Sstevel@tonic-gate * This function returns the node's first property handle
5530Sstevel@tonic-gate */
5540Sstevel@tonic-gate static void
picld_get_first_attr(picl_service_t * in)5550Sstevel@tonic-gate picld_get_first_attr(picl_service_t *in)
5560Sstevel@tonic-gate {
5570Sstevel@tonic-gate picl_retfirstattr_t ret;
5580Sstevel@tonic-gate int err;
5590Sstevel@tonic-gate picl_prophdl_t ptreeh;
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate err = cvt_picl2ptree(in->req_firstattr.nodeh, &ptreeh);
5620Sstevel@tonic-gate if (err != PICL_SUCCESS)
5630Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate ret.cnum = PICL_CNUM_GETFIRSTATTR;
5660Sstevel@tonic-gate ret.nodeh = in->req_firstattr.nodeh;
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate err = ptree_get_first_prop(ptreeh, &ret.attr);
5690Sstevel@tonic-gate if (err != PICL_SUCCESS)
5700Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
5710Sstevel@tonic-gate cvt_ptree2picl(&ret.attr);
5720Sstevel@tonic-gate (void) rw_unlock(&init_lk);
5730Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retfirstattr_t), NULL, 0);
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate /*
5770Sstevel@tonic-gate * This function returns the next property handle in list
5780Sstevel@tonic-gate */
5790Sstevel@tonic-gate static void
picld_get_next_attr(picl_service_t * in)5800Sstevel@tonic-gate picld_get_next_attr(picl_service_t *in)
5810Sstevel@tonic-gate {
5820Sstevel@tonic-gate picl_retnextattr_t ret;
5830Sstevel@tonic-gate int err;
5840Sstevel@tonic-gate picl_prophdl_t ptreeh;
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate err = cvt_picl2ptree(in->req_nextattr.attr, &ptreeh);
5870Sstevel@tonic-gate if (err != PICL_SUCCESS)
5880Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate ret.cnum = PICL_CNUM_GETNEXTATTR;
5910Sstevel@tonic-gate ret.attr = in->req_nextattr.attr;
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate err = ptree_get_next_prop(ptreeh, &ret.nextattr);
5940Sstevel@tonic-gate if (err != PICL_SUCCESS)
5950Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate cvt_ptree2picl(&ret.nextattr);
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate (void) rw_unlock(&init_lk);
6000Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retnextattr_t), NULL, 0);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate /*
6040Sstevel@tonic-gate * This function returns the handle of a property specified by its name
6050Sstevel@tonic-gate */
6060Sstevel@tonic-gate static void
picld_get_attr_by_name(picl_service_t * in)6070Sstevel@tonic-gate picld_get_attr_by_name(picl_service_t *in)
6080Sstevel@tonic-gate {
6090Sstevel@tonic-gate picl_retattrbyname_t ret;
6100Sstevel@tonic-gate int err;
6110Sstevel@tonic-gate picl_prophdl_t ptreeh;
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate err = cvt_picl2ptree(in->req_attrbyname.nodeh, &ptreeh);
6140Sstevel@tonic-gate if (err != PICL_SUCCESS)
6150Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate ret.cnum = PICL_CNUM_GETATTRBYNAME;
6180Sstevel@tonic-gate ret.nodeh = in->req_attrbyname.nodeh;
6190Sstevel@tonic-gate (void) strcpy(ret.propname, in->req_attrbyname.propname);
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate err = ptree_get_prop_by_name(ptreeh, ret.propname, &ret.attr);
6220Sstevel@tonic-gate if (err != PICL_SUCCESS)
6230Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate cvt_ptree2picl(&ret.attr);
6260Sstevel@tonic-gate (void) rw_unlock(&init_lk);
6270Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retattrbyname_t), NULL,
6280Sstevel@tonic-gate 0);
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate /*
6320Sstevel@tonic-gate * This function gets the next property on the same row in the table
6330Sstevel@tonic-gate */
6340Sstevel@tonic-gate static void
picld_get_attr_by_row(picl_service_t * in)6350Sstevel@tonic-gate picld_get_attr_by_row(picl_service_t *in)
6360Sstevel@tonic-gate {
6370Sstevel@tonic-gate picl_retattrbyrow_t ret;
6380Sstevel@tonic-gate int err;
6390Sstevel@tonic-gate picl_prophdl_t ptreeh;
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate err = cvt_picl2ptree(in->req_attrbyrow.attr, &ptreeh);
6420Sstevel@tonic-gate if (err != PICL_SUCCESS)
6430Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate ret.cnum = PICL_CNUM_GETATTRBYROW;
6460Sstevel@tonic-gate ret.attr = in->req_attrbyrow.attr;
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate err = ptree_get_next_by_row(ptreeh, &ret.rowattr);
6490Sstevel@tonic-gate if (err != PICL_SUCCESS)
6500Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
6510Sstevel@tonic-gate cvt_ptree2picl(&ret.rowattr);
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate (void) rw_unlock(&init_lk);
6540Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retattrbyrow_t), NULL, 0);
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate /*
6580Sstevel@tonic-gate * This function returns the handle of the next property in the same column
6590Sstevel@tonic-gate * of the table.
6600Sstevel@tonic-gate */
6610Sstevel@tonic-gate static void
picld_get_attr_by_col(picl_service_t * in)6620Sstevel@tonic-gate picld_get_attr_by_col(picl_service_t *in)
6630Sstevel@tonic-gate {
6640Sstevel@tonic-gate picl_retattrbycol_t ret;
6650Sstevel@tonic-gate int err;
6660Sstevel@tonic-gate picl_prophdl_t ptreeh;
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate err = cvt_picl2ptree(in->req_attrbycol.attr, &ptreeh);
6690Sstevel@tonic-gate if (err != PICL_SUCCESS)
6700Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate ret.cnum = PICL_CNUM_GETATTRBYCOL;
6730Sstevel@tonic-gate ret.attr = in->req_attrbycol.attr;
6740Sstevel@tonic-gate
6750Sstevel@tonic-gate err = ptree_get_next_by_col(ptreeh, &ret.colattr);
6760Sstevel@tonic-gate if (err != PICL_SUCCESS)
6770Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate cvt_ptree2picl(&ret.colattr);
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate (void) rw_unlock(&init_lk);
6820Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (picl_retattrbycol_t), NULL, 0);
6830Sstevel@tonic-gate }
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate /*
6860Sstevel@tonic-gate * This function finds the node in the PICLTREE that matches the given
6870Sstevel@tonic-gate * criteria and returns its handle.
6880Sstevel@tonic-gate */
6890Sstevel@tonic-gate static void
picld_find_node(picl_service_t * in)6900Sstevel@tonic-gate picld_find_node(picl_service_t *in)
6910Sstevel@tonic-gate {
6920Sstevel@tonic-gate picl_retfindnode_t ret;
6930Sstevel@tonic-gate int err;
6940Sstevel@tonic-gate picl_nodehdl_t ptreeh;
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate err = cvt_picl2ptree(in->req_findnode.nodeh, &ptreeh);
6970Sstevel@tonic-gate if (err != PICL_SUCCESS)
6980Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate ret.cnum = PICL_CNUM_FINDNODE;
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate err = ptree_find_node(ptreeh, in->req_findnode.propname,
7030Sstevel@tonic-gate in->req_findnode.ptype, in->req_findnode.valbuf,
7040Sstevel@tonic-gate in->req_findnode.valsize, &ret.rnodeh);
7050Sstevel@tonic-gate if (err != PICL_SUCCESS)
7060Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate cvt_ptree2picl(&ret.rnodeh);
7090Sstevel@tonic-gate
7100Sstevel@tonic-gate (void) rw_unlock(&init_lk);
7110Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate /*
7150Sstevel@tonic-gate * This function finds the property/node that corresponds to the given path
7160Sstevel@tonic-gate * and returns its handle
7170Sstevel@tonic-gate */
7180Sstevel@tonic-gate static void
picld_get_node_by_path(picl_service_t * in)7190Sstevel@tonic-gate picld_get_node_by_path(picl_service_t *in)
7200Sstevel@tonic-gate {
7210Sstevel@tonic-gate picl_retnodebypath_t ret;
7220Sstevel@tonic-gate int err;
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate ret.cnum = PICL_CNUM_NODEBYPATH;
7250Sstevel@tonic-gate err = ptree_get_node_by_path(in->req_nodebypath.pathbuf, &ret.nodeh);
7260Sstevel@tonic-gate if (err != PICL_SUCCESS)
7270Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
7280Sstevel@tonic-gate cvt_ptree2picl(&ret.nodeh);
7290Sstevel@tonic-gate (void) rw_unlock(&init_lk);
7300Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate /*
7340Sstevel@tonic-gate * This function returns finds the frutree parent node for a given node
7350Sstevel@tonic-gate * and returns its handle
7360Sstevel@tonic-gate */
7370Sstevel@tonic-gate static void
picld_get_frutree_parent(picl_service_t * in)7380Sstevel@tonic-gate picld_get_frutree_parent(picl_service_t *in)
7390Sstevel@tonic-gate {
7400Sstevel@tonic-gate picl_retfruparent_t ret;
7410Sstevel@tonic-gate int err;
7420Sstevel@tonic-gate picl_nodehdl_t ptreeh;
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate err = cvt_picl2ptree(in->req_fruparent.devh, &ptreeh);
7450Sstevel@tonic-gate if (err != PICL_SUCCESS)
7460Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate ret.cnum = PICL_CNUM_FRUTREEPARENT;
7490Sstevel@tonic-gate
7500Sstevel@tonic-gate err = ptree_get_frutree_parent(ptreeh, &ret.fruh);
7510Sstevel@tonic-gate if (err != PICL_SUCCESS)
7520Sstevel@tonic-gate picld_return_error(in->in.cnum, err);
7530Sstevel@tonic-gate cvt_ptree2picl(&ret.fruh);
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate (void) rw_unlock(&init_lk);
7560Sstevel@tonic-gate (void) door_return((char *)&ret, sizeof (ret), NULL, 0);
7570Sstevel@tonic-gate }
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate /*
7600Sstevel@tonic-gate * This function is called when an unknown client request is received.
7610Sstevel@tonic-gate */
7620Sstevel@tonic-gate static void
picld_unknown_service(picl_service_t * in)7630Sstevel@tonic-gate picld_unknown_service(picl_service_t *in)
7640Sstevel@tonic-gate {
7650Sstevel@tonic-gate picld_return_error(in->in.cnum, PICL_UNKNOWNSERVICE);
7660Sstevel@tonic-gate }
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate static void
check_denial_of_service(int cnum)7690Sstevel@tonic-gate check_denial_of_service(int cnum)
7700Sstevel@tonic-gate {
7710Sstevel@tonic-gate hrtime_t window;
7720Sstevel@tonic-gate hrtime_t current;
7730Sstevel@tonic-gate int dos_flag;
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate current = gethrtime();
7760Sstevel@tonic-gate dos_flag = 0;
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate if (pthread_mutex_lock(&dos_mutex) != 0)
7790Sstevel@tonic-gate picld_return_error(cnum, PICL_FAILURE);
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate ++service_requests;
7820Sstevel@tonic-gate window = current - orig_time;
7830Sstevel@tonic-gate if (window > MILLI_TO_NANO(sliding_interval_ms)) {
7840Sstevel@tonic-gate orig_time = current;
7850Sstevel@tonic-gate service_requests = 1;
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate if (service_requests > dos_req_limit)
7890Sstevel@tonic-gate dos_flag = 1;
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate if (pthread_mutex_unlock(&dos_mutex) != 0)
7920Sstevel@tonic-gate picld_return_error(cnum, PICL_FAILURE);
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate if (dos_flag)
7950Sstevel@tonic-gate (void) poll(NULL, 0, dos_ms);
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate /* ARGSUSED */
7990Sstevel@tonic-gate static void
picld_door_handler(void * cookie,char * argp,size_t asize,door_desc_t * dp,uint_t n_desc)8000Sstevel@tonic-gate picld_door_handler(void *cookie, char *argp, size_t asize,
8010Sstevel@tonic-gate door_desc_t *dp, uint_t n_desc)
8020Sstevel@tonic-gate {
8030Sstevel@tonic-gate picl_service_t *req;
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate /*LINTED*/
8060Sstevel@tonic-gate req = (picl_service_t *)argp;
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate if (req == NULL)
8090Sstevel@tonic-gate (void) door_return((char *)req, 0, NULL, 0);
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate check_denial_of_service(req->in.cnum);
8120Sstevel@tonic-gate
8130Sstevel@tonic-gate (void) rw_rdlock(&init_lk);
8140Sstevel@tonic-gate switch (req->in.cnum) { /* client call number */
8150Sstevel@tonic-gate case PICL_CNUM_INIT:
8160Sstevel@tonic-gate /*LINTED*/
8170Sstevel@tonic-gate picld_init((picl_service_t *)argp);
8180Sstevel@tonic-gate break;
8190Sstevel@tonic-gate case PICL_CNUM_FINI:
8200Sstevel@tonic-gate /*LINTED*/
8210Sstevel@tonic-gate picld_fini((picl_service_t *)argp);
8220Sstevel@tonic-gate break;
8230Sstevel@tonic-gate case PICL_CNUM_GETROOT:
8240Sstevel@tonic-gate /*LINTED*/
8250Sstevel@tonic-gate picld_getroot((picl_service_t *)argp);
8260Sstevel@tonic-gate break;
8270Sstevel@tonic-gate case PICL_CNUM_GETATTRVAL:
8280Sstevel@tonic-gate /*LINTED*/
8290Sstevel@tonic-gate picld_get_attrval((picl_service_t *)argp);
8300Sstevel@tonic-gate break;
8310Sstevel@tonic-gate case PICL_CNUM_GETATTRVALBYNAME:
8320Sstevel@tonic-gate /*LINTED*/
8330Sstevel@tonic-gate picld_get_attrval_by_name((picl_service_t *)argp);
8340Sstevel@tonic-gate break;
8350Sstevel@tonic-gate case PICL_CNUM_GETATTRINFO:
8360Sstevel@tonic-gate /*LINTED*/
8370Sstevel@tonic-gate picld_get_attrinfo((picl_service_t *)argp);
8380Sstevel@tonic-gate break;
8390Sstevel@tonic-gate case PICL_CNUM_GETFIRSTATTR:
8400Sstevel@tonic-gate /*LINTED*/
8410Sstevel@tonic-gate picld_get_first_attr((picl_service_t *)argp);
8420Sstevel@tonic-gate break;
8430Sstevel@tonic-gate case PICL_CNUM_GETNEXTATTR:
8440Sstevel@tonic-gate /*LINTED*/
8450Sstevel@tonic-gate picld_get_next_attr((picl_service_t *)argp);
8460Sstevel@tonic-gate break;
8470Sstevel@tonic-gate case PICL_CNUM_GETATTRBYNAME:
8480Sstevel@tonic-gate /*LINTED*/
8490Sstevel@tonic-gate picld_get_attr_by_name((picl_service_t *)argp);
8500Sstevel@tonic-gate break;
8510Sstevel@tonic-gate case PICL_CNUM_GETATTRBYROW:
8520Sstevel@tonic-gate /*LINTED*/
8530Sstevel@tonic-gate picld_get_attr_by_row((picl_service_t *)argp);
8540Sstevel@tonic-gate break;
8550Sstevel@tonic-gate case PICL_CNUM_GETATTRBYCOL:
8560Sstevel@tonic-gate /*LINTED*/
8570Sstevel@tonic-gate picld_get_attr_by_col((picl_service_t *)argp);
8580Sstevel@tonic-gate break;
8590Sstevel@tonic-gate case PICL_CNUM_SETATTRVAL:
8600Sstevel@tonic-gate /*LINTED*/
8610Sstevel@tonic-gate picld_set_attrval((picl_service_t *)argp);
8620Sstevel@tonic-gate break;
8630Sstevel@tonic-gate case PICL_CNUM_SETATTRVALBYNAME:
8640Sstevel@tonic-gate /*LINTED*/
8650Sstevel@tonic-gate picld_set_attrval_by_name((picl_service_t *)argp);
8660Sstevel@tonic-gate break;
8670Sstevel@tonic-gate case PICL_CNUM_PING:
8680Sstevel@tonic-gate /*LINTED*/
8690Sstevel@tonic-gate picld_ping((picl_service_t *)argp);
8700Sstevel@tonic-gate break;
8710Sstevel@tonic-gate case PICL_CNUM_WAIT:
8720Sstevel@tonic-gate /*LINTED*/
8730Sstevel@tonic-gate picld_wait((picl_service_t *)argp);
8740Sstevel@tonic-gate break;
8750Sstevel@tonic-gate case PICL_CNUM_FINDNODE:
8760Sstevel@tonic-gate /*LINTED*/
8770Sstevel@tonic-gate picld_find_node((picl_service_t *)argp);
8780Sstevel@tonic-gate break;
8790Sstevel@tonic-gate case PICL_CNUM_NODEBYPATH:
8800Sstevel@tonic-gate /*LINTED*/
8810Sstevel@tonic-gate picld_get_node_by_path((picl_service_t *)argp);
8820Sstevel@tonic-gate break;
8830Sstevel@tonic-gate case PICL_CNUM_FRUTREEPARENT:
8840Sstevel@tonic-gate /*LINTED*/
8850Sstevel@tonic-gate picld_get_frutree_parent((picl_service_t *)argp);
8860Sstevel@tonic-gate break;
8870Sstevel@tonic-gate default:
8880Sstevel@tonic-gate /*LINTED*/
8890Sstevel@tonic-gate picld_unknown_service((picl_service_t *)argp);
8900Sstevel@tonic-gate break;
8910Sstevel@tonic-gate };
8920Sstevel@tonic-gate /*NOTREACHED*/
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate /* ARGSUSED */
8960Sstevel@tonic-gate static void
hup_handler(int sig,siginfo_t * siginfo,void * sigctx)8970Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
8980Sstevel@tonic-gate {
8990Sstevel@tonic-gate doreinit = 1;
9000Sstevel@tonic-gate }
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate /*
9030Sstevel@tonic-gate * "ping" to see if a daemon is already running
9040Sstevel@tonic-gate */
9050Sstevel@tonic-gate static int
daemon_exists(void)9060Sstevel@tonic-gate daemon_exists(void)
9070Sstevel@tonic-gate {
9080Sstevel@tonic-gate door_arg_t darg;
9090Sstevel@tonic-gate picl_reqping_t req_ping;
9100Sstevel@tonic-gate picl_retping_t ret_ping;
9110Sstevel@tonic-gate int doorh;
9120Sstevel@tonic-gate door_info_t dinfo;
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate doorh = open(PICLD_DOOR, O_RDONLY);
9150Sstevel@tonic-gate if (doorh < 0)
9160Sstevel@tonic-gate return (0);
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate if (door_info(doorh, &dinfo) < 0) {
9190Sstevel@tonic-gate (void) close(doorh);
9200Sstevel@tonic-gate return (0);
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate if ((dinfo.di_attributes & DOOR_REVOKED) ||
9241016Sraf (dinfo.di_data != (uintptr_t)PICLD_DOOR_COOKIE)) {
9250Sstevel@tonic-gate (void) close(doorh);
9260Sstevel@tonic-gate return (0);
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate if (dinfo.di_target != getpid()) {
9300Sstevel@tonic-gate (void) close(doorh);
9310Sstevel@tonic-gate return (1);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate req_ping.cnum = PICL_CNUM_PING;
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate darg.data_ptr = (char *)&req_ping;
9370Sstevel@tonic-gate darg.data_size = sizeof (picl_reqping_t);
9380Sstevel@tonic-gate darg.desc_ptr = NULL;
9390Sstevel@tonic-gate darg.desc_num = 0;
9400Sstevel@tonic-gate darg.rbuf = (char *)&ret_ping;
9410Sstevel@tonic-gate darg.rsize = sizeof (picl_retping_t);
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate if (door_call(doorh, &darg) < 0) {
9440Sstevel@tonic-gate (void) close(doorh);
9450Sstevel@tonic-gate return (0);
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate (void) close(doorh);
9490Sstevel@tonic-gate return (1);
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate
9520Sstevel@tonic-gate /*
9537162Sjfrank * picld_create_server_thread - binds the running thread to the private
9547162Sjfrank * door pool, and sets the required cancellation state.
9557162Sjfrank */
9567162Sjfrank /* ARGSUSED */
9577162Sjfrank static void *
picld_create_server_thread(void * arg)9587162Sjfrank picld_create_server_thread(void *arg)
9597162Sjfrank {
9607162Sjfrank /*
9617162Sjfrank * wait for door descriptor to be initialized
9627162Sjfrank */
9637162Sjfrank (void) pthread_mutex_lock(&door_mutex);
9647162Sjfrank while (door_id == -1) {
9657162Sjfrank (void) pthread_cond_wait(&door_cv, &door_mutex);
9667162Sjfrank }
9677162Sjfrank (void) pthread_mutex_unlock(&door_mutex);
9687162Sjfrank
9697162Sjfrank /*
9707162Sjfrank * Bind this thread to the door's private thread pool
9717162Sjfrank */
9727162Sjfrank if (door_bind(door_id) < 0) {
9737162Sjfrank perror("door_bind");
9747162Sjfrank }
9757162Sjfrank
9767162Sjfrank /*
9777162Sjfrank * Disable thread cancellation mechanism
9787162Sjfrank */
9797162Sjfrank (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
9807162Sjfrank (void) door_return(NULL, 0, NULL, 0); /* wait for door invocation */
9817162Sjfrank return (NULL);
9827162Sjfrank }
9837162Sjfrank
9847162Sjfrank /*
9857162Sjfrank * picld_server_create_fn - creates threads for the private door pool
9867162Sjfrank *
9877162Sjfrank */
9887162Sjfrank /* ARGSUSED */
9897162Sjfrank static void
picld_server_create_fn(door_info_t * dip)9907162Sjfrank picld_server_create_fn(door_info_t *dip)
9917162Sjfrank {
9927162Sjfrank pthread_attr_t attr;
9937162Sjfrank
994*8775SMichael.Bergknoff@Sun.COM /*
995*8775SMichael.Bergknoff@Sun.COM * For the non-private pool do nothing. It's used for events which are
996*8775SMichael.Bergknoff@Sun.COM * single threaded anyway. The single thread servicing that pool is
997*8775SMichael.Bergknoff@Sun.COM * created when the event plugin creates its door. Note that the event
998*8775SMichael.Bergknoff@Sun.COM * plugin runs before setup_door instantiates picld_server_create_fn as
999*8775SMichael.Bergknoff@Sun.COM * the new create_proc so the door library default create_proc is used.
1000*8775SMichael.Bergknoff@Sun.COM */
1001*8775SMichael.Bergknoff@Sun.COM if (dip == NULL)
1002*8775SMichael.Bergknoff@Sun.COM return;
1003*8775SMichael.Bergknoff@Sun.COM
10047162Sjfrank (void) pthread_mutex_lock(&pool_mutex);
10057162Sjfrank if (pool_count < MAX_POOL_SIZE) {
10067162Sjfrank (void) pthread_attr_init(&attr);
10077162Sjfrank (void) pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
10087162Sjfrank (void) pthread_attr_setdetachstate(&attr,
10097162Sjfrank PTHREAD_CREATE_DETACHED);
10107162Sjfrank if (pthread_create(NULL, &attr, picld_create_server_thread,
10117162Sjfrank NULL)) {
10127162Sjfrank perror("pthread_create");
10137162Sjfrank } else {
10147162Sjfrank pool_count++;
10157162Sjfrank }
10167162Sjfrank }
10177162Sjfrank (void) pthread_mutex_unlock(&pool_mutex);
10187162Sjfrank }
10197162Sjfrank
10207162Sjfrank /*
10210Sstevel@tonic-gate * Create the picld door
10220Sstevel@tonic-gate */
10230Sstevel@tonic-gate static int
setup_door(void)10240Sstevel@tonic-gate setup_door(void)
10250Sstevel@tonic-gate {
10260Sstevel@tonic-gate struct stat stbuf;
10270Sstevel@tonic-gate
10287162Sjfrank (void) door_server_create(picld_server_create_fn);
10297162Sjfrank (void) pthread_mutex_lock(&door_mutex);
10300Sstevel@tonic-gate /*
10310Sstevel@tonic-gate * Create the door
10320Sstevel@tonic-gate */
10330Sstevel@tonic-gate door_id = door_create(picld_door_handler, PICLD_DOOR_COOKIE,
10347162Sjfrank DOOR_REFUSE_DESC | DOOR_NO_CANCEL | DOOR_PRIVATE);
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate if (door_id < 0) {
10377162Sjfrank (void) pthread_mutex_unlock(&door_mutex);
10380Sstevel@tonic-gate return (-1);
10397162Sjfrank } else {
10407162Sjfrank (void) pthread_cond_signal(&door_cv);
10417162Sjfrank (void) pthread_mutex_unlock(&door_mutex);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate if (stat(PICLD_DOOR, &stbuf) < 0) {
10450Sstevel@tonic-gate int newfd;
10466325Sjfrank mode_t old_mask;
10476325Sjfrank /* ensure that the door file is world-readable */
10486325Sjfrank old_mask = umask(0);
10496325Sjfrank newfd = creat(PICLD_DOOR, 0444);
10506325Sjfrank /* restore the file mode creation mask */
10516325Sjfrank (void) umask(old_mask);
10526325Sjfrank if (newfd < 0)
10530Sstevel@tonic-gate return (-1);
10540Sstevel@tonic-gate (void) close(newfd);
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate if (fattach(door_id, PICLD_DOOR) < 0) {
10580Sstevel@tonic-gate if ((errno != EBUSY) ||
10590Sstevel@tonic-gate (fdetach(PICLD_DOOR) < 0) ||
10600Sstevel@tonic-gate (fattach(door_id, PICLD_DOOR) < 0))
10610Sstevel@tonic-gate return (-1);
10620Sstevel@tonic-gate }
10630Sstevel@tonic-gate return (0);
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate /*
10670Sstevel@tonic-gate * Main function of picl daemon
10680Sstevel@tonic-gate */
10690Sstevel@tonic-gate int
main(int argc,char ** argv)10700Sstevel@tonic-gate main(int argc, char **argv)
10710Sstevel@tonic-gate {
10720Sstevel@tonic-gate struct sigaction act;
10730Sstevel@tonic-gate int c;
10740Sstevel@tonic-gate sigset_t ublk;
10750Sstevel@tonic-gate
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
10780Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate if (getuid() != 0) {
10810Sstevel@tonic-gate syslog(LOG_CRIT, MUST_BE_ROOT);
10820Sstevel@tonic-gate return (0);
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate (void) rwlock_init(&init_lk, USYNC_THREAD, NULL);
10860Sstevel@tonic-gate doreinit = 0;
10870Sstevel@tonic-gate logflag = 1;
10880Sstevel@tonic-gate dos_req_limit = DOS_PICL_REQUESTS_LIMIT;
10890Sstevel@tonic-gate sliding_interval_ms = SLIDING_INTERVAL_MILLISECONDS;
10900Sstevel@tonic-gate dos_ms = DOS_SLEEPTIME_MS;
10910Sstevel@tonic-gate verbose_level = 0;
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate /*
10940Sstevel@tonic-gate * parse arguments
10950Sstevel@tonic-gate */
10960Sstevel@tonic-gate while ((c = getopt(argc, argv, "is:t:l:r:v:d:")) != EOF) {
10970Sstevel@tonic-gate switch (c) {
10980Sstevel@tonic-gate case 'd':
10990Sstevel@tonic-gate dos_ms = strtol(optarg, (char **)NULL, 0);
11000Sstevel@tonic-gate break;
11010Sstevel@tonic-gate case 'i':
11020Sstevel@tonic-gate logflag = 0;
11030Sstevel@tonic-gate break;
11040Sstevel@tonic-gate case 's':
11050Sstevel@tonic-gate sliding_interval_ms = strtoll(optarg, (char **)NULL, 0);
11060Sstevel@tonic-gate break;
11070Sstevel@tonic-gate case 't':
11080Sstevel@tonic-gate dos_req_limit = strtol(optarg, (char **)NULL, 0);
11090Sstevel@tonic-gate break;
11100Sstevel@tonic-gate case 'v':
11110Sstevel@tonic-gate verbose_level = strtol(optarg, (char **)NULL, 0);
11120Sstevel@tonic-gate logflag = 0;
11130Sstevel@tonic-gate break;
11140Sstevel@tonic-gate default:
11150Sstevel@tonic-gate break;
11160Sstevel@tonic-gate }
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate
11190Sstevel@tonic-gate orig_time = gethrtime();
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate /*
11220Sstevel@tonic-gate * is there a daemon already running?
11230Sstevel@tonic-gate */
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate if (daemon_exists()) {
11260Sstevel@tonic-gate syslog(LOG_CRIT, DAEMON_RUNNING);
11270Sstevel@tonic-gate exit(1);
11280Sstevel@tonic-gate }
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate /*
11310Sstevel@tonic-gate * Mask off/block SIGALRM signal so that the environmental plug-in
11320Sstevel@tonic-gate * (piclenvd) can use it to simulate sleep() without being affected
11330Sstevel@tonic-gate * by time being set back. No other PICL plug-in should use SIGALRM
11340Sstevel@tonic-gate * or alarm() for now.
11350Sstevel@tonic-gate */
11360Sstevel@tonic-gate (void) sigemptyset(&ublk);
11370Sstevel@tonic-gate (void) sigaddset(&ublk, SIGALRM);
11380Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &ublk, NULL);
11390Sstevel@tonic-gate
11400Sstevel@tonic-gate /*
11410Sstevel@tonic-gate * Ignore SIGHUP until all the initialization is done.
11420Sstevel@tonic-gate */
11430Sstevel@tonic-gate act.sa_handler = SIG_IGN;
11440Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
11450Sstevel@tonic-gate act.sa_flags = 0;
11460Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1)
11470Sstevel@tonic-gate syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
11480Sstevel@tonic-gate strerror(errno));
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate if (logflag != 0) { /* daemonize */
11510Sstevel@tonic-gate pid_t pid;
11520Sstevel@tonic-gate
11530Sstevel@tonic-gate pid = fork();
11540Sstevel@tonic-gate if (pid < 0)
11550Sstevel@tonic-gate exit(1);
11560Sstevel@tonic-gate if (pid > 0)
11570Sstevel@tonic-gate /* parent */
11580Sstevel@tonic-gate exit(0);
11590Sstevel@tonic-gate
11600Sstevel@tonic-gate /* child */
11610Sstevel@tonic-gate if (chdir("/") == -1) {
11620Sstevel@tonic-gate syslog(LOG_CRIT, CD_ROOT_FAILED);
11630Sstevel@tonic-gate exit(1);
11640Sstevel@tonic-gate }
11650Sstevel@tonic-gate
11660Sstevel@tonic-gate (void) setsid();
1167*8775SMichael.Bergknoff@Sun.COM closefrom(0);
11680Sstevel@tonic-gate (void) open("/dev/null", O_RDWR, 0);
11690Sstevel@tonic-gate (void) dup2(STDIN_FILENO, STDOUT_FILENO);
11700Sstevel@tonic-gate (void) dup2(STDIN_FILENO, STDERR_FILENO);
11710Sstevel@tonic-gate openlog(PICLD, LOG_PID, LOG_DAEMON);
11720Sstevel@tonic-gate }
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate /*
11750Sstevel@tonic-gate * Initialize the PICL Tree
11760Sstevel@tonic-gate */
11770Sstevel@tonic-gate if (xptree_initialize(NULL) != PICL_SUCCESS) {
11780Sstevel@tonic-gate syslog(LOG_CRIT, INIT_FAILED);
11790Sstevel@tonic-gate exit(1);
11800Sstevel@tonic-gate }
11810Sstevel@tonic-gate
11820Sstevel@tonic-gate if (setup_door()) {
11830Sstevel@tonic-gate syslog(LOG_CRIT, DOOR_FAILED);
11840Sstevel@tonic-gate exit(1);
11850Sstevel@tonic-gate }
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate /*
11880Sstevel@tonic-gate * setup signal handlers for post-init
11890Sstevel@tonic-gate */
11900Sstevel@tonic-gate act.sa_sigaction = hup_handler;
11910Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
11920Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
11930Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1)
11940Sstevel@tonic-gate syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGHUP),
11950Sstevel@tonic-gate strerror(errno));
11960Sstevel@tonic-gate
11970Sstevel@tonic-gate /*
11980Sstevel@tonic-gate * wait for requests
11990Sstevel@tonic-gate */
12000Sstevel@tonic-gate for (;;) {
12010Sstevel@tonic-gate (void) pause();
12020Sstevel@tonic-gate if (doreinit) {
12030Sstevel@tonic-gate /*
12040Sstevel@tonic-gate * Block SIGHUP during reinitialization.
12050Sstevel@tonic-gate * Also mask off/block SIGALRM signal so that the
12060Sstevel@tonic-gate * environmental plug-in (piclenvd) can use it to
12070Sstevel@tonic-gate * simulate sleep() without being affected by time
12080Sstevel@tonic-gate * being set back. No ohter PICL plug-in should use
12090Sstevel@tonic-gate * SIGALRM or alarm() for now.
12100Sstevel@tonic-gate */
12110Sstevel@tonic-gate (void) sigemptyset(&ublk);
12120Sstevel@tonic-gate (void) sigaddset(&ublk, SIGHUP);
12130Sstevel@tonic-gate (void) sigaddset(&ublk, SIGALRM);
12140Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &ublk, NULL);
12150Sstevel@tonic-gate (void) sigdelset(&ublk, SIGALRM);
12160Sstevel@tonic-gate doreinit = 0;
12170Sstevel@tonic-gate (void) rw_wrlock(&init_lk);
12180Sstevel@tonic-gate xptree_destroy();
12190Sstevel@tonic-gate (void) xptree_reinitialize();
12200Sstevel@tonic-gate (void) rw_unlock(&init_lk);
12210Sstevel@tonic-gate (void) sigprocmask(SIG_UNBLOCK, &ublk, NULL);
12220Sstevel@tonic-gate }
12230Sstevel@tonic-gate }
12240Sstevel@tonic-gate }
1225