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
loc_create_init_fini_event(nwam_loc_handle_t loch,void * data)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
nwamd_init_locs(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
nwamd_fini_locs(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
loc_is_enabled(nwam_loc_handle_t loch)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
loc_get_activation_mode(nwam_loc_handle_t loch)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
nwamd_loc_activate(const char * object_name)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
nwamd_loc_check(nwamd_object_t object,void * data)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
nwamd_ncu_online_check(nwamd_object_t object,void * data)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
nwamd_loc_check_conditions(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
nwamd_loc_action(const char * loc,nwam_action_t action)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
nwamd_loc_handle_init_event(nwamd_event_t event)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
nwamd_loc_handle_fini_event(nwamd_event_t event)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
nwamd_loc_handle_action_event(nwamd_event_t event)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
nwamd_loc_handle_state_event(nwamd_event_t event)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