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 /* 234a44f0a1SAnurag 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 <limits.h> 346ba597c5SAnurag S. Maskey #include <netdb.h> 356ba597c5SAnurag S. Maskey #include <netinet/in.h> 366ba597c5SAnurag S. Maskey #include <stdio.h> 376ba597c5SAnurag S. Maskey #include <stdlib.h> 386ba597c5SAnurag S. Maskey #include <string.h> 396ba597c5SAnurag S. Maskey #include <sys/socket.h> 406ba597c5SAnurag S. Maskey #include <sys/types.h> 416ba597c5SAnurag S. Maskey 426ba597c5SAnurag S. Maskey #include <libnwam.h> 436ba597c5SAnurag S. Maskey #include "conditions.h" 446ba597c5SAnurag S. Maskey #include "events.h" 456ba597c5SAnurag S. Maskey #include "objects.h" 466ba597c5SAnurag S. Maskey #include "util.h" 476ba597c5SAnurag S. Maskey 486ba597c5SAnurag S. Maskey /* 496ba597c5SAnurag S. Maskey * loc.c - contains routines which handle location abstraction. 506ba597c5SAnurag S. Maskey */ 516ba597c5SAnurag S. Maskey 526ba597c5SAnurag S. Maskey pthread_mutex_t active_loc_mutex = PTHREAD_MUTEX_INITIALIZER; 536ba597c5SAnurag S. Maskey char active_loc[NWAM_MAX_NAME_LEN]; 546ba597c5SAnurag S. Maskey 556ba597c5SAnurag S. Maskey static int 566ba597c5SAnurag S. Maskey loc_create_init_fini_event(nwam_loc_handle_t loch, void *data) 576ba597c5SAnurag S. Maskey { 586ba597c5SAnurag S. Maskey boolean_t *init = data; 596ba597c5SAnurag S. Maskey char *name; 606ba597c5SAnurag S. Maskey nwamd_event_t event; 616ba597c5SAnurag S. Maskey 626ba597c5SAnurag S. Maskey if (nwam_loc_get_name(loch, &name) != NWAM_SUCCESS) { 636ba597c5SAnurag S. Maskey nlog(LOG_ERR, "loc_init_fini: could not get loc name"); 646ba597c5SAnurag S. Maskey return (0); 656ba597c5SAnurag S. Maskey } 666ba597c5SAnurag S. Maskey 676ba597c5SAnurag S. Maskey event = nwamd_event_init(*init ? 686ba597c5SAnurag S. Maskey NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI, 696ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_LOC, 0, name); 706ba597c5SAnurag S. Maskey if (event != NULL) 716ba597c5SAnurag S. Maskey nwamd_event_enqueue(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 locs, creating init events for each. 796ba597c5SAnurag S. Maskey */ 806ba597c5SAnurag S. Maskey void 816ba597c5SAnurag S. Maskey nwamd_init_locs(void) 826ba597c5SAnurag S. Maskey { 836ba597c5SAnurag S. Maskey boolean_t init = B_TRUE; 846ba597c5SAnurag S. Maskey 856ba597c5SAnurag S. Maskey /* Unset active location */ 866ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_loc_mutex); 876ba597c5SAnurag S. Maskey active_loc[0] = '\0'; 886ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_loc_mutex); 896ba597c5SAnurag S. Maskey (void) nwam_walk_locs(loc_create_init_fini_event, &init, 0, NULL); 906ba597c5SAnurag S. Maskey } 916ba597c5SAnurag S. Maskey 926ba597c5SAnurag S. Maskey /* 936ba597c5SAnurag S. Maskey * Walk all locs, creating fini events for each. 946ba597c5SAnurag S. Maskey */ 956ba597c5SAnurag S. Maskey void 966ba597c5SAnurag S. Maskey nwamd_fini_locs(void) 976ba597c5SAnurag S. Maskey { 986ba597c5SAnurag S. Maskey boolean_t init = B_FALSE; 996ba597c5SAnurag S. Maskey 1006ba597c5SAnurag S. Maskey (void) nwam_walk_locs(loc_create_init_fini_event, &init, 0, NULL); 1016ba597c5SAnurag S. Maskey } 1026ba597c5SAnurag S. Maskey 1036ba597c5SAnurag S. Maskey static boolean_t 1046ba597c5SAnurag S. Maskey loc_is_enabled(nwam_loc_handle_t loch) 1056ba597c5SAnurag S. Maskey { 1066ba597c5SAnurag S. Maskey nwam_value_t enabledval; 1076ba597c5SAnurag S. Maskey boolean_t enabled = B_FALSE; 1086ba597c5SAnurag S. Maskey 1096ba597c5SAnurag S. Maskey if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ENABLED, 1106ba597c5SAnurag S. Maskey &enabledval) != NWAM_SUCCESS) { 1116ba597c5SAnurag S. Maskey nlog(LOG_ERR, "loc_is_enabled: could not retrieve " 1126ba597c5SAnurag S. Maskey "enabled value"); 1136ba597c5SAnurag S. Maskey return (B_FALSE); 1146ba597c5SAnurag S. Maskey } 1156ba597c5SAnurag S. Maskey if (nwam_value_get_boolean(enabledval, &enabled) 1166ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 1176ba597c5SAnurag S. Maskey nlog(LOG_ERR, "loc_is_enabled: could not retrieve " 1186ba597c5SAnurag S. Maskey "enabled value"); 1196ba597c5SAnurag S. Maskey nwam_value_free(enabledval); 1206ba597c5SAnurag S. Maskey return (B_FALSE); 1216ba597c5SAnurag S. Maskey } 1226ba597c5SAnurag S. Maskey nwam_value_free(enabledval); 1236ba597c5SAnurag S. Maskey return (enabled); 1246ba597c5SAnurag S. Maskey } 1256ba597c5SAnurag S. Maskey 1266ba597c5SAnurag S. Maskey static int64_t 1276ba597c5SAnurag S. Maskey loc_get_activation_mode(nwam_loc_handle_t loch) 1286ba597c5SAnurag S. Maskey { 1296ba597c5SAnurag S. Maskey nwam_error_t err; 1306ba597c5SAnurag S. Maskey uint64_t activation; 1316ba597c5SAnurag S. Maskey nwam_value_t activationval; 1326ba597c5SAnurag S. Maskey 1336ba597c5SAnurag S. Maskey if (nwam_loc_get_prop_value(loch, NWAM_LOC_PROP_ACTIVATION_MODE, 1346ba597c5SAnurag S. Maskey &activationval) != NWAM_SUCCESS) { 1356ba597c5SAnurag S. Maskey nlog(LOG_ERR, "loc_get_activation_mode: could not retrieve " 1366ba597c5SAnurag S. Maskey "activation mode value"); 1376ba597c5SAnurag S. Maskey return (-1); 1386ba597c5SAnurag S. Maskey } 1396ba597c5SAnurag S. Maskey err = nwam_value_get_uint64(activationval, &activation); 1406ba597c5SAnurag S. Maskey nwam_value_free(activationval); 1416ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 1426ba597c5SAnurag S. Maskey nlog(LOG_ERR, "loc_get_activation_mode: could not retrieve " 1436ba597c5SAnurag S. Maskey "activation mode value"); 1446ba597c5SAnurag S. Maskey return (-1); 1456ba597c5SAnurag S. Maskey } 1466ba597c5SAnurag S. Maskey 1476ba597c5SAnurag S. Maskey return ((int64_t)activation); 1486ba597c5SAnurag S. Maskey } 1496ba597c5SAnurag S. Maskey 1506ba597c5SAnurag S. Maskey /* Enables the location. */ 1516ba597c5SAnurag S. Maskey static void 1526ba597c5SAnurag S. Maskey nwamd_loc_activate(const char *object_name) 1536ba597c5SAnurag S. Maskey { 1546ba597c5SAnurag S. Maskey char *enabled; 1556ba597c5SAnurag S. Maskey 1566ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_activate: activating loc %s", 1576ba597c5SAnurag S. Maskey object_name); 1586ba597c5SAnurag S. Maskey 1596ba597c5SAnurag S. Maskey /* 1606ba597c5SAnurag S. Maskey * Find currently enabled location and change its state to disabled 1616ba597c5SAnurag S. Maskey * if it is a manual location, or offline (if it is not). 1626ba597c5SAnurag S. Maskey * Only manual locations reach disabled, since conditional and 1636ba597c5SAnurag S. Maskey * system locations which are manually disabled simply revert to 1646ba597c5SAnurag S. Maskey * their conditions for activation. 1656ba597c5SAnurag S. Maskey */ 1666ba597c5SAnurag S. Maskey if ((enabled = malloc(NWAM_MAX_NAME_LEN)) != NULL && 1676ba597c5SAnurag S. Maskey nwamd_lookup_string_property(NET_LOC_FMRI, NET_LOC_PG, 1686ba597c5SAnurag S. Maskey NET_LOC_SELECTED_PROP, enabled, NWAM_MAX_NAME_LEN) == 0) { 1696ba597c5SAnurag S. Maskey /* Only change state if current != new */ 1706ba597c5SAnurag S. Maskey if (strcmp(enabled, object_name) != 0) { 1716ba597c5SAnurag S. Maskey boolean_t do_disable = B_FALSE; 1726ba597c5SAnurag S. Maskey nwamd_object_t eobj = nwamd_object_find 1736ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_LOC, enabled); 1746ba597c5SAnurag S. Maskey if (eobj == NULL) { 1754a44f0a1SAnurag S. Maskey nlog(LOG_INFO, "nwamd_loc_activate: could not " 1766ba597c5SAnurag S. Maskey "find old location %s", enabled); 1774a44f0a1SAnurag S. Maskey goto skip_disable; 1786ba597c5SAnurag S. Maskey } 1796ba597c5SAnurag S. Maskey /* 1806ba597c5SAnurag S. Maskey * Disable if the old location was manual, since the 1816ba597c5SAnurag S. Maskey * only way a manual location can deactivate is if 1826ba597c5SAnurag S. Maskey * it is disabled. 1836ba597c5SAnurag S. Maskey */ 1846ba597c5SAnurag S. Maskey do_disable = 1856ba597c5SAnurag S. Maskey (loc_get_activation_mode(eobj->nwamd_object_handle) 1866ba597c5SAnurag S. Maskey == (int64_t)NWAM_ACTIVATION_MODE_MANUAL); 1876ba597c5SAnurag S. Maskey nwamd_object_release(eobj); 1886ba597c5SAnurag S. Maskey 1896ba597c5SAnurag S. Maskey if (do_disable) { 1906ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_activate: " 1916ba597c5SAnurag S. Maskey "disable needed for old location %s", 1926ba597c5SAnurag S. Maskey enabled); 1936ba597c5SAnurag S. Maskey nwamd_object_set_state 1946ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_LOC, enabled, 1956ba597c5SAnurag S. Maskey NWAM_STATE_DISABLED, 1966ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 1976ba597c5SAnurag S. Maskey } else { 1986ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_activate: " 1996ba597c5SAnurag S. Maskey "offline needed for old location %s", 2006ba597c5SAnurag S. Maskey enabled); 2016ba597c5SAnurag S. Maskey nwamd_object_set_state 2026ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_LOC, enabled, 2036ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE, 2046ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 2056ba597c5SAnurag S. Maskey } 2066ba597c5SAnurag S. Maskey } 2076ba597c5SAnurag S. Maskey } 2084a44f0a1SAnurag S. Maskey skip_disable: 2096ba597c5SAnurag S. Maskey free(enabled); 2106ba597c5SAnurag S. Maskey 2116ba597c5SAnurag S. Maskey if (nwamd_set_string_property(NET_LOC_FMRI, NET_LOC_PG, 2126ba597c5SAnurag S. Maskey NET_LOC_SELECTED_PROP, object_name) == 0) { 2136ba597c5SAnurag S. Maskey char *state = smf_get_state(NET_LOC_FMRI); 2144a44f0a1SAnurag S. Maskey nlog(LOG_INFO, "nwamd_loc_activate: set %s/%s to %s; " 2156ba597c5SAnurag S. Maskey "service is in %s state", NET_LOC_PG, NET_LOC_SELECTED_PROP, 2166ba597c5SAnurag S. Maskey object_name, state == NULL ? "unknown" : state); 2176ba597c5SAnurag S. Maskey free(state); 2186ba597c5SAnurag S. Maskey (void) smf_restore_instance(NET_LOC_FMRI); 2196ba597c5SAnurag S. Maskey if (smf_refresh_instance(NET_LOC_FMRI) == 0) { 2206ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_loc_mutex); 2216ba597c5SAnurag S. Maskey (void) strlcpy(active_loc, object_name, 2226ba597c5SAnurag S. Maskey sizeof (active_loc)); 2236ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_loc_mutex); 2246ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_LOC, 2256ba597c5SAnurag S. Maskey object_name, 2266ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE, NWAM_AUX_STATE_ACTIVE); 2276ba597c5SAnurag S. Maskey } else { 2286ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_loc_activate: " 2296ba597c5SAnurag S. Maskey "%s could not be refreshed", NET_LOC_FMRI); 2306ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_LOC, 2316ba597c5SAnurag S. Maskey object_name, 2326ba597c5SAnurag S. Maskey NWAM_STATE_MAINTENANCE, 2336ba597c5SAnurag S. Maskey NWAM_AUX_STATE_METHOD_FAILED); 2346ba597c5SAnurag S. Maskey } 2356ba597c5SAnurag S. Maskey } 2366ba597c5SAnurag S. Maskey } 2376ba597c5SAnurag S. Maskey 2386ba597c5SAnurag S. Maskey struct nwamd_loc_check_walk_arg { 2396ba597c5SAnurag S. Maskey nwamd_object_t winning_object; 2406ba597c5SAnurag S. Maskey uint64_t winning_rating; 2416ba597c5SAnurag S. Maskey }; 2426ba597c5SAnurag S. Maskey 2436ba597c5SAnurag S. Maskey /* 2446ba597c5SAnurag S. Maskey * Determine which location should be activated. 2456ba597c5SAnurag S. Maskey */ 2466ba597c5SAnurag S. Maskey static int 2476ba597c5SAnurag S. Maskey nwamd_loc_check(nwamd_object_t object, void *data) 2486ba597c5SAnurag S. Maskey { 2496ba597c5SAnurag S. Maskey struct nwamd_loc_check_walk_arg *wa = data; 2506ba597c5SAnurag S. Maskey nwam_loc_handle_t loch = object->nwamd_object_handle; 2516ba597c5SAnurag S. Maskey nwam_value_t conditionval; 2526ba597c5SAnurag S. Maskey int64_t lactivation; 2536ba597c5SAnurag S. Maskey uint64_t rating, activation; 2546ba597c5SAnurag S. Maskey boolean_t satisfied; 2556ba597c5SAnurag S. Maskey char **conditions; 2566ba597c5SAnurag S. Maskey uint_t nelem; 2576ba597c5SAnurag S. Maskey 2586ba597c5SAnurag S. Maskey lactivation = loc_get_activation_mode(object->nwamd_object_handle); 2596ba597c5SAnurag S. Maskey 2606ba597c5SAnurag S. Maskey if (lactivation == -1) 2616ba597c5SAnurag S. Maskey return (0); 2626ba597c5SAnurag S. Maskey 2636ba597c5SAnurag S. Maskey activation = (uint64_t)lactivation; 2646ba597c5SAnurag S. Maskey switch (activation) { 2656ba597c5SAnurag S. Maskey case NWAM_ACTIVATION_MODE_MANUAL: 2666ba597c5SAnurag S. Maskey if (loc_is_enabled(loch)) { 2676ba597c5SAnurag S. Maskey /* Manually enabled locations should always win out. */ 2686ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_check: %s is enabled", 2696ba597c5SAnurag S. Maskey object->nwamd_object_name); 2706ba597c5SAnurag S. Maskey wa->winning_object = object; 2716ba597c5SAnurag S. Maskey wa->winning_rating = UINT64_MAX; 2726ba597c5SAnurag S. Maskey } else { 2736ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_check: %s is disabled", 2746ba597c5SAnurag S. Maskey object->nwamd_object_name); 2756ba597c5SAnurag S. Maskey if (object->nwamd_object_state != NWAM_STATE_DISABLED) { 2766ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_LOC, 2776ba597c5SAnurag S. Maskey object->nwamd_object_name, 2786ba597c5SAnurag S. Maskey NWAM_STATE_DISABLED, 2796ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 2806ba597c5SAnurag S. Maskey } 2816ba597c5SAnurag S. Maskey } 2826ba597c5SAnurag S. Maskey 2836ba597c5SAnurag S. Maskey return (0); 2846ba597c5SAnurag S. Maskey 2856ba597c5SAnurag S. Maskey case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY: 2866ba597c5SAnurag S. Maskey case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL: 2876ba597c5SAnurag S. Maskey if (loc_is_enabled(loch)) { 2886ba597c5SAnurag S. Maskey /* Manually enabled locations should always win out. */ 2896ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_check: %s is enabled", 2906ba597c5SAnurag S. Maskey object->nwamd_object_name); 2916ba597c5SAnurag S. Maskey wa->winning_object = object; 2926ba597c5SAnurag S. Maskey wa->winning_rating = UINT64_MAX; 2936ba597c5SAnurag S. Maskey } 2946ba597c5SAnurag S. Maskey 2956ba597c5SAnurag S. Maskey if (nwam_loc_get_prop_value(loch, 2966ba597c5SAnurag S. Maskey NWAM_LOC_PROP_CONDITIONS, &conditionval) != NWAM_SUCCESS) { 2976ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_loc_check: could not retrieve " 2986ba597c5SAnurag S. Maskey "condition value"); 2996ba597c5SAnurag S. Maskey return (0); 3006ba597c5SAnurag S. Maskey } 3016ba597c5SAnurag S. Maskey if (nwam_value_get_string_array(conditionval, 3026ba597c5SAnurag S. Maskey &conditions, &nelem) != NWAM_SUCCESS) { 3036ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_loc_check: could not retrieve " 3046ba597c5SAnurag S. Maskey "condition value"); 3056ba597c5SAnurag S. Maskey nwam_value_free(conditionval); 3066ba597c5SAnurag S. Maskey return (0); 3076ba597c5SAnurag S. Maskey } 3086ba597c5SAnurag S. Maskey satisfied = nwamd_check_conditions(activation, conditions, 3096ba597c5SAnurag S. Maskey nelem); 3106ba597c5SAnurag S. Maskey 3116ba597c5SAnurag S. Maskey if (satisfied) { 3126ba597c5SAnurag S. Maskey rating = nwamd_rate_conditions(activation, 3136ba597c5SAnurag S. Maskey conditions, nelem); 3146ba597c5SAnurag S. Maskey if (rating > wa->winning_rating) { 3156ba597c5SAnurag S. Maskey wa->winning_object = object; 3166ba597c5SAnurag S. Maskey wa->winning_rating = rating; 3176ba597c5SAnurag S. Maskey } 3186ba597c5SAnurag S. Maskey } 3196ba597c5SAnurag S. Maskey nwam_value_free(conditionval); 3206ba597c5SAnurag S. Maskey return (0); 3216ba597c5SAnurag S. Maskey 3226ba597c5SAnurag S. Maskey case NWAM_ACTIVATION_MODE_SYSTEM: 3236ba597c5SAnurag S. Maskey if (loc_is_enabled(loch)) { 3246ba597c5SAnurag S. Maskey /* Manually enabled locations should always win out. */ 3256ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_check: %s is enabled", 3266ba597c5SAnurag S. Maskey object->nwamd_object_name); 3276ba597c5SAnurag S. Maskey wa->winning_object = object; 3286ba597c5SAnurag S. Maskey wa->winning_rating = UINT64_MAX; 3296ba597c5SAnurag S. Maskey } 3306ba597c5SAnurag S. Maskey 3316ba597c5SAnurag S. Maskey /* Either NoNet, Automatic or Legacy location, so skip. */ 3326ba597c5SAnurag S. Maskey 3336ba597c5SAnurag S. Maskey return (0); 3346ba597c5SAnurag S. Maskey default: 3356ba597c5SAnurag S. Maskey return (0); 3366ba597c5SAnurag S. Maskey } 3376ba597c5SAnurag S. Maskey /*NOTREACHED*/ 3386ba597c5SAnurag S. Maskey return (0); 3396ba597c5SAnurag S. Maskey } 3406ba597c5SAnurag S. Maskey 3416ba597c5SAnurag S. Maskey static int 3426ba597c5SAnurag S. Maskey nwamd_ncu_online_check(nwamd_object_t object, void *data) 3436ba597c5SAnurag S. Maskey { 3446ba597c5SAnurag S. Maskey boolean_t *online = data; 3456ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu_data = object->nwamd_object_data; 3466ba597c5SAnurag S. Maskey 3476ba597c5SAnurag S. Maskey if (ncu_data->ncu_type != NWAM_NCU_TYPE_INTERFACE) 3486ba597c5SAnurag S. Maskey return (0); 3496ba597c5SAnurag S. Maskey 3506ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_ONLINE) { 3516ba597c5SAnurag S. Maskey /* An online IP NCU found, stop walk */ 3526ba597c5SAnurag S. Maskey *online = B_TRUE; 3536ba597c5SAnurag S. Maskey return (1); 3546ba597c5SAnurag S. Maskey } 3556ba597c5SAnurag S. Maskey return (0); 3566ba597c5SAnurag S. Maskey } 3576ba597c5SAnurag S. Maskey 3586ba597c5SAnurag S. Maskey void 3596ba597c5SAnurag S. Maskey nwamd_loc_check_conditions(void) 3606ba597c5SAnurag S. Maskey { 3616ba597c5SAnurag S. Maskey struct nwamd_loc_check_walk_arg wa = { NULL, 0 }; 3626ba597c5SAnurag S. Maskey const char *winning_loc; 3636ba597c5SAnurag S. Maskey boolean_t ncu_online = B_FALSE; 3646ba597c5SAnurag S. Maskey boolean_t is_active; 3656ba597c5SAnurag S. Maskey 3666ba597c5SAnurag S. Maskey /* 3676ba597c5SAnurag S. Maskey * Walk the NCUs to find out if at least one IP NCU is online. If so, 3686ba597c5SAnurag S. Maskey * check the activation-mode and conditions. If not, enable the NoNet 3696ba597c5SAnurag S. Maskey * location. 3706ba597c5SAnurag S. Maskey */ 3716ba597c5SAnurag S. Maskey (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, nwamd_ncu_online_check, 3726ba597c5SAnurag S. Maskey &ncu_online); 3736ba597c5SAnurag S. Maskey 3746ba597c5SAnurag S. Maskey if (!ncu_online) { 3756ba597c5SAnurag S. Maskey winning_loc = NWAM_LOC_NAME_NO_NET; 3766ba597c5SAnurag S. Maskey } else { 3776ba597c5SAnurag S. Maskey (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_LOC, nwamd_loc_check, 3786ba597c5SAnurag S. Maskey &wa); 3796ba597c5SAnurag S. Maskey if (wa.winning_object != NULL) 3806ba597c5SAnurag S. Maskey winning_loc = wa.winning_object->nwamd_object_name; 3816ba597c5SAnurag S. Maskey else 3826ba597c5SAnurag S. Maskey winning_loc = NWAM_LOC_NAME_AUTOMATIC; 3836ba597c5SAnurag S. Maskey } 384*f6904bc3SRenee Danson Sommerfeld nlog(LOG_DEBUG, "nwamd_loc_check_conditions: winning loc is %s", 3856ba597c5SAnurag S. Maskey winning_loc); 3866ba597c5SAnurag S. Maskey 3876ba597c5SAnurag S. Maskey /* If the winning location is already active, do nothing */ 3886ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_loc_mutex); 3896ba597c5SAnurag S. Maskey is_active = (strcmp(active_loc, winning_loc) == 0); 3906ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_loc_mutex); 3916ba597c5SAnurag S. Maskey if (is_active) 3926ba597c5SAnurag S. Maskey return; 3936ba597c5SAnurag S. Maskey 3946ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_LOC, winning_loc, 3956ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, NWAM_AUX_STATE_METHOD_RUNNING); 3966ba597c5SAnurag S. Maskey } 3976ba597c5SAnurag S. Maskey 3986ba597c5SAnurag S. Maskey int 3996ba597c5SAnurag S. Maskey nwamd_loc_action(const char *loc, nwam_action_t action) 4006ba597c5SAnurag S. Maskey { 4016ba597c5SAnurag S. Maskey nwamd_event_t event = nwamd_event_init_object_action 4026ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_LOC, loc, NULL, action); 4036ba597c5SAnurag S. Maskey if (event == NULL) 4046ba597c5SAnurag S. Maskey return (1); 4056ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 4066ba597c5SAnurag S. Maskey return (0); 4076ba597c5SAnurag S. Maskey } 4086ba597c5SAnurag S. Maskey 4096ba597c5SAnurag S. Maskey /* 4106ba597c5SAnurag S. Maskey * Event handling functions. 4116ba597c5SAnurag S. Maskey */ 4126ba597c5SAnurag S. Maskey 4136ba597c5SAnurag S. Maskey /* Handle loc initialization/refresh event */ 4146ba597c5SAnurag S. Maskey void 4156ba597c5SAnurag S. Maskey nwamd_loc_handle_init_event(nwamd_event_t event) 4166ba597c5SAnurag S. Maskey { 4176ba597c5SAnurag S. Maskey nwamd_object_t object; 4186ba597c5SAnurag S. Maskey nwam_loc_handle_t loch; 4196ba597c5SAnurag S. Maskey nwam_error_t err; 420ea408ca7SAnurag S. Maskey boolean_t new_enabled, old_enabled = B_FALSE; 4216ba597c5SAnurag S. Maskey nwam_state_t state; 4226ba597c5SAnurag S. Maskey 4236ba597c5SAnurag S. Maskey if ((err = nwam_loc_read(event->event_object, 0, &loch)) 4246ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 4256ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_loc_handle_init_event: could not " 4266ba597c5SAnurag S. Maskey "read object '%s': %s", event->event_object, 4276ba597c5SAnurag S. Maskey nwam_strerror(err)); 4286ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 4296ba597c5SAnurag S. Maskey return; 4306ba597c5SAnurag S. Maskey } 4316ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_LOC, 4326ba597c5SAnurag S. Maskey event->event_object)) != NULL) { 433ea408ca7SAnurag S. Maskey old_enabled = loc_is_enabled(object->nwamd_object_handle); 4346ba597c5SAnurag S. Maskey nwam_loc_free(object->nwamd_object_handle); 4356ba597c5SAnurag S. Maskey object->nwamd_object_handle = loch; 4366ba597c5SAnurag S. Maskey } else { 4376ba597c5SAnurag S. Maskey object = nwamd_object_init(NWAM_OBJECT_TYPE_LOC, 4386ba597c5SAnurag S. Maskey event->event_object, loch, NULL); 4396ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_OFFLINE; 4406ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 4416ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET; 4426ba597c5SAnurag S. Maskey } 443ea408ca7SAnurag S. Maskey new_enabled = loc_is_enabled(loch); 4446ba597c5SAnurag S. Maskey state = object->nwamd_object_state; 4456ba597c5SAnurag S. Maskey nwamd_object_release(object); 4466ba597c5SAnurag S. Maskey 4476ba597c5SAnurag S. Maskey /* 448ea408ca7SAnurag S. Maskey * If this location is ONLINE and the value of the "enabled" property 449ea408ca7SAnurag S. Maskey * has not changed, then this location is getting refreshed because it 450ea408ca7SAnurag S. Maskey * was committed with changes. Change states to re-activate itself. 451ea408ca7SAnurag S. Maskey * If the "enabled" property has changed, then this location is 452ea408ca7SAnurag S. Maskey * getting refreshed as part of a enable/disable action and there is 453ea408ca7SAnurag S. Maskey * no need to change states here. 4546ba597c5SAnurag S. Maskey */ 455ea408ca7SAnurag S. Maskey if (state == NWAM_STATE_ONLINE && old_enabled == new_enabled) { 4566ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_LOC, 4576ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE, 4586ba597c5SAnurag S. Maskey NWAM_AUX_STATE_METHOD_RUNNING); 4596ba597c5SAnurag S. Maskey } 4606ba597c5SAnurag S. Maskey } 4616ba597c5SAnurag S. Maskey 4626ba597c5SAnurag S. Maskey /* Handle loc finish event */ 4636ba597c5SAnurag S. Maskey void 4646ba597c5SAnurag S. Maskey nwamd_loc_handle_fini_event(nwamd_event_t event) 4656ba597c5SAnurag S. Maskey { 4666ba597c5SAnurag S. Maskey nwamd_object_t object; 4676ba597c5SAnurag S. Maskey 4686ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_handle_fini_event(%s)", 4696ba597c5SAnurag S. Maskey event->event_object); 4706ba597c5SAnurag S. Maskey 4716ba597c5SAnurag S. Maskey /* Don't disable the location, as this can enable the Automatic loc */ 4726ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_LOC, 4736ba597c5SAnurag S. Maskey event->event_object)) == NULL) { 474*f6904bc3SRenee Danson Sommerfeld nlog(LOG_INFO, "nwamd_loc_handle_fini_event: " 4756ba597c5SAnurag S. Maskey "loc %s not found", event->event_object); 4766ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 4776ba597c5SAnurag S. Maskey return; 4786ba597c5SAnurag S. Maskey } 4796ba597c5SAnurag S. Maskey nwamd_object_release_and_destroy(object); 4806ba597c5SAnurag S. Maskey } 4816ba597c5SAnurag S. Maskey 4826ba597c5SAnurag S. Maskey void 4836ba597c5SAnurag S. Maskey nwamd_loc_handle_action_event(nwamd_event_t event) 4846ba597c5SAnurag S. Maskey { 4856ba597c5SAnurag S. Maskey nwamd_object_t object; 4866ba597c5SAnurag S. Maskey 4876ba597c5SAnurag S. Maskey switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) { 4886ba597c5SAnurag S. Maskey case NWAM_ACTION_ENABLE: 4896ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_LOC, 4906ba597c5SAnurag S. Maskey event->event_object); 4916ba597c5SAnurag S. Maskey if (object == NULL) { 4926ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_loc_handle_action_event: " 4936ba597c5SAnurag S. Maskey "could not find location %s", event->event_object); 4946ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 4956ba597c5SAnurag S. Maskey return; 4966ba597c5SAnurag S. Maskey } 4976ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_ONLINE) { 4986ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_handle_action_event: " 4996ba597c5SAnurag S. Maskey "location %s already online, nothing to do", 5006ba597c5SAnurag S. Maskey event->event_object); 5016ba597c5SAnurag S. Maskey nwamd_object_release(object); 5026ba597c5SAnurag S. Maskey return; 5036ba597c5SAnurag S. Maskey } 5046ba597c5SAnurag S. Maskey nwamd_object_release(object); 5056ba597c5SAnurag S. Maskey 5066ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_LOC, 5076ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE, 5086ba597c5SAnurag S. Maskey NWAM_AUX_STATE_METHOD_RUNNING); 5096ba597c5SAnurag S. Maskey break; 5106ba597c5SAnurag S. Maskey case NWAM_ACTION_DISABLE: 5116ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_LOC, 5126ba597c5SAnurag S. Maskey event->event_object); 5136ba597c5SAnurag S. Maskey if (object == NULL) { 5146ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_loc_handle_action_event: " 5156ba597c5SAnurag S. Maskey "could not find location %s", event->event_object); 5166ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 5176ba597c5SAnurag S. Maskey return; 5186ba597c5SAnurag S. Maskey } 5196ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_DISABLED) { 5206ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_handle_action_event: " 5216ba597c5SAnurag S. Maskey "location %s already disabled, nothing to do", 5226ba597c5SAnurag S. Maskey event->event_object); 5236ba597c5SAnurag S. Maskey nwamd_object_release(object); 5246ba597c5SAnurag S. Maskey return; 5256ba597c5SAnurag S. Maskey } 5266ba597c5SAnurag S. Maskey nwamd_object_release(object); 5276ba597c5SAnurag S. Maskey 5286ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_LOC, 5296ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE, 5306ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 5316ba597c5SAnurag S. Maskey break; 5326ba597c5SAnurag S. Maskey case NWAM_ACTION_ADD: 5336ba597c5SAnurag S. Maskey case NWAM_ACTION_REFRESH: 5346ba597c5SAnurag S. Maskey nwamd_loc_handle_init_event(event); 5356ba597c5SAnurag S. Maskey break; 5366ba597c5SAnurag S. Maskey case NWAM_ACTION_DESTROY: 5376ba597c5SAnurag S. Maskey nwamd_loc_handle_fini_event(event); 5386ba597c5SAnurag S. Maskey break; 5396ba597c5SAnurag S. Maskey default: 5406ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwam_loc_handle_action_event: " 5416ba597c5SAnurag S. Maskey "unexpected action"); 5426ba597c5SAnurag S. Maskey break; 5436ba597c5SAnurag S. Maskey } 5446ba597c5SAnurag S. Maskey } 5456ba597c5SAnurag S. Maskey 5466ba597c5SAnurag S. Maskey void 5476ba597c5SAnurag S. Maskey nwamd_loc_handle_state_event(nwamd_event_t event) 5486ba597c5SAnurag S. Maskey { 5496ba597c5SAnurag S. Maskey nwamd_object_t object; 5506ba597c5SAnurag S. Maskey nwam_state_t new_state; 5516ba597c5SAnurag S. Maskey nwam_aux_state_t new_aux_state; 5526ba597c5SAnurag S. Maskey 5536ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_LOC, 5546ba597c5SAnurag S. Maskey event->event_object)) == NULL) { 555*f6904bc3SRenee Danson Sommerfeld nlog(LOG_INFO, "nwamd_loc_handle_state_event: " 5566ba597c5SAnurag S. Maskey "state event for nonexistent loc %s", event->event_object); 5576ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 5586ba597c5SAnurag S. Maskey return; 5596ba597c5SAnurag S. Maskey } 5606ba597c5SAnurag S. Maskey new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state; 5616ba597c5SAnurag S. Maskey new_aux_state = 5626ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_object_state.nwe_aux_state; 5636ba597c5SAnurag S. Maskey 5646ba597c5SAnurag S. Maskey if (new_state == object->nwamd_object_state && 5656ba597c5SAnurag S. Maskey new_aux_state == object->nwamd_object_aux_state) { 5666ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_handle_state_event: " 5676ba597c5SAnurag S. Maskey "loc %s already in state (%s , %s)", 5686ba597c5SAnurag S. Maskey object->nwamd_object_name, 5696ba597c5SAnurag S. Maskey nwam_state_to_string(new_state), 5706ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 5716ba597c5SAnurag S. Maskey nwamd_object_release(object); 5726ba597c5SAnurag S. Maskey return; 5736ba597c5SAnurag S. Maskey } 5746ba597c5SAnurag S. Maskey 5756ba597c5SAnurag S. Maskey object->nwamd_object_state = new_state; 5766ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = new_aux_state; 5776ba597c5SAnurag S. Maskey 5786ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_loc_handle_state_event: changing state for loc " 5796ba597c5SAnurag S. Maskey "%s to (%s , %s)", object->nwamd_object_name, 5806ba597c5SAnurag S. Maskey nwam_state_to_string(object->nwamd_object_state), 5816ba597c5SAnurag S. Maskey nwam_aux_state_to_string(object->nwamd_object_aux_state)); 5826ba597c5SAnurag S. Maskey 5836ba597c5SAnurag S. Maskey nwamd_object_release(object); 5846ba597c5SAnurag S. Maskey 5856ba597c5SAnurag S. Maskey /* 5866ba597c5SAnurag S. Maskey * State machine for location. 5876ba597c5SAnurag S. Maskey */ 5886ba597c5SAnurag S. Maskey switch (new_state) { 5896ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE_TO_ONLINE: 5906ba597c5SAnurag S. Maskey nwamd_loc_activate(event->event_object); 5916ba597c5SAnurag S. Maskey break; 5926ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE_TO_OFFLINE: 5936ba597c5SAnurag S. Maskey /* 5946ba597c5SAnurag S. Maskey * Don't need to deactivate current location - condition check 595ea408ca7SAnurag S. Maskey * will activate another. If the currently active location is 596ea408ca7SAnurag S. Maskey * being deactivated, then it is being manually deactivated; 597ea408ca7SAnurag S. Maskey * so also clear active_loc so condition checking is not 598ea408ca7SAnurag S. Maskey * confused. 5996ba597c5SAnurag S. Maskey */ 600ea408ca7SAnurag S. Maskey (void) pthread_mutex_lock(&active_loc_mutex); 601ea408ca7SAnurag S. Maskey if (strcmp(event->event_object, active_loc) == 0) 602ea408ca7SAnurag S. Maskey active_loc[0] = '\0'; 603ea408ca7SAnurag S. Maskey (void) pthread_mutex_unlock(&active_loc_mutex); 6046ba597c5SAnurag S. Maskey nwamd_loc_check_conditions(); 6056ba597c5SAnurag S. Maskey break; 6066ba597c5SAnurag S. Maskey case NWAM_STATE_DISABLED: 6076ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE: 6086ba597c5SAnurag S. Maskey case NWAM_STATE_UNINITIALIZED: 6096ba597c5SAnurag S. Maskey case NWAM_STATE_MAINTENANCE: 6106ba597c5SAnurag S. Maskey case NWAM_STATE_DEGRADED: 6116ba597c5SAnurag S. Maskey default: 6126ba597c5SAnurag S. Maskey /* do nothing */ 6136ba597c5SAnurag S. Maskey break; 6146ba597c5SAnurag S. Maskey } 6156ba597c5SAnurag S. Maskey } 616