xref: /onnv-gate/usr/src/cmd/cmd-inet/lib/nwamd/enm.c (revision 12923:eb113dc3db0b)
111767SAnurag.Maskey@Sun.COM /*
211767SAnurag.Maskey@Sun.COM  * CDDL HEADER START
311767SAnurag.Maskey@Sun.COM  *
411767SAnurag.Maskey@Sun.COM  * The contents of this file are subject to the terms of the
511767SAnurag.Maskey@Sun.COM  * Common Development and Distribution License (the "License").
611767SAnurag.Maskey@Sun.COM  * You may not use this file except in compliance with the License.
711767SAnurag.Maskey@Sun.COM  *
811767SAnurag.Maskey@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911767SAnurag.Maskey@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011767SAnurag.Maskey@Sun.COM  * See the License for the specific language governing permissions
1111767SAnurag.Maskey@Sun.COM  * and limitations under the License.
1211767SAnurag.Maskey@Sun.COM  *
1311767SAnurag.Maskey@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411767SAnurag.Maskey@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511767SAnurag.Maskey@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611767SAnurag.Maskey@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711767SAnurag.Maskey@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811767SAnurag.Maskey@Sun.COM  *
1911767SAnurag.Maskey@Sun.COM  * CDDL HEADER END
2011767SAnurag.Maskey@Sun.COM  */
2111767SAnurag.Maskey@Sun.COM 
2211767SAnurag.Maskey@Sun.COM /*
2312576SAnurag.Maskey@Oracle.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2411767SAnurag.Maskey@Sun.COM  */
2511767SAnurag.Maskey@Sun.COM 
2611767SAnurag.Maskey@Sun.COM #include <arpa/inet.h>
2711767SAnurag.Maskey@Sun.COM #include <errno.h>
2811767SAnurag.Maskey@Sun.COM #include <inet/ip.h>
2911767SAnurag.Maskey@Sun.COM #include <libdladm.h>
3011767SAnurag.Maskey@Sun.COM #include <libdllink.h>
3111767SAnurag.Maskey@Sun.COM #include <libdlwlan.h>
3211767SAnurag.Maskey@Sun.COM #include <libscf.h>
3311767SAnurag.Maskey@Sun.COM #include <netinet/in.h>
3411767SAnurag.Maskey@Sun.COM #include <netdb.h>
3511767SAnurag.Maskey@Sun.COM #include <stdio.h>
3611767SAnurag.Maskey@Sun.COM #include <stdlib.h>
3711767SAnurag.Maskey@Sun.COM #include <string.h>
3811767SAnurag.Maskey@Sun.COM #include <sys/socket.h>
3911767SAnurag.Maskey@Sun.COM #include <sys/types.h>
4011767SAnurag.Maskey@Sun.COM 
4111767SAnurag.Maskey@Sun.COM #include <libnwam.h>
4211767SAnurag.Maskey@Sun.COM #include "conditions.h"
4311767SAnurag.Maskey@Sun.COM #include "events.h"
4411767SAnurag.Maskey@Sun.COM #include "objects.h"
4511767SAnurag.Maskey@Sun.COM #include "util.h"
4611767SAnurag.Maskey@Sun.COM 
4711767SAnurag.Maskey@Sun.COM /*
4811767SAnurag.Maskey@Sun.COM  * enm.c - contains routines which handle ENM (external network modifier)
4911767SAnurag.Maskey@Sun.COM  * abstraction.  ENMs represent scripts or services that can be activated either
5011767SAnurag.Maskey@Sun.COM  * manually or in response to network conditions.
5111767SAnurag.Maskey@Sun.COM  */
5211767SAnurag.Maskey@Sun.COM 
5311767SAnurag.Maskey@Sun.COM #define	CTRUN	"/usr/bin/ctrun"
5411767SAnurag.Maskey@Sun.COM 
5511767SAnurag.Maskey@Sun.COM static int
enm_create_init_fini_event(nwam_enm_handle_t enmh,void * data)5611767SAnurag.Maskey@Sun.COM enm_create_init_fini_event(nwam_enm_handle_t enmh, void *data)
5711767SAnurag.Maskey@Sun.COM {
5811767SAnurag.Maskey@Sun.COM 	boolean_t *init = data;
5911767SAnurag.Maskey@Sun.COM 	char *name;
6011767SAnurag.Maskey@Sun.COM 	nwamd_event_t enm_event;
6111767SAnurag.Maskey@Sun.COM 
6211767SAnurag.Maskey@Sun.COM 	if (nwam_enm_get_name(enmh, &name) != NWAM_SUCCESS) {
63*12923SRenee.Sommerfeld@Oracle.COM 		nlog(LOG_ERR, "enm_init_fini: could not get enm name");
6411767SAnurag.Maskey@Sun.COM 		return (0);
6511767SAnurag.Maskey@Sun.COM 	}
6611767SAnurag.Maskey@Sun.COM 
6711767SAnurag.Maskey@Sun.COM 	enm_event = nwamd_event_init(*init ?
6811767SAnurag.Maskey@Sun.COM 	    NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI,
6911767SAnurag.Maskey@Sun.COM 	    NWAM_OBJECT_TYPE_ENM, 0, name);
7011767SAnurag.Maskey@Sun.COM 	if (enm_event != NULL)
7111767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue(enm_event);
7211767SAnurag.Maskey@Sun.COM 	free(name);
7311767SAnurag.Maskey@Sun.COM 
7411767SAnurag.Maskey@Sun.COM 	return (0);
7511767SAnurag.Maskey@Sun.COM }
7611767SAnurag.Maskey@Sun.COM 
7711767SAnurag.Maskey@Sun.COM /*
7811767SAnurag.Maskey@Sun.COM  * Walk all ENMs, creating init events for each.
7911767SAnurag.Maskey@Sun.COM  */
8011767SAnurag.Maskey@Sun.COM void
nwamd_init_enms(void)8111767SAnurag.Maskey@Sun.COM nwamd_init_enms(void)
8211767SAnurag.Maskey@Sun.COM {
8311767SAnurag.Maskey@Sun.COM 	boolean_t init = B_TRUE;
8411767SAnurag.Maskey@Sun.COM 
8511767SAnurag.Maskey@Sun.COM 	(void) nwam_walk_enms(enm_create_init_fini_event, &init, 0, NULL);
8611767SAnurag.Maskey@Sun.COM }
8711767SAnurag.Maskey@Sun.COM 
8811767SAnurag.Maskey@Sun.COM /*
8911767SAnurag.Maskey@Sun.COM  * Walk all ENMs, creating fini events for each.
9011767SAnurag.Maskey@Sun.COM  */
9111767SAnurag.Maskey@Sun.COM void
nwamd_fini_enms(void)9211767SAnurag.Maskey@Sun.COM nwamd_fini_enms(void)
9311767SAnurag.Maskey@Sun.COM {
9411767SAnurag.Maskey@Sun.COM 	boolean_t init = B_FALSE;
9511767SAnurag.Maskey@Sun.COM 
9611767SAnurag.Maskey@Sun.COM 	(void) nwam_walk_enms(enm_create_init_fini_event, &init, 0, NULL);
9711767SAnurag.Maskey@Sun.COM }
9811767SAnurag.Maskey@Sun.COM 
9911767SAnurag.Maskey@Sun.COM static boolean_t
enm_is_enabled(nwam_enm_handle_t enmh)10011767SAnurag.Maskey@Sun.COM enm_is_enabled(nwam_enm_handle_t enmh)
10111767SAnurag.Maskey@Sun.COM {
10211767SAnurag.Maskey@Sun.COM 	nwam_value_t enabledval;
10311767SAnurag.Maskey@Sun.COM 	boolean_t enabled = B_FALSE;
10411767SAnurag.Maskey@Sun.COM 
10511767SAnurag.Maskey@Sun.COM 	if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ENABLED,
10611767SAnurag.Maskey@Sun.COM 	    &enabledval) != NWAM_SUCCESS) {
10711767SAnurag.Maskey@Sun.COM 		/* It's legal for a conditional ENM to not specify "enabled" */
10811767SAnurag.Maskey@Sun.COM 		return (B_FALSE);
10911767SAnurag.Maskey@Sun.COM 	}
11011767SAnurag.Maskey@Sun.COM 	if (nwam_value_get_boolean(enabledval, &enabled) != NWAM_SUCCESS) {
11111767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "enm_is_enabled: could not retrieve "
11211767SAnurag.Maskey@Sun.COM 		    "enabled value");
11311767SAnurag.Maskey@Sun.COM 	}
11411767SAnurag.Maskey@Sun.COM 	nwam_value_free(enabledval);
11511767SAnurag.Maskey@Sun.COM 	return (enabled);
11611767SAnurag.Maskey@Sun.COM }
11711767SAnurag.Maskey@Sun.COM 
11811767SAnurag.Maskey@Sun.COM static int64_t
enm_get_activation_mode(nwam_enm_handle_t enmh)11911767SAnurag.Maskey@Sun.COM enm_get_activation_mode(nwam_enm_handle_t enmh)
12011767SAnurag.Maskey@Sun.COM {
12111767SAnurag.Maskey@Sun.COM 	uint64_t activation;
12211767SAnurag.Maskey@Sun.COM 	int64_t ret;
12311767SAnurag.Maskey@Sun.COM 	nwam_value_t activationval;
12411767SAnurag.Maskey@Sun.COM 
12511767SAnurag.Maskey@Sun.COM 	if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ACTIVATION_MODE,
12611767SAnurag.Maskey@Sun.COM 	    &activationval)  != NWAM_SUCCESS) {
12711767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "enm_get_activation_mode: could not retrieve "
12811767SAnurag.Maskey@Sun.COM 		    "activation mode value");
12911767SAnurag.Maskey@Sun.COM 		return (-1);
13011767SAnurag.Maskey@Sun.COM 	}
13111767SAnurag.Maskey@Sun.COM 	if (nwam_value_get_uint64(activationval, &activation) != NWAM_SUCCESS) {
13211767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "enm_get_activation_mode: could not retrieve "
13311767SAnurag.Maskey@Sun.COM 		    "activation mode value");
13411767SAnurag.Maskey@Sun.COM 		ret = -1;
13511767SAnurag.Maskey@Sun.COM 	} else {
13611767SAnurag.Maskey@Sun.COM 		ret = activation;
13711767SAnurag.Maskey@Sun.COM 	}
13811767SAnurag.Maskey@Sun.COM 	nwam_value_free(activationval);
13911767SAnurag.Maskey@Sun.COM 
14011767SAnurag.Maskey@Sun.COM 	return (ret);
14111767SAnurag.Maskey@Sun.COM }
14211767SAnurag.Maskey@Sun.COM 
14311767SAnurag.Maskey@Sun.COM static void *
nwamd_enm_activate_deactivate_thread(void * arg)14411767SAnurag.Maskey@Sun.COM nwamd_enm_activate_deactivate_thread(void *arg)
14511767SAnurag.Maskey@Sun.COM {
14611767SAnurag.Maskey@Sun.COM 	char *object_name = arg;
14711767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
14811767SAnurag.Maskey@Sun.COM 	nwam_enm_handle_t enmh;
14911767SAnurag.Maskey@Sun.COM 	nwam_value_t scriptval = NULL;
15011767SAnurag.Maskey@Sun.COM 	nwam_state_t state;
15111767SAnurag.Maskey@Sun.COM 	nwam_aux_state_t aux_state;
15211994SAnurag.Maskey@Sun.COM 	char *script, *copy = NULL;
15311994SAnurag.Maskey@Sun.COM 	const char **argv = NULL;
15411767SAnurag.Maskey@Sun.COM 	boolean_t going_online, disable_succeeded = B_FALSE;
15511767SAnurag.Maskey@Sun.COM 	int ret;
15611767SAnurag.Maskey@Sun.COM 
15711767SAnurag.Maskey@Sun.COM 	object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name);
15811767SAnurag.Maskey@Sun.COM 	if (object == NULL) {
15911767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_enm_activate_deactivate_thread: "
160*12923SRenee.Sommerfeld@Oracle.COM 		    "could not find enm %s", object_name);
16111994SAnurag.Maskey@Sun.COM 		goto done;
16211767SAnurag.Maskey@Sun.COM 	}
16311767SAnurag.Maskey@Sun.COM 	enmh = object->nwamd_object_handle;
16411767SAnurag.Maskey@Sun.COM 
16511767SAnurag.Maskey@Sun.COM 	going_online =
16611767SAnurag.Maskey@Sun.COM 	    (object->nwamd_object_state == NWAM_STATE_OFFLINE_TO_ONLINE);
16711767SAnurag.Maskey@Sun.COM 	/*
16811767SAnurag.Maskey@Sun.COM 	 * We're starting if current state is offline* and stopping otherwise.
16911767SAnurag.Maskey@Sun.COM 	 */
17011767SAnurag.Maskey@Sun.COM 	if (nwam_enm_get_prop_value(enmh,
17111767SAnurag.Maskey@Sun.COM 	    going_online ? NWAM_ENM_PROP_START : NWAM_ENM_PROP_STOP,
17211767SAnurag.Maskey@Sun.COM 	    &scriptval) != NWAM_SUCCESS ||
17311767SAnurag.Maskey@Sun.COM 	    nwam_value_get_string(scriptval, &script) != NWAM_SUCCESS) {
17411767SAnurag.Maskey@Sun.COM 		/*
17511767SAnurag.Maskey@Sun.COM 		 * If we're stopping, it's not an error for no script to
17611767SAnurag.Maskey@Sun.COM 		 * be specified.
17711767SAnurag.Maskey@Sun.COM 		 */
17811767SAnurag.Maskey@Sun.COM 		nlog(going_online ? LOG_ERR : LOG_DEBUG,
17911767SAnurag.Maskey@Sun.COM 		    "nwamd_enm_activate_deactivate_thread: "
18011994SAnurag.Maskey@Sun.COM 		    "no script specified for enm %s", object_name);
18111767SAnurag.Maskey@Sun.COM 		if (going_online) {
18211767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_MAINTENANCE;
18311767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_METHOD_MISSING;
18411767SAnurag.Maskey@Sun.COM 		} else {
18511767SAnurag.Maskey@Sun.COM 			disable_succeeded = B_TRUE;
18611767SAnurag.Maskey@Sun.COM 		}
18711767SAnurag.Maskey@Sun.COM 	} else {
18811994SAnurag.Maskey@Sun.COM 		char *lasts;
18911994SAnurag.Maskey@Sun.COM 		const char **newargv;
19011767SAnurag.Maskey@Sun.COM 		int i = 0;
19111994SAnurag.Maskey@Sun.COM 		struct timeval now;
19211767SAnurag.Maskey@Sun.COM 
19311767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_enm_activate_deactivate_thread: "
194*12923SRenee.Sommerfeld@Oracle.COM 		    "running script %s for enm %s", script, object_name);
19511767SAnurag.Maskey@Sun.COM 
19611767SAnurag.Maskey@Sun.COM 		/*
19711767SAnurag.Maskey@Sun.COM 		 * The script may take a number of arguments. We need to
19811767SAnurag.Maskey@Sun.COM 		 * create a string array consisting of the wrapper command
19911767SAnurag.Maskey@Sun.COM 		 * (ctrun), ENM script name, arguments and NULL array
20011767SAnurag.Maskey@Sun.COM 		 * terminator.  Start with an array of size equal to the
20111767SAnurag.Maskey@Sun.COM 		 * string length (since the number of arguments will always
20211767SAnurag.Maskey@Sun.COM 		 * be less than this) and shrink array to the actual number
20311767SAnurag.Maskey@Sun.COM 		 * of arguments when we have parsed the string.
20411767SAnurag.Maskey@Sun.COM 		 */
20511767SAnurag.Maskey@Sun.COM 		if ((copy = strdup(script)) == NULL ||
20611767SAnurag.Maskey@Sun.COM 		    (argv = calloc(strlen(script), sizeof (char *))) == NULL) {
20711767SAnurag.Maskey@Sun.COM 			ret = 1;
20811767SAnurag.Maskey@Sun.COM 			goto err;
20911767SAnurag.Maskey@Sun.COM 		}
21011767SAnurag.Maskey@Sun.COM 		argv[i++] = CTRUN;
21111767SAnurag.Maskey@Sun.COM 		argv[i++] = strtok_r(copy, " ", &lasts);
21211767SAnurag.Maskey@Sun.COM 		if (argv[1] == NULL) {
21311767SAnurag.Maskey@Sun.COM 			ret = 1;
21411767SAnurag.Maskey@Sun.COM 			goto err;
21511767SAnurag.Maskey@Sun.COM 		}
21611767SAnurag.Maskey@Sun.COM 
21711767SAnurag.Maskey@Sun.COM 		for (; (argv[i] = strtok_r(NULL, " ", &lasts)) != NULL; i++) {}
21811767SAnurag.Maskey@Sun.COM 
21911767SAnurag.Maskey@Sun.COM 		newargv = realloc(argv, (i + 1) * sizeof (char *));
22011767SAnurag.Maskey@Sun.COM 		argv = newargv;
22111767SAnurag.Maskey@Sun.COM 
22211994SAnurag.Maskey@Sun.COM 		/* Store the current time as the time the script began */
22311994SAnurag.Maskey@Sun.COM 		(void) gettimeofday(&now, NULL);
22411994SAnurag.Maskey@Sun.COM 		object->nwamd_script_time = now;
22511994SAnurag.Maskey@Sun.COM 
22611994SAnurag.Maskey@Sun.COM 		/*
22711994SAnurag.Maskey@Sun.COM 		 * Release the object so that it is not blocked while the
22811994SAnurag.Maskey@Sun.COM 		 * script is running.
22911994SAnurag.Maskey@Sun.COM 		 */
23011994SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
23111994SAnurag.Maskey@Sun.COM 
23211767SAnurag.Maskey@Sun.COM 		ret = nwamd_start_childv(CTRUN, argv);
23311767SAnurag.Maskey@Sun.COM 
23411994SAnurag.Maskey@Sun.COM 		/*
23511994SAnurag.Maskey@Sun.COM 		 * Find the object again, now that the script has finished
23611994SAnurag.Maskey@Sun.COM 		 * running.  Check if this ENM was re-read during that time by
23711994SAnurag.Maskey@Sun.COM 		 * comparing the object's script time with the one from above.
23811994SAnurag.Maskey@Sun.COM 		 */
23911994SAnurag.Maskey@Sun.COM 		object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name);
24011994SAnurag.Maskey@Sun.COM 		if (object == NULL) {
24111994SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_activate_deactivate_thread: "
242*12923SRenee.Sommerfeld@Oracle.COM 			    "could not find enm %s after running script",
24311994SAnurag.Maskey@Sun.COM 			    object_name);
24411994SAnurag.Maskey@Sun.COM 			goto done;
24511994SAnurag.Maskey@Sun.COM 		}
24611994SAnurag.Maskey@Sun.COM 
24711994SAnurag.Maskey@Sun.COM 		if (object->nwamd_script_time.tv_sec != now.tv_sec ||
24811994SAnurag.Maskey@Sun.COM 		    object->nwamd_script_time.tv_usec != now.tv_usec) {
24911994SAnurag.Maskey@Sun.COM 			nlog(LOG_INFO, "nwamd_enm_activate_deactivate_thread: "
250*12923SRenee.Sommerfeld@Oracle.COM 			    "enm %s has been refreshed, nothing to do",
25111994SAnurag.Maskey@Sun.COM 			    object_name);
25211994SAnurag.Maskey@Sun.COM 			nwamd_object_release(object);
25311994SAnurag.Maskey@Sun.COM 			goto done;
25411994SAnurag.Maskey@Sun.COM 		}
25511994SAnurag.Maskey@Sun.COM 		(void) gettimeofday(&object->nwamd_script_time, NULL);
25611994SAnurag.Maskey@Sun.COM 
25711767SAnurag.Maskey@Sun.COM err:
25811767SAnurag.Maskey@Sun.COM 		/*
25911767SAnurag.Maskey@Sun.COM 		 * If script execution fails and we're not destroying the
26011767SAnurag.Maskey@Sun.COM 		 * object, go to maintenance.
26111767SAnurag.Maskey@Sun.COM 		 */
26211767SAnurag.Maskey@Sun.COM 		if (ret != 0) {
26311767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_activate_deactivate_thread: "
264*12923SRenee.Sommerfeld@Oracle.COM 			    "execution of '%s' failed for enm %s",
26511994SAnurag.Maskey@Sun.COM 			    script, object_name);
26611767SAnurag.Maskey@Sun.COM 			if (object->nwamd_object_aux_state !=
26711767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_UNINITIALIZED) {
26811767SAnurag.Maskey@Sun.COM 				state = NWAM_STATE_MAINTENANCE;
26911767SAnurag.Maskey@Sun.COM 				aux_state = NWAM_AUX_STATE_METHOD_FAILED;
27011767SAnurag.Maskey@Sun.COM 			} else {
27111767SAnurag.Maskey@Sun.COM 				state = NWAM_STATE_UNINITIALIZED;
27211767SAnurag.Maskey@Sun.COM 				aux_state = NWAM_AUX_STATE_UNINITIALIZED;
27311767SAnurag.Maskey@Sun.COM 			}
27411767SAnurag.Maskey@Sun.COM 		} else {
27511767SAnurag.Maskey@Sun.COM 			if (going_online) {
27611767SAnurag.Maskey@Sun.COM 				state = NWAM_STATE_ONLINE;
27711767SAnurag.Maskey@Sun.COM 				aux_state = NWAM_AUX_STATE_ACTIVE;
27811767SAnurag.Maskey@Sun.COM 			} else {
27911767SAnurag.Maskey@Sun.COM 				disable_succeeded = B_TRUE;
28011767SAnurag.Maskey@Sun.COM 			}
28111767SAnurag.Maskey@Sun.COM 		}
28211767SAnurag.Maskey@Sun.COM 	}
28311767SAnurag.Maskey@Sun.COM 
28411767SAnurag.Maskey@Sun.COM 	if (disable_succeeded) {
28511767SAnurag.Maskey@Sun.COM 		/*
28611767SAnurag.Maskey@Sun.COM 		 * If aux state is "manual disable", we know
28711767SAnurag.Maskey@Sun.COM 		 * this was a disable request, otherwise it was
28811767SAnurag.Maskey@Sun.COM 		 * _fini request or a condition satisfaction
28911767SAnurag.Maskey@Sun.COM 		 * failure.
29011767SAnurag.Maskey@Sun.COM 		 */
29111767SAnurag.Maskey@Sun.COM 		switch (object->nwamd_object_aux_state) {
29211767SAnurag.Maskey@Sun.COM 		case NWAM_AUX_STATE_MANUAL_DISABLE:
29311767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_DISABLED;
29411767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_MANUAL_DISABLE;
29511767SAnurag.Maskey@Sun.COM 			break;
29611767SAnurag.Maskey@Sun.COM 		case NWAM_AUX_STATE_UNINITIALIZED:
29711767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_UNINITIALIZED;
29811767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_UNINITIALIZED;
29911767SAnurag.Maskey@Sun.COM 			break;
30011767SAnurag.Maskey@Sun.COM 		default:
30111767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_OFFLINE;
30211767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_CONDITIONS_NOT_MET;
30311767SAnurag.Maskey@Sun.COM 			break;
30411767SAnurag.Maskey@Sun.COM 		}
30511767SAnurag.Maskey@Sun.COM 	}
30611767SAnurag.Maskey@Sun.COM 
30711767SAnurag.Maskey@Sun.COM 	/* If state/aux state are uninitialized/unintialized, destroy the ENM */
30811767SAnurag.Maskey@Sun.COM 	if (state == NWAM_STATE_UNINITIALIZED &&
30911767SAnurag.Maskey@Sun.COM 	    aux_state == NWAM_AUX_STATE_UNINITIALIZED) {
31011767SAnurag.Maskey@Sun.COM 		object->nwamd_object_state = state;
31111767SAnurag.Maskey@Sun.COM 		object->nwamd_object_aux_state = aux_state;
31211767SAnurag.Maskey@Sun.COM 		(void) nwamd_object_release_and_destroy_after_preserve(object);
31311767SAnurag.Maskey@Sun.COM 	} else {
31411767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
31511767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name, state, aux_state);
31611767SAnurag.Maskey@Sun.COM 		(void) nwamd_object_release_after_preserve(object);
31711767SAnurag.Maskey@Sun.COM 	}
31811767SAnurag.Maskey@Sun.COM 
31911994SAnurag.Maskey@Sun.COM done:
32011994SAnurag.Maskey@Sun.COM 	/* object_name was malloc() before this thread was created, free() it */
32111994SAnurag.Maskey@Sun.COM 	free(object_name);
32211994SAnurag.Maskey@Sun.COM 	free(argv);
32311994SAnurag.Maskey@Sun.COM 	free(copy);
32411994SAnurag.Maskey@Sun.COM 	nwam_value_free(scriptval);
32511767SAnurag.Maskey@Sun.COM 	return (NULL);
32611767SAnurag.Maskey@Sun.COM }
32711767SAnurag.Maskey@Sun.COM 
32811767SAnurag.Maskey@Sun.COM /*
32911767SAnurag.Maskey@Sun.COM  * Run start/stop method for ENM in a separate thread.  The object lock is not
33011767SAnurag.Maskey@Sun.COM  * held across threads, so we duplicate the object name for the method
33111767SAnurag.Maskey@Sun.COM  * execution thread.  Returns true if thread is successfully launched.
33211767SAnurag.Maskey@Sun.COM  */
33311767SAnurag.Maskey@Sun.COM boolean_t
nwamd_enm_run_method(nwamd_object_t object)33411767SAnurag.Maskey@Sun.COM nwamd_enm_run_method(nwamd_object_t object)
33511767SAnurag.Maskey@Sun.COM {
33611767SAnurag.Maskey@Sun.COM 	char *name;
33711767SAnurag.Maskey@Sun.COM 	pthread_t script;
33811767SAnurag.Maskey@Sun.COM 
33911767SAnurag.Maskey@Sun.COM 	/*
34011767SAnurag.Maskey@Sun.COM 	 * Launch separate thread to wait for execution of script
34111767SAnurag.Maskey@Sun.COM 	 * to complete.  Do not hold object lock across threads.
34211767SAnurag.Maskey@Sun.COM 	 */
34311767SAnurag.Maskey@Sun.COM 	if ((name = strdup(object->nwamd_object_name)) == NULL) {
34411767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_enm_run_method: %s: out of memory",
34511767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name);
34611767SAnurag.Maskey@Sun.COM 		return (B_FALSE);
34711767SAnurag.Maskey@Sun.COM 	}
34811767SAnurag.Maskey@Sun.COM 
34911767SAnurag.Maskey@Sun.COM 	if (pthread_create(&script, NULL,
35011767SAnurag.Maskey@Sun.COM 	    nwamd_enm_activate_deactivate_thread, name) != 0) {
35111767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_enm_run_method: could not create "
35211767SAnurag.Maskey@Sun.COM 		    "enm script thread for %s", name);
35311767SAnurag.Maskey@Sun.COM 		free(name);
35411767SAnurag.Maskey@Sun.COM 		return (B_FALSE);
35511767SAnurag.Maskey@Sun.COM 	}
35611767SAnurag.Maskey@Sun.COM 	/* "name" will be freed by the newly-created thread. */
35711767SAnurag.Maskey@Sun.COM 
35811767SAnurag.Maskey@Sun.COM 	/* detach thread so that it doesn't become a zombie */
35911767SAnurag.Maskey@Sun.COM 	(void) pthread_detach(script);
36011767SAnurag.Maskey@Sun.COM 
36111767SAnurag.Maskey@Sun.COM 	return (B_TRUE);
36211767SAnurag.Maskey@Sun.COM }
36311767SAnurag.Maskey@Sun.COM 
36411767SAnurag.Maskey@Sun.COM /*
36511767SAnurag.Maskey@Sun.COM  * Activate the ENM, either in response to an enable event or conditions
36611767SAnurag.Maskey@Sun.COM  * being satisfied.
36711767SAnurag.Maskey@Sun.COM  */
36811767SAnurag.Maskey@Sun.COM static void
nwamd_enm_activate(const char * object_name)36911767SAnurag.Maskey@Sun.COM nwamd_enm_activate(const char *object_name)
37011767SAnurag.Maskey@Sun.COM {
37111767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
37211767SAnurag.Maskey@Sun.COM 	nwam_value_t fmrival;
37311767SAnurag.Maskey@Sun.COM 	char *fmri, *smf_state;
37411767SAnurag.Maskey@Sun.COM 	int ret;
37511767SAnurag.Maskey@Sun.COM 	nwam_enm_handle_t enmh;
37611767SAnurag.Maskey@Sun.COM 	nwam_state_t state;
37711767SAnurag.Maskey@Sun.COM 	nwam_aux_state_t aux_state;
37811767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
37911767SAnurag.Maskey@Sun.COM 	boolean_t ran_method = B_FALSE;
38011767SAnurag.Maskey@Sun.COM 
38111767SAnurag.Maskey@Sun.COM 	object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name);
38211767SAnurag.Maskey@Sun.COM 	if (object == NULL) {
383*12923SRenee.Sommerfeld@Oracle.COM 		nlog(LOG_ERR, "nwamd_enm_activate: could not find enm %s",
38411767SAnurag.Maskey@Sun.COM 		    object_name);
38511767SAnurag.Maskey@Sun.COM 		return;
38611767SAnurag.Maskey@Sun.COM 	}
38711767SAnurag.Maskey@Sun.COM 	state = object->nwamd_object_state;
38811767SAnurag.Maskey@Sun.COM 	aux_state = object->nwamd_object_aux_state;
38911767SAnurag.Maskey@Sun.COM 	enmh = object->nwamd_object_handle;
39011767SAnurag.Maskey@Sun.COM 
391*12923SRenee.Sommerfeld@Oracle.COM 	nlog(LOG_DEBUG, "nwamd_enm_activate: activating enm %s",
39211767SAnurag.Maskey@Sun.COM 	    object->nwamd_object_name);
39311767SAnurag.Maskey@Sun.COM 
39411767SAnurag.Maskey@Sun.COM 	err = nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_FMRI, &fmrival);
39511767SAnurag.Maskey@Sun.COM 	switch (err) {
39611767SAnurag.Maskey@Sun.COM 	case NWAM_SUCCESS:
39711767SAnurag.Maskey@Sun.COM 
39811767SAnurag.Maskey@Sun.COM 		if (nwam_value_get_string(fmrival, &fmri) != NWAM_SUCCESS) {
39911767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_activate: could not retrieve "
400*12923SRenee.Sommerfeld@Oracle.COM 			    "fmri string for enm %s",
40111767SAnurag.Maskey@Sun.COM 			    object->nwamd_object_name);
40211767SAnurag.Maskey@Sun.COM 			nwam_value_free(fmrival);
40311767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_MAINTENANCE;
40411767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_INVALID_CONFIG;
40511767SAnurag.Maskey@Sun.COM 			break;
40611767SAnurag.Maskey@Sun.COM 		}
40711767SAnurag.Maskey@Sun.COM 
40811767SAnurag.Maskey@Sun.COM 		if ((smf_state = smf_get_state(fmri)) == NULL) {
409*12923SRenee.Sommerfeld@Oracle.COM 			nlog(LOG_ERR, "nwamd_enm_activate: invalid fmri %s "
410*12923SRenee.Sommerfeld@Oracle.COM 			    "for enm %s", fmri, object->nwamd_object_name);
41111767SAnurag.Maskey@Sun.COM 			nwam_value_free(fmrival);
41211767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_MAINTENANCE;
41311767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_INVALID_CONFIG;
41411767SAnurag.Maskey@Sun.COM 			break;
41511767SAnurag.Maskey@Sun.COM 		}
41611767SAnurag.Maskey@Sun.COM 
417*12923SRenee.Sommerfeld@Oracle.COM 		nlog(LOG_DEBUG, "nwamd_enm_activate: activating %s for enm %s",
41811767SAnurag.Maskey@Sun.COM 		    fmri, object->nwamd_object_name);
41911767SAnurag.Maskey@Sun.COM 
42011767SAnurag.Maskey@Sun.COM 		if (strcmp(smf_state, SCF_STATE_STRING_ONLINE) == 0)
42111767SAnurag.Maskey@Sun.COM 			ret = smf_restart_instance(fmri);
42211767SAnurag.Maskey@Sun.COM 		else if (strcmp(smf_state, SCF_STATE_STRING_OFFLINE) == 0)
42311767SAnurag.Maskey@Sun.COM 			ret = smf_restart_instance(fmri);
42411767SAnurag.Maskey@Sun.COM 		else if (strcmp(smf_state, SCF_STATE_STRING_DISABLED) == 0)
42511767SAnurag.Maskey@Sun.COM 			ret = smf_enable_instance(fmri, SMF_TEMPORARY);
42611767SAnurag.Maskey@Sun.COM 		else
42711767SAnurag.Maskey@Sun.COM 			ret = smf_restore_instance(fmri);
42811767SAnurag.Maskey@Sun.COM 
42911767SAnurag.Maskey@Sun.COM 		if (ret == 0) {
43011767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_ONLINE;
43111767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_ACTIVE;
43211767SAnurag.Maskey@Sun.COM 		} else {
43311767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_activate: failed to enable "
434*12923SRenee.Sommerfeld@Oracle.COM 			    "fmri %s for enm %s", fmri,
43511767SAnurag.Maskey@Sun.COM 			    object->nwamd_object_name);
43611767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_MAINTENANCE;
43711767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_METHOD_FAILED;
43811767SAnurag.Maskey@Sun.COM 		}
43911767SAnurag.Maskey@Sun.COM 		free(smf_state);
44011767SAnurag.Maskey@Sun.COM 		nwam_value_free(fmrival);
44111767SAnurag.Maskey@Sun.COM 		break;
44211767SAnurag.Maskey@Sun.COM 	default:
44311767SAnurag.Maskey@Sun.COM 		/*
44411767SAnurag.Maskey@Sun.COM 		 * Must be a method-based ENM with start (and stop) script(s).
44511767SAnurag.Maskey@Sun.COM 		 */
44611767SAnurag.Maskey@Sun.COM 		if (!nwamd_enm_run_method(object)) {
44711767SAnurag.Maskey@Sun.COM 			/* Could not launch method execution thread */
44811767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_MAINTENANCE;
44911767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_METHOD_FAILED;
45011767SAnurag.Maskey@Sun.COM 		} else {
45111767SAnurag.Maskey@Sun.COM 			ran_method = B_TRUE;
45211767SAnurag.Maskey@Sun.COM 		}
45311767SAnurag.Maskey@Sun.COM 		break;
45411767SAnurag.Maskey@Sun.COM 	}
45511767SAnurag.Maskey@Sun.COM 
45611767SAnurag.Maskey@Sun.COM 	if (state != object->nwamd_object_state ||
45711767SAnurag.Maskey@Sun.COM 	    aux_state != object->nwamd_object_aux_state) {
45811767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
45911767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name, state, aux_state);
46011767SAnurag.Maskey@Sun.COM 	}
46111767SAnurag.Maskey@Sun.COM 
46211767SAnurag.Maskey@Sun.COM 	/*
46311767SAnurag.Maskey@Sun.COM 	 * If the method thread was created, we drop the lock to the ENM
46411767SAnurag.Maskey@Sun.COM 	 * object without decreasing the reference count, ensuring it will not
46511767SAnurag.Maskey@Sun.COM 	 * be destroyed until method execution has completed.
46611767SAnurag.Maskey@Sun.COM 	 */
46711767SAnurag.Maskey@Sun.COM 	if (ran_method) {
46811767SAnurag.Maskey@Sun.COM 		nwamd_object_release_and_preserve(object);
46911767SAnurag.Maskey@Sun.COM 	} else {
47011767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
47111767SAnurag.Maskey@Sun.COM 	}
47211767SAnurag.Maskey@Sun.COM }
47311767SAnurag.Maskey@Sun.COM 
47411767SAnurag.Maskey@Sun.COM /* Deactivates the ENM. */
47511767SAnurag.Maskey@Sun.COM static void
nwamd_enm_deactivate(const char * object_name)47611767SAnurag.Maskey@Sun.COM nwamd_enm_deactivate(const char *object_name)
47711767SAnurag.Maskey@Sun.COM {
47811767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
47911767SAnurag.Maskey@Sun.COM 	nwam_enm_handle_t enmh;
48011767SAnurag.Maskey@Sun.COM 	nwam_value_t fmrival;
48111767SAnurag.Maskey@Sun.COM 	char *fmri, *smf_state;
48211767SAnurag.Maskey@Sun.COM 	int ret;
48311767SAnurag.Maskey@Sun.COM 	nwam_state_t state;
48411767SAnurag.Maskey@Sun.COM 	nwam_aux_state_t aux_state;
48511767SAnurag.Maskey@Sun.COM 	boolean_t destroying = B_FALSE;
48611767SAnurag.Maskey@Sun.COM 
48711767SAnurag.Maskey@Sun.COM 	object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM, object_name);
48811767SAnurag.Maskey@Sun.COM 	if (object == NULL) {
489*12923SRenee.Sommerfeld@Oracle.COM 		nlog(LOG_ERR, "nwamd_enm_deactivate: could not find enm %s",
49011767SAnurag.Maskey@Sun.COM 		    object_name);
49111767SAnurag.Maskey@Sun.COM 		return;
49211767SAnurag.Maskey@Sun.COM 	}
49311767SAnurag.Maskey@Sun.COM 
49411767SAnurag.Maskey@Sun.COM 	state = object->nwamd_object_state;
49511767SAnurag.Maskey@Sun.COM 	aux_state = object->nwamd_object_aux_state;
49611767SAnurag.Maskey@Sun.COM 	enmh = object->nwamd_object_handle;
49711767SAnurag.Maskey@Sun.COM 	state = object->nwamd_object_state;
49811767SAnurag.Maskey@Sun.COM 	/* If destroying, we don't care about method failure/config err */
49911767SAnurag.Maskey@Sun.COM 	destroying = (aux_state == NWAM_AUX_STATE_UNINITIALIZED);
50011767SAnurag.Maskey@Sun.COM 
50111767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_enm_deactivate: deactivating enm %s",
50211767SAnurag.Maskey@Sun.COM 	    object->nwamd_object_name);
50311767SAnurag.Maskey@Sun.COM 
50411767SAnurag.Maskey@Sun.COM 	if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_FMRI, &fmrival)
50511767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS) {
50611767SAnurag.Maskey@Sun.COM 		/*
50711767SAnurag.Maskey@Sun.COM 		 * Must be a method-based ENM with start (and stop) script(s).
50811767SAnurag.Maskey@Sun.COM 		 * Script execution thread will take care of the rest.
50911767SAnurag.Maskey@Sun.COM 		 * If the method thread was created, we drop the lock to the ENM
51011767SAnurag.Maskey@Sun.COM 		 * object without decreasing the reference count, ensuring it
51111767SAnurag.Maskey@Sun.COM 		 * will not be destroyed until method execution has completed.
51211767SAnurag.Maskey@Sun.COM 		 */
51311767SAnurag.Maskey@Sun.COM 		if (nwamd_enm_run_method(object)) {
51411767SAnurag.Maskey@Sun.COM 			nwamd_object_release_and_preserve(object);
51511767SAnurag.Maskey@Sun.COM 			return;
51611767SAnurag.Maskey@Sun.COM 		}
51711767SAnurag.Maskey@Sun.COM 		/* Could not launch method execution thread */
51811767SAnurag.Maskey@Sun.COM 		if (!destroying) {
51911767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_MAINTENANCE;
52011767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_METHOD_FAILED;
52111767SAnurag.Maskey@Sun.COM 		}
52211767SAnurag.Maskey@Sun.COM 	} else {
52311767SAnurag.Maskey@Sun.COM 		if (nwam_value_get_string(fmrival, &fmri) != NWAM_SUCCESS) {
524*12923SRenee.Sommerfeld@Oracle.COM 			nlog(LOG_ERR, "nwamd_enm_deactivate: could not "
525*12923SRenee.Sommerfeld@Oracle.COM 			    "retrieve fmri string for enm %s",
52611767SAnurag.Maskey@Sun.COM 			    object->nwamd_object_name);
52711767SAnurag.Maskey@Sun.COM 			if (!destroying) {
52811767SAnurag.Maskey@Sun.COM 				state = NWAM_STATE_MAINTENANCE;
52911767SAnurag.Maskey@Sun.COM 				aux_state = NWAM_AUX_STATE_INVALID_CONFIG;
53011767SAnurag.Maskey@Sun.COM 			}
53111767SAnurag.Maskey@Sun.COM 		} else {
53211767SAnurag.Maskey@Sun.COM 			if ((smf_state = smf_get_state(fmri)) == NULL) {
53311767SAnurag.Maskey@Sun.COM 				nlog(LOG_ERR, "nwamd_enm_deactivate: invalid "
534*12923SRenee.Sommerfeld@Oracle.COM 				    "fmri %s for enm %s", fmri,
53511767SAnurag.Maskey@Sun.COM 				    object->nwamd_object_name);
53611767SAnurag.Maskey@Sun.COM 				nwam_value_free(fmrival);
53711767SAnurag.Maskey@Sun.COM 				if (!destroying) {
53811767SAnurag.Maskey@Sun.COM 					state = NWAM_STATE_MAINTENANCE;
53911767SAnurag.Maskey@Sun.COM 					aux_state =
54011767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_INVALID_CONFIG;
54111767SAnurag.Maskey@Sun.COM 				}
54211767SAnurag.Maskey@Sun.COM 				goto done;
54311767SAnurag.Maskey@Sun.COM 			}
54411767SAnurag.Maskey@Sun.COM 			free(smf_state);
54511767SAnurag.Maskey@Sun.COM 
54611767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_enm_deactivate: deactivating %s "
547*12923SRenee.Sommerfeld@Oracle.COM 			    "for enm %s", fmri, object->nwamd_object_name);
54811767SAnurag.Maskey@Sun.COM 
54911767SAnurag.Maskey@Sun.COM 			ret = smf_disable_instance(fmri, SMF_TEMPORARY);
55011767SAnurag.Maskey@Sun.COM 
55111767SAnurag.Maskey@Sun.COM 			if (ret != 0) {
55211767SAnurag.Maskey@Sun.COM 				nlog(LOG_ERR, "nwamd_enm_deactivate: "
55311767SAnurag.Maskey@Sun.COM 				    "smf_disable_instance(%s) failed for "
554*12923SRenee.Sommerfeld@Oracle.COM 				    "enm %s: %s", fmri,
55511767SAnurag.Maskey@Sun.COM 				    object->nwamd_object_name,
55611767SAnurag.Maskey@Sun.COM 				    scf_strerror(scf_error()));
55711767SAnurag.Maskey@Sun.COM 				if (!destroying) {
55811767SAnurag.Maskey@Sun.COM 					state = NWAM_STATE_MAINTENANCE;
55911767SAnurag.Maskey@Sun.COM 					aux_state =
56011767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_METHOD_FAILED;
56111767SAnurag.Maskey@Sun.COM 				}
56211767SAnurag.Maskey@Sun.COM 			}
56311767SAnurag.Maskey@Sun.COM 		}
56411767SAnurag.Maskey@Sun.COM 		nwam_value_free(fmrival);
56511767SAnurag.Maskey@Sun.COM 	}
56611767SAnurag.Maskey@Sun.COM done:
56711767SAnurag.Maskey@Sun.COM 	if (state == object->nwamd_object_state &&
56811767SAnurag.Maskey@Sun.COM 	    aux_state == object->nwamd_object_aux_state) {
56911767SAnurag.Maskey@Sun.COM 		/*
57011767SAnurag.Maskey@Sun.COM 		 * If aux state is "manual disable", we know
57111767SAnurag.Maskey@Sun.COM 		 * this was a disable request, otherwise it was
57211767SAnurag.Maskey@Sun.COM 		 * a _fini request or a condition satisfaction
57311767SAnurag.Maskey@Sun.COM 		 * failure.
57411767SAnurag.Maskey@Sun.COM 		 */
57511767SAnurag.Maskey@Sun.COM 		switch (object->nwamd_object_aux_state) {
57611767SAnurag.Maskey@Sun.COM 		case NWAM_AUX_STATE_MANUAL_DISABLE:
57711767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_DISABLED;
57811767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_MANUAL_DISABLE;
57911767SAnurag.Maskey@Sun.COM 			break;
58011767SAnurag.Maskey@Sun.COM 		case NWAM_AUX_STATE_UNINITIALIZED:
58111767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_UNINITIALIZED;
58211767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_UNINITIALIZED;
58311767SAnurag.Maskey@Sun.COM 			break;
58411767SAnurag.Maskey@Sun.COM 		default:
58511767SAnurag.Maskey@Sun.COM 			state = NWAM_STATE_OFFLINE;
58611767SAnurag.Maskey@Sun.COM 			aux_state = NWAM_AUX_STATE_CONDITIONS_NOT_MET;
58711767SAnurag.Maskey@Sun.COM 			break;
58811767SAnurag.Maskey@Sun.COM 		}
58911767SAnurag.Maskey@Sun.COM 	}
59011767SAnurag.Maskey@Sun.COM 
59111767SAnurag.Maskey@Sun.COM 	/* Only change state if we aren't destroying the ENM */
59211767SAnurag.Maskey@Sun.COM 	if (!destroying && (state != object->nwamd_object_state ||
59311767SAnurag.Maskey@Sun.COM 	    aux_state != object->nwamd_object_aux_state)) {
59411767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
59511767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name, state, aux_state);
59611767SAnurag.Maskey@Sun.COM 	}
59711767SAnurag.Maskey@Sun.COM 
59811767SAnurag.Maskey@Sun.COM 	/* If state/aux state are uninitialized/unintialized, destroy the ENM */
59911767SAnurag.Maskey@Sun.COM 	if (state == NWAM_STATE_UNINITIALIZED &&
60011767SAnurag.Maskey@Sun.COM 	    aux_state == NWAM_AUX_STATE_UNINITIALIZED) {
60111767SAnurag.Maskey@Sun.COM 		(void) nwamd_object_release_and_destroy(object);
60211767SAnurag.Maskey@Sun.COM 	} else {
60311767SAnurag.Maskey@Sun.COM 		(void) nwamd_object_release(object);
60411767SAnurag.Maskey@Sun.COM 	}
60511767SAnurag.Maskey@Sun.COM }
60611767SAnurag.Maskey@Sun.COM 
60711767SAnurag.Maskey@Sun.COM /*
60811767SAnurag.Maskey@Sun.COM  * Determine whether an ENM should be (de)activated.
60911767SAnurag.Maskey@Sun.COM  */
61011767SAnurag.Maskey@Sun.COM /* ARGSUSED1 */
61111767SAnurag.Maskey@Sun.COM static int
nwamd_enm_check(nwamd_object_t object,void * data)61211767SAnurag.Maskey@Sun.COM nwamd_enm_check(nwamd_object_t object, void *data)
61311767SAnurag.Maskey@Sun.COM {
61411767SAnurag.Maskey@Sun.COM 	nwam_enm_handle_t enmh;
61511767SAnurag.Maskey@Sun.COM 	nwam_value_t conditionval;
61611767SAnurag.Maskey@Sun.COM 	int64_t eactivation;
61711767SAnurag.Maskey@Sun.COM 	boolean_t enabled, satisfied;
61811767SAnurag.Maskey@Sun.COM 	char **conditions;
61911767SAnurag.Maskey@Sun.COM 	nwam_state_t state;
62011767SAnurag.Maskey@Sun.COM 	uint_t nelem;
62111767SAnurag.Maskey@Sun.COM 
62211767SAnurag.Maskey@Sun.COM 	state = object->nwamd_object_state;
62311767SAnurag.Maskey@Sun.COM 
62411767SAnurag.Maskey@Sun.COM 	enmh = object->nwamd_object_handle;
62511767SAnurag.Maskey@Sun.COM 
62611767SAnurag.Maskey@Sun.COM 	eactivation = enm_get_activation_mode(enmh);
62711767SAnurag.Maskey@Sun.COM 	if (eactivation == -1)
62811767SAnurag.Maskey@Sun.COM 		return (0);
62911767SAnurag.Maskey@Sun.COM 
63011767SAnurag.Maskey@Sun.COM 	switch (eactivation) {
63111767SAnurag.Maskey@Sun.COM 	case NWAM_ACTIVATION_MODE_MANUAL:
63211767SAnurag.Maskey@Sun.COM 		enabled = enm_is_enabled(enmh);
63311767SAnurag.Maskey@Sun.COM 
63411767SAnurag.Maskey@Sun.COM 		if (enabled) {
63511767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_enm_check: %s is enabled",
63611767SAnurag.Maskey@Sun.COM 			    object->nwamd_object_name);
63711767SAnurag.Maskey@Sun.COM 			switch (state) {
63811767SAnurag.Maskey@Sun.COM 			case NWAM_STATE_ONLINE:
63911767SAnurag.Maskey@Sun.COM 			case NWAM_STATE_MAINTENANCE:
64011767SAnurag.Maskey@Sun.COM 				/* Do nothing */
64111767SAnurag.Maskey@Sun.COM 				break;
64211767SAnurag.Maskey@Sun.COM 			default:
64311767SAnurag.Maskey@Sun.COM 				if (nwamd_enm_action(object->nwamd_object_name,
64411767SAnurag.Maskey@Sun.COM 				    NWAM_ACTION_ENABLE) != 0) {
645*12923SRenee.Sommerfeld@Oracle.COM 					nlog(LOG_ERR, "nwamd_enm_check: "
646*12923SRenee.Sommerfeld@Oracle.COM 					    "enable failed for enm %s",
64711767SAnurag.Maskey@Sun.COM 					    object->nwamd_object_name);
64811767SAnurag.Maskey@Sun.COM 				}
64911767SAnurag.Maskey@Sun.COM 				break;
65011767SAnurag.Maskey@Sun.COM 			}
65111767SAnurag.Maskey@Sun.COM 		} else {
65211767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_enm_check: %s is disabled",
65311767SAnurag.Maskey@Sun.COM 			    object->nwamd_object_name);
65411767SAnurag.Maskey@Sun.COM 			switch (state) {
65511767SAnurag.Maskey@Sun.COM 			case NWAM_STATE_ONLINE:
65611767SAnurag.Maskey@Sun.COM 				if (nwamd_enm_action(object->nwamd_object_name,
65711767SAnurag.Maskey@Sun.COM 				    NWAM_ACTION_DISABLE) != 0) {
65811767SAnurag.Maskey@Sun.COM 					nlog(LOG_ERR, "nwamd_enm_check: "
65911767SAnurag.Maskey@Sun.COM 					    "disable failed for enm %s",
66011767SAnurag.Maskey@Sun.COM 					    object->nwamd_object_name);
66111767SAnurag.Maskey@Sun.COM 				}
66211767SAnurag.Maskey@Sun.COM 				break;
66311767SAnurag.Maskey@Sun.COM 			case NWAM_STATE_MAINTENANCE:
66411767SAnurag.Maskey@Sun.COM 				/* Do nothing */
66511767SAnurag.Maskey@Sun.COM 				break;
66611767SAnurag.Maskey@Sun.COM 			case NWAM_STATE_DISABLED:
66711767SAnurag.Maskey@Sun.COM 				/* Do nothing */
66811767SAnurag.Maskey@Sun.COM 				break;
66911767SAnurag.Maskey@Sun.COM 			default:
67011767SAnurag.Maskey@Sun.COM 				nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
67111767SAnurag.Maskey@Sun.COM 				    object->nwamd_object_name,
67211767SAnurag.Maskey@Sun.COM 				    NWAM_STATE_DISABLED,
67311767SAnurag.Maskey@Sun.COM 				    NWAM_AUX_STATE_MANUAL_DISABLE);
67411767SAnurag.Maskey@Sun.COM 				break;
67511767SAnurag.Maskey@Sun.COM 			}
67611767SAnurag.Maskey@Sun.COM 		}
67711767SAnurag.Maskey@Sun.COM 		break;
67811767SAnurag.Maskey@Sun.COM 
67911767SAnurag.Maskey@Sun.COM 	case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY:
68011767SAnurag.Maskey@Sun.COM 	case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL:
68111767SAnurag.Maskey@Sun.COM 		if (nwam_enm_get_prop_value(enmh,
68211767SAnurag.Maskey@Sun.COM 		    NWAM_ENM_PROP_CONDITIONS, &conditionval) != NWAM_SUCCESS) {
68311767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_check: could not retrieve "
68411767SAnurag.Maskey@Sun.COM 			    "condition value");
68511767SAnurag.Maskey@Sun.COM 			break;
68611767SAnurag.Maskey@Sun.COM 		}
68711767SAnurag.Maskey@Sun.COM 		if (nwam_value_get_string_array(conditionval,
68811767SAnurag.Maskey@Sun.COM 		    &conditions, &nelem) != NWAM_SUCCESS) {
68911767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_check: could not retrieve "
69011767SAnurag.Maskey@Sun.COM 			    "condition value");
69111767SAnurag.Maskey@Sun.COM 			nwam_value_free(conditionval);
69211767SAnurag.Maskey@Sun.COM 			break;
69311767SAnurag.Maskey@Sun.COM 		}
69411767SAnurag.Maskey@Sun.COM 		satisfied = nwamd_check_conditions((uint64_t)eactivation,
69511767SAnurag.Maskey@Sun.COM 		    conditions, nelem);
69611767SAnurag.Maskey@Sun.COM 
69711767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_enm_check: conditions for enm %s "
69811767SAnurag.Maskey@Sun.COM 		    "%s satisfied", object->nwamd_object_name,
69911767SAnurag.Maskey@Sun.COM 		    satisfied ? "is" : "is not");
70011767SAnurag.Maskey@Sun.COM 		if (state != NWAM_STATE_ONLINE && satisfied) {
70111767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
70211767SAnurag.Maskey@Sun.COM 			    object->nwamd_object_name,
70311767SAnurag.Maskey@Sun.COM 			    NWAM_STATE_OFFLINE_TO_ONLINE,
70411767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_METHOD_RUNNING);
70511767SAnurag.Maskey@Sun.COM 		}
70611767SAnurag.Maskey@Sun.COM 		if (state == NWAM_STATE_ONLINE && !satisfied) {
70711767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
70811767SAnurag.Maskey@Sun.COM 			    object->nwamd_object_name,
70911767SAnurag.Maskey@Sun.COM 			    NWAM_STATE_ONLINE_TO_OFFLINE,
71011767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_CONDITIONS_NOT_MET);
71111767SAnurag.Maskey@Sun.COM 		}
71211767SAnurag.Maskey@Sun.COM 		nwam_value_free(conditionval);
71311767SAnurag.Maskey@Sun.COM 		break;
71411767SAnurag.Maskey@Sun.COM 
71511767SAnurag.Maskey@Sun.COM 	}
71611767SAnurag.Maskey@Sun.COM 	return (0);
71711767SAnurag.Maskey@Sun.COM }
71811767SAnurag.Maskey@Sun.COM 
71911767SAnurag.Maskey@Sun.COM void
nwamd_enm_check_conditions(void)72011767SAnurag.Maskey@Sun.COM nwamd_enm_check_conditions(void)
72111767SAnurag.Maskey@Sun.COM {
72211767SAnurag.Maskey@Sun.COM 	(void) nwamd_walk_objects(NWAM_OBJECT_TYPE_ENM, nwamd_enm_check, NULL);
72311767SAnurag.Maskey@Sun.COM }
72411767SAnurag.Maskey@Sun.COM 
72511767SAnurag.Maskey@Sun.COM int
nwamd_enm_action(const char * enm,nwam_action_t action)72611767SAnurag.Maskey@Sun.COM nwamd_enm_action(const char *enm, nwam_action_t action)
72711767SAnurag.Maskey@Sun.COM {
72811767SAnurag.Maskey@Sun.COM 	nwamd_event_t event = nwamd_event_init_object_action
72911767SAnurag.Maskey@Sun.COM 	    (NWAM_OBJECT_TYPE_ENM, enm, NULL, action);
73011767SAnurag.Maskey@Sun.COM 	if (event == NULL)
73111767SAnurag.Maskey@Sun.COM 		return (1);
73211767SAnurag.Maskey@Sun.COM 	nwamd_event_enqueue(event);
73311767SAnurag.Maskey@Sun.COM 	return (0);
73411767SAnurag.Maskey@Sun.COM }
73511767SAnurag.Maskey@Sun.COM 
73611767SAnurag.Maskey@Sun.COM /*
73711767SAnurag.Maskey@Sun.COM  * Event handling functions.
73811767SAnurag.Maskey@Sun.COM  */
73911767SAnurag.Maskey@Sun.COM 
74011767SAnurag.Maskey@Sun.COM /* Handle ENM initialization/refresh event */
74111767SAnurag.Maskey@Sun.COM void
nwamd_enm_handle_init_event(nwamd_event_t event)74211767SAnurag.Maskey@Sun.COM nwamd_enm_handle_init_event(nwamd_event_t event)
74311767SAnurag.Maskey@Sun.COM {
74411767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
74511767SAnurag.Maskey@Sun.COM 	nwam_enm_handle_t enmh;
74611767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
74711767SAnurag.Maskey@Sun.COM 	boolean_t manual_disabled = B_FALSE;
74811767SAnurag.Maskey@Sun.COM 
74911767SAnurag.Maskey@Sun.COM 	if ((err = nwam_enm_read(event->event_object, 0, &enmh))
75011767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS) {
75111767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_enm_handle_init_event: could not "
75211767SAnurag.Maskey@Sun.COM 		    "read object '%s': %s", event->event_object,
75311767SAnurag.Maskey@Sun.COM 		    nwam_strerror(err));
75411767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
75511767SAnurag.Maskey@Sun.COM 		return;
75611767SAnurag.Maskey@Sun.COM 	}
75711767SAnurag.Maskey@Sun.COM 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM,
75811767SAnurag.Maskey@Sun.COM 	    event->event_object)) != NULL) {
75911767SAnurag.Maskey@Sun.COM 		nwam_enm_free(object->nwamd_object_handle);
76011767SAnurag.Maskey@Sun.COM 		object->nwamd_object_handle = enmh;
76111767SAnurag.Maskey@Sun.COM 	} else {
76211767SAnurag.Maskey@Sun.COM 		object = nwamd_object_init(NWAM_OBJECT_TYPE_ENM,
76311767SAnurag.Maskey@Sun.COM 		    event->event_object, enmh, NULL);
76411767SAnurag.Maskey@Sun.COM 		object->nwamd_object_state = NWAM_STATE_OFFLINE;
76511767SAnurag.Maskey@Sun.COM 		object->nwamd_object_aux_state =
76611767SAnurag.Maskey@Sun.COM 		    NWAM_AUX_STATE_CONDITIONS_NOT_MET;
76711767SAnurag.Maskey@Sun.COM 	}
76811994SAnurag.Maskey@Sun.COM 	/* (Re)set script time to now as the object has just been (re)read */
76911994SAnurag.Maskey@Sun.COM 	(void) gettimeofday(&object->nwamd_script_time, NULL);
77011994SAnurag.Maskey@Sun.COM 
77111767SAnurag.Maskey@Sun.COM 	manual_disabled = (enm_get_activation_mode(enmh) ==
77211767SAnurag.Maskey@Sun.COM 	    NWAM_ACTIVATION_MODE_MANUAL && !enm_is_enabled(enmh));
77311767SAnurag.Maskey@Sun.COM 
77411767SAnurag.Maskey@Sun.COM 	/*
77511767SAnurag.Maskey@Sun.COM 	 * If this ENM is ONLINE, and not manual and disabled (since in
77611767SAnurag.Maskey@Sun.COM 	 * that case it was online but we've just set enabled = false as part
77711767SAnurag.Maskey@Sun.COM 	 * of a disable action), then it is still active but refreshing.
77811767SAnurag.Maskey@Sun.COM 	 * Change states to re-activate itself.
77911767SAnurag.Maskey@Sun.COM 	 */
78011767SAnurag.Maskey@Sun.COM 	if (!manual_disabled &&
78111767SAnurag.Maskey@Sun.COM 	    object->nwamd_object_state == NWAM_STATE_ONLINE) {
78211767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
78311767SAnurag.Maskey@Sun.COM 		    event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE,
78411767SAnurag.Maskey@Sun.COM 		    NWAM_AUX_STATE_METHOD_RUNNING);
78511767SAnurag.Maskey@Sun.COM 	}
78611767SAnurag.Maskey@Sun.COM 	nwamd_object_release(object);
78711767SAnurag.Maskey@Sun.COM }
78811767SAnurag.Maskey@Sun.COM 
78911767SAnurag.Maskey@Sun.COM /* Handle ENM finish event */
79011767SAnurag.Maskey@Sun.COM void
nwamd_enm_handle_fini_event(nwamd_event_t event)79111767SAnurag.Maskey@Sun.COM nwamd_enm_handle_fini_event(nwamd_event_t event)
79211767SAnurag.Maskey@Sun.COM {
79311767SAnurag.Maskey@Sun.COM 	nwamd_event_t state_event;
79411767SAnurag.Maskey@Sun.COM 
79511767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_enm_handle_fini_event(%s)", event->event_object);
79611767SAnurag.Maskey@Sun.COM 
79711767SAnurag.Maskey@Sun.COM 	/*
79811767SAnurag.Maskey@Sun.COM 	 * Simulate a state event so that the state machine can correctly
79911767SAnurag.Maskey@Sun.COM 	 * deactivate the ENM and free up the handle.
80011767SAnurag.Maskey@Sun.COM 	 */
80111767SAnurag.Maskey@Sun.COM 	state_event = nwamd_event_init_object_state(NWAM_OBJECT_TYPE_ENM,
80211767SAnurag.Maskey@Sun.COM 	    event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
80311767SAnurag.Maskey@Sun.COM 	    NWAM_AUX_STATE_UNINITIALIZED);
80411767SAnurag.Maskey@Sun.COM 	if (state_event == NULL) {
80511767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
80611767SAnurag.Maskey@Sun.COM 		return;
80711767SAnurag.Maskey@Sun.COM 	}
80811767SAnurag.Maskey@Sun.COM 	nwamd_enm_handle_state_event(state_event);
80911767SAnurag.Maskey@Sun.COM 	nwamd_event_fini(state_event);
81011767SAnurag.Maskey@Sun.COM 	/*
81111767SAnurag.Maskey@Sun.COM 	 * Do not free the handle and object.
81211767SAnurag.Maskey@Sun.COM 	 * nwamd_enm_activate_deactivate_thread() and
81311767SAnurag.Maskey@Sun.COM 	 * nwamd_enm_deactivate() does this after running the stop script
81411767SAnurag.Maskey@Sun.COM 	 * and disabling the FMRI respectively.
81511767SAnurag.Maskey@Sun.COM 	 */
81611767SAnurag.Maskey@Sun.COM }
81711767SAnurag.Maskey@Sun.COM 
81811767SAnurag.Maskey@Sun.COM void
nwamd_enm_handle_action_event(nwamd_event_t event)81911767SAnurag.Maskey@Sun.COM nwamd_enm_handle_action_event(nwamd_event_t event)
82011767SAnurag.Maskey@Sun.COM {
82111767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
82211767SAnurag.Maskey@Sun.COM 
82311767SAnurag.Maskey@Sun.COM 	switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) {
82411767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_ENABLE:
82511767SAnurag.Maskey@Sun.COM 		object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM,
82611767SAnurag.Maskey@Sun.COM 		    event->event_object);
82711767SAnurag.Maskey@Sun.COM 		if (object == NULL) {
82811767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_handle_action_event: "
82911767SAnurag.Maskey@Sun.COM 			    "could not find enm %s", event->event_object);
83011767SAnurag.Maskey@Sun.COM 			nwamd_event_do_not_send(event);
83111767SAnurag.Maskey@Sun.COM 			return;
83211767SAnurag.Maskey@Sun.COM 		}
83311767SAnurag.Maskey@Sun.COM 		if (object->nwamd_object_state == NWAM_STATE_ONLINE) {
83411767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_enm_handle_action_event: "
83511767SAnurag.Maskey@Sun.COM 			    "enm %s already online, nothing to do",
83611767SAnurag.Maskey@Sun.COM 			    event->event_object);
83711767SAnurag.Maskey@Sun.COM 			nwamd_object_release(object);
83811767SAnurag.Maskey@Sun.COM 			return;
83911767SAnurag.Maskey@Sun.COM 		}
84011767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
84111767SAnurag.Maskey@Sun.COM 
84211767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
84311767SAnurag.Maskey@Sun.COM 		    event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE,
84411767SAnurag.Maskey@Sun.COM 		    NWAM_AUX_STATE_METHOD_RUNNING);
84511767SAnurag.Maskey@Sun.COM 		break;
84611767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_DISABLE:
84711767SAnurag.Maskey@Sun.COM 		object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM,
84811767SAnurag.Maskey@Sun.COM 		    event->event_object);
84911767SAnurag.Maskey@Sun.COM 		if (object == NULL) {
85011767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_enm_handle_action_event: "
85111767SAnurag.Maskey@Sun.COM 			    "could not find enm %s", event->event_object);
85211767SAnurag.Maskey@Sun.COM 			nwamd_event_do_not_send(event);
85311767SAnurag.Maskey@Sun.COM 			return;
85411767SAnurag.Maskey@Sun.COM 		}
85511767SAnurag.Maskey@Sun.COM 		if (object->nwamd_object_state == NWAM_STATE_DISABLED) {
85611767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_enm_handle_action_event: "
85711767SAnurag.Maskey@Sun.COM 			    "enm %s already disabled, nothing to do",
85811767SAnurag.Maskey@Sun.COM 			    event->event_object);
85911767SAnurag.Maskey@Sun.COM 			nwamd_object_release(object);
86011767SAnurag.Maskey@Sun.COM 			return;
86111767SAnurag.Maskey@Sun.COM 		}
86211767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
86311767SAnurag.Maskey@Sun.COM 
86411767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM,
86511767SAnurag.Maskey@Sun.COM 		    event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
86611767SAnurag.Maskey@Sun.COM 		    NWAM_AUX_STATE_MANUAL_DISABLE);
86711767SAnurag.Maskey@Sun.COM 		break;
86811767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_ADD:
86911767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_REFRESH:
87011767SAnurag.Maskey@Sun.COM 		nwamd_enm_handle_init_event(event);
87111767SAnurag.Maskey@Sun.COM 		break;
87211767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_DESTROY:
87311767SAnurag.Maskey@Sun.COM 		nwamd_enm_handle_fini_event(event);
87411767SAnurag.Maskey@Sun.COM 		break;
87511767SAnurag.Maskey@Sun.COM 	default:
87611767SAnurag.Maskey@Sun.COM 		nlog(LOG_INFO, "nwam_enm_handle_action_event: "
87711767SAnurag.Maskey@Sun.COM 		    "unexpected action");
87811767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
87911767SAnurag.Maskey@Sun.COM 		break;
88011767SAnurag.Maskey@Sun.COM 	}
88111767SAnurag.Maskey@Sun.COM }
88211767SAnurag.Maskey@Sun.COM 
88311767SAnurag.Maskey@Sun.COM void
nwamd_enm_handle_state_event(nwamd_event_t event)88411767SAnurag.Maskey@Sun.COM nwamd_enm_handle_state_event(nwamd_event_t event)
88511767SAnurag.Maskey@Sun.COM {
88611767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
88711767SAnurag.Maskey@Sun.COM 	nwam_state_t new_state;
88811767SAnurag.Maskey@Sun.COM 	nwam_aux_state_t new_aux_state;
88911767SAnurag.Maskey@Sun.COM 
89011767SAnurag.Maskey@Sun.COM 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_ENM,
89111767SAnurag.Maskey@Sun.COM 	    event->event_object)) == NULL) {
892*12923SRenee.Sommerfeld@Oracle.COM 		nlog(LOG_INFO, "nwamd_enm_handle_state_event: "
893*12923SRenee.Sommerfeld@Oracle.COM 		    "state event for nonexistent enm %s", event->event_object);
89411767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
89511767SAnurag.Maskey@Sun.COM 		return;
89611767SAnurag.Maskey@Sun.COM 	}
89711767SAnurag.Maskey@Sun.COM 	new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state;
89811767SAnurag.Maskey@Sun.COM 	new_aux_state =
89911767SAnurag.Maskey@Sun.COM 	    event->event_msg->nwe_data.nwe_object_state.nwe_aux_state;
90011767SAnurag.Maskey@Sun.COM 
90111767SAnurag.Maskey@Sun.COM 	if (new_state == object->nwamd_object_state &&
90211767SAnurag.Maskey@Sun.COM 	    new_aux_state == object->nwamd_object_aux_state) {
90311767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_enm_handle_state_event: "
904*12923SRenee.Sommerfeld@Oracle.COM 		    "enm %s already in state (%s , %s)",
90511767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name, nwam_state_to_string(new_state),
90611767SAnurag.Maskey@Sun.COM 		    nwam_aux_state_to_string(new_aux_state));
90711767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
90811767SAnurag.Maskey@Sun.COM 		return;
90911767SAnurag.Maskey@Sun.COM 	}
91011767SAnurag.Maskey@Sun.COM 
91111767SAnurag.Maskey@Sun.COM 	object->nwamd_object_state = new_state;
91211767SAnurag.Maskey@Sun.COM 	object->nwamd_object_aux_state = new_aux_state;
91311767SAnurag.Maskey@Sun.COM 
914*12923SRenee.Sommerfeld@Oracle.COM 	nlog(LOG_DEBUG, "nwamd_enm_handle_state_event: changing state for enm "
91511767SAnurag.Maskey@Sun.COM 	    "%s to (%s , %s)", object->nwamd_object_name,
91611767SAnurag.Maskey@Sun.COM 	    nwam_state_to_string(object->nwamd_object_state),
91711767SAnurag.Maskey@Sun.COM 	    nwam_aux_state_to_string(object->nwamd_object_aux_state));
91811767SAnurag.Maskey@Sun.COM 
91911767SAnurag.Maskey@Sun.COM 	nwamd_object_release(object);
92011767SAnurag.Maskey@Sun.COM 
92111767SAnurag.Maskey@Sun.COM 	/*
92211767SAnurag.Maskey@Sun.COM 	 * State machine for ENMs.
92311767SAnurag.Maskey@Sun.COM 	 */
92411767SAnurag.Maskey@Sun.COM 	switch (new_state) {
92511767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_OFFLINE_TO_ONLINE:
92611767SAnurag.Maskey@Sun.COM 		nwamd_enm_activate(event->event_object);
92711767SAnurag.Maskey@Sun.COM 		break;
92811767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_ONLINE_TO_OFFLINE:
92911767SAnurag.Maskey@Sun.COM 		nwamd_enm_deactivate(event->event_object);
93011767SAnurag.Maskey@Sun.COM 		break;
93111767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_DISABLED:
93211767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_OFFLINE:
93311767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_UNINITIALIZED:
93411767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_MAINTENANCE:
93511767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_DEGRADED:
93611767SAnurag.Maskey@Sun.COM 	default:
93711767SAnurag.Maskey@Sun.COM 		/* do nothing */
93811767SAnurag.Maskey@Sun.COM 		break;
93911767SAnurag.Maskey@Sun.COM 	}
94011767SAnurag.Maskey@Sun.COM }
941