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