16ba597c5SAnurag S. Maskey /* 26ba597c5SAnurag S. Maskey * CDDL HEADER START 36ba597c5SAnurag S. Maskey * 46ba597c5SAnurag S. Maskey * The contents of this file are subject to the terms of the 56ba597c5SAnurag S. Maskey * Common Development and Distribution License (the "License"). 66ba597c5SAnurag S. Maskey * You may not use this file except in compliance with the License. 76ba597c5SAnurag S. Maskey * 86ba597c5SAnurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96ba597c5SAnurag S. Maskey * or http://www.opensolaris.org/os/licensing. 106ba597c5SAnurag S. Maskey * See the License for the specific language governing permissions 116ba597c5SAnurag S. Maskey * and limitations under the License. 126ba597c5SAnurag S. Maskey * 136ba597c5SAnurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each 146ba597c5SAnurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156ba597c5SAnurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the 166ba597c5SAnurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying 176ba597c5SAnurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner] 186ba597c5SAnurag S. Maskey * 196ba597c5SAnurag S. Maskey * CDDL HEADER END 206ba597c5SAnurag S. Maskey */ 216ba597c5SAnurag S. Maskey 226ba597c5SAnurag S. Maskey /* 23*f6da83d4SAnurag S. Maskey * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 246ba597c5SAnurag S. Maskey */ 256ba597c5SAnurag S. Maskey 266ba597c5SAnurag S. Maskey #include <arpa/inet.h> 276ba597c5SAnurag S. Maskey #include <errno.h> 286ba597c5SAnurag S. Maskey #include <inet/ip.h> 296ba597c5SAnurag S. Maskey #include <libdladm.h> 306ba597c5SAnurag S. Maskey #include <libdllink.h> 316ba597c5SAnurag S. Maskey #include <libdlwlan.h> 326ba597c5SAnurag S. Maskey #include <libscf.h> 336ba597c5SAnurag S. Maskey #include <netinet/in.h> 346ba597c5SAnurag S. Maskey #include <netdb.h> 356ba597c5SAnurag S. Maskey #include <stdio.h> 366ba597c5SAnurag S. Maskey #include <stdlib.h> 376ba597c5SAnurag S. Maskey #include <string.h> 386ba597c5SAnurag S. Maskey #include <sys/socket.h> 396ba597c5SAnurag S. Maskey #include <sys/types.h> 406ba597c5SAnurag S. Maskey 416ba597c5SAnurag S. Maskey #include <libnwam.h> 426ba597c5SAnurag S. Maskey #include "conditions.h" 436ba597c5SAnurag S. Maskey #include "events.h" 446ba597c5SAnurag S. Maskey #include "objects.h" 456ba597c5SAnurag S. Maskey #include "util.h" 466ba597c5SAnurag S. Maskey 476ba597c5SAnurag S. Maskey /* 486ba597c5SAnurag S. Maskey * enm.c - contains routines which handle ENM (external network modifier) 496ba597c5SAnurag S. Maskey * abstraction. ENMs represent scripts or services that can be activated either 506ba597c5SAnurag S. Maskey * manually or in response to network conditions. 516ba597c5SAnurag S. Maskey */ 526ba597c5SAnurag S. Maskey 536ba597c5SAnurag S. Maskey #define CTRUN "/usr/bin/ctrun" 546ba597c5SAnurag S. Maskey 556ba597c5SAnurag S. Maskey static int 566ba597c5SAnurag S. Maskey enm_create_init_fini_event(nwam_enm_handle_t enmh, void *data) 576ba597c5SAnurag S. Maskey { 586ba597c5SAnurag S. Maskey boolean_t *init = data; 596ba597c5SAnurag S. Maskey char *name; 606ba597c5SAnurag S. Maskey nwamd_event_t enm_event; 616ba597c5SAnurag S. Maskey 626ba597c5SAnurag S. Maskey if (nwam_enm_get_name(enmh, &name) != NWAM_SUCCESS) { 636ba597c5SAnurag S. Maskey nlog(LOG_ERR, "enm_init_fini: could not get ENM name"); 646ba597c5SAnurag S. Maskey return (0); 656ba597c5SAnurag S. Maskey } 666ba597c5SAnurag S. Maskey 676ba597c5SAnurag S. Maskey enm_event = nwamd_event_init(*init ? 686ba597c5SAnurag S. Maskey NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI, 696ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_ENM, 0, name); 706ba597c5SAnurag S. Maskey if (enm_event != NULL) 716ba597c5SAnurag S. Maskey nwamd_event_enqueue(enm_event); 726ba597c5SAnurag S. Maskey free(name); 736ba597c5SAnurag S. Maskey 746ba597c5SAnurag S. Maskey return (0); 756ba597c5SAnurag S. Maskey } 766ba597c5SAnurag S. Maskey 776ba597c5SAnurag S. Maskey /* 786ba597c5SAnurag S. Maskey * Walk all ENMs, creating init events for each. 796ba597c5SAnurag S. Maskey */ 806ba597c5SAnurag S. Maskey void 816ba597c5SAnurag S. Maskey nwamd_init_enms(void) 826ba597c5SAnurag S. Maskey { 836ba597c5SAnurag S. Maskey boolean_t init = B_TRUE; 846ba597c5SAnurag S. Maskey 856ba597c5SAnurag S. Maskey (void) nwam_walk_enms(enm_create_init_fini_event, &init, 0, NULL); 866ba597c5SAnurag S. Maskey } 876ba597c5SAnurag S. Maskey 886ba597c5SAnurag S. Maskey /* 896ba597c5SAnurag S. Maskey * Walk all ENMs, creating fini events for each. 906ba597c5SAnurag S. Maskey */ 916ba597c5SAnurag S. Maskey void 926ba597c5SAnurag S. Maskey nwamd_fini_enms(void) 936ba597c5SAnurag S. Maskey { 946ba597c5SAnurag S. Maskey boolean_t init = B_FALSE; 956ba597c5SAnurag S. Maskey 966ba597c5SAnurag S. Maskey (void) nwam_walk_enms(enm_create_init_fini_event, &init, 0, NULL); 976ba597c5SAnurag S. Maskey } 986ba597c5SAnurag S. Maskey 996ba597c5SAnurag S. Maskey static boolean_t 1006ba597c5SAnurag S. Maskey enm_is_enabled(nwam_enm_handle_t enmh) 1016ba597c5SAnurag S. Maskey { 1026ba597c5SAnurag S. Maskey nwam_value_t enabledval; 1036ba597c5SAnurag S. Maskey boolean_t enabled = B_FALSE; 1046ba597c5SAnurag S. Maskey 1056ba597c5SAnurag S. Maskey if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ENABLED, 1066ba597c5SAnurag S. Maskey &enabledval) != NWAM_SUCCESS) { 1076ba597c5SAnurag S. Maskey /* It's legal for a conditional ENM to not specify "enabled" */ 1086ba597c5SAnurag S. Maskey return (B_FALSE); 1096ba597c5SAnurag S. Maskey } 1106ba597c5SAnurag S. Maskey if (nwam_value_get_boolean(enabledval, &enabled) != NWAM_SUCCESS) { 1116ba597c5SAnurag S. Maskey nlog(LOG_ERR, "enm_is_enabled: could not retrieve " 1126ba597c5SAnurag S. Maskey "enabled value"); 1136ba597c5SAnurag S. Maskey } 1146ba597c5SAnurag S. Maskey nwam_value_free(enabledval); 1156ba597c5SAnurag S. Maskey return (enabled); 1166ba597c5SAnurag S. Maskey } 1176ba597c5SAnurag S. Maskey 1186ba597c5SAnurag S. Maskey static int64_t 1196ba597c5SAnurag S. Maskey enm_get_activation_mode(nwam_enm_handle_t enmh) 1206ba597c5SAnurag S. Maskey { 1216ba597c5SAnurag S. Maskey uint64_t activation; 1226ba597c5SAnurag S. Maskey int64_t ret; 1236ba597c5SAnurag S. Maskey nwam_value_t activationval; 1246ba597c5SAnurag S. Maskey 1256ba597c5SAnurag S. Maskey if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ACTIVATION_MODE, 1266ba597c5SAnurag S. Maskey &activationval) != NWAM_SUCCESS) { 1276ba597c5SAnurag S. Maskey nlog(LOG_ERR, "enm_get_activation_mode: could not retrieve " 1286ba597c5SAnurag S. Maskey "activation mode value"); 1296ba597c5SAnurag S. Maskey return (-1); 1306ba597c5SAnurag S. Maskey } 1316ba597c5SAnurag S. Maskey if (nwam_value_get_uint64(activationval, &activation) != NWAM_SUCCESS) { 1326ba597c5SAnurag S. Maskey nlog(LOG_ERR, "enm_get_activation_mode: could not retrieve " 1336ba597c5SAnurag S. Maskey "activation mode value"); 1346ba597c5SAnurag S. Maskey ret = -1; 1356ba597c5SAnurag S. Maskey } else { 1366ba597c5SAnurag S. Maskey ret = activation; 1376ba597c5SAnurag S. Maskey } 1386ba597c5SAnurag S. Maskey nwam_value_free(activationval); 1396ba597c5SAnurag S. Maskey 1406ba597c5SAnurag S. Maskey return (ret); 1416ba597c5SAnurag S. Maskey } 1426ba597c5SAnurag S. Maskey 1436ba597c5SAnurag S. Maskey static void * 1446ba597c5SAnurag S. Maskey nwamd_enm_activate_deactivate_thread(void *arg) 1456ba597c5SAnurag S. Maskey { 1466ba597c5SAnurag S. Maskey char *object_name = arg; 1476ba597c5SAnurag S. Maskey nwamd_object_t object; 1486ba597c5SAnurag S. Maskey nwam_enm_handle_t enmh; 1496ba597c5SAnurag S. Maskey nwam_value_t scriptval = NULL; 1506ba597c5SAnurag S. Maskey nwam_state_t state; 1516ba597c5SAnurag S. Maskey nwam_aux_state_t aux_state; 152874067a0SAnurag S. Maskey char *script, *copy = NULL; 153874067a0SAnurag S. Maskey const char **argv = NULL; 1546ba597c5SAnurag S. Maskey boolean_t going_online, disable_succeeded = B_FALSE; 1556ba597c5SAnurag S. Maskey int ret; 1566ba597c5SAnurag S. Maskey 1576ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name); 1586ba597c5SAnurag S. Maskey if (object == NULL) { 1596ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_activate_deactivate_thread: " 1606ba597c5SAnurag S. Maskey "could not find ENM %s", object_name); 161874067a0SAnurag S. Maskey goto done; 1626ba597c5SAnurag S. Maskey } 1636ba597c5SAnurag S. Maskey enmh = object->nwamd_object_handle; 1646ba597c5SAnurag S. Maskey 1656ba597c5SAnurag S. Maskey going_online = 1666ba597c5SAnurag S. Maskey (object->nwamd_object_state == NWAM_STATE_OFFLINE_TO_ONLINE); 1676ba597c5SAnurag S. Maskey /* 1686ba597c5SAnurag S. Maskey * We're starting if current state is offline* and stopping otherwise. 1696ba597c5SAnurag S. Maskey */ 1706ba597c5SAnurag S. Maskey if (nwam_enm_get_prop_value(enmh, 1716ba597c5SAnurag S. Maskey going_online ? NWAM_ENM_PROP_START : NWAM_ENM_PROP_STOP, 1726ba597c5SAnurag S. Maskey &scriptval) != NWAM_SUCCESS || 1736ba597c5SAnurag S. Maskey nwam_value_get_string(scriptval, &script) != NWAM_SUCCESS) { 1746ba597c5SAnurag S. Maskey /* 1756ba597c5SAnurag S. Maskey * If we're stopping, it's not an error for no script to 1766ba597c5SAnurag S. Maskey * be specified. 1776ba597c5SAnurag S. Maskey */ 1786ba597c5SAnurag S. Maskey nlog(going_online ? LOG_ERR : LOG_DEBUG, 1796ba597c5SAnurag S. Maskey "nwamd_enm_activate_deactivate_thread: " 180874067a0SAnurag S. Maskey "no script specified for enm %s", object_name); 1816ba597c5SAnurag S. Maskey if (going_online) { 1826ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 1836ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_METHOD_MISSING; 1846ba597c5SAnurag S. Maskey } else { 1856ba597c5SAnurag S. Maskey disable_succeeded = B_TRUE; 1866ba597c5SAnurag S. Maskey } 1876ba597c5SAnurag S. Maskey } else { 188874067a0SAnurag S. Maskey char *lasts; 189874067a0SAnurag S. Maskey const char **newargv; 1906ba597c5SAnurag S. Maskey int i = 0; 191874067a0SAnurag S. Maskey struct timeval now; 1926ba597c5SAnurag S. Maskey 1936ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_activate_deactivate_thread: " 194874067a0SAnurag S. Maskey "running script %s for ENM %s", script, object_name); 1956ba597c5SAnurag S. Maskey 1966ba597c5SAnurag S. Maskey /* 1976ba597c5SAnurag S. Maskey * The script may take a number of arguments. We need to 1986ba597c5SAnurag S. Maskey * create a string array consisting of the wrapper command 1996ba597c5SAnurag S. Maskey * (ctrun), ENM script name, arguments and NULL array 2006ba597c5SAnurag S. Maskey * terminator. Start with an array of size equal to the 2016ba597c5SAnurag S. Maskey * string length (since the number of arguments will always 2026ba597c5SAnurag S. Maskey * be less than this) and shrink array to the actual number 2036ba597c5SAnurag S. Maskey * of arguments when we have parsed the string. 2046ba597c5SAnurag S. Maskey */ 2056ba597c5SAnurag S. Maskey if ((copy = strdup(script)) == NULL || 2066ba597c5SAnurag S. Maskey (argv = calloc(strlen(script), sizeof (char *))) == NULL) { 2076ba597c5SAnurag S. Maskey ret = 1; 2086ba597c5SAnurag S. Maskey goto err; 2096ba597c5SAnurag S. Maskey } 2106ba597c5SAnurag S. Maskey argv[i++] = CTRUN; 2116ba597c5SAnurag S. Maskey argv[i++] = strtok_r(copy, " ", &lasts); 2126ba597c5SAnurag S. Maskey if (argv[1] == NULL) { 2136ba597c5SAnurag S. Maskey ret = 1; 2146ba597c5SAnurag S. Maskey goto err; 2156ba597c5SAnurag S. Maskey } 2166ba597c5SAnurag S. Maskey 2176ba597c5SAnurag S. Maskey for (; (argv[i] = strtok_r(NULL, " ", &lasts)) != NULL; i++) {} 2186ba597c5SAnurag S. Maskey 2196ba597c5SAnurag S. Maskey newargv = realloc(argv, (i + 1) * sizeof (char *)); 2206ba597c5SAnurag S. Maskey argv = newargv; 2216ba597c5SAnurag S. Maskey 222874067a0SAnurag S. Maskey /* Store the current time as the time the script began */ 223874067a0SAnurag S. Maskey (void) gettimeofday(&now, NULL); 224874067a0SAnurag S. Maskey object->nwamd_script_time = now; 225874067a0SAnurag S. Maskey 226874067a0SAnurag S. Maskey /* 227874067a0SAnurag S. Maskey * Release the object so that it is not blocked while the 228874067a0SAnurag S. Maskey * script is running. 229874067a0SAnurag S. Maskey */ 230874067a0SAnurag S. Maskey nwamd_object_release(object); 231874067a0SAnurag S. Maskey 2326ba597c5SAnurag S. Maskey ret = nwamd_start_childv(CTRUN, argv); 2336ba597c5SAnurag S. Maskey 234874067a0SAnurag S. Maskey /* 235874067a0SAnurag S. Maskey * Find the object again, now that the script has finished 236874067a0SAnurag S. Maskey * running. Check if this ENM was re-read during that time by 237874067a0SAnurag S. Maskey * comparing the object's script time with the one from above. 238874067a0SAnurag S. Maskey */ 239874067a0SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name); 240874067a0SAnurag S. Maskey if (object == NULL) { 241874067a0SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_activate_deactivate_thread: " 242874067a0SAnurag S. Maskey "could not find ENM %s after running script", 243874067a0SAnurag S. Maskey object_name); 244874067a0SAnurag S. Maskey goto done; 245874067a0SAnurag S. Maskey } 246874067a0SAnurag S. Maskey 247874067a0SAnurag S. Maskey if (object->nwamd_script_time.tv_sec != now.tv_sec || 248874067a0SAnurag S. Maskey object->nwamd_script_time.tv_usec != now.tv_usec) { 249874067a0SAnurag S. Maskey nlog(LOG_INFO, "nwamd_enm_activate_deactivate_thread: " 250874067a0SAnurag S. Maskey "ENM %s has been refreshed, nothing to do", 251874067a0SAnurag S. Maskey object_name); 252874067a0SAnurag S. Maskey nwamd_object_release(object); 253874067a0SAnurag S. Maskey goto done; 254874067a0SAnurag S. Maskey } 255874067a0SAnurag S. Maskey (void) gettimeofday(&object->nwamd_script_time, NULL); 256874067a0SAnurag S. Maskey 2576ba597c5SAnurag S. Maskey err: 2586ba597c5SAnurag S. Maskey /* 2596ba597c5SAnurag S. Maskey * If script execution fails and we're not destroying the 2606ba597c5SAnurag S. Maskey * object, go to maintenance. 2616ba597c5SAnurag S. Maskey */ 2626ba597c5SAnurag S. Maskey if (ret != 0) { 2636ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_activate_deactivate_thread: " 2646ba597c5SAnurag S. Maskey "execution of '%s' failed for ENM %s", 265874067a0SAnurag S. Maskey script, object_name); 2666ba597c5SAnurag S. Maskey if (object->nwamd_object_aux_state != 2676ba597c5SAnurag S. Maskey NWAM_AUX_STATE_UNINITIALIZED) { 2686ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 2696ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_METHOD_FAILED; 2706ba597c5SAnurag S. Maskey } else { 2716ba597c5SAnurag S. Maskey state = NWAM_STATE_UNINITIALIZED; 2726ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_UNINITIALIZED; 2736ba597c5SAnurag S. Maskey } 2746ba597c5SAnurag S. Maskey } else { 2756ba597c5SAnurag S. Maskey if (going_online) { 2766ba597c5SAnurag S. Maskey state = NWAM_STATE_ONLINE; 2776ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_ACTIVE; 2786ba597c5SAnurag S. Maskey } else { 2796ba597c5SAnurag S. Maskey disable_succeeded = B_TRUE; 2806ba597c5SAnurag S. Maskey } 2816ba597c5SAnurag S. Maskey } 2826ba597c5SAnurag S. Maskey } 2836ba597c5SAnurag S. Maskey 2846ba597c5SAnurag S. Maskey if (disable_succeeded) { 2856ba597c5SAnurag S. Maskey /* 2866ba597c5SAnurag S. Maskey * If aux state is "manual disable", we know 2876ba597c5SAnurag S. Maskey * this was a disable request, otherwise it was 2886ba597c5SAnurag S. Maskey * _fini request or a condition satisfaction 2896ba597c5SAnurag S. Maskey * failure. 2906ba597c5SAnurag S. Maskey */ 2916ba597c5SAnurag S. Maskey switch (object->nwamd_object_aux_state) { 2926ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_MANUAL_DISABLE: 2936ba597c5SAnurag S. Maskey state = NWAM_STATE_DISABLED; 2946ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_MANUAL_DISABLE; 2956ba597c5SAnurag S. Maskey break; 2966ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_UNINITIALIZED: 2976ba597c5SAnurag S. Maskey state = NWAM_STATE_UNINITIALIZED; 2986ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_UNINITIALIZED; 2996ba597c5SAnurag S. Maskey break; 3006ba597c5SAnurag S. Maskey default: 3016ba597c5SAnurag S. Maskey state = NWAM_STATE_OFFLINE; 3026ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_CONDITIONS_NOT_MET; 3036ba597c5SAnurag S. Maskey break; 3046ba597c5SAnurag S. Maskey } 3056ba597c5SAnurag S. Maskey } 3066ba597c5SAnurag S. Maskey 3076ba597c5SAnurag S. Maskey /* If state/aux state are uninitialized/unintialized, destroy the ENM */ 3086ba597c5SAnurag S. Maskey if (state == NWAM_STATE_UNINITIALIZED && 3096ba597c5SAnurag S. Maskey aux_state == NWAM_AUX_STATE_UNINITIALIZED) { 3106ba597c5SAnurag S. Maskey object->nwamd_object_state = state; 3116ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = aux_state; 3126ba597c5SAnurag S. Maskey (void) nwamd_object_release_and_destroy_after_preserve(object); 3136ba597c5SAnurag S. Maskey } else { 3146ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 3156ba597c5SAnurag S. Maskey object->nwamd_object_name, state, aux_state); 3166ba597c5SAnurag S. Maskey (void) nwamd_object_release_after_preserve(object); 3176ba597c5SAnurag S. Maskey } 3186ba597c5SAnurag S. Maskey 319874067a0SAnurag S. Maskey done: 320874067a0SAnurag S. Maskey /* object_name was malloc() before this thread was created, free() it */ 321874067a0SAnurag S. Maskey free(object_name); 322874067a0SAnurag S. Maskey free(argv); 323874067a0SAnurag S. Maskey free(copy); 324874067a0SAnurag S. Maskey nwam_value_free(scriptval); 3256ba597c5SAnurag S. Maskey return (NULL); 3266ba597c5SAnurag S. Maskey } 3276ba597c5SAnurag S. Maskey 3286ba597c5SAnurag S. Maskey /* 3296ba597c5SAnurag S. Maskey * Run start/stop method for ENM in a separate thread. The object lock is not 3306ba597c5SAnurag S. Maskey * held across threads, so we duplicate the object name for the method 3316ba597c5SAnurag S. Maskey * execution thread. Returns true if thread is successfully launched. 3326ba597c5SAnurag S. Maskey */ 3336ba597c5SAnurag S. Maskey boolean_t 3346ba597c5SAnurag S. Maskey nwamd_enm_run_method(nwamd_object_t object) 3356ba597c5SAnurag S. Maskey { 3366ba597c5SAnurag S. Maskey char *name; 3376ba597c5SAnurag S. Maskey pthread_t script; 3386ba597c5SAnurag S. Maskey 3396ba597c5SAnurag S. Maskey /* 3406ba597c5SAnurag S. Maskey * Launch separate thread to wait for execution of script 3416ba597c5SAnurag S. Maskey * to complete. Do not hold object lock across threads. 3426ba597c5SAnurag S. Maskey */ 3436ba597c5SAnurag S. Maskey if ((name = strdup(object->nwamd_object_name)) == NULL) { 3446ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_run_method: %s: out of memory", 3456ba597c5SAnurag S. Maskey object->nwamd_object_name); 3466ba597c5SAnurag S. Maskey return (B_FALSE); 3476ba597c5SAnurag S. Maskey } 3486ba597c5SAnurag S. Maskey 3496ba597c5SAnurag S. Maskey if (pthread_create(&script, NULL, 3506ba597c5SAnurag S. Maskey nwamd_enm_activate_deactivate_thread, name) != 0) { 3516ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_run_method: could not create " 3526ba597c5SAnurag S. Maskey "enm script thread for %s", name); 3536ba597c5SAnurag S. Maskey free(name); 3546ba597c5SAnurag S. Maskey return (B_FALSE); 3556ba597c5SAnurag S. Maskey } 3566ba597c5SAnurag S. Maskey /* "name" will be freed by the newly-created thread. */ 3576ba597c5SAnurag S. Maskey 3586ba597c5SAnurag S. Maskey /* detach thread so that it doesn't become a zombie */ 3596ba597c5SAnurag S. Maskey (void) pthread_detach(script); 3606ba597c5SAnurag S. Maskey 3616ba597c5SAnurag S. Maskey return (B_TRUE); 3626ba597c5SAnurag S. Maskey } 3636ba597c5SAnurag S. Maskey 3646ba597c5SAnurag S. Maskey /* 3656ba597c5SAnurag S. Maskey * Activate the ENM, either in response to an enable event or conditions 3666ba597c5SAnurag S. Maskey * being satisfied. 3676ba597c5SAnurag S. Maskey */ 3686ba597c5SAnurag S. Maskey static void 3696ba597c5SAnurag S. Maskey nwamd_enm_activate(const char *object_name) 3706ba597c5SAnurag S. Maskey { 3716ba597c5SAnurag S. Maskey nwamd_object_t object; 3726ba597c5SAnurag S. Maskey nwam_value_t fmrival; 3736ba597c5SAnurag S. Maskey char *fmri, *smf_state; 3746ba597c5SAnurag S. Maskey int ret; 3756ba597c5SAnurag S. Maskey nwam_enm_handle_t enmh; 3766ba597c5SAnurag S. Maskey nwam_state_t state; 3776ba597c5SAnurag S. Maskey nwam_aux_state_t aux_state; 3786ba597c5SAnurag S. Maskey nwam_error_t err; 3796ba597c5SAnurag S. Maskey boolean_t ran_method = B_FALSE; 3806ba597c5SAnurag S. Maskey 3816ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name); 3826ba597c5SAnurag S. Maskey if (object == NULL) { 3836ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_activate: could not find ENM %s", 3846ba597c5SAnurag S. Maskey object_name); 3856ba597c5SAnurag S. Maskey return; 3866ba597c5SAnurag S. Maskey } 3876ba597c5SAnurag S. Maskey state = object->nwamd_object_state; 3886ba597c5SAnurag S. Maskey aux_state = object->nwamd_object_aux_state; 3896ba597c5SAnurag S. Maskey enmh = object->nwamd_object_handle; 3906ba597c5SAnurag S. Maskey 3916ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_activate: activating ENM %s", 3926ba597c5SAnurag S. Maskey object->nwamd_object_name); 3936ba597c5SAnurag S. Maskey 3946ba597c5SAnurag S. Maskey err = nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_FMRI, &fmrival); 3956ba597c5SAnurag S. Maskey switch (err) { 3966ba597c5SAnurag S. Maskey case NWAM_SUCCESS: 3976ba597c5SAnurag S. Maskey 3986ba597c5SAnurag S. Maskey if (nwam_value_get_string(fmrival, &fmri) != NWAM_SUCCESS) { 3996ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_activate: could not retrieve " 4006ba597c5SAnurag S. Maskey "FMRI string for ENM %s", 4016ba597c5SAnurag S. Maskey object->nwamd_object_name); 4026ba597c5SAnurag S. Maskey nwam_value_free(fmrival); 4036ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 4046ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_INVALID_CONFIG; 4056ba597c5SAnurag S. Maskey break; 4066ba597c5SAnurag S. Maskey } 4076ba597c5SAnurag S. Maskey 4086ba597c5SAnurag S. Maskey if ((smf_state = smf_get_state(fmri)) == NULL) { 4096ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_activate: invalid FMRI %s " 4106ba597c5SAnurag S. Maskey "for ENM %s", fmri, object->nwamd_object_name); 4116ba597c5SAnurag S. Maskey nwam_value_free(fmrival); 4126ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 4136ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_INVALID_CONFIG; 4146ba597c5SAnurag S. Maskey break; 4156ba597c5SAnurag S. Maskey } 4166ba597c5SAnurag S. Maskey 4176ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_activate: activating %s for ENM %s", 4186ba597c5SAnurag S. Maskey fmri, object->nwamd_object_name); 4196ba597c5SAnurag S. Maskey 4206ba597c5SAnurag S. Maskey if (strcmp(smf_state, SCF_STATE_STRING_ONLINE) == 0) 4216ba597c5SAnurag S. Maskey ret = smf_restart_instance(fmri); 4226ba597c5SAnurag S. Maskey else if (strcmp(smf_state, SCF_STATE_STRING_OFFLINE) == 0) 4236ba597c5SAnurag S. Maskey ret = smf_restart_instance(fmri); 4246ba597c5SAnurag S. Maskey else if (strcmp(smf_state, SCF_STATE_STRING_DISABLED) == 0) 4256ba597c5SAnurag S. Maskey ret = smf_enable_instance(fmri, SMF_TEMPORARY); 4266ba597c5SAnurag S. Maskey else 4276ba597c5SAnurag S. Maskey ret = smf_restore_instance(fmri); 4286ba597c5SAnurag S. Maskey 4296ba597c5SAnurag S. Maskey if (ret == 0) { 4306ba597c5SAnurag S. Maskey state = NWAM_STATE_ONLINE; 4316ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_ACTIVE; 4326ba597c5SAnurag S. Maskey } else { 4336ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_activate: failed to enable " 4346ba597c5SAnurag S. Maskey "FMRI %s for ENM %s", fmri, 4356ba597c5SAnurag S. Maskey object->nwamd_object_name); 4366ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 4376ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_METHOD_FAILED; 4386ba597c5SAnurag S. Maskey } 4396ba597c5SAnurag S. Maskey free(smf_state); 4406ba597c5SAnurag S. Maskey nwam_value_free(fmrival); 4416ba597c5SAnurag S. Maskey break; 4426ba597c5SAnurag S. Maskey default: 4436ba597c5SAnurag S. Maskey /* 4446ba597c5SAnurag S. Maskey * Must be a method-based ENM with start (and stop) script(s). 4456ba597c5SAnurag S. Maskey */ 4466ba597c5SAnurag S. Maskey if (!nwamd_enm_run_method(object)) { 4476ba597c5SAnurag S. Maskey /* Could not launch method execution thread */ 4486ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 4496ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_METHOD_FAILED; 4506ba597c5SAnurag S. Maskey } else { 4516ba597c5SAnurag S. Maskey ran_method = B_TRUE; 4526ba597c5SAnurag S. Maskey } 4536ba597c5SAnurag S. Maskey break; 4546ba597c5SAnurag S. Maskey } 4556ba597c5SAnurag S. Maskey 4566ba597c5SAnurag S. Maskey if (state != object->nwamd_object_state || 4576ba597c5SAnurag S. Maskey aux_state != object->nwamd_object_aux_state) { 4586ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 4596ba597c5SAnurag S. Maskey object->nwamd_object_name, state, aux_state); 4606ba597c5SAnurag S. Maskey } 4616ba597c5SAnurag S. Maskey 4626ba597c5SAnurag S. Maskey /* 4636ba597c5SAnurag S. Maskey * If the method thread was created, we drop the lock to the ENM 4646ba597c5SAnurag S. Maskey * object without decreasing the reference count, ensuring it will not 4656ba597c5SAnurag S. Maskey * be destroyed until method execution has completed. 4666ba597c5SAnurag S. Maskey */ 4676ba597c5SAnurag S. Maskey if (ran_method) { 4686ba597c5SAnurag S. Maskey nwamd_object_release_and_preserve(object); 4696ba597c5SAnurag S. Maskey } else { 4706ba597c5SAnurag S. Maskey nwamd_object_release(object); 4716ba597c5SAnurag S. Maskey } 4726ba597c5SAnurag S. Maskey } 4736ba597c5SAnurag S. Maskey 4746ba597c5SAnurag S. Maskey /* Deactivates the ENM. */ 4756ba597c5SAnurag S. Maskey static void 4766ba597c5SAnurag S. Maskey nwamd_enm_deactivate(const char *object_name) 4776ba597c5SAnurag S. Maskey { 4786ba597c5SAnurag S. Maskey nwamd_object_t object; 4796ba597c5SAnurag S. Maskey nwam_enm_handle_t enmh; 4806ba597c5SAnurag S. Maskey nwam_value_t fmrival; 4816ba597c5SAnurag S. Maskey char *fmri, *smf_state; 4826ba597c5SAnurag S. Maskey int ret; 4836ba597c5SAnurag S. Maskey nwam_state_t state; 4846ba597c5SAnurag S. Maskey nwam_aux_state_t aux_state; 4856ba597c5SAnurag S. Maskey boolean_t destroying = B_FALSE; 4866ba597c5SAnurag S. Maskey 4876ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name); 4886ba597c5SAnurag S. Maskey if (object == NULL) { 4896ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_deactivate: could not find ENM %s", 4906ba597c5SAnurag S. Maskey object_name); 4916ba597c5SAnurag S. Maskey return; 4926ba597c5SAnurag S. Maskey } 4936ba597c5SAnurag S. Maskey 4946ba597c5SAnurag S. Maskey state = object->nwamd_object_state; 4956ba597c5SAnurag S. Maskey aux_state = object->nwamd_object_aux_state; 4966ba597c5SAnurag S. Maskey enmh = object->nwamd_object_handle; 4976ba597c5SAnurag S. Maskey state = object->nwamd_object_state; 4986ba597c5SAnurag S. Maskey /* If destroying, we don't care about method failure/config err */ 4996ba597c5SAnurag S. Maskey destroying = (aux_state == NWAM_AUX_STATE_UNINITIALIZED); 5006ba597c5SAnurag S. Maskey 5016ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_deactivate: deactivating enm %s", 5026ba597c5SAnurag S. Maskey object->nwamd_object_name); 5036ba597c5SAnurag S. Maskey 5046ba597c5SAnurag S. Maskey if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_FMRI, &fmrival) 5056ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 5066ba597c5SAnurag S. Maskey /* 5076ba597c5SAnurag S. Maskey * Must be a method-based ENM with start (and stop) script(s). 5086ba597c5SAnurag S. Maskey * Script execution thread will take care of the rest. 5096ba597c5SAnurag S. Maskey * If the method thread was created, we drop the lock to the ENM 5106ba597c5SAnurag S. Maskey * object without decreasing the reference count, ensuring it 5116ba597c5SAnurag S. Maskey * will not be destroyed until method execution has completed. 5126ba597c5SAnurag S. Maskey */ 5136ba597c5SAnurag S. Maskey if (nwamd_enm_run_method(object)) { 5146ba597c5SAnurag S. Maskey nwamd_object_release_and_preserve(object); 5156ba597c5SAnurag S. Maskey return; 5166ba597c5SAnurag S. Maskey } 5176ba597c5SAnurag S. Maskey /* Could not launch method execution thread */ 5186ba597c5SAnurag S. Maskey if (!destroying) { 5196ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 5206ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_METHOD_FAILED; 5216ba597c5SAnurag S. Maskey } 5226ba597c5SAnurag S. Maskey } else { 5236ba597c5SAnurag S. Maskey if (nwam_value_get_string(fmrival, &fmri) != NWAM_SUCCESS) { 5246ba597c5SAnurag S. Maskey nlog(LOG_ERR, 5256ba597c5SAnurag S. Maskey "nwamd_enm_deactivate: could not retrieve " 5266ba597c5SAnurag S. Maskey "FMRI string for ENM %s", 5276ba597c5SAnurag S. Maskey object->nwamd_object_name); 5286ba597c5SAnurag S. Maskey if (!destroying) { 5296ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 5306ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_INVALID_CONFIG; 5316ba597c5SAnurag S. Maskey } 5326ba597c5SAnurag S. Maskey } else { 5336ba597c5SAnurag S. Maskey if ((smf_state = smf_get_state(fmri)) == NULL) { 5346ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_deactivate: invalid " 5356ba597c5SAnurag S. Maskey "FMRI %s for ENM %s", fmri, 5366ba597c5SAnurag S. Maskey object->nwamd_object_name); 5376ba597c5SAnurag S. Maskey nwam_value_free(fmrival); 5386ba597c5SAnurag S. Maskey if (!destroying) { 5396ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 5406ba597c5SAnurag S. Maskey aux_state = 5416ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INVALID_CONFIG; 5426ba597c5SAnurag S. Maskey } 5436ba597c5SAnurag S. Maskey goto done; 5446ba597c5SAnurag S. Maskey } 5456ba597c5SAnurag S. Maskey free(smf_state); 5466ba597c5SAnurag S. Maskey 5476ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_deactivate: deactivating %s " 5486ba597c5SAnurag S. Maskey "for ENM %s", fmri, object->nwamd_object_name); 5496ba597c5SAnurag S. Maskey 5506ba597c5SAnurag S. Maskey ret = smf_disable_instance(fmri, SMF_TEMPORARY); 5516ba597c5SAnurag S. Maskey 5526ba597c5SAnurag S. Maskey if (ret != 0) { 5536ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_deactivate: " 5546ba597c5SAnurag S. Maskey "smf_disable_instance(%s) failed for " 5556ba597c5SAnurag S. Maskey "ENM %s: %s", fmri, 5566ba597c5SAnurag S. Maskey object->nwamd_object_name, 5576ba597c5SAnurag S. Maskey scf_strerror(scf_error())); 5586ba597c5SAnurag S. Maskey if (!destroying) { 5596ba597c5SAnurag S. Maskey state = NWAM_STATE_MAINTENANCE; 5606ba597c5SAnurag S. Maskey aux_state = 5616ba597c5SAnurag S. Maskey NWAM_AUX_STATE_METHOD_FAILED; 5626ba597c5SAnurag S. Maskey } 5636ba597c5SAnurag S. Maskey } 5646ba597c5SAnurag S. Maskey } 5656ba597c5SAnurag S. Maskey nwam_value_free(fmrival); 5666ba597c5SAnurag S. Maskey } 5676ba597c5SAnurag S. Maskey done: 5686ba597c5SAnurag S. Maskey if (state == object->nwamd_object_state && 5696ba597c5SAnurag S. Maskey aux_state == object->nwamd_object_aux_state) { 5706ba597c5SAnurag S. Maskey /* 5716ba597c5SAnurag S. Maskey * If aux state is "manual disable", we know 5726ba597c5SAnurag S. Maskey * this was a disable request, otherwise it was 5736ba597c5SAnurag S. Maskey * a _fini request or a condition satisfaction 5746ba597c5SAnurag S. Maskey * failure. 5756ba597c5SAnurag S. Maskey */ 5766ba597c5SAnurag S. Maskey switch (object->nwamd_object_aux_state) { 5776ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_MANUAL_DISABLE: 5786ba597c5SAnurag S. Maskey state = NWAM_STATE_DISABLED; 5796ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_MANUAL_DISABLE; 5806ba597c5SAnurag S. Maskey break; 5816ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_UNINITIALIZED: 5826ba597c5SAnurag S. Maskey state = NWAM_STATE_UNINITIALIZED; 5836ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_UNINITIALIZED; 5846ba597c5SAnurag S. Maskey break; 5856ba597c5SAnurag S. Maskey default: 5866ba597c5SAnurag S. Maskey state = NWAM_STATE_OFFLINE; 5876ba597c5SAnurag S. Maskey aux_state = NWAM_AUX_STATE_CONDITIONS_NOT_MET; 5886ba597c5SAnurag S. Maskey break; 5896ba597c5SAnurag S. Maskey } 5906ba597c5SAnurag S. Maskey } 5916ba597c5SAnurag S. Maskey 5926ba597c5SAnurag S. Maskey /* Only change state if we aren't destroying the ENM */ 5936ba597c5SAnurag S. Maskey if (!destroying && (state != object->nwamd_object_state || 5946ba597c5SAnurag S. Maskey aux_state != object->nwamd_object_aux_state)) { 5956ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 5966ba597c5SAnurag S. Maskey object->nwamd_object_name, state, aux_state); 5976ba597c5SAnurag S. Maskey } 5986ba597c5SAnurag S. Maskey 5996ba597c5SAnurag S. Maskey /* If state/aux state are uninitialized/unintialized, destroy the ENM */ 6006ba597c5SAnurag S. Maskey if (state == NWAM_STATE_UNINITIALIZED && 6016ba597c5SAnurag S. Maskey aux_state == NWAM_AUX_STATE_UNINITIALIZED) { 6026ba597c5SAnurag S. Maskey (void) nwamd_object_release_and_destroy(object); 6036ba597c5SAnurag S. Maskey } else { 6046ba597c5SAnurag S. Maskey (void) nwamd_object_release(object); 6056ba597c5SAnurag S. Maskey } 6066ba597c5SAnurag S. Maskey } 6076ba597c5SAnurag S. Maskey 6086ba597c5SAnurag S. Maskey /* 6096ba597c5SAnurag S. Maskey * Determine whether an ENM should be (de)activated. 6106ba597c5SAnurag S. Maskey */ 6116ba597c5SAnurag S. Maskey /* ARGSUSED1 */ 6126ba597c5SAnurag S. Maskey static int 6136ba597c5SAnurag S. Maskey nwamd_enm_check(nwamd_object_t object, void *data) 6146ba597c5SAnurag S. Maskey { 6156ba597c5SAnurag S. Maskey nwam_enm_handle_t enmh; 6166ba597c5SAnurag S. Maskey nwam_value_t conditionval; 6176ba597c5SAnurag S. Maskey int64_t eactivation; 6186ba597c5SAnurag S. Maskey boolean_t enabled, satisfied; 6196ba597c5SAnurag S. Maskey char **conditions; 6206ba597c5SAnurag S. Maskey nwam_state_t state; 6216ba597c5SAnurag S. Maskey uint_t nelem; 6226ba597c5SAnurag S. Maskey 6236ba597c5SAnurag S. Maskey state = object->nwamd_object_state; 6246ba597c5SAnurag S. Maskey 6256ba597c5SAnurag S. Maskey enmh = object->nwamd_object_handle; 6266ba597c5SAnurag S. Maskey 6276ba597c5SAnurag S. Maskey eactivation = enm_get_activation_mode(enmh); 6286ba597c5SAnurag S. Maskey if (eactivation == -1) 6296ba597c5SAnurag S. Maskey return (0); 6306ba597c5SAnurag S. Maskey 6316ba597c5SAnurag S. Maskey switch (eactivation) { 6326ba597c5SAnurag S. Maskey case NWAM_ACTIVATION_MODE_MANUAL: 6336ba597c5SAnurag S. Maskey enabled = enm_is_enabled(enmh); 6346ba597c5SAnurag S. Maskey 6356ba597c5SAnurag S. Maskey if (enabled) { 6366ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_check: %s is enabled", 6376ba597c5SAnurag S. Maskey object->nwamd_object_name); 6386ba597c5SAnurag S. Maskey switch (state) { 6396ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE: 6406ba597c5SAnurag S. Maskey case NWAM_STATE_MAINTENANCE: 6416ba597c5SAnurag S. Maskey /* Do nothing */ 6426ba597c5SAnurag S. Maskey break; 6436ba597c5SAnurag S. Maskey default: 6446ba597c5SAnurag S. Maskey if (nwamd_enm_action(object->nwamd_object_name, 6456ba597c5SAnurag S. Maskey NWAM_ACTION_ENABLE) != 0) { 6466ba597c5SAnurag S. Maskey nlog(LOG_ERR, 6476ba597c5SAnurag S. Maskey "nwamd_enm_check: enable failed " 6486ba597c5SAnurag S. Maskey "for enm %s", 6496ba597c5SAnurag S. Maskey object->nwamd_object_name); 6506ba597c5SAnurag S. Maskey } 6516ba597c5SAnurag S. Maskey break; 6526ba597c5SAnurag S. Maskey } 6536ba597c5SAnurag S. Maskey } else { 6546ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_check: %s is disabled", 6556ba597c5SAnurag S. Maskey object->nwamd_object_name); 6566ba597c5SAnurag S. Maskey switch (state) { 6576ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE: 6586ba597c5SAnurag S. Maskey if (nwamd_enm_action(object->nwamd_object_name, 6596ba597c5SAnurag S. Maskey NWAM_ACTION_DISABLE) != 0) { 6606ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_check: " 6616ba597c5SAnurag S. Maskey "disable failed for enm %s", 6626ba597c5SAnurag S. Maskey object->nwamd_object_name); 6636ba597c5SAnurag S. Maskey } 6646ba597c5SAnurag S. Maskey break; 6656ba597c5SAnurag S. Maskey case NWAM_STATE_MAINTENANCE: 6666ba597c5SAnurag S. Maskey /* Do nothing */ 6676ba597c5SAnurag S. Maskey break; 6686ba597c5SAnurag S. Maskey case NWAM_STATE_DISABLED: 6696ba597c5SAnurag S. Maskey /* Do nothing */ 6706ba597c5SAnurag S. Maskey break; 6716ba597c5SAnurag S. Maskey default: 6726ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 6736ba597c5SAnurag S. Maskey object->nwamd_object_name, 6746ba597c5SAnurag S. Maskey NWAM_STATE_DISABLED, 6756ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 6766ba597c5SAnurag S. Maskey break; 6776ba597c5SAnurag S. Maskey } 6786ba597c5SAnurag S. Maskey } 6796ba597c5SAnurag S. Maskey break; 6806ba597c5SAnurag S. Maskey 6816ba597c5SAnurag S. Maskey case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY: 6826ba597c5SAnurag S. Maskey case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL: 6836ba597c5SAnurag S. Maskey if (nwam_enm_get_prop_value(enmh, 6846ba597c5SAnurag S. Maskey NWAM_ENM_PROP_CONDITIONS, &conditionval) != NWAM_SUCCESS) { 6856ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_check: could not retrieve " 6866ba597c5SAnurag S. Maskey "condition value"); 6876ba597c5SAnurag S. Maskey break; 6886ba597c5SAnurag S. Maskey } 6896ba597c5SAnurag S. Maskey if (nwam_value_get_string_array(conditionval, 6906ba597c5SAnurag S. Maskey &conditions, &nelem) != NWAM_SUCCESS) { 6916ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_check: could not retrieve " 6926ba597c5SAnurag S. Maskey "condition value"); 6936ba597c5SAnurag S. Maskey nwam_value_free(conditionval); 6946ba597c5SAnurag S. Maskey break; 6956ba597c5SAnurag S. Maskey } 6966ba597c5SAnurag S. Maskey satisfied = nwamd_check_conditions((uint64_t)eactivation, 6976ba597c5SAnurag S. Maskey conditions, nelem); 6986ba597c5SAnurag S. Maskey 6996ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_check: conditions for enm %s " 7006ba597c5SAnurag S. Maskey "%s satisfied", object->nwamd_object_name, 7016ba597c5SAnurag S. Maskey satisfied ? "is" : "is not"); 7026ba597c5SAnurag S. Maskey if (state != NWAM_STATE_ONLINE && satisfied) { 7036ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 7046ba597c5SAnurag S. Maskey object->nwamd_object_name, 7056ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 7066ba597c5SAnurag S. Maskey NWAM_AUX_STATE_METHOD_RUNNING); 7076ba597c5SAnurag S. Maskey } 7086ba597c5SAnurag S. Maskey if (state == NWAM_STATE_ONLINE && !satisfied) { 7096ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 7106ba597c5SAnurag S. Maskey object->nwamd_object_name, 7116ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 7126ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 7136ba597c5SAnurag S. Maskey } 7146ba597c5SAnurag S. Maskey nwam_value_free(conditionval); 7156ba597c5SAnurag S. Maskey break; 7166ba597c5SAnurag S. Maskey 7176ba597c5SAnurag S. Maskey } 7186ba597c5SAnurag S. Maskey return (0); 7196ba597c5SAnurag S. Maskey } 7206ba597c5SAnurag S. Maskey 7216ba597c5SAnurag S. Maskey void 7226ba597c5SAnurag S. Maskey nwamd_enm_check_conditions(void) 7236ba597c5SAnurag S. Maskey { 7246ba597c5SAnurag S. Maskey (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_ENM, nwamd_enm_check, NULL); 7256ba597c5SAnurag S. Maskey } 7266ba597c5SAnurag S. Maskey 7276ba597c5SAnurag S. Maskey int 7286ba597c5SAnurag S. Maskey nwamd_enm_action(const char *enm, nwam_action_t action) 7296ba597c5SAnurag S. Maskey { 7306ba597c5SAnurag S. Maskey nwamd_event_t event = nwamd_event_init_object_action 7316ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_ENM, enm, NULL, action); 7326ba597c5SAnurag S. Maskey if (event == NULL) 7336ba597c5SAnurag S. Maskey return (1); 7346ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 7356ba597c5SAnurag S. Maskey return (0); 7366ba597c5SAnurag S. Maskey } 7376ba597c5SAnurag S. Maskey 7386ba597c5SAnurag S. Maskey /* 7396ba597c5SAnurag S. Maskey * Event handling functions. 7406ba597c5SAnurag S. Maskey */ 7416ba597c5SAnurag S. Maskey 7426ba597c5SAnurag S. Maskey /* Handle ENM initialization/refresh event */ 7436ba597c5SAnurag S. Maskey void 7446ba597c5SAnurag S. Maskey nwamd_enm_handle_init_event(nwamd_event_t event) 7456ba597c5SAnurag S. Maskey { 7466ba597c5SAnurag S. Maskey nwamd_object_t object; 7476ba597c5SAnurag S. Maskey nwam_enm_handle_t enmh; 7486ba597c5SAnurag S. Maskey nwam_error_t err; 7496ba597c5SAnurag S. Maskey boolean_t manual_disabled = B_FALSE; 7506ba597c5SAnurag S. Maskey 7516ba597c5SAnurag S. Maskey if ((err = nwam_enm_read(event->event_object, 0, &enmh)) 7526ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 7536ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_handle_init_event: could not " 7546ba597c5SAnurag S. Maskey "read object '%s': %s", event->event_object, 7556ba597c5SAnurag S. Maskey nwam_strerror(err)); 7566ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 7576ba597c5SAnurag S. Maskey return; 7586ba597c5SAnurag S. Maskey } 7596ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, 7606ba597c5SAnurag S. Maskey event->event_object)) != NULL) { 7616ba597c5SAnurag S. Maskey nwam_enm_free(object->nwamd_object_handle); 7626ba597c5SAnurag S. Maskey object->nwamd_object_handle = enmh; 7636ba597c5SAnurag S. Maskey } else { 7646ba597c5SAnurag S. Maskey object = nwamd_object_init(NWAM_OBJECT_TYPE_ENM, 7656ba597c5SAnurag S. Maskey event->event_object, enmh, NULL); 7666ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_OFFLINE; 7676ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 7686ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET; 7696ba597c5SAnurag S. Maskey } 770874067a0SAnurag S. Maskey /* (Re)set script time to now as the object has just been (re)read */ 771874067a0SAnurag S. Maskey (void) gettimeofday(&object->nwamd_script_time, NULL); 772874067a0SAnurag S. Maskey 7736ba597c5SAnurag S. Maskey manual_disabled = (enm_get_activation_mode(enmh) == 7746ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_MANUAL && !enm_is_enabled(enmh)); 7756ba597c5SAnurag S. Maskey 7766ba597c5SAnurag S. Maskey /* 7776ba597c5SAnurag S. Maskey * If this ENM is ONLINE, and not manual and disabled (since in 7786ba597c5SAnurag S. Maskey * that case it was online but we've just set enabled = false as part 7796ba597c5SAnurag S. Maskey * of a disable action), then it is still active but refreshing. 7806ba597c5SAnurag S. Maskey * Change states to re-activate itself. 7816ba597c5SAnurag S. Maskey */ 7826ba597c5SAnurag S. Maskey if (!manual_disabled && 7836ba597c5SAnurag S. Maskey object->nwamd_object_state == NWAM_STATE_ONLINE) { 7846ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 7856ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE, 7866ba597c5SAnurag S. Maskey NWAM_AUX_STATE_METHOD_RUNNING); 7876ba597c5SAnurag S. Maskey } 7886ba597c5SAnurag S. Maskey nwamd_object_release(object); 7896ba597c5SAnurag S. Maskey } 7906ba597c5SAnurag S. Maskey 7916ba597c5SAnurag S. Maskey /* Handle ENM finish event */ 7926ba597c5SAnurag S. Maskey void 7936ba597c5SAnurag S. Maskey nwamd_enm_handle_fini_event(nwamd_event_t event) 7946ba597c5SAnurag S. Maskey { 7956ba597c5SAnurag S. Maskey nwamd_event_t state_event; 7966ba597c5SAnurag S. Maskey 7976ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_handle_fini_event(%s)", event->event_object); 7986ba597c5SAnurag S. Maskey 7996ba597c5SAnurag S. Maskey /* 8006ba597c5SAnurag S. Maskey * Simulate a state event so that the state machine can correctly 8016ba597c5SAnurag S. Maskey * deactivate the ENM and free up the handle. 8026ba597c5SAnurag S. Maskey */ 8036ba597c5SAnurag S. Maskey state_event = nwamd_event_init_object_state(NWAM_OBJECT_TYPE_ENM, 8046ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE, 8056ba597c5SAnurag S. Maskey NWAM_AUX_STATE_UNINITIALIZED); 8066ba597c5SAnurag S. Maskey if (state_event == NULL) { 8076ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 8086ba597c5SAnurag S. Maskey return; 8096ba597c5SAnurag S. Maskey } 8106ba597c5SAnurag S. Maskey nwamd_enm_handle_state_event(state_event); 8116ba597c5SAnurag S. Maskey nwamd_event_fini(state_event); 8126ba597c5SAnurag S. Maskey /* 8136ba597c5SAnurag S. Maskey * Do not free the handle and object. 8146ba597c5SAnurag S. Maskey * nwamd_enm_activate_deactivate_thread() and 8156ba597c5SAnurag S. Maskey * nwamd_enm_deactivate() does this after running the stop script 8166ba597c5SAnurag S. Maskey * and disabling the FMRI respectively. 8176ba597c5SAnurag S. Maskey */ 8186ba597c5SAnurag S. Maskey } 8196ba597c5SAnurag S. Maskey 8206ba597c5SAnurag S. Maskey void 8216ba597c5SAnurag S. Maskey nwamd_enm_handle_action_event(nwamd_event_t event) 8226ba597c5SAnurag S. Maskey { 8236ba597c5SAnurag S. Maskey nwamd_object_t object; 8246ba597c5SAnurag S. Maskey 8256ba597c5SAnurag S. Maskey switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) { 8266ba597c5SAnurag S. Maskey case NWAM_ACTION_ENABLE: 8276ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, 8286ba597c5SAnurag S. Maskey event->event_object); 8296ba597c5SAnurag S. Maskey if (object == NULL) { 8306ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_handle_action_event: " 8316ba597c5SAnurag S. Maskey "could not find enm %s", event->event_object); 8326ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 8336ba597c5SAnurag S. Maskey return; 8346ba597c5SAnurag S. Maskey } 8356ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_ONLINE) { 8366ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_handle_action_event: " 8376ba597c5SAnurag S. Maskey "enm %s already online, nothing to do", 8386ba597c5SAnurag S. Maskey event->event_object); 8396ba597c5SAnurag S. Maskey nwamd_object_release(object); 8406ba597c5SAnurag S. Maskey return; 8416ba597c5SAnurag S. Maskey } 8426ba597c5SAnurag S. Maskey nwamd_object_release(object); 8436ba597c5SAnurag S. Maskey 8446ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 8456ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE, 8466ba597c5SAnurag S. Maskey NWAM_AUX_STATE_METHOD_RUNNING); 8476ba597c5SAnurag S. Maskey break; 8486ba597c5SAnurag S. Maskey case NWAM_ACTION_DISABLE: 8496ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, 8506ba597c5SAnurag S. Maskey event->event_object); 8516ba597c5SAnurag S. Maskey if (object == NULL) { 8526ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_handle_action_event: " 8536ba597c5SAnurag S. Maskey "could not find enm %s", event->event_object); 8546ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 8556ba597c5SAnurag S. Maskey return; 8566ba597c5SAnurag S. Maskey } 8576ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_DISABLED) { 8586ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_handle_action_event: " 8596ba597c5SAnurag S. Maskey "enm %s already disabled, nothing to do", 8606ba597c5SAnurag S. Maskey event->event_object); 8616ba597c5SAnurag S. Maskey nwamd_object_release(object); 8626ba597c5SAnurag S. Maskey return; 8636ba597c5SAnurag S. Maskey } 8646ba597c5SAnurag S. Maskey nwamd_object_release(object); 8656ba597c5SAnurag S. Maskey 8666ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM, 8676ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE, 8686ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 8696ba597c5SAnurag S. Maskey break; 8706ba597c5SAnurag S. Maskey case NWAM_ACTION_ADD: 8716ba597c5SAnurag S. Maskey case NWAM_ACTION_REFRESH: 8726ba597c5SAnurag S. Maskey nwamd_enm_handle_init_event(event); 8736ba597c5SAnurag S. Maskey break; 8746ba597c5SAnurag S. Maskey case NWAM_ACTION_DESTROY: 8756ba597c5SAnurag S. Maskey nwamd_enm_handle_fini_event(event); 8766ba597c5SAnurag S. Maskey break; 8776ba597c5SAnurag S. Maskey default: 8786ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwam_enm_handle_action_event: " 8796ba597c5SAnurag S. Maskey "unexpected action"); 8806ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 8816ba597c5SAnurag S. Maskey break; 8826ba597c5SAnurag S. Maskey } 8836ba597c5SAnurag S. Maskey } 8846ba597c5SAnurag S. Maskey 8856ba597c5SAnurag S. Maskey void 8866ba597c5SAnurag S. Maskey nwamd_enm_handle_state_event(nwamd_event_t event) 8876ba597c5SAnurag S. Maskey { 8886ba597c5SAnurag S. Maskey nwamd_object_t object; 8896ba597c5SAnurag S. Maskey nwam_state_t new_state; 8906ba597c5SAnurag S. Maskey nwam_aux_state_t new_aux_state; 8916ba597c5SAnurag S. Maskey 8926ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, 8936ba597c5SAnurag S. Maskey event->event_object)) == NULL) { 8946ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_enm_handle_state_event: " 8956ba597c5SAnurag S. Maskey "state event for nonexistent ENM %s", event->event_object); 8966ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 8976ba597c5SAnurag S. Maskey return; 8986ba597c5SAnurag S. Maskey } 8996ba597c5SAnurag S. Maskey new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state; 9006ba597c5SAnurag S. Maskey new_aux_state = 9016ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_object_state.nwe_aux_state; 9026ba597c5SAnurag S. Maskey 9036ba597c5SAnurag S. Maskey if (new_state == object->nwamd_object_state && 9046ba597c5SAnurag S. Maskey new_aux_state == object->nwamd_object_aux_state) { 9056ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_handle_state_event: " 9066ba597c5SAnurag S. Maskey "ENM %s already in state (%s , %s)", 9076ba597c5SAnurag S. Maskey object->nwamd_object_name, nwam_state_to_string(new_state), 9086ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 9096ba597c5SAnurag S. Maskey nwamd_object_release(object); 9106ba597c5SAnurag S. Maskey return; 9116ba597c5SAnurag S. Maskey } 9126ba597c5SAnurag S. Maskey 9136ba597c5SAnurag S. Maskey object->nwamd_object_state = new_state; 9146ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = new_aux_state; 9156ba597c5SAnurag S. Maskey 9166ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_enm_handle_state_event: changing state for ENM " 9176ba597c5SAnurag S. Maskey "%s to (%s , %s)", object->nwamd_object_name, 9186ba597c5SAnurag S. Maskey nwam_state_to_string(object->nwamd_object_state), 9196ba597c5SAnurag S. Maskey nwam_aux_state_to_string(object->nwamd_object_aux_state)); 9206ba597c5SAnurag S. Maskey 9216ba597c5SAnurag S. Maskey nwamd_object_release(object); 9226ba597c5SAnurag S. Maskey 9236ba597c5SAnurag S. Maskey /* 9246ba597c5SAnurag S. Maskey * State machine for ENMs. 9256ba597c5SAnurag S. Maskey */ 9266ba597c5SAnurag S. Maskey switch (new_state) { 9276ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE_TO_ONLINE: 9286ba597c5SAnurag S. Maskey nwamd_enm_activate(event->event_object); 9296ba597c5SAnurag S. Maskey break; 9306ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE_TO_OFFLINE: 9316ba597c5SAnurag S. Maskey nwamd_enm_deactivate(event->event_object); 9326ba597c5SAnurag S. Maskey break; 9336ba597c5SAnurag S. Maskey case NWAM_STATE_DISABLED: 9346ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE: 9356ba597c5SAnurag S. Maskey case NWAM_STATE_UNINITIALIZED: 9366ba597c5SAnurag S. Maskey case NWAM_STATE_MAINTENANCE: 9376ba597c5SAnurag S. Maskey case NWAM_STATE_DEGRADED: 9386ba597c5SAnurag S. Maskey default: 9396ba597c5SAnurag S. Maskey /* do nothing */ 9406ba597c5SAnurag S. Maskey break; 9416ba597c5SAnurag S. Maskey } 9426ba597c5SAnurag S. Maskey } 943