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 (c) 1999-2001 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #include <door.h>
28*7c478bd9Sstevel@tonic-gate #include <assert.h>
29*7c478bd9Sstevel@tonic-gate #include <sys/acl.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
31*7c478bd9Sstevel@tonic-gate #include <librcm_event.h>
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include "rcm_impl.h"
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate /*
36*7c478bd9Sstevel@tonic-gate  * Event handling routine
37*7c478bd9Sstevel@tonic-gate  */
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #define	RCM_NOTIFY	0
40*7c478bd9Sstevel@tonic-gate #define	RCM_GETINFO	1
41*7c478bd9Sstevel@tonic-gate #define	RCM_REQUEST	2
42*7c478bd9Sstevel@tonic-gate #define	RCM_EFAULT	3
43*7c478bd9Sstevel@tonic-gate #define	RCM_EPERM	4
44*7c478bd9Sstevel@tonic-gate #define	RCM_EINVAL	5
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate static void process_event(int, int, nvlist_t *, nvlist_t **);
47*7c478bd9Sstevel@tonic-gate static void generate_reply_event(int, rcm_info_t *, nvlist_t **);
48*7c478bd9Sstevel@tonic-gate static void rcm_print_nvlist(nvlist_t *);
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate /*
51*7c478bd9Sstevel@tonic-gate  * Top level function for event service
52*7c478bd9Sstevel@tonic-gate  */
53*7c478bd9Sstevel@tonic-gate void
event_service(void ** data,size_t * datalen)54*7c478bd9Sstevel@tonic-gate event_service(void **data, size_t *datalen)
55*7c478bd9Sstevel@tonic-gate {
56*7c478bd9Sstevel@tonic-gate 	int cmd;
57*7c478bd9Sstevel@tonic-gate 	int lerrno;
58*7c478bd9Sstevel@tonic-gate 	int seq_num;
59*7c478bd9Sstevel@tonic-gate 	nvlist_t *nvl;
60*7c478bd9Sstevel@tonic-gate 	nvlist_t *ret;
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "received door operation\n");
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	/* Decode the data from the door into an unpacked nvlist */
65*7c478bd9Sstevel@tonic-gate 	if (data == NULL || datalen == NULL) {
66*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, "received null door argument\n");
67*7c478bd9Sstevel@tonic-gate 		return;
68*7c478bd9Sstevel@tonic-gate 	}
69*7c478bd9Sstevel@tonic-gate 	if (lerrno = nvlist_unpack(*data, *datalen, &nvl, 0)) {
70*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, "received bad door argument, %s\n",
71*7c478bd9Sstevel@tonic-gate 		    strerror(lerrno));
72*7c478bd9Sstevel@tonic-gate 		return;
73*7c478bd9Sstevel@tonic-gate 	}
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 	/* Do nothing if the door is just being knocked on */
76*7c478bd9Sstevel@tonic-gate 	if (errno = nvlist_lookup_int32(nvl, RCM_CMD, &cmd)) {
77*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
78*7c478bd9Sstevel@tonic-gate 		    "bad door argument (nvlist_lookup=%s)\n", strerror(errno));
79*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvl);
80*7c478bd9Sstevel@tonic-gate 		return;
81*7c478bd9Sstevel@tonic-gate 	}
82*7c478bd9Sstevel@tonic-gate 	if (cmd == CMD_KNOCK) {
83*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_TRACE1, "door event was just a knock\n");
84*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvl);
85*7c478bd9Sstevel@tonic-gate 		*data = NULL;
86*7c478bd9Sstevel@tonic-gate 		*datalen = 0;
87*7c478bd9Sstevel@tonic-gate 		return;
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	/*
91*7c478bd9Sstevel@tonic-gate 	 * Go increment thread count. Before daemon is fully initialized,
92*7c478bd9Sstevel@tonic-gate 	 * the event processing blocks inside this function.
93*7c478bd9Sstevel@tonic-gate 	 */
94*7c478bd9Sstevel@tonic-gate 	seq_num = rcmd_thr_incr(cmd);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	process_event(cmd, seq_num, nvl, &ret);
97*7c478bd9Sstevel@tonic-gate 	nvlist_free(nvl);
98*7c478bd9Sstevel@tonic-gate 	assert(ret != NULL);
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	/*
101*7c478bd9Sstevel@tonic-gate 	 * Decrement thread count
102*7c478bd9Sstevel@tonic-gate 	 */
103*7c478bd9Sstevel@tonic-gate 	rcmd_thr_decr();
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate out:
106*7c478bd9Sstevel@tonic-gate 	*data = ret;
107*7c478bd9Sstevel@tonic-gate 	*datalen = 0;
108*7c478bd9Sstevel@tonic-gate }
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate /*
111*7c478bd9Sstevel@tonic-gate  * Actually processes events; returns a reply event
112*7c478bd9Sstevel@tonic-gate  */
113*7c478bd9Sstevel@tonic-gate static void
process_event(int cmd,int seq_num,nvlist_t * nvl,nvlist_t ** ret)114*7c478bd9Sstevel@tonic-gate process_event(int cmd, int seq_num, nvlist_t *nvl, nvlist_t **ret)
115*7c478bd9Sstevel@tonic-gate {
116*7c478bd9Sstevel@tonic-gate 	int i;
117*7c478bd9Sstevel@tonic-gate 	int error;
118*7c478bd9Sstevel@tonic-gate 	uint_t nvl_nrsrcs = 0;
119*7c478bd9Sstevel@tonic-gate 	pid_t pid;
120*7c478bd9Sstevel@tonic-gate 	uint32_t flag = (uint32_t)0;
121*7c478bd9Sstevel@tonic-gate 	uint64_t pid64 = (uint64_t)0;
122*7c478bd9Sstevel@tonic-gate 	size_t buflen = 0;
123*7c478bd9Sstevel@tonic-gate 	size_t interval_size = 0;
124*7c478bd9Sstevel@tonic-gate 	timespec_t *interval = NULL;
125*7c478bd9Sstevel@tonic-gate 	nvlist_t *change_data = NULL;
126*7c478bd9Sstevel@tonic-gate 	nvlist_t *event_data = NULL;
127*7c478bd9Sstevel@tonic-gate 	rcm_info_t *info = NULL;
128*7c478bd9Sstevel@tonic-gate 	char *modname = NULL;
129*7c478bd9Sstevel@tonic-gate 	char *buf = NULL;
130*7c478bd9Sstevel@tonic-gate 	char **rsrcnames = NULL;
131*7c478bd9Sstevel@tonic-gate 	char **nvl_rsrcs = NULL;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE2, "servicing door command=%d\n", cmd);
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 	rcm_print_nvlist(nvl);
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	/*
138*7c478bd9Sstevel@tonic-gate 	 * Extract data from the door argument nvlist.  Not all arguments
139*7c478bd9Sstevel@tonic-gate 	 * are needed; sanity checks are performed later.
140*7c478bd9Sstevel@tonic-gate 	 */
141*7c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string_array(nvl, RCM_RSRCNAMES, &nvl_rsrcs,
142*7c478bd9Sstevel@tonic-gate 	    &nvl_nrsrcs);
143*7c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string(nvl, RCM_CLIENT_MODNAME, &modname);
144*7c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_uint64(nvl, RCM_CLIENT_ID, (uint64_t *)&pid64);
145*7c478bd9Sstevel@tonic-gate 	pid = (pid_t)pid64;
146*7c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_uint32(nvl, RCM_REQUEST_FLAG, (uint32_t *)&flag);
147*7c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_byte_array(nvl, RCM_SUSPEND_INTERVAL,
148*7c478bd9Sstevel@tonic-gate 	    (uchar_t **)&interval, &interval_size);
149*7c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_byte_array(nvl, RCM_CHANGE_DATA, (uchar_t **)&buf,
150*7c478bd9Sstevel@tonic-gate 	    &buflen);
151*7c478bd9Sstevel@tonic-gate 	if (buf != NULL && buflen > 0) {
152*7c478bd9Sstevel@tonic-gate 		(void) nvlist_unpack(buf, buflen, &change_data, 0);
153*7c478bd9Sstevel@tonic-gate 		buf = NULL;
154*7c478bd9Sstevel@tonic-gate 		buflen = 0;
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_byte_array(nvl, RCM_EVENT_DATA, (uchar_t **)&buf,
157*7c478bd9Sstevel@tonic-gate 	    &buflen);
158*7c478bd9Sstevel@tonic-gate 	if (buf != NULL && buflen > 0)
159*7c478bd9Sstevel@tonic-gate 		(void) nvlist_unpack(buf, buflen, &event_data, 0);
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	rsrcnames = s_calloc(nvl_nrsrcs + 1, sizeof (char *));
162*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nvl_nrsrcs; i++) {
163*7c478bd9Sstevel@tonic-gate 		rsrcnames[i] = nvl_rsrcs[i];
164*7c478bd9Sstevel@tonic-gate 	}
165*7c478bd9Sstevel@tonic-gate 	rsrcnames[nvl_nrsrcs] = NULL;
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	/*
168*7c478bd9Sstevel@tonic-gate 	 * Switch off the command being performed to do the appropriate
169*7c478bd9Sstevel@tonic-gate 	 * sanity checks and dispatch the arguments to the appropriate
170*7c478bd9Sstevel@tonic-gate 	 * implementation routine.
171*7c478bd9Sstevel@tonic-gate 	 */
172*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
173*7c478bd9Sstevel@tonic-gate 	case CMD_REGISTER:
174*7c478bd9Sstevel@tonic-gate 		if ((modname == NULL) || (rsrcnames == NULL) ||
175*7c478bd9Sstevel@tonic-gate 		    (rsrcnames[0] == NULL))
176*7c478bd9Sstevel@tonic-gate 			goto faildata;
177*7c478bd9Sstevel@tonic-gate 		error = add_resource_client(modname, rsrcnames[0], pid, flag,
178*7c478bd9Sstevel@tonic-gate 		    &info);
179*7c478bd9Sstevel@tonic-gate 		break;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	case CMD_UNREGISTER:
182*7c478bd9Sstevel@tonic-gate 		if ((modname == NULL) || (rsrcnames == NULL) ||
183*7c478bd9Sstevel@tonic-gate 		    (rsrcnames[0] == NULL))
184*7c478bd9Sstevel@tonic-gate 			goto faildata;
185*7c478bd9Sstevel@tonic-gate 		error = remove_resource_client(modname, rsrcnames[0], pid,
186*7c478bd9Sstevel@tonic-gate 		    flag);
187*7c478bd9Sstevel@tonic-gate 		break;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	case CMD_GETINFO:
190*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) &&
191*7c478bd9Sstevel@tonic-gate 		    ((flag & (RCM_DR_OPERATION | RCM_MOD_INFO)) == 0))
192*7c478bd9Sstevel@tonic-gate 			goto faildata;
193*7c478bd9Sstevel@tonic-gate 		if ((error = get_resource_info(rsrcnames, flag, seq_num, &info))
194*7c478bd9Sstevel@tonic-gate 		    == EINVAL) {
195*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_DEBUG,
196*7c478bd9Sstevel@tonic-gate 			    "invalid argument in get info request\n");
197*7c478bd9Sstevel@tonic-gate 			generate_reply_event(EINVAL, NULL, ret);
198*7c478bd9Sstevel@tonic-gate 			return;
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 		break;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	case CMD_SUSPEND:
203*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
204*7c478bd9Sstevel@tonic-gate 		    (interval == NULL))
205*7c478bd9Sstevel@tonic-gate 			goto faildata;
206*7c478bd9Sstevel@tonic-gate 		error = process_resource_suspend(rsrcnames, pid, flag, seq_num,
207*7c478bd9Sstevel@tonic-gate 		    interval, &info);
208*7c478bd9Sstevel@tonic-gate 		break;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	case CMD_RESUME:
211*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
212*7c478bd9Sstevel@tonic-gate 			goto faildata;
213*7c478bd9Sstevel@tonic-gate 		error = notify_resource_resume(rsrcnames, pid, flag, seq_num,
214*7c478bd9Sstevel@tonic-gate 		    &info);
215*7c478bd9Sstevel@tonic-gate 		break;
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	case CMD_OFFLINE:
218*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
219*7c478bd9Sstevel@tonic-gate 			goto faildata;
220*7c478bd9Sstevel@tonic-gate 		error = process_resource_offline(rsrcnames, pid, flag, seq_num,
221*7c478bd9Sstevel@tonic-gate 		    &info);
222*7c478bd9Sstevel@tonic-gate 		break;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	case CMD_ONLINE:
225*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
226*7c478bd9Sstevel@tonic-gate 			goto faildata;
227*7c478bd9Sstevel@tonic-gate 		error = notify_resource_online(rsrcnames, pid, flag, seq_num,
228*7c478bd9Sstevel@tonic-gate 		    &info);
229*7c478bd9Sstevel@tonic-gate 		break;
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	case CMD_REMOVE:
232*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
233*7c478bd9Sstevel@tonic-gate 			goto faildata;
234*7c478bd9Sstevel@tonic-gate 		error = notify_resource_remove(rsrcnames, pid, flag, seq_num,
235*7c478bd9Sstevel@tonic-gate 		    &info);
236*7c478bd9Sstevel@tonic-gate 		break;
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	case CMD_EVENT:
239*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
240*7c478bd9Sstevel@tonic-gate 		    (event_data == NULL))
241*7c478bd9Sstevel@tonic-gate 			goto faildata;
242*7c478bd9Sstevel@tonic-gate 		error = notify_resource_event(rsrcnames[0], pid, flag, seq_num,
243*7c478bd9Sstevel@tonic-gate 		    event_data, &info);
244*7c478bd9Sstevel@tonic-gate 		nvlist_free(event_data);
245*7c478bd9Sstevel@tonic-gate 		break;
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	case CMD_REQUEST_CHANGE:
248*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
249*7c478bd9Sstevel@tonic-gate 		    (change_data == NULL))
250*7c478bd9Sstevel@tonic-gate 			goto faildata;
251*7c478bd9Sstevel@tonic-gate 		error = request_capacity_change(rsrcnames[0], pid, flag,
252*7c478bd9Sstevel@tonic-gate 		    seq_num, change_data, &info);
253*7c478bd9Sstevel@tonic-gate 		nvlist_free(change_data);
254*7c478bd9Sstevel@tonic-gate 		break;
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	case CMD_NOTIFY_CHANGE:
257*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
258*7c478bd9Sstevel@tonic-gate 		    (change_data == NULL))
259*7c478bd9Sstevel@tonic-gate 			goto faildata;
260*7c478bd9Sstevel@tonic-gate 		error = notify_capacity_change(rsrcnames[0], pid, flag, seq_num,
261*7c478bd9Sstevel@tonic-gate 		    change_data, &info);
262*7c478bd9Sstevel@tonic-gate 		nvlist_free(change_data);
263*7c478bd9Sstevel@tonic-gate 		break;
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	case CMD_GETSTATE:
266*7c478bd9Sstevel@tonic-gate 		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
267*7c478bd9Sstevel@tonic-gate 			goto faildata;
268*7c478bd9Sstevel@tonic-gate 		error = get_resource_state(rsrcnames[0], pid, &info);
269*7c478bd9Sstevel@tonic-gate 		break;
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	default:
272*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_WARNING,
273*7c478bd9Sstevel@tonic-gate 		    gettext("unknown door command: %d\n"), cmd);
274*7c478bd9Sstevel@tonic-gate 		generate_reply_event(EFAULT, NULL, ret);
275*7c478bd9Sstevel@tonic-gate 		(void) free(rsrcnames);
276*7c478bd9Sstevel@tonic-gate 		return;
277*7c478bd9Sstevel@tonic-gate 	}
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE2, "finish processing event 0x%x\n", cmd);
280*7c478bd9Sstevel@tonic-gate 	generate_reply_event(error, info, ret);
281*7c478bd9Sstevel@tonic-gate 	(void) free(rsrcnames);
282*7c478bd9Sstevel@tonic-gate 	return;
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate faildata:
285*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_WARNING,
286*7c478bd9Sstevel@tonic-gate 	    gettext("data error in door arguments for cmd 0x%x\n"), cmd);
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	generate_reply_event(EFAULT, NULL, ret);
289*7c478bd9Sstevel@tonic-gate 	(void) free(rsrcnames);
290*7c478bd9Sstevel@tonic-gate }
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate /*
294*7c478bd9Sstevel@tonic-gate  * Generate reply event from resource registration information
295*7c478bd9Sstevel@tonic-gate  */
296*7c478bd9Sstevel@tonic-gate static void
generate_reply_event(int error,rcm_info_t * info,nvlist_t ** ret)297*7c478bd9Sstevel@tonic-gate generate_reply_event(int error, rcm_info_t *info, nvlist_t **ret)
298*7c478bd9Sstevel@tonic-gate {
299*7c478bd9Sstevel@tonic-gate 	nvlist_t *nvl = NULL;
300*7c478bd9Sstevel@tonic-gate 	rcm_info_t *tmp;
301*7c478bd9Sstevel@tonic-gate 	char *buf = NULL;
302*7c478bd9Sstevel@tonic-gate 	size_t buflen = 0;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE4, "generating reply event\n");
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	/* Allocate an empty nvlist */
307*7c478bd9Sstevel@tonic-gate 	if ((errno = nvlist_alloc(&nvl, 0, 0)) > 0) {
308*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
309*7c478bd9Sstevel@tonic-gate 		    gettext("nvlist_alloc failed: %s\n"), strerror(errno));
310*7c478bd9Sstevel@tonic-gate 		rcmd_exit(errno);
311*7c478bd9Sstevel@tonic-gate 	}
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	/* Encode the result of the operation in the nvlist */
314*7c478bd9Sstevel@tonic-gate 	if (errno = nvlist_add_int32(nvl, RCM_RESULT, error)) {
315*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
316*7c478bd9Sstevel@tonic-gate 		    gettext("nvlist_add(RESULT) failed: %s\n"),
317*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
318*7c478bd9Sstevel@tonic-gate 		rcmd_exit(errno);
319*7c478bd9Sstevel@tonic-gate 	}
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	/* Go through the RCM info tuples, appending them all to the nvlist */
322*7c478bd9Sstevel@tonic-gate 	tmp = info;
323*7c478bd9Sstevel@tonic-gate 	while (tmp) {
324*7c478bd9Sstevel@tonic-gate 		if (tmp->info) {
325*7c478bd9Sstevel@tonic-gate 			buf = NULL;
326*7c478bd9Sstevel@tonic-gate 			buflen = 0;
327*7c478bd9Sstevel@tonic-gate 			if (errno = nvlist_pack(tmp->info, &buf, &buflen,
328*7c478bd9Sstevel@tonic-gate 			    NV_ENCODE_NATIVE, 0)) {
329*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_ERROR,
330*7c478bd9Sstevel@tonic-gate 				    gettext("nvlist_pack(INFO) failed: %s\n"),
331*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
332*7c478bd9Sstevel@tonic-gate 				rcmd_exit(errno);
333*7c478bd9Sstevel@tonic-gate 			}
334*7c478bd9Sstevel@tonic-gate 			if (errno = nvlist_add_byte_array(nvl, RCM_RESULT_INFO,
335*7c478bd9Sstevel@tonic-gate 			    (uchar_t *)buf, buflen)) {
336*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_ERROR,
337*7c478bd9Sstevel@tonic-gate 				    gettext("nvlist_add(INFO) failed: %s\n"),
338*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
339*7c478bd9Sstevel@tonic-gate 				rcmd_exit(errno);
340*7c478bd9Sstevel@tonic-gate 			}
341*7c478bd9Sstevel@tonic-gate 			(void) free(buf);
342*7c478bd9Sstevel@tonic-gate 			nvlist_free(tmp->info);
343*7c478bd9Sstevel@tonic-gate 		}
344*7c478bd9Sstevel@tonic-gate 		info = tmp->next;
345*7c478bd9Sstevel@tonic-gate 		(void) free(tmp);
346*7c478bd9Sstevel@tonic-gate 		tmp = info;
347*7c478bd9Sstevel@tonic-gate 	}
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	/* Return the nvlist (unpacked) in the return argument */
350*7c478bd9Sstevel@tonic-gate 	rcm_print_nvlist(nvl);
351*7c478bd9Sstevel@tonic-gate 	*ret = nvl;
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate static void
rcm_print_nvlist(nvlist_t * nvl)355*7c478bd9Sstevel@tonic-gate rcm_print_nvlist(nvlist_t *nvl)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	uchar_t data_byte;
358*7c478bd9Sstevel@tonic-gate 	int16_t data_int16;
359*7c478bd9Sstevel@tonic-gate 	uint16_t data_uint16;
360*7c478bd9Sstevel@tonic-gate 	int32_t data_int32;
361*7c478bd9Sstevel@tonic-gate 	uint32_t data_uint32;
362*7c478bd9Sstevel@tonic-gate 	int64_t data_int64;
363*7c478bd9Sstevel@tonic-gate 	uint64_t data_uint64;
364*7c478bd9Sstevel@tonic-gate 	char *data_string;
365*7c478bd9Sstevel@tonic-gate 	char **data_strings;
366*7c478bd9Sstevel@tonic-gate 	uint_t data_nstrings;
367*7c478bd9Sstevel@tonic-gate 	nvpair_t *nvp = NULL;
368*7c478bd9Sstevel@tonic-gate 	int i;
369*7c478bd9Sstevel@tonic-gate 	char *name;
370*7c478bd9Sstevel@tonic-gate 	data_type_t type;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE3, "event attributes:\n");
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	while (nvp = nvlist_next_nvpair(nvl, nvp)) {
375*7c478bd9Sstevel@tonic-gate 		type = nvpair_type(nvp);
376*7c478bd9Sstevel@tonic-gate 		name = nvpair_name(nvp);
377*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_TRACE3, "\t%s(%d)=", name, type);
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 		switch (type) {
380*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_BOOLEAN:
381*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "True (boolean)\n");
382*7c478bd9Sstevel@tonic-gate 			break;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_BYTE:
385*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_byte(nvp, &data_byte);
386*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "0x%x (byte)\n",
387*7c478bd9Sstevel@tonic-gate 			    data_byte);
388*7c478bd9Sstevel@tonic-gate 			break;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_INT16:
391*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_int16(nvp, &data_int16);
392*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "0x%x (int16)\n",
393*7c478bd9Sstevel@tonic-gate 			    data_int16);
394*7c478bd9Sstevel@tonic-gate 			break;
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_UINT16:
397*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint16(nvp, &data_uint16);
398*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "0x%x (uint16)\n",
399*7c478bd9Sstevel@tonic-gate 			    data_uint16);
400*7c478bd9Sstevel@tonic-gate 			break;
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_INT32:
403*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_int32(nvp, &data_int32);
404*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "0x%x (int32)\n",
405*7c478bd9Sstevel@tonic-gate 			    data_int32);
406*7c478bd9Sstevel@tonic-gate 			break;
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_UINT32:
409*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint32(nvp, &data_uint32);
410*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "0x%x (uint32)\n",
411*7c478bd9Sstevel@tonic-gate 			    data_uint32);
412*7c478bd9Sstevel@tonic-gate 			break;
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_INT64:
415*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_int64(nvp, &data_int64);
416*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "0x%lx (int64)\n",
417*7c478bd9Sstevel@tonic-gate 			    data_int64);
418*7c478bd9Sstevel@tonic-gate 			break;
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_UINT64:
421*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_uint64(nvp, &data_uint64);
422*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "0x%lx (uint64)\n",
423*7c478bd9Sstevel@tonic-gate 			    data_uint64);
424*7c478bd9Sstevel@tonic-gate 			break;
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_STRING:
427*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string(nvp, &data_string);
428*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "\"%s\" (string)\n",
429*7c478bd9Sstevel@tonic-gate 			    data_string);
430*7c478bd9Sstevel@tonic-gate 			break;
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 		case DATA_TYPE_STRING_ARRAY:
433*7c478bd9Sstevel@tonic-gate 			(void) nvpair_value_string_array(nvp, &data_strings,
434*7c478bd9Sstevel@tonic-gate 			    &data_nstrings);
435*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < data_nstrings; i++) {
436*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_TRACE3,
437*7c478bd9Sstevel@tonic-gate 				    "\t\"%s\" (string)\n", data_strings[i]);
438*7c478bd9Sstevel@tonic-gate 				if (i < (data_nstrings - 1))
439*7c478bd9Sstevel@tonic-gate 					rcm_log_message(RCM_TRACE3, "\t\t\t");
440*7c478bd9Sstevel@tonic-gate 			}
441*7c478bd9Sstevel@tonic-gate 			break;
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 		default:
444*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_TRACE3, "<not dumped>\n");
445*7c478bd9Sstevel@tonic-gate 			break;
446*7c478bd9Sstevel@tonic-gate 		}
447*7c478bd9Sstevel@tonic-gate 	}
448*7c478bd9Sstevel@tonic-gate }
449