17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*691b55abSvikram * Common Development and Distribution License (the "License"). 6*691b55abSvikram * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*691b55abSvikram * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include "librcm_impl.h" 297c478bd9Sstevel@tonic-gate #include "librcm_event.h" 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #ifdef DEBUG 327c478bd9Sstevel@tonic-gate static int rcm_debug = 1; 337c478bd9Sstevel@tonic-gate #define dprintf(args) if (rcm_debug) (void) fprintf args 347c478bd9Sstevel@tonic-gate #else 357c478bd9Sstevel@tonic-gate #define dprintf(args) /* nothing */ 367c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate static int extract_info(nvlist_t *, rcm_info_t **); 397c478bd9Sstevel@tonic-gate static int rcm_daemon_is_alive(); 407c478bd9Sstevel@tonic-gate static int rcm_common(int, rcm_handle_t *, char **, uint_t, void *, 417c478bd9Sstevel@tonic-gate rcm_info_t **); 427c478bd9Sstevel@tonic-gate static int rcm_direct_call(int, rcm_handle_t *, char **, uint_t, void *, 437c478bd9Sstevel@tonic-gate rcm_info_t **); 447c478bd9Sstevel@tonic-gate static int rcm_daemon_call(int, rcm_handle_t *, char **, uint_t, void *, 457c478bd9Sstevel@tonic-gate rcm_info_t **); 467c478bd9Sstevel@tonic-gate static int rcm_generate_nvlist(int, rcm_handle_t *, char **, uint_t, void *, 477c478bd9Sstevel@tonic-gate char **, size_t *); 487c478bd9Sstevel@tonic-gate static int rcm_check_permission(void); 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * Allocate a handle structure 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 547c478bd9Sstevel@tonic-gate int 557c478bd9Sstevel@tonic-gate rcm_alloc_handle(char *modname, uint_t flag, void *arg, rcm_handle_t **hdp) 567c478bd9Sstevel@tonic-gate { 577c478bd9Sstevel@tonic-gate rcm_handle_t *hd; 587c478bd9Sstevel@tonic-gate void *temp; 597c478bd9Sstevel@tonic-gate char namebuf[MAXPATHLEN]; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate if ((hdp == NULL) || (flag & ~RCM_ALLOC_HDL_MASK)) { 627c478bd9Sstevel@tonic-gate errno = EINVAL; 637c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate if (rcm_check_permission() == 0) { 677c478bd9Sstevel@tonic-gate errno = EPERM; 687c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate if ((hd = calloc(1, sizeof (*hd))) == NULL) { 727c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate if (modname) { 767c478bd9Sstevel@tonic-gate (void) snprintf(namebuf, MAXPATHLEN, "%s%s", modname, 777c478bd9Sstevel@tonic-gate RCM_MODULE_SUFFIX); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate if ((hd->modname = strdup(namebuf)) == NULL) { 807c478bd9Sstevel@tonic-gate free(hd); 817c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate if ((temp = rcm_module_open(namebuf)) == NULL) { 857c478bd9Sstevel@tonic-gate free(hd->modname); 867c478bd9Sstevel@tonic-gate free(hd); 877c478bd9Sstevel@tonic-gate errno = EINVAL; 887c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate rcm_module_close(temp); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate if (flag & RCM_NOPID) { 957c478bd9Sstevel@tonic-gate hd->pid = (pid_t)0; 967c478bd9Sstevel@tonic-gate } else { 977c478bd9Sstevel@tonic-gate hd->pid = (pid_t)getpid(); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate *hdp = hd; 1017c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* free handle structure */ 1057c478bd9Sstevel@tonic-gate int 1067c478bd9Sstevel@tonic-gate rcm_free_handle(rcm_handle_t *hd) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate if (hd == NULL) { 1097c478bd9Sstevel@tonic-gate errno = EINVAL; 1107c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if (hd->modname) { 1147c478bd9Sstevel@tonic-gate free(hd->modname); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate free(hd); 1187c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * Operations which require daemon processing 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* get registration and DR information from rcm_daemon */ 1277c478bd9Sstevel@tonic-gate int 1287c478bd9Sstevel@tonic-gate rcm_get_info(rcm_handle_t *hd, char *rsrcname, uint_t flag, rcm_info_t **infop) 1297c478bd9Sstevel@tonic-gate { 1307c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate if ((flag & ~RCM_GET_INFO_MASK) || (infop == NULL)) { 1337c478bd9Sstevel@tonic-gate errno = EINVAL; 1347c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * rsrcname may be NULL if requesting dr operations or modinfo 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate if ((rsrcname == NULL) && 1417c478bd9Sstevel@tonic-gate ((flag & RCM_DR_OPERATION|RCM_MOD_INFO) == 0)) { 1427c478bd9Sstevel@tonic-gate errno = EINVAL; 1437c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 1477c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop)); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* get registration and DR information from rcm_daemon (list version) */ 1537c478bd9Sstevel@tonic-gate int 1547c478bd9Sstevel@tonic-gate rcm_get_info_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 1557c478bd9Sstevel@tonic-gate rcm_info_t **infop) 1567c478bd9Sstevel@tonic-gate { 1577c478bd9Sstevel@tonic-gate /* Requesting the current DR operations with a *list() is invalid */ 1587c478bd9Sstevel@tonic-gate if ((flag & RCM_DR_OPERATION) || (flag & RCM_MOD_INFO)) { 1597c478bd9Sstevel@tonic-gate errno = EINVAL; 1607c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop)); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* request to offline a resource before DR removal */ 1677c478bd9Sstevel@tonic-gate int 1687c478bd9Sstevel@tonic-gate rcm_request_offline(rcm_handle_t *hd, char *rsrcname, uint_t flag, 1697c478bd9Sstevel@tonic-gate rcm_info_t **infop) 1707c478bd9Sstevel@tonic-gate { 1717c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 1747c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate return (rcm_request_offline_list(hd, rsrcnames, flag, infop)); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* request to offline a resource before DR removal (list version) */ 1807c478bd9Sstevel@tonic-gate int 1817c478bd9Sstevel@tonic-gate rcm_request_offline_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 1827c478bd9Sstevel@tonic-gate rcm_info_t **infop) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate if (flag & ~RCM_REQUEST_MASK) { 1857c478bd9Sstevel@tonic-gate errno = EINVAL; 1867c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate return (rcm_common(CMD_OFFLINE, hd, rsrcnames, flag, NULL, infop)); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* cancel offline request and allow apps to use rsrcname */ 1937c478bd9Sstevel@tonic-gate int 1947c478bd9Sstevel@tonic-gate rcm_notify_online(rcm_handle_t *hd, char *rsrcname, uint_t flag, 1957c478bd9Sstevel@tonic-gate rcm_info_t **infop) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 2007c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate return (rcm_notify_online_list(hd, rsrcnames, flag, infop)); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* cancel offline and allow apps to use resources (list version) */ 2067c478bd9Sstevel@tonic-gate int 2077c478bd9Sstevel@tonic-gate rcm_notify_online_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 2087c478bd9Sstevel@tonic-gate rcm_info_t **infop) 2097c478bd9Sstevel@tonic-gate { 2107c478bd9Sstevel@tonic-gate if (flag & ~RCM_NOTIFY_MASK) { 2117c478bd9Sstevel@tonic-gate errno = EINVAL; 2127c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate return (rcm_common(CMD_ONLINE, hd, rsrcnames, flag, NULL, infop)); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* notify that rsrcname has been removed */ 2197c478bd9Sstevel@tonic-gate int 2207c478bd9Sstevel@tonic-gate rcm_notify_remove(rcm_handle_t *hd, char *rsrcname, uint_t flag, 2217c478bd9Sstevel@tonic-gate rcm_info_t **infop) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 2267c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate return (rcm_notify_remove_list(hd, rsrcnames, flag, infop)); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* notify that resrouces have been removed (list form) */ 2327c478bd9Sstevel@tonic-gate int 2337c478bd9Sstevel@tonic-gate rcm_notify_remove_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 2347c478bd9Sstevel@tonic-gate rcm_info_t **infop) 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate if (flag & ~RCM_NOTIFY_MASK) { 2377c478bd9Sstevel@tonic-gate errno = EINVAL; 2387c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REMOVE, hd, rsrcnames, flag, NULL, infop)); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* request for permission to suspend resource of interval time */ 2457c478bd9Sstevel@tonic-gate int 2467c478bd9Sstevel@tonic-gate rcm_request_suspend(rcm_handle_t *hd, char *rsrcname, uint_t flag, 2477c478bd9Sstevel@tonic-gate timespec_t *interval, rcm_info_t **infop) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 2527c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate return (rcm_request_suspend_list(hd, rsrcnames, flag, interval, infop)); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* request for permission to suspend resource of interval time (list form) */ 2587c478bd9Sstevel@tonic-gate int 2597c478bd9Sstevel@tonic-gate rcm_request_suspend_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 2607c478bd9Sstevel@tonic-gate timespec_t *interval, rcm_info_t **infop) 2617c478bd9Sstevel@tonic-gate { 2627c478bd9Sstevel@tonic-gate if ((flag & ~RCM_REQUEST_MASK) || (interval == NULL) || 2637c478bd9Sstevel@tonic-gate (interval->tv_sec < 0) || (interval->tv_nsec < 0)) { 2647c478bd9Sstevel@tonic-gate errno = EINVAL; 2657c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate return (rcm_common(CMD_SUSPEND, hd, rsrcnames, flag, (void *)interval, 2697c478bd9Sstevel@tonic-gate infop)); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* notify apps of the completion of resource suspension */ 2737c478bd9Sstevel@tonic-gate int 2747c478bd9Sstevel@tonic-gate rcm_notify_resume(rcm_handle_t *hd, char *rsrcname, uint_t flag, 2757c478bd9Sstevel@tonic-gate rcm_info_t **infop) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 2807c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate return (rcm_notify_resume_list(hd, rsrcnames, flag, infop)); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* notify apps of the completion of resource suspension (list form) */ 2867c478bd9Sstevel@tonic-gate int 2877c478bd9Sstevel@tonic-gate rcm_notify_resume_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, 2887c478bd9Sstevel@tonic-gate rcm_info_t **infop) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate if (flag & ~(RCM_NOTIFY_MASK | RCM_SUSPENDED)) { 2917c478bd9Sstevel@tonic-gate errno = EINVAL; 2927c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate return (rcm_common(CMD_RESUME, hd, rsrcnames, flag, NULL, infop)); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate /* request a capacity change from apps */ 2997c478bd9Sstevel@tonic-gate int 3007c478bd9Sstevel@tonic-gate rcm_request_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag, 3017c478bd9Sstevel@tonic-gate nvlist_t *nvl, rcm_info_t **infop) 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate int rv; 3047c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) { 3077c478bd9Sstevel@tonic-gate errno = EINVAL; 3087c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 3127c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate rv = rcm_common(CMD_REQUEST_CHANGE, hd, rsrcnames, flag, (void *)nvl, 3157c478bd9Sstevel@tonic-gate infop); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate return (rv); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* notify apps of a capacity change */ 3217c478bd9Sstevel@tonic-gate int 3227c478bd9Sstevel@tonic-gate rcm_notify_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag, 3237c478bd9Sstevel@tonic-gate nvlist_t *nvl, rcm_info_t **infop) 3247c478bd9Sstevel@tonic-gate { 3257c478bd9Sstevel@tonic-gate int rv; 3267c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) { 3297c478bd9Sstevel@tonic-gate errno = EINVAL; 3307c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 3347c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate rv = rcm_common(CMD_NOTIFY_CHANGE, hd, rsrcnames, flag, (void *)nvl, 3377c478bd9Sstevel@tonic-gate infop); 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate return (rv); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* notify apps of an event */ 3437c478bd9Sstevel@tonic-gate int 3447c478bd9Sstevel@tonic-gate rcm_notify_event(rcm_handle_t *hd, char *rsrcname, uint_t flag, nvlist_t *nvl, 3457c478bd9Sstevel@tonic-gate rcm_info_t **infop) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate int rv; 3487c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* No flags are defined yet for rcm_notify_event() */ 3517c478bd9Sstevel@tonic-gate if ((nvl == NULL) || (flag != 0)) { 3527c478bd9Sstevel@tonic-gate errno = EINVAL; 3537c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 3577c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate rv = rcm_common(CMD_EVENT, hd, rsrcnames, 0, (void *)nvl, infop); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate return (rv); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * Register to receive capacity changes. This requires a module to exist in 3667c478bd9Sstevel@tonic-gate * module directory. It should be called prior to using a new resource. 3677c478bd9Sstevel@tonic-gate */ 3687c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3697c478bd9Sstevel@tonic-gate int 3707c478bd9Sstevel@tonic-gate rcm_register_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag, 3717c478bd9Sstevel@tonic-gate rcm_info_t **infop) 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 3767c478bd9Sstevel@tonic-gate errno = EINVAL; 3777c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_CAPACITY; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 3837c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* unregister interest in capacity changes */ 3897c478bd9Sstevel@tonic-gate int 3907c478bd9Sstevel@tonic-gate rcm_unregister_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 3957c478bd9Sstevel@tonic-gate errno = EINVAL; 3967c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_CAPACITY; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 4027c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Register to receive events. This requires a module to exist in module 4097c478bd9Sstevel@tonic-gate * directory. It should be called prior to using a new resource. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4127c478bd9Sstevel@tonic-gate int 4137c478bd9Sstevel@tonic-gate rcm_register_event(rcm_handle_t *hd, char *rsrcname, uint_t flag, 4147c478bd9Sstevel@tonic-gate rcm_info_t **infop) 4157c478bd9Sstevel@tonic-gate { 4167c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 4197c478bd9Sstevel@tonic-gate errno = EINVAL; 4207c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_EVENT; 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 4267c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate /* unregister interest in events */ 4327c478bd9Sstevel@tonic-gate int 4337c478bd9Sstevel@tonic-gate rcm_unregister_event(rcm_handle_t *hd, char *rsrcname, uint_t flag) 4347c478bd9Sstevel@tonic-gate { 4357c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 4387c478bd9Sstevel@tonic-gate errno = EINVAL; 4397c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_EVENT; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 4457c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * Register interest in a resource. This requires a module to exist in module 4527c478bd9Sstevel@tonic-gate * directory. It should be called prior to using a new resource. 4537c478bd9Sstevel@tonic-gate * 4547c478bd9Sstevel@tonic-gate * Registration may be denied if it is presently locked by a DR operation. 4557c478bd9Sstevel@tonic-gate */ 4567c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4577c478bd9Sstevel@tonic-gate int 4587c478bd9Sstevel@tonic-gate rcm_register_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag, 4597c478bd9Sstevel@tonic-gate rcm_info_t **infop) 4607c478bd9Sstevel@tonic-gate { 4617c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 4647c478bd9Sstevel@tonic-gate errno = EINVAL; 4657c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_DR; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 4717c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate /* unregister interest in rsrcname */ 4777c478bd9Sstevel@tonic-gate int 4787c478bd9Sstevel@tonic-gate rcm_unregister_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag) 4797c478bd9Sstevel@tonic-gate { 4807c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if (flag & ~RCM_REGISTER_MASK) { 4837c478bd9Sstevel@tonic-gate errno = EINVAL; 4847c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate flag |= RCM_REGISTER_DR; 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 4907c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* get the current state of a resource */ 4967c478bd9Sstevel@tonic-gate int 4977c478bd9Sstevel@tonic-gate rcm_get_rsrcstate(rcm_handle_t *hd, char *rsrcname, int *statep) 4987c478bd9Sstevel@tonic-gate { 4997c478bd9Sstevel@tonic-gate int result; 5007c478bd9Sstevel@tonic-gate int flag = 0; 5017c478bd9Sstevel@tonic-gate rcm_info_t *infop = NULL; 5027c478bd9Sstevel@tonic-gate rcm_info_tuple_t *tuple = NULL; 5037c478bd9Sstevel@tonic-gate char *rsrcnames[2]; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate if (statep == NULL) { 5067c478bd9Sstevel@tonic-gate errno = EINVAL; 5077c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate rsrcnames[0] = rsrcname; 5117c478bd9Sstevel@tonic-gate rsrcnames[1] = NULL; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate result = rcm_common(CMD_GETSTATE, hd, rsrcnames, flag, NULL, &infop); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * A successful result implies the presence of exactly one RCM info 5177c478bd9Sstevel@tonic-gate * tuple containing the state of this resource (a combination of each 5187c478bd9Sstevel@tonic-gate * client's resources). If that's not true, change the result to 5197c478bd9Sstevel@tonic-gate * RCM_FAILURE. 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate if (result == RCM_SUCCESS) { 5227c478bd9Sstevel@tonic-gate if ((infop == NULL) || 5237c478bd9Sstevel@tonic-gate ((tuple = rcm_info_next(infop, NULL)) == NULL) || 5247c478bd9Sstevel@tonic-gate (rcm_info_next(infop, tuple) != NULL)) { 5257c478bd9Sstevel@tonic-gate result = RCM_FAILURE; 5267c478bd9Sstevel@tonic-gate } else if (infop && tuple) { 5277c478bd9Sstevel@tonic-gate *statep = rcm_info_state(tuple); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate if (infop) 5327c478bd9Sstevel@tonic-gate rcm_free_info(infop); 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate return (result); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* 5387c478bd9Sstevel@tonic-gate * RCM helper functions exposed to librcm callers. 5397c478bd9Sstevel@tonic-gate */ 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* Free linked list of registration info */ 5427c478bd9Sstevel@tonic-gate void 5437c478bd9Sstevel@tonic-gate rcm_free_info(rcm_info_t *info) 5447c478bd9Sstevel@tonic-gate { 5457c478bd9Sstevel@tonic-gate while (info) { 5467c478bd9Sstevel@tonic-gate rcm_info_t *tmp = info->next; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (info->info) 5497c478bd9Sstevel@tonic-gate nvlist_free(info->info); 5507c478bd9Sstevel@tonic-gate free(info); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate info = tmp; 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate /* return the next tuple in the info structure */ 5577c478bd9Sstevel@tonic-gate rcm_info_tuple_t * 5587c478bd9Sstevel@tonic-gate rcm_info_next(rcm_info_t *info, rcm_info_tuple_t *tuple) 5597c478bd9Sstevel@tonic-gate { 5607c478bd9Sstevel@tonic-gate if (info == NULL) { 5617c478bd9Sstevel@tonic-gate errno = EINVAL; 5627c478bd9Sstevel@tonic-gate return (NULL); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (tuple == NULL) { 5667c478bd9Sstevel@tonic-gate return ((rcm_info_tuple_t *)info); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate return ((rcm_info_tuple_t *)tuple->next); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* return resource name */ 5727c478bd9Sstevel@tonic-gate const char * 5737c478bd9Sstevel@tonic-gate rcm_info_rsrc(rcm_info_tuple_t *tuple) 5747c478bd9Sstevel@tonic-gate { 5757c478bd9Sstevel@tonic-gate char *rsrcname = NULL; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 5787c478bd9Sstevel@tonic-gate errno = EINVAL; 5797c478bd9Sstevel@tonic-gate return (NULL); 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_RSRCNAME, &rsrcname)) 5837c478bd9Sstevel@tonic-gate return (NULL); 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate return (rsrcname); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate const char * 5897c478bd9Sstevel@tonic-gate rcm_info_info(rcm_info_tuple_t *tuple) 5907c478bd9Sstevel@tonic-gate { 5917c478bd9Sstevel@tonic-gate char *info = NULL; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 5947c478bd9Sstevel@tonic-gate errno = EINVAL; 5957c478bd9Sstevel@tonic-gate return (NULL); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_INFO, &info)) 5997c478bd9Sstevel@tonic-gate return (NULL); 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate return (info); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate const char * 6057c478bd9Sstevel@tonic-gate rcm_info_error(rcm_info_tuple_t *tuple) 6067c478bd9Sstevel@tonic-gate { 6077c478bd9Sstevel@tonic-gate char *errstr = NULL; 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 6107c478bd9Sstevel@tonic-gate errno = EINVAL; 6117c478bd9Sstevel@tonic-gate return (NULL); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_ERROR, 6157c478bd9Sstevel@tonic-gate &errstr)) 6167c478bd9Sstevel@tonic-gate return (NULL); 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate return (errstr); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate /* return info string in the tuple */ 6227c478bd9Sstevel@tonic-gate const char * 6237c478bd9Sstevel@tonic-gate rcm_info_modname(rcm_info_tuple_t *tuple) 6247c478bd9Sstevel@tonic-gate { 6257c478bd9Sstevel@tonic-gate char *modname = NULL; 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 6287c478bd9Sstevel@tonic-gate errno = EINVAL; 6297c478bd9Sstevel@tonic-gate return (NULL); 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_MODNAME, 6337c478bd9Sstevel@tonic-gate &modname)) 6347c478bd9Sstevel@tonic-gate return (NULL); 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate return (modname); 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate /* return client pid in the tuple */ 6407c478bd9Sstevel@tonic-gate pid_t 6417c478bd9Sstevel@tonic-gate rcm_info_pid(rcm_info_tuple_t *tuple) 6427c478bd9Sstevel@tonic-gate { 6437c478bd9Sstevel@tonic-gate uint64_t pid64 = (uint64_t)0; 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 6467c478bd9Sstevel@tonic-gate errno = EINVAL; 6477c478bd9Sstevel@tonic-gate return ((pid_t)0); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_uint64(tuple->info, RCM_CLIENT_ID, &pid64)) 6517c478bd9Sstevel@tonic-gate return ((pid_t)0); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate return ((pid_t)pid64); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* return client state in the tuple */ 6577c478bd9Sstevel@tonic-gate int 6587c478bd9Sstevel@tonic-gate rcm_info_state(rcm_info_tuple_t *tuple) 6597c478bd9Sstevel@tonic-gate { 6607c478bd9Sstevel@tonic-gate int state; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 6637c478bd9Sstevel@tonic-gate errno = EINVAL; 6647c478bd9Sstevel@tonic-gate return (RCM_STATE_UNKNOWN); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_int32(tuple->info, RCM_RSRCSTATE, &state)) 6687c478bd9Sstevel@tonic-gate return (RCM_STATE_UNKNOWN); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate return (state); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* return the generic properties in the tuple */ 6747c478bd9Sstevel@tonic-gate nvlist_t * 6757c478bd9Sstevel@tonic-gate rcm_info_properties(rcm_info_tuple_t *tuple) 6767c478bd9Sstevel@tonic-gate { 6777c478bd9Sstevel@tonic-gate char *buf; 6787c478bd9Sstevel@tonic-gate uint_t buflen; 6797c478bd9Sstevel@tonic-gate nvlist_t *nvl; 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 6827c478bd9Sstevel@tonic-gate errno = EINVAL; 6837c478bd9Sstevel@tonic-gate return (NULL); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_byte_array(tuple->info, RCM_CLIENT_PROPERTIES, 6877c478bd9Sstevel@tonic-gate (uchar_t **)&buf, &buflen)) 6887c478bd9Sstevel@tonic-gate return (NULL); 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate if (errno = nvlist_unpack(buf, buflen, &nvl, 0)) { 6917c478bd9Sstevel@tonic-gate free(buf); 6927c478bd9Sstevel@tonic-gate return (NULL); 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate return (nvl); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate /* 6997c478bd9Sstevel@tonic-gate * return operation sequence number 7007c478bd9Sstevel@tonic-gate * 7017c478bd9Sstevel@tonic-gate * This is private. Called by rcmctl only for testing purposes. 7027c478bd9Sstevel@tonic-gate */ 7037c478bd9Sstevel@tonic-gate int 7047c478bd9Sstevel@tonic-gate rcm_info_seqnum(rcm_info_tuple_t *tuple) 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate int seqnum; 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if (tuple == NULL || tuple->info == NULL) { 7097c478bd9Sstevel@tonic-gate errno = EINVAL; 7107c478bd9Sstevel@tonic-gate return (-1); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate if (errno = nvlist_lookup_int32(tuple->info, RCM_SEQ_NUM, &seqnum)) 7147c478bd9Sstevel@tonic-gate return (-1); 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate return (seqnum); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate /* 7217c478bd9Sstevel@tonic-gate * The following interfaces are PRIVATE to the RCM framework. They are not 7227c478bd9Sstevel@tonic-gate * declared static because they are called by rcm_daemon. 7237c478bd9Sstevel@tonic-gate */ 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate /* 7267c478bd9Sstevel@tonic-gate * Invoke shell to execute command in MT safe manner. 7277c478bd9Sstevel@tonic-gate * Returns wait status or -1 on error. 7287c478bd9Sstevel@tonic-gate */ 7297c478bd9Sstevel@tonic-gate int 7307c478bd9Sstevel@tonic-gate rcm_exec_cmd(char *cmd) 7317c478bd9Sstevel@tonic-gate { 7327c478bd9Sstevel@tonic-gate pid_t pid; 7337c478bd9Sstevel@tonic-gate int status, w; 7347c478bd9Sstevel@tonic-gate char *argvec[] = {"sh", "-c", NULL, NULL}; 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate argvec[2] = cmd; 7377c478bd9Sstevel@tonic-gate if ((pid = fork1()) == 0) { 7387c478bd9Sstevel@tonic-gate (void) execv("/bin/sh", argvec); 7397c478bd9Sstevel@tonic-gate _exit(127); 7407c478bd9Sstevel@tonic-gate } else if (pid == -1) { 7417c478bd9Sstevel@tonic-gate return (-1); 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate do { 7457c478bd9Sstevel@tonic-gate w = waitpid(pid, &status, 0); 7467c478bd9Sstevel@tonic-gate } while (w == -1 && errno == EINTR); 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate return ((w == -1) ? w : status); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate /* Append info at the very end */ 7527c478bd9Sstevel@tonic-gate int 7537c478bd9Sstevel@tonic-gate rcm_append_info(rcm_info_t **head, rcm_info_t *info) 7547c478bd9Sstevel@tonic-gate { 7557c478bd9Sstevel@tonic-gate rcm_info_t *tuple; 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate if (head == NULL) { 7587c478bd9Sstevel@tonic-gate errno = EINVAL; 7597c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate if ((tuple = *head) == NULL) { 7637c478bd9Sstevel@tonic-gate *head = info; 7647c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate while (tuple->next) { 7687c478bd9Sstevel@tonic-gate tuple = tuple->next; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate tuple->next = info; 7717c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate /* get rcm module and rcm script directory names */ 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate #define N_MODULE_DIR 3 /* search 3 directories for modules */ 7777c478bd9Sstevel@tonic-gate #define MODULE_DIR_HW "/usr/platform/%s/lib/rcm/modules/" 7787c478bd9Sstevel@tonic-gate #define MODULE_DIR_GEN "/usr/lib/rcm/modules/" 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate #define N_SCRIPT_DIR 4 /* search 4 directories for scripts */ 7817c478bd9Sstevel@tonic-gate #define SCRIPT_DIR_HW "/usr/platform/%s/lib/rcm/scripts/" 7827c478bd9Sstevel@tonic-gate #define SCRIPT_DIR_GEN "/usr/lib/rcm/scripts/" 7837c478bd9Sstevel@tonic-gate #define SCRIPT_DIR_ETC "/etc/rcm/scripts/" 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate char * 7877c478bd9Sstevel@tonic-gate rcm_module_dir(uint_t dirnum) 7887c478bd9Sstevel@tonic-gate { 7897c478bd9Sstevel@tonic-gate if (dirnum < N_MODULE_DIR) 7907c478bd9Sstevel@tonic-gate return (rcm_dir(dirnum, NULL)); 7917c478bd9Sstevel@tonic-gate else 7927c478bd9Sstevel@tonic-gate return (NULL); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate char * 7967c478bd9Sstevel@tonic-gate rcm_script_dir(uint_t dirnum) 7977c478bd9Sstevel@tonic-gate { 7987c478bd9Sstevel@tonic-gate if (dirnum < N_SCRIPT_DIR) 7997c478bd9Sstevel@tonic-gate return (rcm_dir(dirnum + N_MODULE_DIR, NULL)); 8007c478bd9Sstevel@tonic-gate else 8017c478bd9Sstevel@tonic-gate return (NULL); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate char * 8057c478bd9Sstevel@tonic-gate rcm_dir(uint_t dirnum, int *rcm_script) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate static char dir_name[N_MODULE_DIR + N_SCRIPT_DIR][MAXPATHLEN]; 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate char infobuf[MAXPATHLEN]; 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate if (dirnum >= (N_MODULE_DIR + N_SCRIPT_DIR)) 8127c478bd9Sstevel@tonic-gate return (NULL); 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate if (dir_name[0][0] == '\0') { 8157c478bd9Sstevel@tonic-gate /* 8167c478bd9Sstevel@tonic-gate * construct the module directory names 8177c478bd9Sstevel@tonic-gate */ 8187c478bd9Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, infobuf, MAXPATHLEN) == -1) { 8197c478bd9Sstevel@tonic-gate dprintf((stderr, "sysinfo %s\n", strerror(errno))); 8207c478bd9Sstevel@tonic-gate return (NULL); 8217c478bd9Sstevel@tonic-gate } else { 8227c478bd9Sstevel@tonic-gate if (snprintf(dir_name[0], MAXPATHLEN, MODULE_DIR_HW, 8237c478bd9Sstevel@tonic-gate infobuf) >= MAXPATHLEN || 8247c478bd9Sstevel@tonic-gate snprintf(dir_name[N_MODULE_DIR + 1], MAXPATHLEN, 8257c478bd9Sstevel@tonic-gate SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) { 8267c478bd9Sstevel@tonic-gate dprintf((stderr, 8277c478bd9Sstevel@tonic-gate "invalid module or script directory for " 8287c478bd9Sstevel@tonic-gate "platform %s\n", infobuf)); 8297c478bd9Sstevel@tonic-gate return (NULL); 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if (sysinfo(SI_MACHINE, infobuf, MAXPATHLEN) == -1) { 8347c478bd9Sstevel@tonic-gate dprintf((stderr, "sysinfo %s\n", strerror(errno))); 8357c478bd9Sstevel@tonic-gate return (NULL); 8367c478bd9Sstevel@tonic-gate } else { 8377c478bd9Sstevel@tonic-gate if (snprintf(dir_name[1], MAXPATHLEN, MODULE_DIR_HW, 8387c478bd9Sstevel@tonic-gate infobuf) >= MAXPATHLEN || 8397c478bd9Sstevel@tonic-gate snprintf(dir_name[N_MODULE_DIR + 2], MAXPATHLEN, 8407c478bd9Sstevel@tonic-gate SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) { 8417c478bd9Sstevel@tonic-gate dprintf((stderr, 8427c478bd9Sstevel@tonic-gate "invalid module or script directory for " 8437c478bd9Sstevel@tonic-gate "machine type %s\n", infobuf)); 8447c478bd9Sstevel@tonic-gate return (NULL); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate if (strlcpy(dir_name[2], MODULE_DIR_GEN, MAXPATHLEN) >= 8497c478bd9Sstevel@tonic-gate MAXPATHLEN || 8507c478bd9Sstevel@tonic-gate strlcpy(dir_name[N_MODULE_DIR + 3], SCRIPT_DIR_GEN, 8517c478bd9Sstevel@tonic-gate MAXPATHLEN) >= MAXPATHLEN || 8527c478bd9Sstevel@tonic-gate strlcpy(dir_name[N_MODULE_DIR + 0], SCRIPT_DIR_ETC, 8537c478bd9Sstevel@tonic-gate MAXPATHLEN) >= MAXPATHLEN) { 8547c478bd9Sstevel@tonic-gate dprintf((stderr, 8557c478bd9Sstevel@tonic-gate "invalid module or script generic directory\n")); 8567c478bd9Sstevel@tonic-gate return (NULL); 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate if (rcm_script) 8617c478bd9Sstevel@tonic-gate *rcm_script = (dirnum < N_MODULE_DIR) ? 0 : 1; 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate return (dir_name[dirnum]); 8647c478bd9Sstevel@tonic-gate } 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate /* 8677c478bd9Sstevel@tonic-gate * Find the directory where the script is located. 8687c478bd9Sstevel@tonic-gate * If the script is found return a pointer to the directory where the 8697c478bd9Sstevel@tonic-gate * script was found otherwise return NULL. 8707c478bd9Sstevel@tonic-gate */ 8717c478bd9Sstevel@tonic-gate char * 8727c478bd9Sstevel@tonic-gate rcm_get_script_dir(char *script_name) 8737c478bd9Sstevel@tonic-gate { 8747c478bd9Sstevel@tonic-gate uint_t i; 8757c478bd9Sstevel@tonic-gate char *dir_name; 8767c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 8777c478bd9Sstevel@tonic-gate struct stat stats; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate for (i = 0; (dir_name = rcm_script_dir(i)) != NULL; i++) { 8807c478bd9Sstevel@tonic-gate if (snprintf(path, MAXPATHLEN, "%s%s", dir_name, script_name) 8817c478bd9Sstevel@tonic-gate >= MAXPATHLEN) { 8827c478bd9Sstevel@tonic-gate dprintf((stderr, "invalid script %s skipped\n", 8837c478bd9Sstevel@tonic-gate script_name)); 8847c478bd9Sstevel@tonic-gate continue; 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate if (stat(path, &stats) == 0) 8877c478bd9Sstevel@tonic-gate return (dir_name); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate return (NULL); 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* 8947c478bd9Sstevel@tonic-gate * Returns 1 if the filename is an rcm script. 8957c478bd9Sstevel@tonic-gate * Returns 0 if the filename is an rcm module. 8967c478bd9Sstevel@tonic-gate */ 8977c478bd9Sstevel@tonic-gate int 8987c478bd9Sstevel@tonic-gate rcm_is_script(char *filename) 8997c478bd9Sstevel@tonic-gate { 9007c478bd9Sstevel@tonic-gate char *tmp; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate if (((tmp = strstr(filename, RCM_MODULE_SUFFIX)) != NULL) && 9037c478bd9Sstevel@tonic-gate (tmp[strlen(RCM_MODULE_SUFFIX)] == '\0')) 9047c478bd9Sstevel@tonic-gate return (0); 9057c478bd9Sstevel@tonic-gate else 9067c478bd9Sstevel@tonic-gate return (1); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate /* Locate the module and call dlopen */ 9107c478bd9Sstevel@tonic-gate void * 9117c478bd9Sstevel@tonic-gate rcm_module_open(char *modname) 9127c478bd9Sstevel@tonic-gate { 9137c478bd9Sstevel@tonic-gate unsigned i; 9147c478bd9Sstevel@tonic-gate char *dir_name; 9157c478bd9Sstevel@tonic-gate void *dlhandle = NULL; 9167c478bd9Sstevel@tonic-gate char modpath[MAXPATHLEN]; 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate #ifdef DEBUG 9197c478bd9Sstevel@tonic-gate struct stat sbuf; 9207c478bd9Sstevel@tonic-gate #endif 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /* 9237c478bd9Sstevel@tonic-gate * dlopen the module 9247c478bd9Sstevel@tonic-gate */ 9257c478bd9Sstevel@tonic-gate for (i = 0; (dir_name = rcm_module_dir(i)) != NULL; i++) { 9267c478bd9Sstevel@tonic-gate if (snprintf(modpath, MAXPATHLEN, "%s%s", dir_name, modname) 9277c478bd9Sstevel@tonic-gate >= MAXPATHLEN) { 9287c478bd9Sstevel@tonic-gate dprintf((stderr, "invalid module %s skipped\n", 9297c478bd9Sstevel@tonic-gate modname)); 9307c478bd9Sstevel@tonic-gate continue; 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate if ((dlhandle = dlopen(modpath, RTLD_LAZY)) != NULL) { 9347c478bd9Sstevel@tonic-gate return (dlhandle); 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate dprintf((stderr, "failure (dlopen=%s)\n", dlerror())); 9387c478bd9Sstevel@tonic-gate #ifdef DEBUG 9397c478bd9Sstevel@tonic-gate if (stat(modpath, &sbuf) == 0) { 9407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s is not a valid module\n", 9417c478bd9Sstevel@tonic-gate modpath); 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate #endif 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate dprintf((stderr, "module %s not found\n", modname)); 9477c478bd9Sstevel@tonic-gate return (NULL); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* dlclose module */ 9517c478bd9Sstevel@tonic-gate void 9527c478bd9Sstevel@tonic-gate rcm_module_close(void *dlhandle) 9537c478bd9Sstevel@tonic-gate { 9547c478bd9Sstevel@tonic-gate if (dlclose(dlhandle) == 0) 9557c478bd9Sstevel@tonic-gate return; 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate dprintf((stderr, "dlclose: %s\n", dlerror())); 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* 9627c478bd9Sstevel@tonic-gate * stub implementation of rcm_log_message allows dlopen of rcm modules 9637c478bd9Sstevel@tonic-gate * to proceed in absence of rcm_daemon. 9647c478bd9Sstevel@tonic-gate * 9657c478bd9Sstevel@tonic-gate * This definition is interposed by the definition in rcm_daemon because of the 9667c478bd9Sstevel@tonic-gate * default search order implemented by the linker and dlsym(). All RCM modules 9677c478bd9Sstevel@tonic-gate * will see the daemon version when loaded by the rcm_daemon. 9687c478bd9Sstevel@tonic-gate */ 9697c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9707c478bd9Sstevel@tonic-gate void 9717c478bd9Sstevel@tonic-gate rcm_log_message(int level, char *message, ...) 9727c478bd9Sstevel@tonic-gate { 9737c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_log_message stub\n")); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate /* 9777c478bd9Sstevel@tonic-gate * Helper functions 9787c478bd9Sstevel@tonic-gate */ 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate /* 9817c478bd9Sstevel@tonic-gate * Common routine for all rcm calls which require daemon processing 9827c478bd9Sstevel@tonic-gate */ 9837c478bd9Sstevel@tonic-gate static int 9847c478bd9Sstevel@tonic-gate rcm_common(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, void *arg, 9857c478bd9Sstevel@tonic-gate rcm_info_t **infop) 9867c478bd9Sstevel@tonic-gate { 9877c478bd9Sstevel@tonic-gate int i; 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate if (hd == NULL) { 9907c478bd9Sstevel@tonic-gate errno = EINVAL; 9917c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate if (getuid() != 0) { 9957c478bd9Sstevel@tonic-gate errno = EPERM; 9967c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate if ((flag & (RCM_DR_OPERATION | RCM_MOD_INFO)) == 0) { 10007c478bd9Sstevel@tonic-gate if ((rsrcnames == NULL) || (rsrcnames[0] == NULL)) { 10017c478bd9Sstevel@tonic-gate errno = EINVAL; 10027c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate for (i = 0; rsrcnames[i] != NULL; i++) { 10067c478bd9Sstevel@tonic-gate if (*rsrcnames[i] == '\0') { 10077c478bd9Sstevel@tonic-gate errno = EINVAL; 10087c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate /* 10147c478bd9Sstevel@tonic-gate * Check if handle is allocated by rcm_daemon. If so, this call came 10157c478bd9Sstevel@tonic-gate * from an RCM module, so we make a direct call into rcm_daemon. 10167c478bd9Sstevel@tonic-gate */ 10177c478bd9Sstevel@tonic-gate if (hd->lrcm_ops != NULL) { 10187c478bd9Sstevel@tonic-gate return (rcm_direct_call(cmd, hd, rsrcnames, flag, arg, infop)); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate /* 10227c478bd9Sstevel@tonic-gate * When not called from a RCM module (i.e. no recursion), zero the 10237c478bd9Sstevel@tonic-gate * pointer just in case caller did not do so. For recursive calls, 10247c478bd9Sstevel@tonic-gate * we want to append rcm_info_t after infop; zero it may cause 10257c478bd9Sstevel@tonic-gate * memory leaks. 10267c478bd9Sstevel@tonic-gate */ 10277c478bd9Sstevel@tonic-gate if (infop) { 10287c478bd9Sstevel@tonic-gate *infop = NULL; 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate /* 10327c478bd9Sstevel@tonic-gate * Now call into the daemon. 10337c478bd9Sstevel@tonic-gate */ 10347c478bd9Sstevel@tonic-gate return (rcm_daemon_call(cmd, hd, rsrcnames, flag, arg, infop)); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate /* 10387c478bd9Sstevel@tonic-gate * Caller is an RCM module, call directly into rcm_daemon. 10397c478bd9Sstevel@tonic-gate */ 10407c478bd9Sstevel@tonic-gate static int 10417c478bd9Sstevel@tonic-gate rcm_direct_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, 10427c478bd9Sstevel@tonic-gate void *arg, rcm_info_t **infop) 10437c478bd9Sstevel@tonic-gate { 10447c478bd9Sstevel@tonic-gate int error; 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate librcm_ops_t *ops = (librcm_ops_t *)hd->lrcm_ops; 10477c478bd9Sstevel@tonic-gate switch (cmd) { 10487c478bd9Sstevel@tonic-gate case CMD_GETINFO: 10497c478bd9Sstevel@tonic-gate error = ops->librcm_getinfo(rsrcnames, flag, hd->seq_num, 10507c478bd9Sstevel@tonic-gate infop); 10517c478bd9Sstevel@tonic-gate break; 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate case CMD_OFFLINE: 10547c478bd9Sstevel@tonic-gate error = ops->librcm_offline(rsrcnames, hd->pid, flag, 10557c478bd9Sstevel@tonic-gate hd->seq_num, infop); 10567c478bd9Sstevel@tonic-gate break; 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate case CMD_ONLINE: 10597c478bd9Sstevel@tonic-gate error = ops->librcm_online(rsrcnames, hd->pid, flag, 10607c478bd9Sstevel@tonic-gate hd->seq_num, infop); 10617c478bd9Sstevel@tonic-gate break; 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate case CMD_REMOVE: 10647c478bd9Sstevel@tonic-gate error = ops->librcm_remove(rsrcnames, hd->pid, flag, 10657c478bd9Sstevel@tonic-gate hd->seq_num, infop); 10667c478bd9Sstevel@tonic-gate break; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate case CMD_SUSPEND: 10697c478bd9Sstevel@tonic-gate error = ops->librcm_suspend(rsrcnames, hd->pid, flag, 10707c478bd9Sstevel@tonic-gate hd->seq_num, (timespec_t *)arg, infop); 10717c478bd9Sstevel@tonic-gate break; 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate case CMD_RESUME: 10747c478bd9Sstevel@tonic-gate error = ops->librcm_resume(rsrcnames, hd->pid, flag, 10757c478bd9Sstevel@tonic-gate hd->seq_num, infop); 10767c478bd9Sstevel@tonic-gate break; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate case CMD_REGISTER: 10797c478bd9Sstevel@tonic-gate error = ops->librcm_regis(hd->modname, rsrcnames[0], hd->pid, 10807c478bd9Sstevel@tonic-gate flag, infop); 10817c478bd9Sstevel@tonic-gate break; 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate case CMD_UNREGISTER: 10847c478bd9Sstevel@tonic-gate error = ops->librcm_unregis(hd->modname, rsrcnames[0], hd->pid, 10857c478bd9Sstevel@tonic-gate flag); 10867c478bd9Sstevel@tonic-gate break; 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate case CMD_REQUEST_CHANGE: 10897c478bd9Sstevel@tonic-gate error = ops->librcm_request_change(rsrcnames[0], hd->pid, flag, 10907c478bd9Sstevel@tonic-gate hd->seq_num, (nvlist_t *)arg, infop); 10917c478bd9Sstevel@tonic-gate break; 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate case CMD_NOTIFY_CHANGE: 10947c478bd9Sstevel@tonic-gate error = ops->librcm_notify_change(rsrcnames[0], hd->pid, flag, 10957c478bd9Sstevel@tonic-gate hd->seq_num, (nvlist_t *)arg, infop); 10967c478bd9Sstevel@tonic-gate break; 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate case CMD_EVENT: 10997c478bd9Sstevel@tonic-gate error = ops->librcm_notify_event(rsrcnames[0], hd->pid, flag, 11007c478bd9Sstevel@tonic-gate hd->seq_num, (nvlist_t *)arg, infop); 11017c478bd9Sstevel@tonic-gate break; 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate case CMD_GETSTATE: 11047c478bd9Sstevel@tonic-gate error = ops->librcm_getstate(rsrcnames[0], hd->pid, infop); 11057c478bd9Sstevel@tonic-gate break; 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate default: 11087c478bd9Sstevel@tonic-gate dprintf((stderr, "invalid command: %d\n", cmd)); 11097c478bd9Sstevel@tonic-gate error = EFAULT; 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate if (error > 0) { 11137c478bd9Sstevel@tonic-gate errno = error; 11147c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate return (error); 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate /* 11207c478bd9Sstevel@tonic-gate * Call into rcm_daemon door to process the request 11217c478bd9Sstevel@tonic-gate */ 11227c478bd9Sstevel@tonic-gate static int 11237c478bd9Sstevel@tonic-gate rcm_daemon_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, 11247c478bd9Sstevel@tonic-gate void *arg, rcm_info_t **infop) 11257c478bd9Sstevel@tonic-gate { 11267c478bd9Sstevel@tonic-gate int errno_found; 1127*691b55abSvikram int daemon_errno = 0; 11287c478bd9Sstevel@tonic-gate int error = RCM_SUCCESS; 11297c478bd9Sstevel@tonic-gate int delay = 300; 11307c478bd9Sstevel@tonic-gate int maxdelay = 10000; /* 10 seconds */ 11317c478bd9Sstevel@tonic-gate char *nvl_packed = NULL; 11327c478bd9Sstevel@tonic-gate size_t nvl_size = 0; 11337c478bd9Sstevel@tonic-gate nvlist_t *ret = NULL; 11347c478bd9Sstevel@tonic-gate nvpair_t *nvp; 11357c478bd9Sstevel@tonic-gate size_t rsize = 0; 11367c478bd9Sstevel@tonic-gate rcm_info_t *info = NULL; 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate errno = 0; 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate /* 11417c478bd9Sstevel@tonic-gate * Decide whether to start the daemon 11427c478bd9Sstevel@tonic-gate */ 11437c478bd9Sstevel@tonic-gate switch (cmd) { 11447c478bd9Sstevel@tonic-gate case CMD_GETINFO: 11457c478bd9Sstevel@tonic-gate case CMD_OFFLINE: 11467c478bd9Sstevel@tonic-gate case CMD_ONLINE: 11477c478bd9Sstevel@tonic-gate case CMD_REMOVE: 11487c478bd9Sstevel@tonic-gate case CMD_SUSPEND: 11497c478bd9Sstevel@tonic-gate case CMD_RESUME: 11507c478bd9Sstevel@tonic-gate case CMD_REGISTER: 11517c478bd9Sstevel@tonic-gate case CMD_UNREGISTER: 11527c478bd9Sstevel@tonic-gate case CMD_EVENT: 11537c478bd9Sstevel@tonic-gate case CMD_REQUEST_CHANGE: 11547c478bd9Sstevel@tonic-gate case CMD_NOTIFY_CHANGE: 11557c478bd9Sstevel@tonic-gate case CMD_GETSTATE: 11567c478bd9Sstevel@tonic-gate break; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate default: 11597c478bd9Sstevel@tonic-gate errno = EFAULT; 11607c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate if (rcm_daemon_is_alive() != 1) { 11647c478bd9Sstevel@tonic-gate dprintf((stderr, "failed to start rcm_daemon\n")); 11657c478bd9Sstevel@tonic-gate errno = EFAULT; 11667c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate /* 11707c478bd9Sstevel@tonic-gate * Generate a packed nvlist for the request 11717c478bd9Sstevel@tonic-gate */ 11727c478bd9Sstevel@tonic-gate if (rcm_generate_nvlist(cmd, hd, rsrcnames, flag, arg, &nvl_packed, 11737c478bd9Sstevel@tonic-gate &nvl_size) < 0) { 11747c478bd9Sstevel@tonic-gate dprintf((stderr, "error in nvlist generation\n")); 11757c478bd9Sstevel@tonic-gate errno = EFAULT; 11767c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate /* 11807c478bd9Sstevel@tonic-gate * Make the door call and get a return event. We go into a retry loop 11817c478bd9Sstevel@tonic-gate * when RCM_ET_EAGAIN is returned. 11827c478bd9Sstevel@tonic-gate */ 11837c478bd9Sstevel@tonic-gate retry: 11847c478bd9Sstevel@tonic-gate if (get_event_service(RCM_SERVICE_DOOR, (void *)nvl_packed, nvl_size, 11857c478bd9Sstevel@tonic-gate (void **)&ret, &rsize) < 0) { 11867c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_daemon call failed: %s\n", 11877c478bd9Sstevel@tonic-gate strerror(errno))); 11887c478bd9Sstevel@tonic-gate free(nvl_packed); 11897c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate assert(ret != NULL); 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate /* 11957c478bd9Sstevel@tonic-gate * nvlist_lookup_* routines don't work because the returned nvlist 11967c478bd9Sstevel@tonic-gate * was nvlist_alloc'ed without the NV_UNIQUE_NAME flag. Implement 11977c478bd9Sstevel@tonic-gate * a sequential search manually, which is fine since there is only 11987c478bd9Sstevel@tonic-gate * one RCM_RESULT value in the nvlist. 11997c478bd9Sstevel@tonic-gate */ 12007c478bd9Sstevel@tonic-gate errno_found = 0; 12017c478bd9Sstevel@tonic-gate nvp = NULL; 12027c478bd9Sstevel@tonic-gate while (nvp = nvlist_next_nvpair(ret, nvp)) { 12037c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvp), RCM_RESULT) == 0) { 12047c478bd9Sstevel@tonic-gate if (errno = nvpair_value_int32(nvp, &daemon_errno)) { 12057c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 12067c478bd9Sstevel@tonic-gate goto out; 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate errno_found++; 12097c478bd9Sstevel@tonic-gate break; 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate if (errno_found == 0) { 12137c478bd9Sstevel@tonic-gate errno = EFAULT; 12147c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 12157c478bd9Sstevel@tonic-gate goto out; 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate if (daemon_errno == EAGAIN) { 12197c478bd9Sstevel@tonic-gate /* 12207c478bd9Sstevel@tonic-gate * Wait and retry 12217c478bd9Sstevel@tonic-gate */ 12227c478bd9Sstevel@tonic-gate dprintf((stderr, "retry door_call\n")); 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate if (delay > maxdelay) { 12257c478bd9Sstevel@tonic-gate errno = EAGAIN; 12267c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 12277c478bd9Sstevel@tonic-gate goto out; 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, delay); 12317c478bd9Sstevel@tonic-gate delay *= 2; /* exponential back off */ 12327c478bd9Sstevel@tonic-gate nvlist_free(ret); 12337c478bd9Sstevel@tonic-gate goto retry; 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate /* 12377c478bd9Sstevel@tonic-gate * The door call succeeded. Now extract info from returned event. 12387c478bd9Sstevel@tonic-gate */ 12397c478bd9Sstevel@tonic-gate if (extract_info(ret, &info) != 0) { 12407c478bd9Sstevel@tonic-gate dprintf((stderr, "error in extracting event data\n")); 12417c478bd9Sstevel@tonic-gate errno = EFAULT; 12427c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 12437c478bd9Sstevel@tonic-gate goto out; 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate if (infop) 12477c478bd9Sstevel@tonic-gate *infop = info; 12487c478bd9Sstevel@tonic-gate else 12497c478bd9Sstevel@tonic-gate rcm_free_info(info); 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate if (daemon_errno) { 12527c478bd9Sstevel@tonic-gate if (daemon_errno > 0) { 12537c478bd9Sstevel@tonic-gate errno = daemon_errno; 12547c478bd9Sstevel@tonic-gate error = RCM_FAILURE; 12557c478bd9Sstevel@tonic-gate } else { 12567c478bd9Sstevel@tonic-gate error = daemon_errno; 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate out: 12617c478bd9Sstevel@tonic-gate if (nvl_packed) 12627c478bd9Sstevel@tonic-gate free(nvl_packed); 12637c478bd9Sstevel@tonic-gate if (ret) 12647c478bd9Sstevel@tonic-gate nvlist_free(ret); 12657c478bd9Sstevel@tonic-gate dprintf((stderr, "daemon call is done. error = %d, errno = %s\n", error, 12667c478bd9Sstevel@tonic-gate strerror(errno))); 12677c478bd9Sstevel@tonic-gate return (error); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate /* 12717c478bd9Sstevel@tonic-gate * Extract registration info from event data. 12727c478bd9Sstevel@tonic-gate * Return 0 on success and -1 on failure. 12737c478bd9Sstevel@tonic-gate */ 12747c478bd9Sstevel@tonic-gate static int 12757c478bd9Sstevel@tonic-gate extract_info(nvlist_t *nvl, rcm_info_t **infop) 12767c478bd9Sstevel@tonic-gate { 12777c478bd9Sstevel@tonic-gate rcm_info_t *info = NULL; 12787c478bd9Sstevel@tonic-gate rcm_info_t *prev = NULL; 12797c478bd9Sstevel@tonic-gate rcm_info_t *tmp = NULL; 12807c478bd9Sstevel@tonic-gate char *buf; 12817c478bd9Sstevel@tonic-gate uint_t buflen; 12827c478bd9Sstevel@tonic-gate nvpair_t *nvp = NULL; 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate while (nvp = nvlist_next_nvpair(nvl, nvp)) { 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate buf = NULL; 12877c478bd9Sstevel@tonic-gate buflen = 0; 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvp), RCM_RESULT_INFO) != 0) 12907c478bd9Sstevel@tonic-gate continue; 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { 12937c478bd9Sstevel@tonic-gate dprintf((stderr, "out of memory\n")); 12947c478bd9Sstevel@tonic-gate goto fail; 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate if (errno = nvpair_value_byte_array(nvp, (uchar_t **)&buf, 12987c478bd9Sstevel@tonic-gate &buflen)) { 12997c478bd9Sstevel@tonic-gate free(tmp); 13007c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvpair_value=%s)\n", 13017c478bd9Sstevel@tonic-gate strerror(errno))); 13027c478bd9Sstevel@tonic-gate goto fail; 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate if (errno = nvlist_unpack(buf, buflen, &(tmp->info), 0)) { 13057c478bd9Sstevel@tonic-gate free(tmp); 13067c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_unpack=%s)\n", 13077c478bd9Sstevel@tonic-gate strerror(errno))); 13087c478bd9Sstevel@tonic-gate goto fail; 13097c478bd9Sstevel@tonic-gate } 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate if (info == NULL) { 13127c478bd9Sstevel@tonic-gate prev = info = tmp; 13137c478bd9Sstevel@tonic-gate } else { 13147c478bd9Sstevel@tonic-gate prev->next = tmp; 13157c478bd9Sstevel@tonic-gate prev = tmp; 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate *infop = info; 13207c478bd9Sstevel@tonic-gate return (0); 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate fail: 13237c478bd9Sstevel@tonic-gate rcm_free_info(info); 13247c478bd9Sstevel@tonic-gate *infop = NULL; 13257c478bd9Sstevel@tonic-gate return (-1); 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate /* Generate a packed nvlist for communicating with RCM daemon */ 13297c478bd9Sstevel@tonic-gate static int 13307c478bd9Sstevel@tonic-gate rcm_generate_nvlist(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, 13317c478bd9Sstevel@tonic-gate void *arg, char **nvl_packed, size_t *nvl_size) 13327c478bd9Sstevel@tonic-gate { 13337c478bd9Sstevel@tonic-gate int nrsrcnames; 13347c478bd9Sstevel@tonic-gate char *buf = NULL; 13357c478bd9Sstevel@tonic-gate size_t buflen = 0; 13367c478bd9Sstevel@tonic-gate nvlist_t *nvl = NULL; 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate assert((nvl_packed != NULL) && (nvl_size != NULL)); 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate *nvl_size = 0; 13417c478bd9Sstevel@tonic-gate *nvl_packed = NULL; 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate /* Allocate an empty nvlist */ 13447c478bd9Sstevel@tonic-gate if ((errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) > 0) { 13457c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_alloc=%s).\n", 13467c478bd9Sstevel@tonic-gate strerror(errno))); 13477c478bd9Sstevel@tonic-gate return (-1); 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate /* Stuff in all the arguments for the daemon call */ 13517c478bd9Sstevel@tonic-gate if (nvlist_add_int32(nvl, RCM_CMD, cmd) != 0) { 13527c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_add(CMD)=%s).\n", 13537c478bd9Sstevel@tonic-gate strerror(errno))); 13547c478bd9Sstevel@tonic-gate goto fail; 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate if (rsrcnames) { 13577c478bd9Sstevel@tonic-gate nrsrcnames = 0; 13587c478bd9Sstevel@tonic-gate while (rsrcnames[nrsrcnames] != NULL) 13597c478bd9Sstevel@tonic-gate nrsrcnames++; 13607c478bd9Sstevel@tonic-gate if (nvlist_add_string_array(nvl, RCM_RSRCNAMES, rsrcnames, 13617c478bd9Sstevel@tonic-gate nrsrcnames) != 0) { 13627c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_add(RSRCNAMES)=%s).\n", 13637c478bd9Sstevel@tonic-gate strerror(errno))); 13647c478bd9Sstevel@tonic-gate goto fail; 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate if (hd->modname) { 13687c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvl, RCM_CLIENT_MODNAME, hd->modname) 13697c478bd9Sstevel@tonic-gate != 0) { 13707c478bd9Sstevel@tonic-gate dprintf((stderr, 13717c478bd9Sstevel@tonic-gate "failed (nvlist_add(CLIENT_MODNAME)=%s).\n", 13727c478bd9Sstevel@tonic-gate strerror(errno))); 13737c478bd9Sstevel@tonic-gate goto fail; 13747c478bd9Sstevel@tonic-gate } 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate if (hd->pid) { 13777c478bd9Sstevel@tonic-gate if (nvlist_add_uint64(nvl, RCM_CLIENT_ID, hd->pid) != 0) { 13787c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_add(CLIENT_ID)=%s).\n", 13797c478bd9Sstevel@tonic-gate strerror(errno))); 13807c478bd9Sstevel@tonic-gate goto fail; 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate if (flag) { 13847c478bd9Sstevel@tonic-gate if (nvlist_add_uint32(nvl, RCM_REQUEST_FLAG, flag) != 0) { 13857c478bd9Sstevel@tonic-gate dprintf((stderr, 13867c478bd9Sstevel@tonic-gate "failed (nvlist_add(REQUEST_FLAG)=%s).\n", 13877c478bd9Sstevel@tonic-gate strerror(errno))); 13887c478bd9Sstevel@tonic-gate goto fail; 13897c478bd9Sstevel@tonic-gate } 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate if (arg && cmd == CMD_SUSPEND) { 13927c478bd9Sstevel@tonic-gate if (nvlist_add_byte_array(nvl, RCM_SUSPEND_INTERVAL, 13937c478bd9Sstevel@tonic-gate (uchar_t *)arg, sizeof (timespec_t)) != 0) { 13947c478bd9Sstevel@tonic-gate dprintf((stderr, 13957c478bd9Sstevel@tonic-gate "failed (nvlist_add(SUSPEND_INTERVAL)=%s).\n", 13967c478bd9Sstevel@tonic-gate strerror(errno))); 13977c478bd9Sstevel@tonic-gate goto fail; 13987c478bd9Sstevel@tonic-gate } 13997c478bd9Sstevel@tonic-gate } 14007c478bd9Sstevel@tonic-gate if (arg && 14017c478bd9Sstevel@tonic-gate ((cmd == CMD_REQUEST_CHANGE) || (cmd == CMD_NOTIFY_CHANGE))) { 14027c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE, 14037c478bd9Sstevel@tonic-gate 0)) { 14047c478bd9Sstevel@tonic-gate dprintf((stderr, 14057c478bd9Sstevel@tonic-gate "failed (nvlist_pack(CHANGE_DATA)=%s).\n", 14067c478bd9Sstevel@tonic-gate strerror(errno))); 14077c478bd9Sstevel@tonic-gate goto fail; 14087c478bd9Sstevel@tonic-gate } 14097c478bd9Sstevel@tonic-gate if (nvlist_add_byte_array(nvl, RCM_CHANGE_DATA, (uchar_t *)buf, 14107c478bd9Sstevel@tonic-gate buflen) != 0) { 14117c478bd9Sstevel@tonic-gate dprintf((stderr, 14127c478bd9Sstevel@tonic-gate "failed (nvlist_add(CHANGE_DATA)=%s).\n", 14137c478bd9Sstevel@tonic-gate strerror(errno))); 14147c478bd9Sstevel@tonic-gate goto fail; 14157c478bd9Sstevel@tonic-gate } 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate if (arg && cmd == CMD_EVENT) { 14187c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE, 14197c478bd9Sstevel@tonic-gate 0)) { 14207c478bd9Sstevel@tonic-gate dprintf((stderr, 14217c478bd9Sstevel@tonic-gate "failed (nvlist_pack(CHANGE_DATA)=%s).\n", 14227c478bd9Sstevel@tonic-gate strerror(errno))); 14237c478bd9Sstevel@tonic-gate goto fail; 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate if (nvlist_add_byte_array(nvl, RCM_EVENT_DATA, (uchar_t *)buf, 14267c478bd9Sstevel@tonic-gate buflen) != 0) { 14277c478bd9Sstevel@tonic-gate dprintf((stderr, 14287c478bd9Sstevel@tonic-gate "failed (nvlist_add(EVENT_DATA)=%s).\n", 14297c478bd9Sstevel@tonic-gate strerror(errno))); 14307c478bd9Sstevel@tonic-gate goto fail; 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* Pack the nvlist */ 14357c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(nvl, nvl_packed, nvl_size, NV_ENCODE_NATIVE, 14367c478bd9Sstevel@tonic-gate 0)) { 14377c478bd9Sstevel@tonic-gate dprintf((stderr, "failed (nvlist_pack=%s).\n", 14387c478bd9Sstevel@tonic-gate strerror(errno))); 14397c478bd9Sstevel@tonic-gate goto fail; 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate /* If an argument was packed intermediately, free the buffer */ 14437c478bd9Sstevel@tonic-gate if (buf) 14447c478bd9Sstevel@tonic-gate free(buf); 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate /* Free the unpacked version of the nvlist and return the packed list */ 14477c478bd9Sstevel@tonic-gate nvlist_free(nvl); 14487c478bd9Sstevel@tonic-gate return (0); 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate fail: 14517c478bd9Sstevel@tonic-gate if (buf) 14527c478bd9Sstevel@tonic-gate free(buf); 14537c478bd9Sstevel@tonic-gate if (nvl) 14547c478bd9Sstevel@tonic-gate nvlist_free(nvl); 14557c478bd9Sstevel@tonic-gate if (*nvl_packed) 14567c478bd9Sstevel@tonic-gate free(*nvl_packed); 14577c478bd9Sstevel@tonic-gate *nvl_packed = NULL; 14587c478bd9Sstevel@tonic-gate *nvl_size = 0; 14597c478bd9Sstevel@tonic-gate return (-1); 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* check if rcm_daemon is up and running */ 14637c478bd9Sstevel@tonic-gate static int 14647c478bd9Sstevel@tonic-gate rcm_daemon_is_alive() 14657c478bd9Sstevel@tonic-gate { 14667c478bd9Sstevel@tonic-gate int lasttry; 14677c478bd9Sstevel@tonic-gate struct stat st; 14687c478bd9Sstevel@tonic-gate nvlist_t *nvl; 14697c478bd9Sstevel@tonic-gate char *buf = NULL; 14707c478bd9Sstevel@tonic-gate size_t buflen = 0; 14717c478bd9Sstevel@tonic-gate int delay = 300; 14727c478bd9Sstevel@tonic-gate const int maxdelay = 10000; /* 10 sec */ 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate /* generate a packed nvlist for the door knocking */ 14757c478bd9Sstevel@tonic-gate if (errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) { 14767c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_alloc failed: %s\n", strerror(errno))); 14777c478bd9Sstevel@tonic-gate return (0); 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate if (errno = nvlist_add_int32(nvl, RCM_CMD, CMD_KNOCK)) { 14807c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add failed: %s\n", strerror(errno))); 14817c478bd9Sstevel@tonic-gate nvlist_free(nvl); 14827c478bd9Sstevel@tonic-gate return (0); 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate if (errno = nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_NATIVE, 0)) { 14857c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_pack failed: %s\n", strerror(errno))); 14867c478bd9Sstevel@tonic-gate nvlist_free(nvl); 14877c478bd9Sstevel@tonic-gate return (0); 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate nvlist_free(nvl); 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate /* 14927c478bd9Sstevel@tonic-gate * check the door and knock on it 14937c478bd9Sstevel@tonic-gate */ 14947c478bd9Sstevel@tonic-gate if ((stat(RCM_SERVICE_DOOR, &st) == 0) && 14957c478bd9Sstevel@tonic-gate (get_event_service(RCM_SERVICE_DOOR, (void *)buf, buflen, NULL, 14967c478bd9Sstevel@tonic-gate NULL) == 0)) { 14977c478bd9Sstevel@tonic-gate free(buf); 14987c478bd9Sstevel@tonic-gate return (1); /* daemon is alive */ 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate /* 15027c478bd9Sstevel@tonic-gate * Attempt to start the daemon. 15037c478bd9Sstevel@tonic-gate * If caller has SIGCHLD set to SIG_IGN or its SA_NOCLDWAIT 15047c478bd9Sstevel@tonic-gate * flag set, waitpid(2) (hence rcm_exec_cmd) will fail. 15057c478bd9Sstevel@tonic-gate * get_event_service will determine if the rcm_daemon started. 15067c478bd9Sstevel@tonic-gate */ 15077c478bd9Sstevel@tonic-gate dprintf((stderr, "exec: %s\n", RCM_DAEMON_START)); 15087c478bd9Sstevel@tonic-gate (void) rcm_exec_cmd(RCM_DAEMON_START); 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate /* 15117c478bd9Sstevel@tonic-gate * Wait for daemon to respond, timeout at 10 sec 15127c478bd9Sstevel@tonic-gate */ 15137c478bd9Sstevel@tonic-gate while (((lasttry = get_event_service(RCM_SERVICE_DOOR, (void *)buf, 15147c478bd9Sstevel@tonic-gate buflen, NULL, NULL)) != 0) && 15157c478bd9Sstevel@tonic-gate ((errno == EBADF) || (errno == ESRCH))) { 15167c478bd9Sstevel@tonic-gate if (delay > maxdelay) { 15177c478bd9Sstevel@tonic-gate break; 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, delay); 15207c478bd9Sstevel@tonic-gate delay *= 2; 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate free(buf); 15247c478bd9Sstevel@tonic-gate if (lasttry == 0) 15257c478bd9Sstevel@tonic-gate return (1); 15267c478bd9Sstevel@tonic-gate return (0); 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate /* 15307c478bd9Sstevel@tonic-gate * Check permission. 15317c478bd9Sstevel@tonic-gate * 15327c478bd9Sstevel@tonic-gate * The policy is root only for now. Need to relax this when interface level 15337c478bd9Sstevel@tonic-gate * is raised. 15347c478bd9Sstevel@tonic-gate */ 15357c478bd9Sstevel@tonic-gate static int 15367c478bd9Sstevel@tonic-gate rcm_check_permission(void) 15377c478bd9Sstevel@tonic-gate { 15387c478bd9Sstevel@tonic-gate return (getuid() == 0); 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate /* 15427c478bd9Sstevel@tonic-gate * Project private function - for use by RCM MSTC tests 15437c478bd9Sstevel@tonic-gate * 15447c478bd9Sstevel@tonic-gate * Get the client name (rcm module name or script name) corresponding to 15457c478bd9Sstevel@tonic-gate * the given rcm handle. 15467c478bd9Sstevel@tonic-gate */ 15477c478bd9Sstevel@tonic-gate const char * 15487c478bd9Sstevel@tonic-gate rcm_get_client_name(rcm_handle_t *hd) 15497c478bd9Sstevel@tonic-gate { 15507c478bd9Sstevel@tonic-gate return (hd->modname); 15517c478bd9Sstevel@tonic-gate } 1552