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