xref: /onnv-gate/usr/src/lib/libcontract/common/libcontract.c (revision 6073:47f6aa7a8077)
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
54845Svikram  * Common Development and Distribution License (the "License").
64845Svikram  * 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  */
210Sstevel@tonic-gate /*
22*6073Sacruz  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/ctfs.h>
290Sstevel@tonic-gate #include <sys/contract.h>
30*6073Sacruz #include <string.h>
310Sstevel@tonic-gate #include <libnvpair.h>
320Sstevel@tonic-gate #include <assert.h>
330Sstevel@tonic-gate #include <unistd.h>
340Sstevel@tonic-gate #include <errno.h>
350Sstevel@tonic-gate #include <libcontract.h>
360Sstevel@tonic-gate #include "libcontract_impl.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * Common template routines
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate 
420Sstevel@tonic-gate int
ct_tmpl_activate(int fd)430Sstevel@tonic-gate ct_tmpl_activate(int fd)
440Sstevel@tonic-gate {
450Sstevel@tonic-gate 	if (ioctl(fd, CT_TACTIVATE) == -1)
460Sstevel@tonic-gate 		return (errno);
470Sstevel@tonic-gate 	return (0);
480Sstevel@tonic-gate }
490Sstevel@tonic-gate 
500Sstevel@tonic-gate int
ct_tmpl_clear(int fd)510Sstevel@tonic-gate ct_tmpl_clear(int fd)
520Sstevel@tonic-gate {
530Sstevel@tonic-gate 	if (ioctl(fd, CT_TCLEAR) == -1)
540Sstevel@tonic-gate 		return (errno);
550Sstevel@tonic-gate 	return (0);
560Sstevel@tonic-gate }
570Sstevel@tonic-gate 
580Sstevel@tonic-gate int
ct_tmpl_create(int fd,ctid_t * ctidp)590Sstevel@tonic-gate ct_tmpl_create(int fd, ctid_t *ctidp)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	ctid_t ctid = ioctl(fd, CT_TCREATE);
620Sstevel@tonic-gate 	if (ctid == -1)
630Sstevel@tonic-gate 		return (errno);
640Sstevel@tonic-gate 	*ctidp = ctid;
650Sstevel@tonic-gate 	return (0);
660Sstevel@tonic-gate }
670Sstevel@tonic-gate 
680Sstevel@tonic-gate int
ct_tmpl_set_internal(int fd,uint_t id,uintptr_t value)694845Svikram ct_tmpl_set_internal(int fd, uint_t id, uintptr_t value)
700Sstevel@tonic-gate {
710Sstevel@tonic-gate 	ct_param_t param;
72*6073Sacruz 	uint64_t param_value = value;
73*6073Sacruz 
740Sstevel@tonic-gate 	param.ctpm_id = id;
75*6073Sacruz 	param.ctpm_size = sizeof (uint64_t);
76*6073Sacruz 	param.ctpm_value = &param_value;
770Sstevel@tonic-gate 	if (ioctl(fd, CT_TSET, &param) == -1)
780Sstevel@tonic-gate 		return (errno);
79*6073Sacruz 
80*6073Sacruz 	return (0);
81*6073Sacruz }
82*6073Sacruz 
83*6073Sacruz int
ct_tmpl_set_internal_string(int fd,uint_t id,const char * value)84*6073Sacruz ct_tmpl_set_internal_string(int fd, uint_t id, const char *value)
85*6073Sacruz {
86*6073Sacruz 	ct_param_t param;
87*6073Sacruz 
88*6073Sacruz 	if (value == NULL)
89*6073Sacruz 		return (EINVAL);
90*6073Sacruz 	param.ctpm_id = id;
91*6073Sacruz 	param.ctpm_size = strlen(value) + 1;
92*6073Sacruz 	param.ctpm_value = (void *)value;
93*6073Sacruz 	if (ioctl(fd, CT_TSET, &param) == -1)
94*6073Sacruz 		return (errno);
95*6073Sacruz 
960Sstevel@tonic-gate 	return (0);
970Sstevel@tonic-gate }
980Sstevel@tonic-gate 
990Sstevel@tonic-gate int
ct_tmpl_set_critical(int fd,uint_t events)1000Sstevel@tonic-gate ct_tmpl_set_critical(int fd, uint_t events)
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	return (ct_tmpl_set_internal(fd, CTP_EV_CRITICAL, events));
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate int
ct_tmpl_set_informative(int fd,uint_t events)1060Sstevel@tonic-gate ct_tmpl_set_informative(int fd, uint_t events)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	return (ct_tmpl_set_internal(fd, CTP_EV_INFO, events));
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate int
ct_tmpl_set_cookie(int fd,uint64_t cookie)1120Sstevel@tonic-gate ct_tmpl_set_cookie(int fd, uint64_t cookie)
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate 	ct_param_t param;
115*6073Sacruz 	uint64_t param_value = cookie;
116*6073Sacruz 
1170Sstevel@tonic-gate 	param.ctpm_id = CTP_COOKIE;
118*6073Sacruz 	param.ctpm_size = sizeof (uint64_t);
119*6073Sacruz 	param.ctpm_value = &param_value;
1200Sstevel@tonic-gate 	if (ioctl(fd, CT_TSET, &param) == -1)
1210Sstevel@tonic-gate 		return (errno);
1220Sstevel@tonic-gate 	return (0);
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate int
ct_tmpl_get_internal(int fd,uint_t id,uint_t * value)1260Sstevel@tonic-gate ct_tmpl_get_internal(int fd, uint_t id, uint_t *value)
1270Sstevel@tonic-gate {
1280Sstevel@tonic-gate 	ct_param_t param;
129*6073Sacruz 	uint64_t param_value;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	param.ctpm_id = id;
132*6073Sacruz 	param.ctpm_size = sizeof (uint64_t);
133*6073Sacruz 	param.ctpm_value = &param_value;
1340Sstevel@tonic-gate 	if (ioctl(fd, CT_TGET, &param) == -1)
1350Sstevel@tonic-gate 		return (errno);
136*6073Sacruz 	*value = param_value;
1370Sstevel@tonic-gate 	return (0);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate int
ct_tmpl_get_internal_string(int fd,uint32_t id,char * buf,size_t size)141*6073Sacruz ct_tmpl_get_internal_string(int fd, uint32_t id, char *buf, size_t size)
1424845Svikram {
1434845Svikram 	ct_param_t param;
1444845Svikram 
1454845Svikram 	param.ctpm_id = id;
146*6073Sacruz 	param.ctpm_size = size;
147*6073Sacruz 	param.ctpm_value = buf;
1484845Svikram 	if (ioctl(fd, CT_TGET, &param) == -1)
149*6073Sacruz 		return (-1);
150*6073Sacruz 	return (param.ctpm_size);
1514845Svikram }
1524845Svikram 
1534845Svikram int
ct_tmpl_get_critical(int fd,uint_t * events)1540Sstevel@tonic-gate ct_tmpl_get_critical(int fd, uint_t *events)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 	return (ct_tmpl_get_internal(fd, CTP_EV_CRITICAL, events));
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate int
ct_tmpl_get_informative(int fd,uint_t * events)1600Sstevel@tonic-gate ct_tmpl_get_informative(int fd, uint_t *events)
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate 	return (ct_tmpl_get_internal(fd, CTP_EV_INFO, events));
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate int
ct_tmpl_get_cookie(int fd,uint64_t * cookie)1660Sstevel@tonic-gate ct_tmpl_get_cookie(int fd, uint64_t *cookie)
1670Sstevel@tonic-gate {
1680Sstevel@tonic-gate 	ct_param_t param;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	param.ctpm_id = CTP_COOKIE;
171*6073Sacruz 	param.ctpm_size = sizeof (uint64_t);
172*6073Sacruz 	param.ctpm_value = cookie;
1730Sstevel@tonic-gate 	if (ioctl(fd, CT_TGET, &param) == -1)
1740Sstevel@tonic-gate 		return (errno);
1750Sstevel@tonic-gate 	return (0);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate  * Common ctl routines
1800Sstevel@tonic-gate  */
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate int
ct_ctl_adopt(int fd)1830Sstevel@tonic-gate ct_ctl_adopt(int fd)
1840Sstevel@tonic-gate {
1850Sstevel@tonic-gate 	if (ioctl(fd, CT_CADOPT) == -1)
1860Sstevel@tonic-gate 		return (errno);
1870Sstevel@tonic-gate 	return (0);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate int
ct_ctl_abandon(int fd)1910Sstevel@tonic-gate ct_ctl_abandon(int fd)
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate 	if (ioctl(fd, CT_CABANDON) == -1)
1940Sstevel@tonic-gate 		return (errno);
1950Sstevel@tonic-gate 	return (0);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate /*ARGSUSED*/
1990Sstevel@tonic-gate int
ct_ctl_newct(int cfd,ctevid_t evid,int tfd)2000Sstevel@tonic-gate ct_ctl_newct(int cfd, ctevid_t evid, int tfd)
2010Sstevel@tonic-gate {
2020Sstevel@tonic-gate 	if (ioctl(cfd, CT_CNEWCT, tfd) == -1)
2030Sstevel@tonic-gate 		return (errno);
2040Sstevel@tonic-gate 	return (0);
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate int
ct_ctl_ack(int fd,ctevid_t event)2080Sstevel@tonic-gate ct_ctl_ack(int fd, ctevid_t event)
2090Sstevel@tonic-gate {
2100Sstevel@tonic-gate 	if (ioctl(fd, CT_CACK, &event) == -1)
2110Sstevel@tonic-gate 		return (errno);
2120Sstevel@tonic-gate 	return (0);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate int
ct_ctl_nack(int fd,ctevid_t event)2164845Svikram ct_ctl_nack(int fd, ctevid_t event)
2174845Svikram {
2184845Svikram 	if (ioctl(fd, CT_CNACK, &event) == -1)
2194845Svikram 		return (errno);
2204845Svikram 	return (0);
2214845Svikram }
2224845Svikram 
2234845Svikram int
ct_ctl_qack(int fd,ctevid_t event)2240Sstevel@tonic-gate ct_ctl_qack(int fd, ctevid_t event)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate 	if (ioctl(fd, CT_CQREQ, &event) == -1)
2270Sstevel@tonic-gate 		return (errno);
2280Sstevel@tonic-gate 	return (0);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate /*
2320Sstevel@tonic-gate  * Common status routines
2330Sstevel@tonic-gate  */
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate int
ct_status_read(int fd,int detail,ct_stathdl_t * stathdl)2360Sstevel@tonic-gate ct_status_read(int fd, int detail, ct_stathdl_t *stathdl)
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate 	char *status_buffer = NULL;
2390Sstevel@tonic-gate 	int status_nbytes = 0;
2400Sstevel@tonic-gate 	struct ctlib_status_info *info;
2410Sstevel@tonic-gate 	int error;
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	info = malloc(sizeof (struct ctlib_status_info));
2440Sstevel@tonic-gate 	if (info == NULL)
2450Sstevel@tonic-gate 		return (errno);
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	info->status.ctst_detail = detail;
2480Sstevel@tonic-gate 	if (detail != CTD_COMMON) {
2490Sstevel@tonic-gate 		for (;;) {
2500Sstevel@tonic-gate 			info->status.ctst_nbytes = status_nbytes;
2510Sstevel@tonic-gate 			info->status.ctst_buffer = status_buffer;
2520Sstevel@tonic-gate 			do
2530Sstevel@tonic-gate 				error = ioctl(fd, CT_SSTATUS, &info->status);
2540Sstevel@tonic-gate 			while (error == -1 && errno == EINTR);
2550Sstevel@tonic-gate 			if (error == -1)
2560Sstevel@tonic-gate 				goto errout;
2570Sstevel@tonic-gate 			if (info->status.ctst_nbytes <= status_nbytes)
2580Sstevel@tonic-gate 				break;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 			if (status_buffer)
2610Sstevel@tonic-gate 				free(status_buffer);
2620Sstevel@tonic-gate 			status_nbytes = info->status.ctst_nbytes;
2630Sstevel@tonic-gate 			status_buffer = malloc(status_nbytes);
2640Sstevel@tonic-gate 			if (status_buffer == NULL)
2650Sstevel@tonic-gate 				goto errout;
2660Sstevel@tonic-gate 		}
2670Sstevel@tonic-gate 		if ((errno = nvlist_unpack(info->status.ctst_buffer,
2680Sstevel@tonic-gate 		    info->status.ctst_nbytes, &info->nvl, 0)) != 0)
2690Sstevel@tonic-gate 			goto errout;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 		free(status_buffer);
2720Sstevel@tonic-gate 		status_buffer = NULL;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	} else {
2750Sstevel@tonic-gate 		info->status.ctst_nbytes = 0;
2760Sstevel@tonic-gate 		info->nvl = NULL;
2770Sstevel@tonic-gate 		if (ioctl(fd, CT_SSTATUS, &info->status) == -1)
2780Sstevel@tonic-gate 			goto errout;
2790Sstevel@tonic-gate 	}
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	*stathdl = info;
2820Sstevel@tonic-gate 	return (0);
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate errout:
2850Sstevel@tonic-gate 	error = errno;
2860Sstevel@tonic-gate 	if (status_buffer)
2870Sstevel@tonic-gate 		free(status_buffer);
2880Sstevel@tonic-gate 	if (info)
2890Sstevel@tonic-gate 		free(info);
2900Sstevel@tonic-gate 	return (error);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate void
ct_status_free(ct_stathdl_t stathdl)2940Sstevel@tonic-gate ct_status_free(ct_stathdl_t stathdl)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	if (info->nvl) {
2990Sstevel@tonic-gate 		assert(info->status.ctst_detail != CTD_COMMON);
3000Sstevel@tonic-gate 		nvlist_free(info->nvl);
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	free(info);
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate ctid_t
ct_status_get_id(ct_stathdl_t stathdl)3070Sstevel@tonic-gate ct_status_get_id(ct_stathdl_t stathdl)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3100Sstevel@tonic-gate 	return (info->status.ctst_id);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate zoneid_t
ct_status_get_zoneid(ct_stathdl_t stathdl)3140Sstevel@tonic-gate ct_status_get_zoneid(ct_stathdl_t stathdl)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3170Sstevel@tonic-gate 	return (info->status.ctst_zoneid);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate const char *
ct_status_get_type(ct_stathdl_t stathdl)3210Sstevel@tonic-gate ct_status_get_type(ct_stathdl_t stathdl)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3240Sstevel@tonic-gate 	return (types[info->status.ctst_type].type_name);
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate id_t
ct_status_get_holder(ct_stathdl_t stathdl)3280Sstevel@tonic-gate ct_status_get_holder(ct_stathdl_t stathdl)
3290Sstevel@tonic-gate {
3300Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3310Sstevel@tonic-gate 	return (info->status.ctst_holder);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate ctstate_t
ct_status_get_state(ct_stathdl_t stathdl)3350Sstevel@tonic-gate ct_status_get_state(ct_stathdl_t stathdl)
3360Sstevel@tonic-gate {
3370Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3380Sstevel@tonic-gate 	return (info->status.ctst_state);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate int
ct_status_get_nevents(ct_stathdl_t stathdl)3420Sstevel@tonic-gate ct_status_get_nevents(ct_stathdl_t stathdl)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3450Sstevel@tonic-gate 	return (info->status.ctst_nevents);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate int
ct_status_get_ntime(ct_stathdl_t stathdl)3490Sstevel@tonic-gate ct_status_get_ntime(ct_stathdl_t stathdl)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3520Sstevel@tonic-gate 	return (info->status.ctst_ntime);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate int
ct_status_get_qtime(ct_stathdl_t stathdl)3560Sstevel@tonic-gate ct_status_get_qtime(ct_stathdl_t stathdl)
3570Sstevel@tonic-gate {
3580Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3590Sstevel@tonic-gate 	return (info->status.ctst_qtime);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate ctevid_t
ct_status_get_nevid(ct_stathdl_t stathdl)3630Sstevel@tonic-gate ct_status_get_nevid(ct_stathdl_t stathdl)
3640Sstevel@tonic-gate {
3650Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3660Sstevel@tonic-gate 	return (info->status.ctst_nevid);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate uint_t
ct_status_get_informative(ct_stathdl_t stathdl)3700Sstevel@tonic-gate ct_status_get_informative(ct_stathdl_t stathdl)
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3730Sstevel@tonic-gate 	return (info->status.ctst_informative);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate uint_t
ct_status_get_critical(ct_stathdl_t stathdl)3770Sstevel@tonic-gate ct_status_get_critical(ct_stathdl_t stathdl)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3800Sstevel@tonic-gate 	return (info->status.ctst_critical);
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate uint64_t
ct_status_get_cookie(ct_stathdl_t stathdl)3840Sstevel@tonic-gate ct_status_get_cookie(ct_stathdl_t stathdl)
3850Sstevel@tonic-gate {
3860Sstevel@tonic-gate 	struct ctlib_status_info *info = stathdl;
3870Sstevel@tonic-gate 	return (info->status.ctst_cookie);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate  * Common event routines
3920Sstevel@tonic-gate  */
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate static int
unpack_and_merge(nvlist_t ** nvl,char * buffer,size_t len)3950Sstevel@tonic-gate unpack_and_merge(nvlist_t **nvl, char *buffer, size_t len)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 	nvlist_t *tmpnvl;
3980Sstevel@tonic-gate 	int error;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	if ((error = nvlist_unpack(buffer, len, &tmpnvl, 0)) != 0)
4010Sstevel@tonic-gate 		return (error);
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	if (*nvl == NULL) {
4040Sstevel@tonic-gate 		*nvl = tmpnvl;
4050Sstevel@tonic-gate 		return (0);
4060Sstevel@tonic-gate 	}
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	error = nvlist_merge(*nvl, tmpnvl, 0);
4090Sstevel@tonic-gate 	nvlist_free(tmpnvl);
4100Sstevel@tonic-gate 	return (error);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate static int
ct_event_read_internal(int fd,int cmd,ct_evthdl_t * evt)4140Sstevel@tonic-gate ct_event_read_internal(int fd, int cmd, ct_evthdl_t *evt)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate 	char *event_buffer = NULL;
4170Sstevel@tonic-gate 	int event_nbytes = 0;
4180Sstevel@tonic-gate 	struct ctlib_event_info *info;
4190Sstevel@tonic-gate 	ct_event_t *event;
4200Sstevel@tonic-gate 	int error;
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	info = malloc(sizeof (struct ctlib_event_info));
4230Sstevel@tonic-gate 	if (info == NULL)
4240Sstevel@tonic-gate 		return (errno);
4250Sstevel@tonic-gate 	info->nvl = NULL;
4260Sstevel@tonic-gate 	event = &info->event;
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	for (;;) {
4290Sstevel@tonic-gate 		event->ctev_nbytes = event_nbytes;
4300Sstevel@tonic-gate 		event->ctev_buffer = event_buffer;
4310Sstevel@tonic-gate 		do
4320Sstevel@tonic-gate 			error = ioctl(fd, cmd, event);
4330Sstevel@tonic-gate 		while (error == -1 && errno == EINTR);
4340Sstevel@tonic-gate 		if (error == -1) {
4350Sstevel@tonic-gate 			error = errno;
4360Sstevel@tonic-gate 			goto errout;
4370Sstevel@tonic-gate 		}
4380Sstevel@tonic-gate 		if (event->ctev_nbytes <= event_nbytes)
4390Sstevel@tonic-gate 			break;
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 		if (event_buffer)
4420Sstevel@tonic-gate 			free(event_buffer);
4430Sstevel@tonic-gate 		event_nbytes = event->ctev_nbytes;
4440Sstevel@tonic-gate 		event_buffer = malloc(event_nbytes);
4450Sstevel@tonic-gate 		if (event_buffer == NULL) {
4460Sstevel@tonic-gate 			error = errno;
4470Sstevel@tonic-gate 			goto errout;
4480Sstevel@tonic-gate 		}
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	if (event->ctev_goffset > 0 && (error = unpack_and_merge(&info->nvl,
4520Sstevel@tonic-gate 	    event->ctev_buffer, event->ctev_goffset)) != 0)
4530Sstevel@tonic-gate 		goto errout;
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	if (event->ctev_goffset < event->ctev_nbytes &&
4560Sstevel@tonic-gate 	    (error = unpack_and_merge(&info->nvl,
4570Sstevel@tonic-gate 	    event->ctev_buffer + event->ctev_goffset,
4580Sstevel@tonic-gate 	    event->ctev_nbytes - event->ctev_goffset)) != 0)
4590Sstevel@tonic-gate 		goto errout;
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	free(event_buffer);
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	*evt = info;
4640Sstevel@tonic-gate 	return (0);
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate errout:
4670Sstevel@tonic-gate 	if (event_buffer)
4680Sstevel@tonic-gate 		free(event_buffer);
4690Sstevel@tonic-gate 	if (info) {
4700Sstevel@tonic-gate 		if (info->nvl)
4710Sstevel@tonic-gate 			nvlist_free(info->nvl);
4720Sstevel@tonic-gate 		free(info);
4730Sstevel@tonic-gate 	}
4740Sstevel@tonic-gate 	return (error);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate int
ct_event_read(int fd,ct_evthdl_t * evthdl)4780Sstevel@tonic-gate ct_event_read(int fd, ct_evthdl_t *evthdl)
4790Sstevel@tonic-gate {
4800Sstevel@tonic-gate 	return (ct_event_read_internal(fd, CT_ERECV, evthdl));
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate int
ct_event_read_critical(int fd,ct_evthdl_t * evthdl)4840Sstevel@tonic-gate ct_event_read_critical(int fd, ct_evthdl_t *evthdl)
4850Sstevel@tonic-gate {
4860Sstevel@tonic-gate 	return (ct_event_read_internal(fd, CT_ECRECV, evthdl));
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate int
ct_event_reset(int fd)4900Sstevel@tonic-gate ct_event_reset(int fd)
4910Sstevel@tonic-gate {
4920Sstevel@tonic-gate 	if (ioctl(fd, CT_ERESET) == -1)
4930Sstevel@tonic-gate 		return (errno);
4940Sstevel@tonic-gate 	return (0);
4950Sstevel@tonic-gate }
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate int
ct_event_reliable(int fd)4980Sstevel@tonic-gate ct_event_reliable(int fd)
4990Sstevel@tonic-gate {
5000Sstevel@tonic-gate 	if (ioctl(fd, CT_ERELIABLE) == -1)
5010Sstevel@tonic-gate 		return (errno);
5020Sstevel@tonic-gate 	return (0);
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate void
ct_event_free(ct_evthdl_t evthdl)5060Sstevel@tonic-gate ct_event_free(ct_evthdl_t evthdl)
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate 	struct ctlib_event_info *info = evthdl;
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	if (info->nvl)
5110Sstevel@tonic-gate 		nvlist_free(info->nvl);
5120Sstevel@tonic-gate 	free(info);
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate uint_t
ct_event_get_flags(ct_evthdl_t evthdl)5170Sstevel@tonic-gate ct_event_get_flags(ct_evthdl_t evthdl)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate 	struct ctlib_event_info *info = evthdl;
5200Sstevel@tonic-gate 	return (info->event.ctev_flags);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate ctid_t
ct_event_get_ctid(ct_evthdl_t evthdl)5240Sstevel@tonic-gate ct_event_get_ctid(ct_evthdl_t evthdl)
5250Sstevel@tonic-gate {
5260Sstevel@tonic-gate 	struct ctlib_event_info *info = evthdl;
5270Sstevel@tonic-gate 	return (info->event.ctev_id);
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate ctevid_t
ct_event_get_evid(ct_evthdl_t evthdl)5310Sstevel@tonic-gate ct_event_get_evid(ct_evthdl_t evthdl)
5320Sstevel@tonic-gate {
5330Sstevel@tonic-gate 	struct ctlib_event_info *info = evthdl;
5340Sstevel@tonic-gate 	return (info->event.ctev_evid);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate uint_t
ct_event_get_type(ct_evthdl_t evthdl)5380Sstevel@tonic-gate ct_event_get_type(ct_evthdl_t evthdl)
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate 	struct ctlib_event_info *info = evthdl;
5410Sstevel@tonic-gate 	return (info->event.ctev_type);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate int
ct_event_get_nevid(ct_evthdl_t evthdl,ctevid_t * evidp)5450Sstevel@tonic-gate ct_event_get_nevid(ct_evthdl_t evthdl, ctevid_t *evidp)
5460Sstevel@tonic-gate {
5470Sstevel@tonic-gate 	struct ctlib_event_info *info = evthdl;
5480Sstevel@tonic-gate 	if (info->nvl == NULL ||
5490Sstevel@tonic-gate 	    nvlist_lookup_uint64(info->nvl, CTS_NEVID, evidp))
5500Sstevel@tonic-gate 		return (EINVAL);
5510Sstevel@tonic-gate 	return (0);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate int
ct_event_get_newct(ct_evthdl_t evthdl,ctid_t * ctidp)5550Sstevel@tonic-gate ct_event_get_newct(ct_evthdl_t evthdl, ctid_t *ctidp)
5560Sstevel@tonic-gate {
5570Sstevel@tonic-gate 	struct ctlib_event_info *info = evthdl;
5580Sstevel@tonic-gate 	if (info->nvl == NULL ||
5590Sstevel@tonic-gate 	    nvlist_lookup_int32(info->nvl, CTS_NEWCT, (int *)ctidp))
5600Sstevel@tonic-gate 		return (EINVAL);
5610Sstevel@tonic-gate 	return (0);
5620Sstevel@tonic-gate }
563