1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "librcm_impl.h" 30*7c478bd9Sstevel@tonic-gate #include "librcm_event.h" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 33*7c478bd9Sstevel@tonic-gate static int rcm_debug = 1; 34*7c478bd9Sstevel@tonic-gate #define dprintf(args) if (rcm_debug) (void) fprintf args 35*7c478bd9Sstevel@tonic-gate #else 36*7c478bd9Sstevel@tonic-gate #define dprintf(args) /* nothing */ 37*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate static int extract_info(nvlist_t *, rcm_info_t **); 40*7c478bd9Sstevel@tonic-gate static int rcm_daemon_is_alive(); 41*7c478bd9Sstevel@tonic-gate static int rcm_common(int, rcm_handle_t *, char **, uint_t, void *, 42*7c478bd9Sstevel@tonic-gate rcm_info_t **); 43*7c478bd9Sstevel@tonic-gate static int rcm_direct_call(int, rcm_handle_t *, char **, uint_t, void *, 44*7c478bd9Sstevel@tonic-gate rcm_info_t **); 45*7c478bd9Sstevel@tonic-gate static int rcm_daemon_call(int, rcm_handle_t *, char **, uint_t, void *, 46*7c478bd9Sstevel@tonic-gate rcm_info_t **); 47*7c478bd9Sstevel@tonic-gate static int rcm_generate_nvlist(int, rcm_handle_t *, char **, uint_t, void *, 48*7c478bd9Sstevel@tonic-gate char **, size_t *); 49*7c478bd9Sstevel@tonic-gate static int rcm_check_permission(void); 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate /* 52*7c478bd9Sstevel@tonic-gate * Allocate a handle structure 53*7c478bd9Sstevel@tonic-gate */ 54*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 55*7c478bd9Sstevel@tonic-gate int 56*7c478bd9Sstevel@tonic-gate rcm_alloc_handle(char *modname, uint_t flag, void *arg, rcm_handle_t **hdp) 57*7c478bd9Sstevel@tonic-gate { 58*7c478bd9Sstevel@tonic-gate rcm_handle_t *hd; 59*7c478bd9Sstevel@tonic-gate void *temp; 60*7c478bd9Sstevel@tonic-gate char namebuf[MAXPATHLEN]; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate if ((hdp == NULL) || (flag & ~RCM_ALLOC_HDL_MASK)) { 63*7c478bd9Sstevel@tonic-gate errno = EINVAL; 64*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 65*7c478bd9Sstevel@tonic-gate } 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate if (rcm_check_permission() == 0) { 68*7c478bd9Sstevel@tonic-gate errno = EPERM; 69*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 70*7c478bd9Sstevel@tonic-gate } 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate if ((hd = calloc(1, sizeof (*hd))) == NULL) { 73*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate if (modname) { 77*7c478bd9Sstevel@tonic-gate (void) snprintf(namebuf, MAXPATHLEN, "%s%s", modname, 78*7c478bd9Sstevel@tonic-gate RCM_MODULE_SUFFIX); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate if ((hd->modname = strdup(namebuf)) == NULL) { 81*7c478bd9Sstevel@tonic-gate free(hd); 82*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate if ((temp = rcm_module_open(namebuf)) == NULL) { 86*7c478bd9Sstevel@tonic-gate free(hd->modname); 87*7c478bd9Sstevel@tonic-gate free(hd); 88*7c478bd9Sstevel@tonic-gate errno = EINVAL; 89*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate rcm_module_close(temp); 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate if (flag & RCM_NOPID) { 96*7c478bd9Sstevel@tonic-gate hd->pid = (pid_t)0; 97*7c478bd9Sstevel@tonic-gate } else { 98*7c478bd9Sstevel@tonic-gate hd->pid = (pid_t)getpid(); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate *hdp = hd; 102*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* free handle structure */ 106*7c478bd9Sstevel@tonic-gate int 107*7c478bd9Sstevel@tonic-gate rcm_free_handle(rcm_handle_t *hd) 108*7c478bd9Sstevel@tonic-gate { 109*7c478bd9Sstevel@tonic-gate if (hd == NULL) { 110*7c478bd9Sstevel@tonic-gate errno = EINVAL; 111*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate if (hd->modname) { 115*7c478bd9Sstevel@tonic-gate free(hd->modname); 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate free(hd); 119*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * Operations which require daemon processing 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* get registration and DR information from rcm_daemon */ 128*7c478bd9Sstevel@tonic-gate int 129*7c478bd9Sstevel@tonic-gate rcm_get_info(rcm_handle_t *hd, char *rsrcname, uint_t flag, rcm_info_t **infop) 130*7c478bd9Sstevel@tonic-gate { 131*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate if ((flag & ~RCM_GET_INFO_MASK) || (infop == NULL)) { 134*7c478bd9Sstevel@tonic-gate errno = EINVAL; 135*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* 139*7c478bd9Sstevel@tonic-gate * rsrcname may be NULL if requesting dr operations or modinfo 140*7c478bd9Sstevel@tonic-gate */ 141*7c478bd9Sstevel@tonic-gate if ((rsrcname == NULL) && 142*7c478bd9Sstevel@tonic-gate ((flag & RCM_DR_OPERATION|RCM_MOD_INFO) == 0)) { 143*7c478bd9Sstevel@tonic-gate errno = EINVAL; 144*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 148*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop)); 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate /* get registration and DR information from rcm_daemon (list version) */ 154*7c478bd9Sstevel@tonic-gate int 155*7c478bd9Sstevel@tonic-gate rcm_get_info_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 156*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 157*7c478bd9Sstevel@tonic-gate { 158*7c478bd9Sstevel@tonic-gate /* Requesting the current DR operations with a *list() is invalid */ 159*7c478bd9Sstevel@tonic-gate if ((flag & RCM_DR_OPERATION) || (flag & RCM_MOD_INFO)) { 160*7c478bd9Sstevel@tonic-gate errno = EINVAL; 161*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop)); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* request to offline a resource before DR removal */ 168*7c478bd9Sstevel@tonic-gate int 169*7c478bd9Sstevel@tonic-gate rcm_request_offline(rcm_handle_t *hd, char *rsrcname, uint_t flag, 170*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 171*7c478bd9Sstevel@tonic-gate { 172*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 175*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate return (rcm_request_offline_list(hd, rsrcnames, flag, infop)); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* request to offline a resource before DR removal (list version) */ 181*7c478bd9Sstevel@tonic-gate int 182*7c478bd9Sstevel@tonic-gate rcm_request_offline_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 183*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_REQUEST_MASK) { 186*7c478bd9Sstevel@tonic-gate errno = EINVAL; 187*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_OFFLINE, hd, rsrcnames, flag, NULL, infop)); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* cancel offline request and allow apps to use rsrcname */ 194*7c478bd9Sstevel@tonic-gate int 195*7c478bd9Sstevel@tonic-gate rcm_notify_online(rcm_handle_t *hd, char *rsrcname, uint_t flag, 196*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 197*7c478bd9Sstevel@tonic-gate { 198*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 201*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate return (rcm_notify_online_list(hd, rsrcnames, flag, infop)); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* cancel offline and allow apps to use resources (list version) */ 207*7c478bd9Sstevel@tonic-gate int 208*7c478bd9Sstevel@tonic-gate rcm_notify_online_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 209*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_NOTIFY_MASK) { 212*7c478bd9Sstevel@tonic-gate errno = EINVAL; 213*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_ONLINE, hd, rsrcnames, flag, NULL, infop)); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate /* notify that rsrcname has been removed */ 220*7c478bd9Sstevel@tonic-gate int 221*7c478bd9Sstevel@tonic-gate rcm_notify_remove(rcm_handle_t *hd, char *rsrcname, uint_t flag, 222*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 227*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate return (rcm_notify_remove_list(hd, rsrcnames, flag, infop)); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate /* notify that resrouces have been removed (list form) */ 233*7c478bd9Sstevel@tonic-gate int 234*7c478bd9Sstevel@tonic-gate rcm_notify_remove_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 235*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 236*7c478bd9Sstevel@tonic-gate { 237*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_NOTIFY_MASK) { 238*7c478bd9Sstevel@tonic-gate errno = EINVAL; 239*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REMOVE, hd, rsrcnames, flag, NULL, infop)); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* request for permission to suspend resource of interval time */ 246*7c478bd9Sstevel@tonic-gate int 247*7c478bd9Sstevel@tonic-gate rcm_request_suspend(rcm_handle_t *hd, char *rsrcname, uint_t flag, 248*7c478bd9Sstevel@tonic-gate timespec_t *interval, rcm_info_t **infop) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 253*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate return (rcm_request_suspend_list(hd, rsrcnames, flag, interval, infop)); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate /* request for permission to suspend resource of interval time (list form) */ 259*7c478bd9Sstevel@tonic-gate int 260*7c478bd9Sstevel@tonic-gate rcm_request_suspend_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 261*7c478bd9Sstevel@tonic-gate timespec_t *interval, rcm_info_t **infop) 262*7c478bd9Sstevel@tonic-gate { 263*7c478bd9Sstevel@tonic-gate if ((flag & ~RCM_REQUEST_MASK) || (interval == NULL) || 264*7c478bd9Sstevel@tonic-gate (interval->tv_sec < 0) || (interval->tv_nsec < 0)) { 265*7c478bd9Sstevel@tonic-gate errno = EINVAL; 266*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_SUSPEND, hd, rsrcnames, flag, (void *)interval, 270*7c478bd9Sstevel@tonic-gate infop)); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* notify apps of the completion of resource suspension */ 274*7c478bd9Sstevel@tonic-gate int 275*7c478bd9Sstevel@tonic-gate rcm_notify_resume(rcm_handle_t *hd, char *rsrcname, uint_t flag, 276*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 281*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate return (rcm_notify_resume_list(hd, rsrcnames, flag, infop)); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate /* notify apps of the completion of resource suspension (list form) */ 287*7c478bd9Sstevel@tonic-gate int 288*7c478bd9Sstevel@tonic-gate rcm_notify_resume_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 289*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate if (flag & ~(RCM_NOTIFY_MASK | RCM_SUSPENDED)) { 292*7c478bd9Sstevel@tonic-gate errno = EINVAL; 293*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_RESUME, hd, rsrcnames, flag, NULL, infop)); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate /* request a capacity change from apps */ 300*7c478bd9Sstevel@tonic-gate int 301*7c478bd9Sstevel@tonic-gate rcm_request_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag, 302*7c478bd9Sstevel@tonic-gate nvlist_t *nvl, rcm_info_t **infop) 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate int rv; 305*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) { 308*7c478bd9Sstevel@tonic-gate errno = EINVAL; 309*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 313*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate rv = rcm_common(CMD_REQUEST_CHANGE, hd, rsrcnames, flag, (void *)nvl, 316*7c478bd9Sstevel@tonic-gate infop); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate return (rv); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* notify apps of a capacity change */ 322*7c478bd9Sstevel@tonic-gate int 323*7c478bd9Sstevel@tonic-gate rcm_notify_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag, 324*7c478bd9Sstevel@tonic-gate nvlist_t *nvl, rcm_info_t **infop) 325*7c478bd9Sstevel@tonic-gate { 326*7c478bd9Sstevel@tonic-gate int rv; 327*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) { 330*7c478bd9Sstevel@tonic-gate errno = EINVAL; 331*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 335*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate rv = rcm_common(CMD_NOTIFY_CHANGE, hd, rsrcnames, flag, (void *)nvl, 338*7c478bd9Sstevel@tonic-gate infop); 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate return (rv); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* notify apps of an event */ 344*7c478bd9Sstevel@tonic-gate int 345*7c478bd9Sstevel@tonic-gate rcm_notify_event(rcm_handle_t *hd, char *rsrcname, uint_t flag, nvlist_t *nvl, 346*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 347*7c478bd9Sstevel@tonic-gate { 348*7c478bd9Sstevel@tonic-gate int rv; 349*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /* No flags are defined yet for rcm_notify_event() */ 352*7c478bd9Sstevel@tonic-gate if ((nvl == NULL) || (flag != 0)) { 353*7c478bd9Sstevel@tonic-gate errno = EINVAL; 354*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 358*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate rv = rcm_common(CMD_EVENT, hd, rsrcnames, 0, (void *)nvl, infop); 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate return (rv); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Register to receive capacity changes. This requires a module to exist in 367*7c478bd9Sstevel@tonic-gate * module directory. It should be called prior to using a new resource. 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 370*7c478bd9Sstevel@tonic-gate int 371*7c478bd9Sstevel@tonic-gate rcm_register_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag, 372*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 373*7c478bd9Sstevel@tonic-gate { 374*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 377*7c478bd9Sstevel@tonic-gate errno = EINVAL; 378*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_CAPACITY; 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 384*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* unregister interest in capacity changes */ 390*7c478bd9Sstevel@tonic-gate int 391*7c478bd9Sstevel@tonic-gate rcm_unregister_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag) 392*7c478bd9Sstevel@tonic-gate { 393*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 396*7c478bd9Sstevel@tonic-gate errno = EINVAL; 397*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_CAPACITY; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 403*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * Register to receive events. This requires a module to exist in module 410*7c478bd9Sstevel@tonic-gate * directory. It should be called prior to using a new resource. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 413*7c478bd9Sstevel@tonic-gate int 414*7c478bd9Sstevel@tonic-gate rcm_register_event(rcm_handle_t *hd, char *rsrcname, uint_t flag, 415*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 416*7c478bd9Sstevel@tonic-gate { 417*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 420*7c478bd9Sstevel@tonic-gate errno = EINVAL; 421*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_EVENT; 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 427*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate /* unregister interest in events */ 433*7c478bd9Sstevel@tonic-gate int 434*7c478bd9Sstevel@tonic-gate rcm_unregister_event(rcm_handle_t *hd, char *rsrcname, uint_t flag) 435*7c478bd9Sstevel@tonic-gate { 436*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 439*7c478bd9Sstevel@tonic-gate errno = EINVAL; 440*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_EVENT; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 446*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * Register interest in a resource. This requires a module to exist in module 453*7c478bd9Sstevel@tonic-gate * directory. It should be called prior to using a new resource. 454*7c478bd9Sstevel@tonic-gate * 455*7c478bd9Sstevel@tonic-gate * Registration may be denied if it is presently locked by a DR operation. 456*7c478bd9Sstevel@tonic-gate */ 457*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 458*7c478bd9Sstevel@tonic-gate int 459*7c478bd9Sstevel@tonic-gate rcm_register_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag, 460*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 461*7c478bd9Sstevel@tonic-gate { 462*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 465*7c478bd9Sstevel@tonic-gate errno = EINVAL; 466*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_DR; 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 472*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* unregister interest in rsrcname */ 478*7c478bd9Sstevel@tonic-gate int 479*7c478bd9Sstevel@tonic-gate rcm_unregister_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag) 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 484*7c478bd9Sstevel@tonic-gate errno = EINVAL; 485*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_DR; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 491*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate /* get the current state of a resource */ 497*7c478bd9Sstevel@tonic-gate int 498*7c478bd9Sstevel@tonic-gate rcm_get_rsrcstate(rcm_handle_t *hd, char *rsrcname, int *statep) 499*7c478bd9Sstevel@tonic-gate { 500*7c478bd9Sstevel@tonic-gate int result; 501*7c478bd9Sstevel@tonic-gate int flag = 0; 502*7c478bd9Sstevel@tonic-gate rcm_info_t *infop = NULL; 503*7c478bd9Sstevel@tonic-gate rcm_info_tuple_t *tuple = NULL; 504*7c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if (statep == NULL) { 507*7c478bd9Sstevel@tonic-gate errno = EINVAL; 508*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 512*7c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate result = rcm_common(CMD_GETSTATE, hd, rsrcnames, flag, NULL, &infop); 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * A successful result implies the presence of exactly one RCM info 518*7c478bd9Sstevel@tonic-gate * tuple containing the state of this resource (a combination of each 519*7c478bd9Sstevel@tonic-gate * client's resources). If that's not true, change the result to 520*7c478bd9Sstevel@tonic-gate * RCM_FAILURE. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate if (result == RCM_SUCCESS) { 523*7c478bd9Sstevel@tonic-gate if ((infop == NULL) || 524*7c478bd9Sstevel@tonic-gate ((tuple = rcm_info_next(infop, NULL)) == NULL) || 525*7c478bd9Sstevel@tonic-gate (rcm_info_next(infop, tuple) != NULL)) { 526*7c478bd9Sstevel@tonic-gate result = RCM_FAILURE; 527*7c478bd9Sstevel@tonic-gate } else if (infop && tuple) { 528*7c478bd9Sstevel@tonic-gate *statep = rcm_info_state(tuple); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate if (infop) 533*7c478bd9Sstevel@tonic-gate rcm_free_info(infop); 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate return (result); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* 539*7c478bd9Sstevel@tonic-gate * RCM helper functions exposed to librcm callers. 540*7c478bd9Sstevel@tonic-gate */ 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate /* Free linked list of registration info */ 543*7c478bd9Sstevel@tonic-gate void 544*7c478bd9Sstevel@tonic-gate rcm_free_info(rcm_info_t *info) 545*7c478bd9Sstevel@tonic-gate { 546*7c478bd9Sstevel@tonic-gate while (info) { 547*7c478bd9Sstevel@tonic-gate rcm_info_t *tmp = info->next; 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate if (info->info) 550*7c478bd9Sstevel@tonic-gate nvlist_free(info->info); 551*7c478bd9Sstevel@tonic-gate free(info); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate info = tmp; 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /* return the next tuple in the info structure */ 558*7c478bd9Sstevel@tonic-gate rcm_info_tuple_t * 559*7c478bd9Sstevel@tonic-gate rcm_info_next(rcm_info_t *info, rcm_info_tuple_t *tuple) 560*7c478bd9Sstevel@tonic-gate { 561*7c478bd9Sstevel@tonic-gate if (info == NULL) { 562*7c478bd9Sstevel@tonic-gate errno = EINVAL; 563*7c478bd9Sstevel@tonic-gate return (NULL); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate if (tuple == NULL) { 567*7c478bd9Sstevel@tonic-gate return ((rcm_info_tuple_t *)info); 568*7c478bd9Sstevel@tonic-gate } 569*7c478bd9Sstevel@tonic-gate return ((rcm_info_tuple_t *)tuple->next); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* return resource name */ 573*7c478bd9Sstevel@tonic-gate const char * 574*7c478bd9Sstevel@tonic-gate rcm_info_rsrc(rcm_info_tuple_t *tuple) 575*7c478bd9Sstevel@tonic-gate { 576*7c478bd9Sstevel@tonic-gate char *rsrcname = NULL; 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 579*7c478bd9Sstevel@tonic-gate errno = EINVAL; 580*7c478bd9Sstevel@tonic-gate return (NULL); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_RSRCNAME, &rsrcname)) 584*7c478bd9Sstevel@tonic-gate return (NULL); 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate return (rsrcname); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate const char * 590*7c478bd9Sstevel@tonic-gate rcm_info_info(rcm_info_tuple_t *tuple) 591*7c478bd9Sstevel@tonic-gate { 592*7c478bd9Sstevel@tonic-gate char *info = NULL; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 595*7c478bd9Sstevel@tonic-gate errno = EINVAL; 596*7c478bd9Sstevel@tonic-gate return (NULL); 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_INFO, &info)) 600*7c478bd9Sstevel@tonic-gate return (NULL); 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate return (info); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate const char * 606*7c478bd9Sstevel@tonic-gate rcm_info_error(rcm_info_tuple_t *tuple) 607*7c478bd9Sstevel@tonic-gate { 608*7c478bd9Sstevel@tonic-gate char *errstr = NULL; 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 611*7c478bd9Sstevel@tonic-gate errno = EINVAL; 612*7c478bd9Sstevel@tonic-gate return (NULL); 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_ERROR, 616*7c478bd9Sstevel@tonic-gate &errstr)) 617*7c478bd9Sstevel@tonic-gate return (NULL); 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate return (errstr); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate /* return info string in the tuple */ 623*7c478bd9Sstevel@tonic-gate const char * 624*7c478bd9Sstevel@tonic-gate rcm_info_modname(rcm_info_tuple_t *tuple) 625*7c478bd9Sstevel@tonic-gate { 626*7c478bd9Sstevel@tonic-gate char *modname = NULL; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 629*7c478bd9Sstevel@tonic-gate errno = EINVAL; 630*7c478bd9Sstevel@tonic-gate return (NULL); 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_MODNAME, 634*7c478bd9Sstevel@tonic-gate &modname)) 635*7c478bd9Sstevel@tonic-gate return (NULL); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate return (modname); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* return client pid in the tuple */ 641*7c478bd9Sstevel@tonic-gate pid_t 642*7c478bd9Sstevel@tonic-gate rcm_info_pid(rcm_info_tuple_t *tuple) 643*7c478bd9Sstevel@tonic-gate { 644*7c478bd9Sstevel@tonic-gate uint64_t pid64 = (uint64_t)0; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 647*7c478bd9Sstevel@tonic-gate errno = EINVAL; 648*7c478bd9Sstevel@tonic-gate return ((pid_t)0); 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_uint64(tuple->info, RCM_CLIENT_ID, &pid64)) 652*7c478bd9Sstevel@tonic-gate return ((pid_t)0); 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate return ((pid_t)pid64); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate /* return client state in the tuple */ 658*7c478bd9Sstevel@tonic-gate int 659*7c478bd9Sstevel@tonic-gate rcm_info_state(rcm_info_tuple_t *tuple) 660*7c478bd9Sstevel@tonic-gate { 661*7c478bd9Sstevel@tonic-gate int state; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 664*7c478bd9Sstevel@tonic-gate errno = EINVAL; 665*7c478bd9Sstevel@tonic-gate return (RCM_STATE_UNKNOWN); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_int32(tuple->info, RCM_RSRCSTATE, &state)) 669*7c478bd9Sstevel@tonic-gate return (RCM_STATE_UNKNOWN); 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate return (state); 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate /* return the generic properties in the tuple */ 675*7c478bd9Sstevel@tonic-gate nvlist_t * 676*7c478bd9Sstevel@tonic-gate rcm_info_properties(rcm_info_tuple_t *tuple) 677*7c478bd9Sstevel@tonic-gate { 678*7c478bd9Sstevel@tonic-gate char *buf; 679*7c478bd9Sstevel@tonic-gate uint_t buflen; 680*7c478bd9Sstevel@tonic-gate nvlist_t *nvl; 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 683*7c478bd9Sstevel@tonic-gate errno = EINVAL; 684*7c478bd9Sstevel@tonic-gate return (NULL); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_byte_array(tuple->info, RCM_CLIENT_PROPERTIES, 688*7c478bd9Sstevel@tonic-gate (uchar_t **)&buf, &buflen)) 689*7c478bd9Sstevel@tonic-gate return (NULL); 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate if (errno = nvlist_unpack(buf, buflen, &nvl, 0)) { 692*7c478bd9Sstevel@tonic-gate free(buf); 693*7c478bd9Sstevel@tonic-gate return (NULL); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate return (nvl); 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate * return operation sequence number 701*7c478bd9Sstevel@tonic-gate * 702*7c478bd9Sstevel@tonic-gate * This is private. Called by rcmctl only for testing purposes. 703*7c478bd9Sstevel@tonic-gate */ 704*7c478bd9Sstevel@tonic-gate int 705*7c478bd9Sstevel@tonic-gate rcm_info_seqnum(rcm_info_tuple_t *tuple) 706*7c478bd9Sstevel@tonic-gate { 707*7c478bd9Sstevel@tonic-gate int seqnum; 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 710*7c478bd9Sstevel@tonic-gate errno = EINVAL; 711*7c478bd9Sstevel@tonic-gate return (-1); 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_int32(tuple->info, RCM_SEQ_NUM, &seqnum)) 715*7c478bd9Sstevel@tonic-gate return (-1); 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate return (seqnum); 718*7c478bd9Sstevel@tonic-gate } 719*7c478bd9Sstevel@tonic-gate 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate /* 722*7c478bd9Sstevel@tonic-gate * The following interfaces are PRIVATE to the RCM framework. They are not 723*7c478bd9Sstevel@tonic-gate * declared static because they are called by rcm_daemon. 724*7c478bd9Sstevel@tonic-gate */ 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate /* 727*7c478bd9Sstevel@tonic-gate * Invoke shell to execute command in MT safe manner. 728*7c478bd9Sstevel@tonic-gate * Returns wait status or -1 on error. 729*7c478bd9Sstevel@tonic-gate */ 730*7c478bd9Sstevel@tonic-gate int 731*7c478bd9Sstevel@tonic-gate rcm_exec_cmd(char *cmd) 732*7c478bd9Sstevel@tonic-gate { 733*7c478bd9Sstevel@tonic-gate pid_t pid; 734*7c478bd9Sstevel@tonic-gate int status, w; 735*7c478bd9Sstevel@tonic-gate char *argvec[] = {"sh", "-c", NULL, NULL}; 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate argvec[2] = cmd; 738*7c478bd9Sstevel@tonic-gate if ((pid = fork1()) == 0) { 739*7c478bd9Sstevel@tonic-gate (void) execv("/bin/sh", argvec); 740*7c478bd9Sstevel@tonic-gate _exit(127); 741*7c478bd9Sstevel@tonic-gate } else if (pid == -1) { 742*7c478bd9Sstevel@tonic-gate return (-1); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate do { 746*7c478bd9Sstevel@tonic-gate w = waitpid(pid, &status, 0); 747*7c478bd9Sstevel@tonic-gate } while (w == -1 && errno == EINTR); 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate return ((w == -1) ? w : status); 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate /* Append info at the very end */ 753*7c478bd9Sstevel@tonic-gate int 754*7c478bd9Sstevel@tonic-gate rcm_append_info(rcm_info_t **head, rcm_info_t *info) 755*7c478bd9Sstevel@tonic-gate { 756*7c478bd9Sstevel@tonic-gate rcm_info_t *tuple; 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate if (head == NULL) { 759*7c478bd9Sstevel@tonic-gate errno = EINVAL; 760*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate if ((tuple = *head) == NULL) { 764*7c478bd9Sstevel@tonic-gate *head = info; 765*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate while (tuple->next) { 769*7c478bd9Sstevel@tonic-gate tuple = tuple->next; 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate tuple->next = info; 772*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate /* get rcm module and rcm script directory names */ 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate #define N_MODULE_DIR 3 /* search 3 directories for modules */ 778*7c478bd9Sstevel@tonic-gate #define MODULE_DIR_HW "/usr/platform/%s/lib/rcm/modules/" 779*7c478bd9Sstevel@tonic-gate #define MODULE_DIR_GEN "/usr/lib/rcm/modules/" 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate #define N_SCRIPT_DIR 4 /* search 4 directories for scripts */ 782*7c478bd9Sstevel@tonic-gate #define SCRIPT_DIR_HW "/usr/platform/%s/lib/rcm/scripts/" 783*7c478bd9Sstevel@tonic-gate #define SCRIPT_DIR_GEN "/usr/lib/rcm/scripts/" 784*7c478bd9Sstevel@tonic-gate #define SCRIPT_DIR_ETC "/etc/rcm/scripts/" 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate char * 788*7c478bd9Sstevel@tonic-gate rcm_module_dir(uint_t dirnum) 789*7c478bd9Sstevel@tonic-gate { 790*7c478bd9Sstevel@tonic-gate if (dirnum < N_MODULE_DIR) 791*7c478bd9Sstevel@tonic-gate return (rcm_dir(dirnum, NULL)); 792*7c478bd9Sstevel@tonic-gate else 793*7c478bd9Sstevel@tonic-gate return (NULL); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate char * 797*7c478bd9Sstevel@tonic-gate rcm_script_dir(uint_t dirnum) 798*7c478bd9Sstevel@tonic-gate { 799*7c478bd9Sstevel@tonic-gate if (dirnum < N_SCRIPT_DIR) 800*7c478bd9Sstevel@tonic-gate return (rcm_dir(dirnum + N_MODULE_DIR, NULL)); 801*7c478bd9Sstevel@tonic-gate else 802*7c478bd9Sstevel@tonic-gate return (NULL); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate char * 806*7c478bd9Sstevel@tonic-gate rcm_dir(uint_t dirnum, int *rcm_script) 807*7c478bd9Sstevel@tonic-gate { 808*7c478bd9Sstevel@tonic-gate static char dir_name[N_MODULE_DIR + N_SCRIPT_DIR][MAXPATHLEN]; 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate char infobuf[MAXPATHLEN]; 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate if (dirnum >= (N_MODULE_DIR + N_SCRIPT_DIR)) 813*7c478bd9Sstevel@tonic-gate return (NULL); 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate if (dir_name[0][0] == '\0') { 816*7c478bd9Sstevel@tonic-gate /* 817*7c478bd9Sstevel@tonic-gate * construct the module directory names 818*7c478bd9Sstevel@tonic-gate */ 819*7c478bd9Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, infobuf, MAXPATHLEN) == -1) { 820*7c478bd9Sstevel@tonic-gate dprintf((stderr, "sysinfo %s\n", strerror(errno))); 821*7c478bd9Sstevel@tonic-gate return (NULL); 822*7c478bd9Sstevel@tonic-gate } else { 823*7c478bd9Sstevel@tonic-gate if (snprintf(dir_name[0], MAXPATHLEN, MODULE_DIR_HW, 824*7c478bd9Sstevel@tonic-gate infobuf) >= MAXPATHLEN || 825*7c478bd9Sstevel@tonic-gate snprintf(dir_name[N_MODULE_DIR + 1], MAXPATHLEN, 826*7c478bd9Sstevel@tonic-gate SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) { 827*7c478bd9Sstevel@tonic-gate dprintf((stderr, 828*7c478bd9Sstevel@tonic-gate "invalid module or script directory for " 829*7c478bd9Sstevel@tonic-gate "platform %s\n", infobuf)); 830*7c478bd9Sstevel@tonic-gate return (NULL); 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if (sysinfo(SI_MACHINE, infobuf, MAXPATHLEN) == -1) { 835*7c478bd9Sstevel@tonic-gate dprintf((stderr, "sysinfo %s\n", strerror(errno))); 836*7c478bd9Sstevel@tonic-gate return (NULL); 837*7c478bd9Sstevel@tonic-gate } else { 838*7c478bd9Sstevel@tonic-gate if (snprintf(dir_name[1], MAXPATHLEN, MODULE_DIR_HW, 839*7c478bd9Sstevel@tonic-gate infobuf) >= MAXPATHLEN || 840*7c478bd9Sstevel@tonic-gate snprintf(dir_name[N_MODULE_DIR + 2], MAXPATHLEN, 841*7c478bd9Sstevel@tonic-gate SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) { 842*7c478bd9Sstevel@tonic-gate dprintf((stderr, 843*7c478bd9Sstevel@tonic-gate "invalid module or script directory for " 844*7c478bd9Sstevel@tonic-gate "machine type %s\n", infobuf)); 845*7c478bd9Sstevel@tonic-gate return (NULL); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate if (strlcpy(dir_name[2], MODULE_DIR_GEN, MAXPATHLEN) >= 850*7c478bd9Sstevel@tonic-gate MAXPATHLEN || 851*7c478bd9Sstevel@tonic-gate strlcpy(dir_name[N_MODULE_DIR + 3], SCRIPT_DIR_GEN, 852*7c478bd9Sstevel@tonic-gate MAXPATHLEN) >= MAXPATHLEN || 853*7c478bd9Sstevel@tonic-gate strlcpy(dir_name[N_MODULE_DIR + 0], SCRIPT_DIR_ETC, 854*7c478bd9Sstevel@tonic-gate MAXPATHLEN) >= MAXPATHLEN) { 855*7c478bd9Sstevel@tonic-gate dprintf((stderr, 856*7c478bd9Sstevel@tonic-gate "invalid module or script generic directory\n")); 857*7c478bd9Sstevel@tonic-gate return (NULL); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate if (rcm_script) 862*7c478bd9Sstevel@tonic-gate *rcm_script = (dirnum < N_MODULE_DIR) ? 0 : 1; 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate return (dir_name[dirnum]); 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate /* 868*7c478bd9Sstevel@tonic-gate * Find the directory where the script is located. 869*7c478bd9Sstevel@tonic-gate * If the script is found return a pointer to the directory where the 870*7c478bd9Sstevel@tonic-gate * script was found otherwise return NULL. 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate char * 873*7c478bd9Sstevel@tonic-gate rcm_get_script_dir(char *script_name) 874*7c478bd9Sstevel@tonic-gate { 875*7c478bd9Sstevel@tonic-gate uint_t i; 876*7c478bd9Sstevel@tonic-gate char *dir_name; 877*7c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 878*7c478bd9Sstevel@tonic-gate struct stat stats; 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate for (i = 0; (dir_name = rcm_script_dir(i)) != NULL; i++) { 881*7c478bd9Sstevel@tonic-gate if (snprintf(path, MAXPATHLEN, "%s%s", dir_name, script_name) 882*7c478bd9Sstevel@tonic-gate >= MAXPATHLEN) { 883*7c478bd9Sstevel@tonic-gate dprintf((stderr, "invalid script %s skipped\n", 884*7c478bd9Sstevel@tonic-gate script_name)); 885*7c478bd9Sstevel@tonic-gate continue; 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate if (stat(path, &stats) == 0) 888*7c478bd9Sstevel@tonic-gate return (dir_name); 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate return (NULL); 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate /* 895*7c478bd9Sstevel@tonic-gate * Returns 1 if the filename is an rcm script. 896*7c478bd9Sstevel@tonic-gate * Returns 0 if the filename is an rcm module. 897*7c478bd9Sstevel@tonic-gate */ 898*7c478bd9Sstevel@tonic-gate int 899*7c478bd9Sstevel@tonic-gate rcm_is_script(char *filename) 900*7c478bd9Sstevel@tonic-gate { 901*7c478bd9Sstevel@tonic-gate char *tmp; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate if (((tmp = strstr(filename, RCM_MODULE_SUFFIX)) != NULL) && 904*7c478bd9Sstevel@tonic-gate (tmp[strlen(RCM_MODULE_SUFFIX)] == '\0')) 905*7c478bd9Sstevel@tonic-gate return (0); 906*7c478bd9Sstevel@tonic-gate else 907*7c478bd9Sstevel@tonic-gate return (1); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate /* Locate the module and call dlopen */ 911*7c478bd9Sstevel@tonic-gate void * 912*7c478bd9Sstevel@tonic-gate rcm_module_open(char *modname) 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate unsigned i; 915*7c478bd9Sstevel@tonic-gate char *dir_name; 916*7c478bd9Sstevel@tonic-gate void *dlhandle = NULL; 917*7c478bd9Sstevel@tonic-gate char modpath[MAXPATHLEN]; 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 920*7c478bd9Sstevel@tonic-gate struct stat sbuf; 921*7c478bd9Sstevel@tonic-gate #endif 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate /* 924*7c478bd9Sstevel@tonic-gate * dlopen the module 925*7c478bd9Sstevel@tonic-gate */ 926*7c478bd9Sstevel@tonic-gate for (i = 0; (dir_name = rcm_module_dir(i)) != NULL; i++) { 927*7c478bd9Sstevel@tonic-gate if (snprintf(modpath, MAXPATHLEN, "%s%s", dir_name, modname) 928*7c478bd9Sstevel@tonic-gate >= MAXPATHLEN) { 929*7c478bd9Sstevel@tonic-gate dprintf((stderr, "invalid module %s skipped\n", 930*7c478bd9Sstevel@tonic-gate modname)); 931*7c478bd9Sstevel@tonic-gate continue; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate if ((dlhandle = dlopen(modpath, RTLD_LAZY)) != NULL) { 935*7c478bd9Sstevel@tonic-gate return (dlhandle); 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failure (dlopen=%s)\n", dlerror())); 939*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 940*7c478bd9Sstevel@tonic-gate if (stat(modpath, &sbuf) == 0) { 941*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s is not a valid module\n", 942*7c478bd9Sstevel@tonic-gate modpath); 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate #endif 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate dprintf((stderr, "module %s not found\n", modname)); 948*7c478bd9Sstevel@tonic-gate return (NULL); 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate /* dlclose module */ 952*7c478bd9Sstevel@tonic-gate void 953*7c478bd9Sstevel@tonic-gate rcm_module_close(void *dlhandle) 954*7c478bd9Sstevel@tonic-gate { 955*7c478bd9Sstevel@tonic-gate if (dlclose(dlhandle) == 0) 956*7c478bd9Sstevel@tonic-gate return; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate dprintf((stderr, "dlclose: %s\n", dlerror())); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate /* 963*7c478bd9Sstevel@tonic-gate * stub implementation of rcm_log_message allows dlopen of rcm modules 964*7c478bd9Sstevel@tonic-gate * to proceed in absence of rcm_daemon. 965*7c478bd9Sstevel@tonic-gate * 966*7c478bd9Sstevel@tonic-gate * This definition is interposed by the definition in rcm_daemon because of the 967*7c478bd9Sstevel@tonic-gate * default search order implemented by the linker and dlsym(). All RCM modules 968*7c478bd9Sstevel@tonic-gate * will see the daemon version when loaded by the rcm_daemon. 969*7c478bd9Sstevel@tonic-gate */ 970*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 971*7c478bd9Sstevel@tonic-gate void 972*7c478bd9Sstevel@tonic-gate rcm_log_message(int level, char *message, ...) 973*7c478bd9Sstevel@tonic-gate { 974*7c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_log_message stub\n")); 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate /* 978*7c478bd9Sstevel@tonic-gate * Helper functions 979*7c478bd9Sstevel@tonic-gate */ 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate /* 982*7c478bd9Sstevel@tonic-gate * Common routine for all rcm calls which require daemon processing 983*7c478bd9Sstevel@tonic-gate */ 984*7c478bd9Sstevel@tonic-gate static int 985*7c478bd9Sstevel@tonic-gate rcm_common(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, void *arg, 986*7c478bd9Sstevel@tonic-gate rcm_info_t **infop) 987*7c478bd9Sstevel@tonic-gate { 988*7c478bd9Sstevel@tonic-gate int i; 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate if (hd == NULL) { 991*7c478bd9Sstevel@tonic-gate errno = EINVAL; 992*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate if (getuid() != 0) { 996*7c478bd9Sstevel@tonic-gate errno = EPERM; 997*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 998*7c478bd9Sstevel@tonic-gate } 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate if ((flag & (RCM_DR_OPERATION | RCM_MOD_INFO)) == 0) { 1001*7c478bd9Sstevel@tonic-gate if ((rsrcnames == NULL) || (rsrcnames[0] == NULL)) { 1002*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1003*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate for (i = 0; rsrcnames[i] != NULL; i++) { 1007*7c478bd9Sstevel@tonic-gate if (*rsrcnames[i] == '\0') { 1008*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1009*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate } 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate /* 1015*7c478bd9Sstevel@tonic-gate * Check if handle is allocated by rcm_daemon. If so, this call came 1016*7c478bd9Sstevel@tonic-gate * from an RCM module, so we make a direct call into rcm_daemon. 1017*7c478bd9Sstevel@tonic-gate */ 1018*7c478bd9Sstevel@tonic-gate if (hd->lrcm_ops != NULL) { 1019*7c478bd9Sstevel@tonic-gate return (rcm_direct_call(cmd, hd, rsrcnames, flag, arg, infop)); 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate /* 1023*7c478bd9Sstevel@tonic-gate * When not called from a RCM module (i.e. no recursion), zero the 1024*7c478bd9Sstevel@tonic-gate * pointer just in case caller did not do so. For recursive calls, 1025*7c478bd9Sstevel@tonic-gate * we want to append rcm_info_t after infop; zero it may cause 1026*7c478bd9Sstevel@tonic-gate * memory leaks. 1027*7c478bd9Sstevel@tonic-gate */ 1028*7c478bd9Sstevel@tonic-gate if (infop) { 1029*7c478bd9Sstevel@tonic-gate *infop = NULL; 1030*7c478bd9Sstevel@tonic-gate } 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate /* 1033*7c478bd9Sstevel@tonic-gate * Now call into the daemon. 1034*7c478bd9Sstevel@tonic-gate */ 1035*7c478bd9Sstevel@tonic-gate return (rcm_daemon_call(cmd, hd, rsrcnames, flag, arg, infop)); 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate /* 1039*7c478bd9Sstevel@tonic-gate * Caller is an RCM module, call directly into rcm_daemon. 1040*7c478bd9Sstevel@tonic-gate */ 1041*7c478bd9Sstevel@tonic-gate static int 1042*7c478bd9Sstevel@tonic-gate rcm_direct_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, 1043*7c478bd9Sstevel@tonic-gate void *arg, rcm_info_t **infop) 1044*7c478bd9Sstevel@tonic-gate { 1045*7c478bd9Sstevel@tonic-gate int error; 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate librcm_ops_t *ops = (librcm_ops_t *)hd->lrcm_ops; 1048*7c478bd9Sstevel@tonic-gate switch (cmd) { 1049*7c478bd9Sstevel@tonic-gate case CMD_GETINFO: 1050*7c478bd9Sstevel@tonic-gate error = ops->librcm_getinfo(rsrcnames, flag, hd->seq_num, 1051*7c478bd9Sstevel@tonic-gate infop); 1052*7c478bd9Sstevel@tonic-gate break; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate case CMD_OFFLINE: 1055*7c478bd9Sstevel@tonic-gate error = ops->librcm_offline(rsrcnames, hd->pid, flag, 1056*7c478bd9Sstevel@tonic-gate hd->seq_num, infop); 1057*7c478bd9Sstevel@tonic-gate break; 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate case CMD_ONLINE: 1060*7c478bd9Sstevel@tonic-gate error = ops->librcm_online(rsrcnames, hd->pid, flag, 1061*7c478bd9Sstevel@tonic-gate hd->seq_num, infop); 1062*7c478bd9Sstevel@tonic-gate break; 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate case CMD_REMOVE: 1065*7c478bd9Sstevel@tonic-gate error = ops->librcm_remove(rsrcnames, hd->pid, flag, 1066*7c478bd9Sstevel@tonic-gate hd->seq_num, infop); 1067*7c478bd9Sstevel@tonic-gate break; 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate case CMD_SUSPEND: 1070*7c478bd9Sstevel@tonic-gate error = ops->librcm_suspend(rsrcnames, hd->pid, flag, 1071*7c478bd9Sstevel@tonic-gate hd->seq_num, (timespec_t *)arg, infop); 1072*7c478bd9Sstevel@tonic-gate break; 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate case CMD_RESUME: 1075*7c478bd9Sstevel@tonic-gate error = ops->librcm_resume(rsrcnames, hd->pid, flag, 1076*7c478bd9Sstevel@tonic-gate hd->seq_num, infop); 1077*7c478bd9Sstevel@tonic-gate break; 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate case CMD_REGISTER: 1080*7c478bd9Sstevel@tonic-gate error = ops->librcm_regis(hd->modname, rsrcnames[0], hd->pid, 1081*7c478bd9Sstevel@tonic-gate flag, infop); 1082*7c478bd9Sstevel@tonic-gate break; 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate case CMD_UNREGISTER: 1085*7c478bd9Sstevel@tonic-gate error = ops->librcm_unregis(hd->modname, rsrcnames[0], hd->pid, 1086*7c478bd9Sstevel@tonic-gate flag); 1087*7c478bd9Sstevel@tonic-gate break; 1088*7c478bd9Sstevel@tonic-gate 1089*7c478bd9Sstevel@tonic-gate case CMD_REQUEST_CHANGE: 1090*7c478bd9Sstevel@tonic-gate error = ops->librcm_request_change(rsrcnames[0], hd->pid, flag, 1091*7c478bd9Sstevel@tonic-gate hd->seq_num, (nvlist_t *)arg, infop); 1092*7c478bd9Sstevel@tonic-gate break; 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate case CMD_NOTIFY_CHANGE: 1095*7c478bd9Sstevel@tonic-gate error = ops->librcm_notify_change(rsrcnames[0], hd->pid, flag, 1096*7c478bd9Sstevel@tonic-gate hd->seq_num, (nvlist_t *)arg, infop); 1097*7c478bd9Sstevel@tonic-gate break; 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate case CMD_EVENT: 1100*7c478bd9Sstevel@tonic-gate error = ops->librcm_notify_event(rsrcnames[0], hd->pid, flag, 1101*7c478bd9Sstevel@tonic-gate hd->seq_num, (nvlist_t *)arg, infop); 1102*7c478bd9Sstevel@tonic-gate break; 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate case CMD_GETSTATE: 1105*7c478bd9Sstevel@tonic-gate error = ops->librcm_getstate(rsrcnames[0], hd->pid, infop); 1106*7c478bd9Sstevel@tonic-gate break; 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate default: 1109*7c478bd9Sstevel@tonic-gate dprintf((stderr, "invalid command: %d\n", cmd)); 1110*7c478bd9Sstevel@tonic-gate error = EFAULT; 1111*7c478bd9Sstevel@tonic-gate } 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate if (error > 0) { 1114*7c478bd9Sstevel@tonic-gate errno = error; 1115*7c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate return (error); 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate /* 1121*7c478bd9Sstevel@tonic-gate * Call into rcm_daemon door to process the request 1122*7c478bd9Sstevel@tonic-gate */ 1123*7c478bd9Sstevel@tonic-gate static int 1124*7c478bd9Sstevel@tonic-gate rcm_daemon_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, 1125*7c478bd9Sstevel@tonic-gate void *arg, rcm_info_t **infop) 1126*7c478bd9Sstevel@tonic-gate { 1127*7c478bd9Sstevel@tonic-gate int errno_found; 1128*7c478bd9Sstevel@tonic-gate int daemon_errno; 1129*7c478bd9Sstevel@tonic-gate int error = RCM_SUCCESS; 1130*7c478bd9Sstevel@tonic-gate int delay = 300; 1131*7c478bd9Sstevel@tonic-gate int maxdelay = 10000; /* 10 seconds */ 1132*7c478bd9Sstevel@tonic-gate char *nvl_packed = NULL; 1133*7c478bd9Sstevel@tonic-gate size_t nvl_size = 0; 1134*7c478bd9Sstevel@tonic-gate nvlist_t *ret = NULL; 1135*7c478bd9Sstevel@tonic-gate nvpair_t *nvp; 1136*7c478bd9Sstevel@tonic-gate size_t rsize = 0; 1137*7c478bd9Sstevel@tonic-gate rcm_info_t *info = NULL; 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate errno = 0; 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate /* 1142*7c478bd9Sstevel@tonic-gate * Decide whether to start the daemon 1143*7c478bd9Sstevel@tonic-gate */ 1144*7c478bd9Sstevel@tonic-gate switch (cmd) { 1145*7c478bd9Sstevel@tonic-gate case CMD_GETINFO: 1146*7c478bd9Sstevel@tonic-gate case CMD_OFFLINE: 1147*7c478bd9Sstevel@tonic-gate case CMD_ONLINE: 1148*7c478bd9Sstevel@tonic-gate case CMD_REMOVE: 1149*7c478bd9Sstevel@tonic-gate case CMD_SUSPEND: 1150*7c478bd9Sstevel@tonic-gate case CMD_RESUME: 1151*7c478bd9Sstevel@tonic-gate case CMD_REGISTER: 1152*7c478bd9Sstevel@tonic-gate case CMD_UNREGISTER: 1153*7c478bd9Sstevel@tonic-gate case CMD_EVENT: 1154*7c478bd9Sstevel@tonic-gate case CMD_REQUEST_CHANGE: 1155*7c478bd9Sstevel@tonic-gate case CMD_NOTIFY_CHANGE: 1156*7c478bd9Sstevel@tonic-gate case CMD_GETSTATE: 1157*7c478bd9Sstevel@tonic-gate break; 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate default: 1160*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1161*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1162*7c478bd9Sstevel@tonic-gate } 1163*7c478bd9Sstevel@tonic-gate 1164*7c478bd9Sstevel@tonic-gate if (rcm_daemon_is_alive() != 1) { 1165*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed to start rcm_daemon\n")); 1166*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1167*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1168*7c478bd9Sstevel@tonic-gate } 1169*7c478bd9Sstevel@tonic-gate 1170*7c478bd9Sstevel@tonic-gate /* 1171*7c478bd9Sstevel@tonic-gate * Generate a packed nvlist for the request 1172*7c478bd9Sstevel@tonic-gate */ 1173*7c478bd9Sstevel@tonic-gate if (rcm_generate_nvlist(cmd, hd, rsrcnames, flag, arg, &nvl_packed, 1174*7c478bd9Sstevel@tonic-gate &nvl_size) < 0) { 1175*7c478bd9Sstevel@tonic-gate dprintf((stderr, "error in nvlist generation\n")); 1176*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1177*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1178*7c478bd9Sstevel@tonic-gate } 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate /* 1181*7c478bd9Sstevel@tonic-gate * Make the door call and get a return event. We go into a retry loop 1182*7c478bd9Sstevel@tonic-gate * when RCM_ET_EAGAIN is returned. 1183*7c478bd9Sstevel@tonic-gate */ 1184*7c478bd9Sstevel@tonic-gate retry: 1185*7c478bd9Sstevel@tonic-gate if (get_event_service(RCM_SERVICE_DOOR, (void *)nvl_packed, nvl_size, 1186*7c478bd9Sstevel@tonic-gate (void **)&ret, &rsize) < 0) { 1187*7c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_daemon call failed: %s\n", 1188*7c478bd9Sstevel@tonic-gate strerror(errno))); 1189*7c478bd9Sstevel@tonic-gate free(nvl_packed); 1190*7c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate assert(ret != NULL); 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate /* 1196*7c478bd9Sstevel@tonic-gate * nvlist_lookup_* routines don't work because the returned nvlist 1197*7c478bd9Sstevel@tonic-gate * was nvlist_alloc'ed without the NV_UNIQUE_NAME flag. Implement 1198*7c478bd9Sstevel@tonic-gate * a sequential search manually, which is fine since there is only 1199*7c478bd9Sstevel@tonic-gate * one RCM_RESULT value in the nvlist. 1200*7c478bd9Sstevel@tonic-gate */ 1201*7c478bd9Sstevel@tonic-gate errno_found = 0; 1202*7c478bd9Sstevel@tonic-gate nvp = NULL; 1203*7c478bd9Sstevel@tonic-gate while (nvp = nvlist_next_nvpair(ret, nvp)) { 1204*7c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvp), RCM_RESULT) == 0) { 1205*7c478bd9Sstevel@tonic-gate if (errno = nvpair_value_int32(nvp, &daemon_errno)) { 1206*7c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 1207*7c478bd9Sstevel@tonic-gate goto out; 1208*7c478bd9Sstevel@tonic-gate } 1209*7c478bd9Sstevel@tonic-gate errno_found++; 1210*7c478bd9Sstevel@tonic-gate break; 1211*7c478bd9Sstevel@tonic-gate } 1212*7c478bd9Sstevel@tonic-gate } 1213*7c478bd9Sstevel@tonic-gate if (errno_found == 0) { 1214*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1215*7c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 1216*7c478bd9Sstevel@tonic-gate goto out; 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate if (daemon_errno == EAGAIN) { 1220*7c478bd9Sstevel@tonic-gate /* 1221*7c478bd9Sstevel@tonic-gate * Wait and retry 1222*7c478bd9Sstevel@tonic-gate */ 1223*7c478bd9Sstevel@tonic-gate dprintf((stderr, "retry door_call\n")); 1224*7c478bd9Sstevel@tonic-gate 1225*7c478bd9Sstevel@tonic-gate if (delay > maxdelay) { 1226*7c478bd9Sstevel@tonic-gate errno = EAGAIN; 1227*7c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 1228*7c478bd9Sstevel@tonic-gate goto out; 1229*7c478bd9Sstevel@tonic-gate } 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, delay); 1232*7c478bd9Sstevel@tonic-gate delay *= 2; /* exponential back off */ 1233*7c478bd9Sstevel@tonic-gate nvlist_free(ret); 1234*7c478bd9Sstevel@tonic-gate goto retry; 1235*7c478bd9Sstevel@tonic-gate } 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate /* 1238*7c478bd9Sstevel@tonic-gate * The door call succeeded. Now extract info from returned event. 1239*7c478bd9Sstevel@tonic-gate */ 1240*7c478bd9Sstevel@tonic-gate if (extract_info(ret, &info) != 0) { 1241*7c478bd9Sstevel@tonic-gate dprintf((stderr, "error in extracting event data\n")); 1242*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1243*7c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 1244*7c478bd9Sstevel@tonic-gate goto out; 1245*7c478bd9Sstevel@tonic-gate } 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate if (infop) 1248*7c478bd9Sstevel@tonic-gate *infop = info; 1249*7c478bd9Sstevel@tonic-gate else 1250*7c478bd9Sstevel@tonic-gate rcm_free_info(info); 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate if (daemon_errno) { 1253*7c478bd9Sstevel@tonic-gate if (daemon_errno > 0) { 1254*7c478bd9Sstevel@tonic-gate errno = daemon_errno; 1255*7c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 1256*7c478bd9Sstevel@tonic-gate } else { 1257*7c478bd9Sstevel@tonic-gate error = daemon_errno; 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate } 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate out: 1262*7c478bd9Sstevel@tonic-gate if (nvl_packed) 1263*7c478bd9Sstevel@tonic-gate free(nvl_packed); 1264*7c478bd9Sstevel@tonic-gate if (ret) 1265*7c478bd9Sstevel@tonic-gate nvlist_free(ret); 1266*7c478bd9Sstevel@tonic-gate dprintf((stderr, "daemon call is done. error = %d, errno = %s\n", error, 1267*7c478bd9Sstevel@tonic-gate strerror(errno))); 1268*7c478bd9Sstevel@tonic-gate return (error); 1269*7c478bd9Sstevel@tonic-gate } 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate /* 1272*7c478bd9Sstevel@tonic-gate * Extract registration info from event data. 1273*7c478bd9Sstevel@tonic-gate * Return 0 on success and -1 on failure. 1274*7c478bd9Sstevel@tonic-gate */ 1275*7c478bd9Sstevel@tonic-gate static int 1276*7c478bd9Sstevel@tonic-gate extract_info(nvlist_t *nvl, rcm_info_t **infop) 1277*7c478bd9Sstevel@tonic-gate { 1278*7c478bd9Sstevel@tonic-gate rcm_info_t *info = NULL; 1279*7c478bd9Sstevel@tonic-gate rcm_info_t *prev = NULL; 1280*7c478bd9Sstevel@tonic-gate rcm_info_t *tmp = NULL; 1281*7c478bd9Sstevel@tonic-gate char *buf; 1282*7c478bd9Sstevel@tonic-gate uint_t buflen; 1283*7c478bd9Sstevel@tonic-gate nvpair_t *nvp = NULL; 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate while (nvp = nvlist_next_nvpair(nvl, nvp)) { 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate buf = NULL; 1288*7c478bd9Sstevel@tonic-gate buflen = 0; 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvp), RCM_RESULT_INFO) != 0) 1291*7c478bd9Sstevel@tonic-gate continue; 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { 1294*7c478bd9Sstevel@tonic-gate dprintf((stderr, "out of memory\n")); 1295*7c478bd9Sstevel@tonic-gate goto fail; 1296*7c478bd9Sstevel@tonic-gate } 1297*7c478bd9Sstevel@tonic-gate 1298*7c478bd9Sstevel@tonic-gate if (errno = nvpair_value_byte_array(nvp, (uchar_t **)&buf, 1299*7c478bd9Sstevel@tonic-gate &buflen)) { 1300*7c478bd9Sstevel@tonic-gate free(tmp); 1301*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvpair_value=%s)\n", 1302*7c478bd9Sstevel@tonic-gate strerror(errno))); 1303*7c478bd9Sstevel@tonic-gate goto fail; 1304*7c478bd9Sstevel@tonic-gate } 1305*7c478bd9Sstevel@tonic-gate if (errno = nvlist_unpack(buf, buflen, &(tmp->info), 0)) { 1306*7c478bd9Sstevel@tonic-gate free(tmp); 1307*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_unpack=%s)\n", 1308*7c478bd9Sstevel@tonic-gate strerror(errno))); 1309*7c478bd9Sstevel@tonic-gate goto fail; 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate if (info == NULL) { 1313*7c478bd9Sstevel@tonic-gate prev = info = tmp; 1314*7c478bd9Sstevel@tonic-gate } else { 1315*7c478bd9Sstevel@tonic-gate prev->next = tmp; 1316*7c478bd9Sstevel@tonic-gate prev = tmp; 1317*7c478bd9Sstevel@tonic-gate } 1318*7c478bd9Sstevel@tonic-gate } 1319*7c478bd9Sstevel@tonic-gate 1320*7c478bd9Sstevel@tonic-gate *infop = info; 1321*7c478bd9Sstevel@tonic-gate return (0); 1322*7c478bd9Sstevel@tonic-gate 1323*7c478bd9Sstevel@tonic-gate fail: 1324*7c478bd9Sstevel@tonic-gate rcm_free_info(info); 1325*7c478bd9Sstevel@tonic-gate *infop = NULL; 1326*7c478bd9Sstevel@tonic-gate return (-1); 1327*7c478bd9Sstevel@tonic-gate } 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate /* Generate a packed nvlist for communicating with RCM daemon */ 1330*7c478bd9Sstevel@tonic-gate static int 1331*7c478bd9Sstevel@tonic-gate rcm_generate_nvlist(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, 1332*7c478bd9Sstevel@tonic-gate void *arg, char **nvl_packed, size_t *nvl_size) 1333*7c478bd9Sstevel@tonic-gate { 1334*7c478bd9Sstevel@tonic-gate int nrsrcnames; 1335*7c478bd9Sstevel@tonic-gate char *buf = NULL; 1336*7c478bd9Sstevel@tonic-gate size_t buflen = 0; 1337*7c478bd9Sstevel@tonic-gate nvlist_t *nvl = NULL; 1338*7c478bd9Sstevel@tonic-gate 1339*7c478bd9Sstevel@tonic-gate assert((nvl_packed != NULL) && (nvl_size != NULL)); 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate *nvl_size = 0; 1342*7c478bd9Sstevel@tonic-gate *nvl_packed = NULL; 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate /* Allocate an empty nvlist */ 1345*7c478bd9Sstevel@tonic-gate if ((errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) > 0) { 1346*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_alloc=%s).\n", 1347*7c478bd9Sstevel@tonic-gate strerror(errno))); 1348*7c478bd9Sstevel@tonic-gate return (-1); 1349*7c478bd9Sstevel@tonic-gate } 1350*7c478bd9Sstevel@tonic-gate 1351*7c478bd9Sstevel@tonic-gate /* Stuff in all the arguments for the daemon call */ 1352*7c478bd9Sstevel@tonic-gate if (nvlist_add_int32(nvl, RCM_CMD, cmd) != 0) { 1353*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_add(CMD)=%s).\n", 1354*7c478bd9Sstevel@tonic-gate strerror(errno))); 1355*7c478bd9Sstevel@tonic-gate goto fail; 1356*7c478bd9Sstevel@tonic-gate } 1357*7c478bd9Sstevel@tonic-gate if (rsrcnames) { 1358*7c478bd9Sstevel@tonic-gate nrsrcnames = 0; 1359*7c478bd9Sstevel@tonic-gate while (rsrcnames[nrsrcnames] != NULL) 1360*7c478bd9Sstevel@tonic-gate nrsrcnames++; 1361*7c478bd9Sstevel@tonic-gate if (nvlist_add_string_array(nvl, RCM_RSRCNAMES, rsrcnames, 1362*7c478bd9Sstevel@tonic-gate nrsrcnames) != 0) { 1363*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_add(RSRCNAMES)=%s).\n", 1364*7c478bd9Sstevel@tonic-gate strerror(errno))); 1365*7c478bd9Sstevel@tonic-gate goto fail; 1366*7c478bd9Sstevel@tonic-gate } 1367*7c478bd9Sstevel@tonic-gate } 1368*7c478bd9Sstevel@tonic-gate if (hd->modname) { 1369*7c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, RCM_CLIENT_MODNAME, hd->modname) 1370*7c478bd9Sstevel@tonic-gate != 0) { 1371*7c478bd9Sstevel@tonic-gate dprintf((stderr, 1372*7c478bd9Sstevel@tonic-gate "failed (nvlist_add(CLIENT_MODNAME)=%s).\n", 1373*7c478bd9Sstevel@tonic-gate strerror(errno))); 1374*7c478bd9Sstevel@tonic-gate goto fail; 1375*7c478bd9Sstevel@tonic-gate } 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate if (hd->pid) { 1378*7c478bd9Sstevel@tonic-gate if (nvlist_add_uint64(nvl, RCM_CLIENT_ID, hd->pid) != 0) { 1379*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_add(CLIENT_ID)=%s).\n", 1380*7c478bd9Sstevel@tonic-gate strerror(errno))); 1381*7c478bd9Sstevel@tonic-gate goto fail; 1382*7c478bd9Sstevel@tonic-gate } 1383*7c478bd9Sstevel@tonic-gate } 1384*7c478bd9Sstevel@tonic-gate if (flag) { 1385*7c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, RCM_REQUEST_FLAG, flag) != 0) { 1386*7c478bd9Sstevel@tonic-gate dprintf((stderr, 1387*7c478bd9Sstevel@tonic-gate "failed (nvlist_add(REQUEST_FLAG)=%s).\n", 1388*7c478bd9Sstevel@tonic-gate strerror(errno))); 1389*7c478bd9Sstevel@tonic-gate goto fail; 1390*7c478bd9Sstevel@tonic-gate } 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate if (arg && cmd == CMD_SUSPEND) { 1393*7c478bd9Sstevel@tonic-gate if (nvlist_add_byte_array(nvl, RCM_SUSPEND_INTERVAL, 1394*7c478bd9Sstevel@tonic-gate (uchar_t *)arg, sizeof (timespec_t)) != 0) { 1395*7c478bd9Sstevel@tonic-gate dprintf((stderr, 1396*7c478bd9Sstevel@tonic-gate "failed (nvlist_add(SUSPEND_INTERVAL)=%s).\n", 1397*7c478bd9Sstevel@tonic-gate strerror(errno))); 1398*7c478bd9Sstevel@tonic-gate goto fail; 1399*7c478bd9Sstevel@tonic-gate } 1400*7c478bd9Sstevel@tonic-gate } 1401*7c478bd9Sstevel@tonic-gate if (arg && 1402*7c478bd9Sstevel@tonic-gate ((cmd == CMD_REQUEST_CHANGE) || (cmd == CMD_NOTIFY_CHANGE))) { 1403*7c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE, 1404*7c478bd9Sstevel@tonic-gate 0)) { 1405*7c478bd9Sstevel@tonic-gate dprintf((stderr, 1406*7c478bd9Sstevel@tonic-gate "failed (nvlist_pack(CHANGE_DATA)=%s).\n", 1407*7c478bd9Sstevel@tonic-gate strerror(errno))); 1408*7c478bd9Sstevel@tonic-gate goto fail; 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate if (nvlist_add_byte_array(nvl, RCM_CHANGE_DATA, (uchar_t *)buf, 1411*7c478bd9Sstevel@tonic-gate buflen) != 0) { 1412*7c478bd9Sstevel@tonic-gate dprintf((stderr, 1413*7c478bd9Sstevel@tonic-gate "failed (nvlist_add(CHANGE_DATA)=%s).\n", 1414*7c478bd9Sstevel@tonic-gate strerror(errno))); 1415*7c478bd9Sstevel@tonic-gate goto fail; 1416*7c478bd9Sstevel@tonic-gate } 1417*7c478bd9Sstevel@tonic-gate } 1418*7c478bd9Sstevel@tonic-gate if (arg && cmd == CMD_EVENT) { 1419*7c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE, 1420*7c478bd9Sstevel@tonic-gate 0)) { 1421*7c478bd9Sstevel@tonic-gate dprintf((stderr, 1422*7c478bd9Sstevel@tonic-gate "failed (nvlist_pack(CHANGE_DATA)=%s).\n", 1423*7c478bd9Sstevel@tonic-gate strerror(errno))); 1424*7c478bd9Sstevel@tonic-gate goto fail; 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate if (nvlist_add_byte_array(nvl, RCM_EVENT_DATA, (uchar_t *)buf, 1427*7c478bd9Sstevel@tonic-gate buflen) != 0) { 1428*7c478bd9Sstevel@tonic-gate dprintf((stderr, 1429*7c478bd9Sstevel@tonic-gate "failed (nvlist_add(EVENT_DATA)=%s).\n", 1430*7c478bd9Sstevel@tonic-gate strerror(errno))); 1431*7c478bd9Sstevel@tonic-gate goto fail; 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate } 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate /* Pack the nvlist */ 1436*7c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(nvl, nvl_packed, nvl_size, NV_ENCODE_NATIVE, 1437*7c478bd9Sstevel@tonic-gate 0)) { 1438*7c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_pack=%s).\n", 1439*7c478bd9Sstevel@tonic-gate strerror(errno))); 1440*7c478bd9Sstevel@tonic-gate goto fail; 1441*7c478bd9Sstevel@tonic-gate } 1442*7c478bd9Sstevel@tonic-gate 1443*7c478bd9Sstevel@tonic-gate /* If an argument was packed intermediately, free the buffer */ 1444*7c478bd9Sstevel@tonic-gate if (buf) 1445*7c478bd9Sstevel@tonic-gate free(buf); 1446*7c478bd9Sstevel@tonic-gate 1447*7c478bd9Sstevel@tonic-gate /* Free the unpacked version of the nvlist and return the packed list */ 1448*7c478bd9Sstevel@tonic-gate nvlist_free(nvl); 1449*7c478bd9Sstevel@tonic-gate return (0); 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate fail: 1452*7c478bd9Sstevel@tonic-gate if (buf) 1453*7c478bd9Sstevel@tonic-gate free(buf); 1454*7c478bd9Sstevel@tonic-gate if (nvl) 1455*7c478bd9Sstevel@tonic-gate nvlist_free(nvl); 1456*7c478bd9Sstevel@tonic-gate if (*nvl_packed) 1457*7c478bd9Sstevel@tonic-gate free(*nvl_packed); 1458*7c478bd9Sstevel@tonic-gate *nvl_packed = NULL; 1459*7c478bd9Sstevel@tonic-gate *nvl_size = 0; 1460*7c478bd9Sstevel@tonic-gate return (-1); 1461*7c478bd9Sstevel@tonic-gate } 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate /* check if rcm_daemon is up and running */ 1464*7c478bd9Sstevel@tonic-gate static int 1465*7c478bd9Sstevel@tonic-gate rcm_daemon_is_alive() 1466*7c478bd9Sstevel@tonic-gate { 1467*7c478bd9Sstevel@tonic-gate int lasttry; 1468*7c478bd9Sstevel@tonic-gate struct stat st; 1469*7c478bd9Sstevel@tonic-gate nvlist_t *nvl; 1470*7c478bd9Sstevel@tonic-gate char *buf = NULL; 1471*7c478bd9Sstevel@tonic-gate size_t buflen = 0; 1472*7c478bd9Sstevel@tonic-gate int delay = 300; 1473*7c478bd9Sstevel@tonic-gate const int maxdelay = 10000; /* 10 sec */ 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate /* generate a packed nvlist for the door knocking */ 1476*7c478bd9Sstevel@tonic-gate if (errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) { 1477*7c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_alloc failed: %s\n", strerror(errno))); 1478*7c478bd9Sstevel@tonic-gate return (0); 1479*7c478bd9Sstevel@tonic-gate } 1480*7c478bd9Sstevel@tonic-gate if (errno = nvlist_add_int32(nvl, RCM_CMD, CMD_KNOCK)) { 1481*7c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add failed: %s\n", strerror(errno))); 1482*7c478bd9Sstevel@tonic-gate nvlist_free(nvl); 1483*7c478bd9Sstevel@tonic-gate return (0); 1484*7c478bd9Sstevel@tonic-gate } 1485*7c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_NATIVE, 0)) { 1486*7c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_pack failed: %s\n", strerror(errno))); 1487*7c478bd9Sstevel@tonic-gate nvlist_free(nvl); 1488*7c478bd9Sstevel@tonic-gate return (0); 1489*7c478bd9Sstevel@tonic-gate } 1490*7c478bd9Sstevel@tonic-gate nvlist_free(nvl); 1491*7c478bd9Sstevel@tonic-gate 1492*7c478bd9Sstevel@tonic-gate /* 1493*7c478bd9Sstevel@tonic-gate * check the door and knock on it 1494*7c478bd9Sstevel@tonic-gate */ 1495*7c478bd9Sstevel@tonic-gate if ((stat(RCM_SERVICE_DOOR, &st) == 0) && 1496*7c478bd9Sstevel@tonic-gate (get_event_service(RCM_SERVICE_DOOR, (void *)buf, buflen, NULL, 1497*7c478bd9Sstevel@tonic-gate NULL) == 0)) { 1498*7c478bd9Sstevel@tonic-gate free(buf); 1499*7c478bd9Sstevel@tonic-gate return (1); /* daemon is alive */ 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate 1502*7c478bd9Sstevel@tonic-gate /* 1503*7c478bd9Sstevel@tonic-gate * Attempt to start the daemon. 1504*7c478bd9Sstevel@tonic-gate * If caller has SIGCHLD set to SIG_IGN or its SA_NOCLDWAIT 1505*7c478bd9Sstevel@tonic-gate * flag set, waitpid(2) (hence rcm_exec_cmd) will fail. 1506*7c478bd9Sstevel@tonic-gate * get_event_service will determine if the rcm_daemon started. 1507*7c478bd9Sstevel@tonic-gate */ 1508*7c478bd9Sstevel@tonic-gate dprintf((stderr, "exec: %s\n", RCM_DAEMON_START)); 1509*7c478bd9Sstevel@tonic-gate (void) rcm_exec_cmd(RCM_DAEMON_START); 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate /* 1512*7c478bd9Sstevel@tonic-gate * Wait for daemon to respond, timeout at 10 sec 1513*7c478bd9Sstevel@tonic-gate */ 1514*7c478bd9Sstevel@tonic-gate while (((lasttry = get_event_service(RCM_SERVICE_DOOR, (void *)buf, 1515*7c478bd9Sstevel@tonic-gate buflen, NULL, NULL)) != 0) && 1516*7c478bd9Sstevel@tonic-gate ((errno == EBADF) || (errno == ESRCH))) { 1517*7c478bd9Sstevel@tonic-gate if (delay > maxdelay) { 1518*7c478bd9Sstevel@tonic-gate break; 1519*7c478bd9Sstevel@tonic-gate } 1520*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, delay); 1521*7c478bd9Sstevel@tonic-gate delay *= 2; 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate free(buf); 1525*7c478bd9Sstevel@tonic-gate if (lasttry == 0) 1526*7c478bd9Sstevel@tonic-gate return (1); 1527*7c478bd9Sstevel@tonic-gate return (0); 1528*7c478bd9Sstevel@tonic-gate } 1529*7c478bd9Sstevel@tonic-gate 1530*7c478bd9Sstevel@tonic-gate /* 1531*7c478bd9Sstevel@tonic-gate * Check permission. 1532*7c478bd9Sstevel@tonic-gate * 1533*7c478bd9Sstevel@tonic-gate * The policy is root only for now. Need to relax this when interface level 1534*7c478bd9Sstevel@tonic-gate * is raised. 1535*7c478bd9Sstevel@tonic-gate */ 1536*7c478bd9Sstevel@tonic-gate static int 1537*7c478bd9Sstevel@tonic-gate rcm_check_permission(void) 1538*7c478bd9Sstevel@tonic-gate { 1539*7c478bd9Sstevel@tonic-gate return (getuid() == 0); 1540*7c478bd9Sstevel@tonic-gate } 1541*7c478bd9Sstevel@tonic-gate 1542*7c478bd9Sstevel@tonic-gate /* 1543*7c478bd9Sstevel@tonic-gate * Project private function - for use by RCM MSTC tests 1544*7c478bd9Sstevel@tonic-gate * 1545*7c478bd9Sstevel@tonic-gate * Get the client name (rcm module name or script name) corresponding to 1546*7c478bd9Sstevel@tonic-gate * the given rcm handle. 1547*7c478bd9Sstevel@tonic-gate */ 1548*7c478bd9Sstevel@tonic-gate const char * 1549*7c478bd9Sstevel@tonic-gate rcm_get_client_name(rcm_handle_t *hd) 1550*7c478bd9Sstevel@tonic-gate { 1551*7c478bd9Sstevel@tonic-gate return (hd->modname); 1552*7c478bd9Sstevel@tonic-gate } 1553