xref: /onnv-gate/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c (revision 12953:7a5c324190b8)
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 /*
2312371SAnurag.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 <assert.h>
2811767SAnurag.Maskey@Sun.COM #include <libdlaggr.h>
2911767SAnurag.Maskey@Sun.COM #include <libdllink.h>
3011767SAnurag.Maskey@Sun.COM #include <libdlstat.h>
3111767SAnurag.Maskey@Sun.COM #include <libnwam.h>
3211767SAnurag.Maskey@Sun.COM #include <libscf.h>
3311767SAnurag.Maskey@Sun.COM #include <netinet/in.h>
3411767SAnurag.Maskey@Sun.COM #include <stdlib.h>
3511767SAnurag.Maskey@Sun.COM #include <strings.h>
3611767SAnurag.Maskey@Sun.COM #include <sys/socket.h>
3711767SAnurag.Maskey@Sun.COM #include <sys/time.h>
3811767SAnurag.Maskey@Sun.COM #include <sys/types.h>
3911767SAnurag.Maskey@Sun.COM #include <values.h>
40*12953SRishi.Srivatsavai@Sun.COM #include <zone.h>
4111767SAnurag.Maskey@Sun.COM 
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 "ncp.h"
4611767SAnurag.Maskey@Sun.COM #include "util.h"
4711767SAnurag.Maskey@Sun.COM 
4811767SAnurag.Maskey@Sun.COM /*
4911767SAnurag.Maskey@Sun.COM  * ncu.c - handles various NCU tasks - intialization/refresh, state machine
5011767SAnurag.Maskey@Sun.COM  * for NCUs etc.
5111767SAnurag.Maskey@Sun.COM  */
5211767SAnurag.Maskey@Sun.COM 
5311767SAnurag.Maskey@Sun.COM #define	VBOX_IFACE_PREFIX	"vboxnet"
5411767SAnurag.Maskey@Sun.COM 
5512576SAnurag.Maskey@Oracle.COM static void populate_ip_ncu_properties(nwam_ncu_handle_t, nwamd_ncu_t *);
5612576SAnurag.Maskey@Oracle.COM 
5711767SAnurag.Maskey@Sun.COM /*
5811767SAnurag.Maskey@Sun.COM  * Find ncu of specified type for link/interface name.
5911767SAnurag.Maskey@Sun.COM  */
6011767SAnurag.Maskey@Sun.COM nwamd_object_t
nwamd_ncu_object_find(nwam_ncu_type_t type,const char * name)6111767SAnurag.Maskey@Sun.COM nwamd_ncu_object_find(nwam_ncu_type_t type, const char *name)
6211767SAnurag.Maskey@Sun.COM {
6311767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
6411767SAnurag.Maskey@Sun.COM 	char *object_name;
6511767SAnurag.Maskey@Sun.COM 	nwamd_object_t ncu_obj = NULL;
6611767SAnurag.Maskey@Sun.COM 
6711767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_name_to_typed_name(name, type, &object_name))
6811767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS) {
6911767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_ncu_find: nwam_ncu_name_to_typed_name "
7011767SAnurag.Maskey@Sun.COM 		    "returned %s", nwam_strerror(err));
7111767SAnurag.Maskey@Sun.COM 		return (NULL);
7211767SAnurag.Maskey@Sun.COM 	}
7311767SAnurag.Maskey@Sun.COM 	ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name);
7411767SAnurag.Maskey@Sun.COM 
7511767SAnurag.Maskey@Sun.COM 	free(object_name);
7611767SAnurag.Maskey@Sun.COM 	return (ncu_obj);
7711767SAnurag.Maskey@Sun.COM }
7811767SAnurag.Maskey@Sun.COM 
7911767SAnurag.Maskey@Sun.COM nwam_error_t
nwamd_set_ncu_string(nwam_ncu_handle_t ncuh,char ** strval,uint_t cnt,const char * prop)8011767SAnurag.Maskey@Sun.COM nwamd_set_ncu_string(nwam_ncu_handle_t ncuh, char **strval, uint_t cnt,
8111767SAnurag.Maskey@Sun.COM     const char *prop)
8211767SAnurag.Maskey@Sun.COM {
8311767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
8411767SAnurag.Maskey@Sun.COM 	nwam_value_t val;
8511767SAnurag.Maskey@Sun.COM 
8611767SAnurag.Maskey@Sun.COM 	if ((err = nwam_value_create_string_array(strval, cnt, &val))
8711767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS)
8811767SAnurag.Maskey@Sun.COM 		return (err);
8911767SAnurag.Maskey@Sun.COM 	err = nwam_ncu_set_prop_value(ncuh, prop, val);
9011767SAnurag.Maskey@Sun.COM 	nwam_value_free(val);
9111767SAnurag.Maskey@Sun.COM 	return (err);
9211767SAnurag.Maskey@Sun.COM }
9311767SAnurag.Maskey@Sun.COM 
9411767SAnurag.Maskey@Sun.COM nwam_error_t
nwamd_set_ncu_uint(nwam_ncu_handle_t ncuh,uint64_t * uintval,uint_t cnt,const char * prop)9511767SAnurag.Maskey@Sun.COM nwamd_set_ncu_uint(nwam_ncu_handle_t ncuh, uint64_t *uintval, uint_t cnt,
9611767SAnurag.Maskey@Sun.COM     const char *prop)
9711767SAnurag.Maskey@Sun.COM {
9811767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
9911767SAnurag.Maskey@Sun.COM 	nwam_value_t val;
10011767SAnurag.Maskey@Sun.COM 
10111767SAnurag.Maskey@Sun.COM 	if ((err = nwam_value_create_uint64_array(uintval, cnt, &val))
10211767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS)
10311767SAnurag.Maskey@Sun.COM 		return (err);
10411767SAnurag.Maskey@Sun.COM 	err = nwam_ncu_set_prop_value(ncuh, prop, val);
10511767SAnurag.Maskey@Sun.COM 	nwam_value_free(val);
10611767SAnurag.Maskey@Sun.COM 	return (err);
10711767SAnurag.Maskey@Sun.COM }
10811767SAnurag.Maskey@Sun.COM 
10911767SAnurag.Maskey@Sun.COM nwam_error_t
nwamd_get_ncu_string(nwam_ncu_handle_t ncuh,nwam_value_t * val,char *** strval,uint_t * cnt,const char * prop)11011767SAnurag.Maskey@Sun.COM nwamd_get_ncu_string(nwam_ncu_handle_t ncuh, nwam_value_t *val, char ***strval,
11111767SAnurag.Maskey@Sun.COM     uint_t *cnt, const char *prop)
11211767SAnurag.Maskey@Sun.COM {
11311767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
11411767SAnurag.Maskey@Sun.COM 
11511767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS)
11611767SAnurag.Maskey@Sun.COM 		return (err);
11711767SAnurag.Maskey@Sun.COM 	return (nwam_value_get_string_array(*val, strval, cnt));
11811767SAnurag.Maskey@Sun.COM }
11911767SAnurag.Maskey@Sun.COM 
12011767SAnurag.Maskey@Sun.COM nwam_error_t
nwamd_get_ncu_uint(nwam_ncu_handle_t ncuh,nwam_value_t * val,uint64_t ** uintval,uint_t * cnt,const char * prop)12111767SAnurag.Maskey@Sun.COM nwamd_get_ncu_uint(nwam_ncu_handle_t ncuh, nwam_value_t *val,
12211767SAnurag.Maskey@Sun.COM     uint64_t **uintval, uint_t *cnt, const char *prop)
12311767SAnurag.Maskey@Sun.COM {
12411767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
12511767SAnurag.Maskey@Sun.COM 
12611767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS)
12711767SAnurag.Maskey@Sun.COM 		return (err);
12811767SAnurag.Maskey@Sun.COM 	return (nwam_value_get_uint64_array(*val, uintval, cnt));
12911767SAnurag.Maskey@Sun.COM }
13011767SAnurag.Maskey@Sun.COM 
13111767SAnurag.Maskey@Sun.COM /*
13211767SAnurag.Maskey@Sun.COM  * Run link/interface state machine in response to a state change
13311767SAnurag.Maskey@Sun.COM  * or enable/disable action event.
13411767SAnurag.Maskey@Sun.COM  */
13511767SAnurag.Maskey@Sun.COM static void
nwamd_ncu_state_machine(const char * object_name)13611767SAnurag.Maskey@Sun.COM nwamd_ncu_state_machine(const char *object_name)
13711767SAnurag.Maskey@Sun.COM {
13811767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
13911767SAnurag.Maskey@Sun.COM 	nwamd_ncu_t *ncu;
14011767SAnurag.Maskey@Sun.COM 	link_state_t link_state;
14111767SAnurag.Maskey@Sun.COM 	nwamd_event_t event;
14211767SAnurag.Maskey@Sun.COM 	nwam_wlan_t key_wlan, connected_wlan;
14311767SAnurag.Maskey@Sun.COM 	nwamd_link_t *link;
14411767SAnurag.Maskey@Sun.COM 	char linkname[NWAM_MAX_NAME_LEN];
14511767SAnurag.Maskey@Sun.COM 	boolean_t up;
14611767SAnurag.Maskey@Sun.COM 
14711767SAnurag.Maskey@Sun.COM 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name))
14811767SAnurag.Maskey@Sun.COM 	    == NULL) {
14911767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_ncu_state_machine: "
15011767SAnurag.Maskey@Sun.COM 		    "request for nonexistent NCU %s", object_name);
15111767SAnurag.Maskey@Sun.COM 		return;
15211767SAnurag.Maskey@Sun.COM 	}
15311767SAnurag.Maskey@Sun.COM 
15411767SAnurag.Maskey@Sun.COM 	ncu = object->nwamd_object_data;
15512576SAnurag.Maskey@Oracle.COM 	link = &ncu->ncu_link;
15611767SAnurag.Maskey@Sun.COM 
15711767SAnurag.Maskey@Sun.COM 	switch (object->nwamd_object_aux_state) {
15811767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_INITIALIZED:
15911767SAnurag.Maskey@Sun.COM 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
16011767SAnurag.Maskey@Sun.COM 			/*
16111767SAnurag.Maskey@Sun.COM 			 * For wired/wireless links, need to get link
16211767SAnurag.Maskey@Sun.COM 			 * up/down events and even if these are not supported,
16311767SAnurag.Maskey@Sun.COM 			 * dlpi_open()ing the link prevents the driver from
16411767SAnurag.Maskey@Sun.COM 			 * being unloaded.
16511767SAnurag.Maskey@Sun.COM 			 */
16611767SAnurag.Maskey@Sun.COM 			nwamd_dlpi_add_link(object);
16711767SAnurag.Maskey@Sun.COM 
16811767SAnurag.Maskey@Sun.COM 			if (link->nwamd_link_media == DL_WIFI) {
16911767SAnurag.Maskey@Sun.COM 				/*
17011767SAnurag.Maskey@Sun.COM 				 * First, if we're unexpectedly connected,
17111767SAnurag.Maskey@Sun.COM 				 * disconnect.
17211767SAnurag.Maskey@Sun.COM 				 */
17311767SAnurag.Maskey@Sun.COM 				if (!link->nwamd_link_wifi_connected &&
17411767SAnurag.Maskey@Sun.COM 				    nwamd_wlan_connected(object)) {
17511767SAnurag.Maskey@Sun.COM 					nlog(LOG_DEBUG,
17611767SAnurag.Maskey@Sun.COM 					    "nwamd_ncu_state_machine: "
17711767SAnurag.Maskey@Sun.COM 					    "WiFi unexpectedly connected, "
17811767SAnurag.Maskey@Sun.COM 					    "disconnecting...");
17911767SAnurag.Maskey@Sun.COM 					(void) dladm_wlan_disconnect(dld_handle,
18011767SAnurag.Maskey@Sun.COM 					    link->nwamd_link_id);
18111767SAnurag.Maskey@Sun.COM 					nwamd_set_selected_connected(ncu,
18211767SAnurag.Maskey@Sun.COM 					    B_FALSE, B_FALSE);
18311767SAnurag.Maskey@Sun.COM 				}
18411767SAnurag.Maskey@Sun.COM 				/* move to scanning aux state */
18511767SAnurag.Maskey@Sun.COM 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
18611767SAnurag.Maskey@Sun.COM 				    object_name, object->nwamd_object_state,
18711767SAnurag.Maskey@Sun.COM 				    NWAM_AUX_STATE_LINK_WIFI_SCANNING);
18811767SAnurag.Maskey@Sun.COM 			} else {
18911767SAnurag.Maskey@Sun.COM 				/*
19011767SAnurag.Maskey@Sun.COM 				 * If initial wired link state is unknown, we
19111767SAnurag.Maskey@Sun.COM 				 * will need to assume the link is up, since
19211767SAnurag.Maskey@Sun.COM 				 * we won´t get DL_NOTE_LINK_UP/DOWN events.
19311767SAnurag.Maskey@Sun.COM 				 */
19411767SAnurag.Maskey@Sun.COM 				link_state = nwamd_get_link_state
19511767SAnurag.Maskey@Sun.COM 				    (ncu->ncu_name);
19611767SAnurag.Maskey@Sun.COM 				if (link_state == LINK_STATE_UP ||
19711767SAnurag.Maskey@Sun.COM 				    link_state == LINK_STATE_UNKNOWN) {
19811767SAnurag.Maskey@Sun.COM 					nwamd_object_set_state
19911767SAnurag.Maskey@Sun.COM 					    (NWAM_OBJECT_TYPE_NCU,
20011767SAnurag.Maskey@Sun.COM 					    object_name, NWAM_STATE_ONLINE,
20111767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_UP);
20211767SAnurag.Maskey@Sun.COM 				} else {
20311767SAnurag.Maskey@Sun.COM 					nwamd_object_set_state
20411767SAnurag.Maskey@Sun.COM 					    (NWAM_OBJECT_TYPE_NCU,
20511767SAnurag.Maskey@Sun.COM 					    object_name,
20611767SAnurag.Maskey@Sun.COM 					    NWAM_STATE_ONLINE_TO_OFFLINE,
20711767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_DOWN);
20811767SAnurag.Maskey@Sun.COM 				}
20911767SAnurag.Maskey@Sun.COM 			}
21011767SAnurag.Maskey@Sun.COM 		} else {
21111767SAnurag.Maskey@Sun.COM 			/*
21211767SAnurag.Maskey@Sun.COM 			 * In the current implementation, initialization has to
21311767SAnurag.Maskey@Sun.COM 			 * start from scratch since the complexity of minimizing
21411767SAnurag.Maskey@Sun.COM 			 * configuration change is considerable (e.g. if we
21511767SAnurag.Maskey@Sun.COM 			 * refresh and had DHCP running on the physical
21611767SAnurag.Maskey@Sun.COM 			 * interface, and now have changed to static assignment,
21711767SAnurag.Maskey@Sun.COM 			 * we need to remove DHCP etc).  To avoid all this,
21811767SAnurag.Maskey@Sun.COM 			 * unplumb before re-plumbing the protocols and
21911767SAnurag.Maskey@Sun.COM 			 * addresses we wish to configure.  In the future, it
22011767SAnurag.Maskey@Sun.COM 			 * would be good to try and minimize configuration
22111767SAnurag.Maskey@Sun.COM 			 * changes.
22211767SAnurag.Maskey@Sun.COM 			 */
22312576SAnurag.Maskey@Oracle.COM 			nwamd_unplumb_interface(ncu, AF_INET);
22412576SAnurag.Maskey@Oracle.COM 			nwamd_unplumb_interface(ncu, AF_INET6);
22512576SAnurag.Maskey@Oracle.COM 
22612576SAnurag.Maskey@Oracle.COM 			/*
22712576SAnurag.Maskey@Oracle.COM 			 * We may be restarting the state machine.  Re-read
22812576SAnurag.Maskey@Oracle.COM 			 * the IP NCU properties as the ipadm_addrobj_t in
22912576SAnurag.Maskey@Oracle.COM 			 * nwamd_if_address should not be reused.
23012576SAnurag.Maskey@Oracle.COM 			 */
23112576SAnurag.Maskey@Oracle.COM 			populate_ip_ncu_properties(object->nwamd_object_handle,
23212576SAnurag.Maskey@Oracle.COM 			    ncu);
23311767SAnurag.Maskey@Sun.COM 
23411767SAnurag.Maskey@Sun.COM 			/*
23511767SAnurag.Maskey@Sun.COM 			 * Enqueue a WAITING_FOR_ADDR aux state change so that
23611767SAnurag.Maskey@Sun.COM 			 * we are eligible to receive the IF_STATE events
23711767SAnurag.Maskey@Sun.COM 			 * associated with static, DHCP, DHCPv6 and autoconf
23811767SAnurag.Maskey@Sun.COM 			 * address assignment.  The latter two can happen
23911767SAnurag.Maskey@Sun.COM 			 * quite quickly after plumbing so we need to be ready.
24011767SAnurag.Maskey@Sun.COM 			 */
24111767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
24211767SAnurag.Maskey@Sun.COM 			    object_name, NWAM_STATE_OFFLINE_TO_ONLINE,
24311767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_IF_WAITING_FOR_ADDR);
24411767SAnurag.Maskey@Sun.COM 
24512576SAnurag.Maskey@Oracle.COM 			if (ncu->ncu_if.nwamd_if_ipv4)
24612576SAnurag.Maskey@Oracle.COM 				nwamd_plumb_interface(ncu, AF_INET);
24711767SAnurag.Maskey@Sun.COM 
24812576SAnurag.Maskey@Oracle.COM 			if (ncu->ncu_if.nwamd_if_ipv6)
24912576SAnurag.Maskey@Oracle.COM 				nwamd_plumb_interface(ncu, AF_INET6);
25012576SAnurag.Maskey@Oracle.COM 
25112576SAnurag.Maskey@Oracle.COM 			/* Configure addresses */
25211767SAnurag.Maskey@Sun.COM 			nwamd_configure_interface_addresses(ncu);
25311767SAnurag.Maskey@Sun.COM 		}
25411767SAnurag.Maskey@Sun.COM 		break;
25511767SAnurag.Maskey@Sun.COM 
25611767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_IF_DHCP_TIMED_OUT:
25711767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_IF_WAITING_FOR_ADDR:
25811767SAnurag.Maskey@Sun.COM 		/*
25911767SAnurag.Maskey@Sun.COM 		 * nothing to do here - RTM_NEWADDRs will trigger IF_STATE
26011767SAnurag.Maskey@Sun.COM 		 * events to move us online.
26111767SAnurag.Maskey@Sun.COM 		 */
26211767SAnurag.Maskey@Sun.COM 		break;
26311767SAnurag.Maskey@Sun.COM 
26411767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_LINK_WIFI_SCANNING:
26511767SAnurag.Maskey@Sun.COM 		/* launch scan thread */
26611767SAnurag.Maskey@Sun.COM 		(void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
26711767SAnurag.Maskey@Sun.COM 		(void) nwamd_wlan_scan(linkname);
26811767SAnurag.Maskey@Sun.COM 		/* Create periodic scan event */
26911767SAnurag.Maskey@Sun.COM 		nwamd_ncu_create_periodic_scan_event(object);
27011767SAnurag.Maskey@Sun.COM 		break;
27111767SAnurag.Maskey@Sun.COM 
27211767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION:
27311767SAnurag.Maskey@Sun.COM 		/* send "need choice" event */
27411767SAnurag.Maskey@Sun.COM 		event = nwamd_event_init_wlan
27511767SAnurag.Maskey@Sun.COM 		    (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_CHOICE, B_FALSE,
27611767SAnurag.Maskey@Sun.COM 		    link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr,
27711767SAnurag.Maskey@Sun.COM 		    link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num);
27811767SAnurag.Maskey@Sun.COM 		if (event == NULL)
27911767SAnurag.Maskey@Sun.COM 			break;
28011767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue(event);
28111767SAnurag.Maskey@Sun.COM 		nwamd_set_selected_connected(ncu, B_FALSE, B_FALSE);
28211767SAnurag.Maskey@Sun.COM 		break;
28311767SAnurag.Maskey@Sun.COM 
28411767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_LINK_WIFI_NEED_KEY:
28511767SAnurag.Maskey@Sun.COM 		/*
28611767SAnurag.Maskey@Sun.COM 		 * Send "need key" event.  Set selected to true, connected
28711767SAnurag.Maskey@Sun.COM 		 * and have_key to false.  Do not fill in WLAN details as
28811767SAnurag.Maskey@Sun.COM 		 * multiple WLANs may match the ESSID name, and each may
28911767SAnurag.Maskey@Sun.COM 		 * have a different speed and channel.
29011767SAnurag.Maskey@Sun.COM 		 */
29111767SAnurag.Maskey@Sun.COM 		bzero(&key_wlan, sizeof (key_wlan));
29211767SAnurag.Maskey@Sun.COM 		(void) strlcpy(key_wlan.nww_essid, link->nwamd_link_wifi_essid,
29311767SAnurag.Maskey@Sun.COM 		    sizeof (key_wlan.nww_essid));
29411767SAnurag.Maskey@Sun.COM 		(void) strlcpy(key_wlan.nww_bssid, link->nwamd_link_wifi_bssid,
29511767SAnurag.Maskey@Sun.COM 		    sizeof (key_wlan.nww_bssid));
29611767SAnurag.Maskey@Sun.COM 		key_wlan.nww_security_mode =
29711767SAnurag.Maskey@Sun.COM 		    link->nwamd_link_wifi_security_mode;
29811767SAnurag.Maskey@Sun.COM 		key_wlan.nww_selected = B_TRUE;
29911767SAnurag.Maskey@Sun.COM 		key_wlan.nww_connected = B_FALSE;
30011767SAnurag.Maskey@Sun.COM 		key_wlan.nww_have_key = B_FALSE;
30111767SAnurag.Maskey@Sun.COM 		event = nwamd_event_init_wlan
30211767SAnurag.Maskey@Sun.COM 		    (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_KEY, B_FALSE,
30311767SAnurag.Maskey@Sun.COM 		    &key_wlan, 1);
30411767SAnurag.Maskey@Sun.COM 		if (event == NULL)
30511767SAnurag.Maskey@Sun.COM 			break;
30611767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue(event);
30711767SAnurag.Maskey@Sun.COM 		break;
30811767SAnurag.Maskey@Sun.COM 
30911767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_LINK_WIFI_CONNECTING:
31011767SAnurag.Maskey@Sun.COM 		(void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
31111767SAnurag.Maskey@Sun.COM 		nwamd_wlan_connect(linkname);
31211767SAnurag.Maskey@Sun.COM 		break;
31311767SAnurag.Maskey@Sun.COM 
31411767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_UP:
31511767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_DOWN:
31611767SAnurag.Maskey@Sun.COM 		up = (object->nwamd_object_aux_state == NWAM_AUX_STATE_UP);
31711767SAnurag.Maskey@Sun.COM 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
31811767SAnurag.Maskey@Sun.COM 			if (link->nwamd_link_media == DL_WIFI) {
31911767SAnurag.Maskey@Sun.COM 				/*
32011767SAnurag.Maskey@Sun.COM 				 * Connected/disconnected - send WLAN
32111767SAnurag.Maskey@Sun.COM 				 * connection report.
32211767SAnurag.Maskey@Sun.COM 				 */
32311767SAnurag.Maskey@Sun.COM 				link->nwamd_link_wifi_connected = up;
32411767SAnurag.Maskey@Sun.COM 				nwamd_set_selected_connected(ncu, B_TRUE, up);
32511767SAnurag.Maskey@Sun.COM 
32611767SAnurag.Maskey@Sun.COM 				(void) strlcpy(connected_wlan.nww_essid,
32711767SAnurag.Maskey@Sun.COM 				    link->nwamd_link_wifi_essid,
32811767SAnurag.Maskey@Sun.COM 				    sizeof (connected_wlan.nww_essid));
32911767SAnurag.Maskey@Sun.COM 				(void) strlcpy(connected_wlan.nww_bssid,
33011767SAnurag.Maskey@Sun.COM 				    link->nwamd_link_wifi_bssid,
33111767SAnurag.Maskey@Sun.COM 				    sizeof (connected_wlan.nww_bssid));
33211767SAnurag.Maskey@Sun.COM 				connected_wlan.nww_security_mode =
33311767SAnurag.Maskey@Sun.COM 				    link->nwamd_link_wifi_security_mode;
33411767SAnurag.Maskey@Sun.COM 				event = nwamd_event_init_wlan
33511767SAnurag.Maskey@Sun.COM 				    (ncu->ncu_name,
33611767SAnurag.Maskey@Sun.COM 				    NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT, up,
33711767SAnurag.Maskey@Sun.COM 				    &connected_wlan, 1);
33811767SAnurag.Maskey@Sun.COM 				if (event == NULL)
33911767SAnurag.Maskey@Sun.COM 					break;
34011767SAnurag.Maskey@Sun.COM 				nwamd_event_enqueue(event);
34111767SAnurag.Maskey@Sun.COM 
34211767SAnurag.Maskey@Sun.COM 				/*
34311767SAnurag.Maskey@Sun.COM 				 * If disconnected, restart the state machine
34411767SAnurag.Maskey@Sun.COM 				 * for the WiFi link (WiFi is always trying
34511767SAnurag.Maskey@Sun.COM 				 * to connect).
34611767SAnurag.Maskey@Sun.COM 				 *
34711767SAnurag.Maskey@Sun.COM 				 * If connected, start signal strength
34811767SAnurag.Maskey@Sun.COM 				 * monitoring thread.
34911767SAnurag.Maskey@Sun.COM 				 */
35011767SAnurag.Maskey@Sun.COM 				if (!up && ncu->ncu_enabled) {
35111767SAnurag.Maskey@Sun.COM 					nlog(LOG_DEBUG,
35211767SAnurag.Maskey@Sun.COM 					    "nwamd_ncu_state_machine: "
35311767SAnurag.Maskey@Sun.COM 					    "wifi disconnect - start over "
35411767SAnurag.Maskey@Sun.COM 					    "after %dsec interval",
35511767SAnurag.Maskey@Sun.COM 					    WIRELESS_RETRY_INTERVAL);
35611767SAnurag.Maskey@Sun.COM 					link->nwamd_link_wifi_connected =
35711767SAnurag.Maskey@Sun.COM 					    B_FALSE;
35811767SAnurag.Maskey@Sun.COM 					/* propogate down event to IP NCU */
35911767SAnurag.Maskey@Sun.COM 					nwamd_propogate_link_up_down_to_ip
36011767SAnurag.Maskey@Sun.COM 					    (ncu->ncu_name, B_FALSE);
36111767SAnurag.Maskey@Sun.COM 					nwamd_object_set_state_timed
36211767SAnurag.Maskey@Sun.COM 					    (NWAM_OBJECT_TYPE_NCU, object_name,
36311767SAnurag.Maskey@Sun.COM 					    NWAM_STATE_OFFLINE_TO_ONLINE,
36411767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_INITIALIZED,
36511767SAnurag.Maskey@Sun.COM 					    WIRELESS_RETRY_INTERVAL);
36611767SAnurag.Maskey@Sun.COM 				} else {
36711767SAnurag.Maskey@Sun.COM 					nlog(LOG_DEBUG,
36811767SAnurag.Maskey@Sun.COM 					    "nwamd_ncu_state_machine: "
36911767SAnurag.Maskey@Sun.COM 					    "wifi connected, start monitoring");
37011767SAnurag.Maskey@Sun.COM 					(void) strlcpy(linkname, ncu->ncu_name,
37111767SAnurag.Maskey@Sun.COM 					    sizeof (linkname));
37211767SAnurag.Maskey@Sun.COM 					nwamd_wlan_monitor_signal(linkname);
37311767SAnurag.Maskey@Sun.COM 				}
37411767SAnurag.Maskey@Sun.COM 			}
37511767SAnurag.Maskey@Sun.COM 		}
37611767SAnurag.Maskey@Sun.COM 
37711767SAnurag.Maskey@Sun.COM 		/* If not in ONLINE/OFFLINE state yet, change state */
37811767SAnurag.Maskey@Sun.COM 		if ((up && object->nwamd_object_state != NWAM_STATE_ONLINE) ||
37911767SAnurag.Maskey@Sun.COM 		    (!up && object->nwamd_object_state != NWAM_STATE_OFFLINE)) {
38011767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_ncu_state_machine: "
38111767SAnurag.Maskey@Sun.COM 			    "%s is moving %s", object_name,
38211767SAnurag.Maskey@Sun.COM 			    up ? "online" : "offline");
38311767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
38411767SAnurag.Maskey@Sun.COM 			    object_name,
38511767SAnurag.Maskey@Sun.COM 			    up ? NWAM_STATE_ONLINE : NWAM_STATE_OFFLINE,
38611767SAnurag.Maskey@Sun.COM 			    up ? NWAM_AUX_STATE_UP : NWAM_AUX_STATE_DOWN);
38711767SAnurag.Maskey@Sun.COM 
38811767SAnurag.Maskey@Sun.COM 			if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) {
38911767SAnurag.Maskey@Sun.COM 				if (up) {
39011767SAnurag.Maskey@Sun.COM 					/*
39111767SAnurag.Maskey@Sun.COM 					 * Moving online, add v4/v6 default
39211767SAnurag.Maskey@Sun.COM 					 * routes (if any).
39311767SAnurag.Maskey@Sun.COM 					 */
39411767SAnurag.Maskey@Sun.COM 					nwamd_add_default_routes(ncu);
39511767SAnurag.Maskey@Sun.COM 				} else {
39611767SAnurag.Maskey@Sun.COM 					/*
39711767SAnurag.Maskey@Sun.COM 					 * If this is an interface NCU and we
39811767SAnurag.Maskey@Sun.COM 					 * got a down event, it is a consequence
39911767SAnurag.Maskey@Sun.COM 					 * of NCU refresh, so reapply addresses
40011767SAnurag.Maskey@Sun.COM 					 * by reinitializing.
40111767SAnurag.Maskey@Sun.COM 					 */
40211767SAnurag.Maskey@Sun.COM 					nwamd_object_set_state
40311767SAnurag.Maskey@Sun.COM 					    (NWAM_OBJECT_TYPE_NCU, object_name,
40411767SAnurag.Maskey@Sun.COM 					    NWAM_STATE_OFFLINE_TO_ONLINE,
40511767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_INITIALIZED);
40611767SAnurag.Maskey@Sun.COM 				}
40711767SAnurag.Maskey@Sun.COM 			}
40811767SAnurag.Maskey@Sun.COM 		} else {
40911767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_ncu_state_machine: "
41011767SAnurag.Maskey@Sun.COM 			    "%s is %s", object_name,
41111767SAnurag.Maskey@Sun.COM 			    up ? "online" : "offline");
41211767SAnurag.Maskey@Sun.COM 		}
41311767SAnurag.Maskey@Sun.COM 		/*
41411767SAnurag.Maskey@Sun.COM 		 * NCU is UP or DOWN, trigger all condition checking, even if
41511767SAnurag.Maskey@Sun.COM 		 * the NCU is already in the ONLINE state - an ENM may depend
41611767SAnurag.Maskey@Sun.COM 		 * on NCU activity.
41711767SAnurag.Maskey@Sun.COM 		 */
41811767SAnurag.Maskey@Sun.COM 		nwamd_create_triggered_condition_check_event(NEXT_FEW_SECONDS);
41911767SAnurag.Maskey@Sun.COM 		break;
42011767SAnurag.Maskey@Sun.COM 
42111767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_CONDITIONS_NOT_MET:
42211767SAnurag.Maskey@Sun.COM 		/*
42311767SAnurag.Maskey@Sun.COM 		 * Link/interface is moving offline.  Nothing to do except
42411767SAnurag.Maskey@Sun.COM 		 * for WiFi, where we disconnect.  Don't unplumb IP on
42511767SAnurag.Maskey@Sun.COM 		 * a link since it may be a transient change.
42611767SAnurag.Maskey@Sun.COM 		 */
42711767SAnurag.Maskey@Sun.COM 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
42811767SAnurag.Maskey@Sun.COM 			if (link->nwamd_link_media == DL_WIFI) {
42911767SAnurag.Maskey@Sun.COM 				(void) dladm_wlan_disconnect(dld_handle,
43011767SAnurag.Maskey@Sun.COM 				    link->nwamd_link_id);
43111767SAnurag.Maskey@Sun.COM 				link->nwamd_link_wifi_connected = B_FALSE;
43211767SAnurag.Maskey@Sun.COM 				nwamd_set_selected_connected(ncu, B_FALSE,
43311767SAnurag.Maskey@Sun.COM 				    B_FALSE);
43411767SAnurag.Maskey@Sun.COM 			}
43511767SAnurag.Maskey@Sun.COM 		} else {
43611767SAnurag.Maskey@Sun.COM 			/*
43711767SAnurag.Maskey@Sun.COM 			 * Unplumb here. In the future we may elaborate on
43811767SAnurag.Maskey@Sun.COM 			 * the approach used and not unplumb for WiFi
43911767SAnurag.Maskey@Sun.COM 			 * until we reconnect to a different WLAN (i.e. with
44011767SAnurag.Maskey@Sun.COM 			 * a different ESSID).
44111767SAnurag.Maskey@Sun.COM 			 */
44212576SAnurag.Maskey@Oracle.COM 			nwamd_unplumb_interface(ncu, AF_INET);
44312576SAnurag.Maskey@Oracle.COM 			nwamd_unplumb_interface(ncu, AF_INET6);
44411767SAnurag.Maskey@Sun.COM 		}
44511767SAnurag.Maskey@Sun.COM 		if (object->nwamd_object_state != NWAM_STATE_OFFLINE) {
44611767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
44711767SAnurag.Maskey@Sun.COM 			    object_name, NWAM_STATE_OFFLINE,
44811767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_CONDITIONS_NOT_MET);
44911767SAnurag.Maskey@Sun.COM 		}
45011767SAnurag.Maskey@Sun.COM 		break;
45111767SAnurag.Maskey@Sun.COM 
45211767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_MANUAL_DISABLE:
45311767SAnurag.Maskey@Sun.COM 		/* Manual disable, set enabled state appropriately. */
45411767SAnurag.Maskey@Sun.COM 		ncu->ncu_enabled = B_FALSE;
45511767SAnurag.Maskey@Sun.COM 		/* FALLTHROUGH */
45611767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_UNINITIALIZED:
45711767SAnurag.Maskey@Sun.COM 	case NWAM_AUX_STATE_NOT_FOUND:
45811767SAnurag.Maskey@Sun.COM 		/*
45911767SAnurag.Maskey@Sun.COM 		 * Link/interface NCU has been disabled/deactivated/removed.
46011767SAnurag.Maskey@Sun.COM 		 * For WiFi links disconnect, and for IP interfaces we unplumb.
46111767SAnurag.Maskey@Sun.COM 		 */
46211767SAnurag.Maskey@Sun.COM 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
46311767SAnurag.Maskey@Sun.COM 			if (link->nwamd_link_media == DL_WIFI) {
46411767SAnurag.Maskey@Sun.COM 				(void) dladm_wlan_disconnect(dld_handle,
46511767SAnurag.Maskey@Sun.COM 				    link->nwamd_link_id);
46611767SAnurag.Maskey@Sun.COM 				link->nwamd_link_wifi_connected = B_FALSE;
46711767SAnurag.Maskey@Sun.COM 				nwamd_set_selected_connected(ncu, B_FALSE,
46811767SAnurag.Maskey@Sun.COM 				    B_FALSE);
46911767SAnurag.Maskey@Sun.COM 			}
47011767SAnurag.Maskey@Sun.COM 			nwamd_dlpi_delete_link(object);
47111767SAnurag.Maskey@Sun.COM 		} else {
47211767SAnurag.Maskey@Sun.COM 			/* Unplumb here. */
47312576SAnurag.Maskey@Oracle.COM 			if (ncu->ncu_if.nwamd_if_ipv4) {
47412576SAnurag.Maskey@Oracle.COM 				nwamd_unplumb_interface(ncu, AF_INET);
47511767SAnurag.Maskey@Sun.COM 			}
47612576SAnurag.Maskey@Oracle.COM 			if (ncu->ncu_if.nwamd_if_ipv6) {
47712576SAnurag.Maskey@Oracle.COM 				nwamd_unplumb_interface(ncu, AF_INET6);
47811767SAnurag.Maskey@Sun.COM 			}
47911767SAnurag.Maskey@Sun.COM 			/* trigger location condition checking */
48011767SAnurag.Maskey@Sun.COM 			nwamd_create_triggered_condition_check_event(0);
48111767SAnurag.Maskey@Sun.COM 		}
48211767SAnurag.Maskey@Sun.COM 
48311767SAnurag.Maskey@Sun.COM 		switch (object->nwamd_object_aux_state) {
48411767SAnurag.Maskey@Sun.COM 		case NWAM_AUX_STATE_MANUAL_DISABLE:
48511767SAnurag.Maskey@Sun.COM 			/* Change state to DISABLED if manually disabled */
48611767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
48711767SAnurag.Maskey@Sun.COM 			    object_name, NWAM_STATE_DISABLED,
48811767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_MANUAL_DISABLE);
48911767SAnurag.Maskey@Sun.COM 			/* Note that NCU has been disabled */
49011767SAnurag.Maskey@Sun.COM 			ncu->ncu_enabled = B_FALSE;
49111767SAnurag.Maskey@Sun.COM 			break;
49211767SAnurag.Maskey@Sun.COM 		case NWAM_AUX_STATE_NOT_FOUND:
49311767SAnurag.Maskey@Sun.COM 			/* Change state to UNINITIALIZED for device removal */
49411767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
49511767SAnurag.Maskey@Sun.COM 			    object_name, NWAM_STATE_UNINITIALIZED,
49611767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_NOT_FOUND);
49711767SAnurag.Maskey@Sun.COM 			break;
49811767SAnurag.Maskey@Sun.COM 		default:
49911767SAnurag.Maskey@Sun.COM 			break;
50011767SAnurag.Maskey@Sun.COM 		}
50111767SAnurag.Maskey@Sun.COM 		break;
50211767SAnurag.Maskey@Sun.COM 	default:
50311767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_ncu_state_machine: unexpected state");
50411767SAnurag.Maskey@Sun.COM 		break;
50511767SAnurag.Maskey@Sun.COM 	}
50611767SAnurag.Maskey@Sun.COM 
50711767SAnurag.Maskey@Sun.COM 	nwamd_object_release(object);
50811767SAnurag.Maskey@Sun.COM }
50911767SAnurag.Maskey@Sun.COM 
51011767SAnurag.Maskey@Sun.COM static int
ncu_create_init_fini_event(nwam_ncu_handle_t ncuh,void * data)51111767SAnurag.Maskey@Sun.COM ncu_create_init_fini_event(nwam_ncu_handle_t ncuh, void *data)
51211767SAnurag.Maskey@Sun.COM {
51311767SAnurag.Maskey@Sun.COM 	boolean_t *init = data;
51411767SAnurag.Maskey@Sun.COM 	char *name, *typedname;
51511767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
51611767SAnurag.Maskey@Sun.COM 	nwam_value_t typeval = NULL;
51711767SAnurag.Maskey@Sun.COM 	uint64_t *type;
51811767SAnurag.Maskey@Sun.COM 	uint_t numvalues;
51911767SAnurag.Maskey@Sun.COM 	nwamd_event_t ncu_event;
52011767SAnurag.Maskey@Sun.COM 
52111767SAnurag.Maskey@Sun.COM 	if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) {
52211767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR,
52311767SAnurag.Maskey@Sun.COM 		    "ncu_create_init_fini_event: could not get NCU name");
52411767SAnurag.Maskey@Sun.COM 		return (0);
52511767SAnurag.Maskey@Sun.COM 	}
52611767SAnurag.Maskey@Sun.COM 
52711767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "ncu_create_init_fini_event(%s, %p)", name, data);
52811767SAnurag.Maskey@Sun.COM 
52911767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_uint(ncuh, &typeval, &type, &numvalues,
53011767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_TYPE)) != NWAM_SUCCESS) {
53111767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "ncu_create_init_fini_event: "
53211767SAnurag.Maskey@Sun.COM 		    "could not get NCU type: %s", nwam_strerror(err));
53311767SAnurag.Maskey@Sun.COM 		free(name);
53411767SAnurag.Maskey@Sun.COM 		nwam_value_free(typeval);
53511767SAnurag.Maskey@Sun.COM 		return (0);
53611767SAnurag.Maskey@Sun.COM 	}
53711767SAnurag.Maskey@Sun.COM 
53811767SAnurag.Maskey@Sun.COM 	/* convert name to typedname for event */
53911767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_name_to_typed_name(name, *type, &typedname))
54011767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS) {
54111767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "ncu_create_init_fini_event: "
54211767SAnurag.Maskey@Sun.COM 		    "NCU name translation failed: %s", nwam_strerror(err));
54311767SAnurag.Maskey@Sun.COM 		free(name);
54411767SAnurag.Maskey@Sun.COM 		return (0);
54511767SAnurag.Maskey@Sun.COM 	}
54611767SAnurag.Maskey@Sun.COM 	free(name);
54711767SAnurag.Maskey@Sun.COM 	nwam_value_free(typeval);
54811767SAnurag.Maskey@Sun.COM 
54911767SAnurag.Maskey@Sun.COM 	ncu_event = nwamd_event_init(*init ?
55011767SAnurag.Maskey@Sun.COM 	    NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI,
55111767SAnurag.Maskey@Sun.COM 	    NWAM_OBJECT_TYPE_NCU, 0, typedname);
55211767SAnurag.Maskey@Sun.COM 	if (ncu_event != NULL)
55311767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue(ncu_event);
55411767SAnurag.Maskey@Sun.COM 	free(typedname);
55511767SAnurag.Maskey@Sun.COM 
55611767SAnurag.Maskey@Sun.COM 	return (0);
55711767SAnurag.Maskey@Sun.COM }
55811767SAnurag.Maskey@Sun.COM 
55911767SAnurag.Maskey@Sun.COM /*
56011767SAnurag.Maskey@Sun.COM  * Initialization - walk the NCUs, creating initialization events for each
56111767SAnurag.Maskey@Sun.COM  * NCU.  nwamd_ncu_handle_init_event() will check if the associated
56211767SAnurag.Maskey@Sun.COM  * physical link exists or not.
56311767SAnurag.Maskey@Sun.COM  */
56411767SAnurag.Maskey@Sun.COM void
nwamd_init_ncus(void)56511767SAnurag.Maskey@Sun.COM nwamd_init_ncus(void)
56611767SAnurag.Maskey@Sun.COM {
56711767SAnurag.Maskey@Sun.COM 	boolean_t init = B_TRUE;
56811767SAnurag.Maskey@Sun.COM 
56911767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_lock(&active_ncp_mutex);
57011767SAnurag.Maskey@Sun.COM 	if (active_ncph != NULL) {
57111767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_init_ncus: "
57211767SAnurag.Maskey@Sun.COM 		    "(re)intializing NCUs for NCP %s", active_ncp);
57311767SAnurag.Maskey@Sun.COM 		(void) nwam_ncp_walk_ncus(active_ncph,
57411767SAnurag.Maskey@Sun.COM 		    ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL,
57511767SAnurag.Maskey@Sun.COM 		    NULL);
57611767SAnurag.Maskey@Sun.COM 	}
57711767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_unlock(&active_ncp_mutex);
57811767SAnurag.Maskey@Sun.COM }
57911767SAnurag.Maskey@Sun.COM 
58011767SAnurag.Maskey@Sun.COM void
nwamd_fini_ncus(void)58111767SAnurag.Maskey@Sun.COM nwamd_fini_ncus(void)
58211767SAnurag.Maskey@Sun.COM {
58311767SAnurag.Maskey@Sun.COM 	boolean_t init = B_FALSE;
58411767SAnurag.Maskey@Sun.COM 
58511767SAnurag.Maskey@Sun.COM 	/* We may not have an active NCP on initialization, so skip fini */
58611767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_lock(&active_ncp_mutex);
58711767SAnurag.Maskey@Sun.COM 	if (active_ncph != NULL) {
58811767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_fini_ncus: deinitializing NCUs for %s",
58911767SAnurag.Maskey@Sun.COM 		    active_ncp);
59011767SAnurag.Maskey@Sun.COM 		(void) nwam_ncp_walk_ncus(active_ncph,
59111767SAnurag.Maskey@Sun.COM 		    ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL,
59211767SAnurag.Maskey@Sun.COM 		    NULL);
59311767SAnurag.Maskey@Sun.COM 	}
59411767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_unlock(&active_ncp_mutex);
59511767SAnurag.Maskey@Sun.COM }
59611767SAnurag.Maskey@Sun.COM 
59711767SAnurag.Maskey@Sun.COM /*
59811767SAnurag.Maskey@Sun.COM  * Most properties of this type don't need to be cached locally.  Only those
59911767SAnurag.Maskey@Sun.COM  * interesting to the daemon are stored in an nwamd_ncu_t.
60011767SAnurag.Maskey@Sun.COM  */
60111767SAnurag.Maskey@Sun.COM static void
populate_common_ncu_properties(nwam_ncu_handle_t ncuh,nwamd_ncu_t * ncu_data)60211767SAnurag.Maskey@Sun.COM populate_common_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
60311767SAnurag.Maskey@Sun.COM {
60411767SAnurag.Maskey@Sun.COM 	nwam_value_t ncu_prop;
60511767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
60611767SAnurag.Maskey@Sun.COM 	boolean_t enablevalue;
60711767SAnurag.Maskey@Sun.COM 	uint_t numvalues;
60811767SAnurag.Maskey@Sun.COM 	char **parent;
60911767SAnurag.Maskey@Sun.COM 
61011767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED,
61111767SAnurag.Maskey@Sun.COM 	    &ncu_prop)) != NWAM_SUCCESS) {
61211767SAnurag.Maskey@Sun.COM 		char *name;
61311767SAnurag.Maskey@Sun.COM 		(void) nwam_ncu_name_to_typed_name(ncu_data->ncu_name,
61411767SAnurag.Maskey@Sun.COM 		    ncu_data->ncu_type, &name);
61511767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwam_ncu_get_prop_value %s ENABLED failed: %s",
61611767SAnurag.Maskey@Sun.COM 		    name, nwam_strerror(err));
61711767SAnurag.Maskey@Sun.COM 		free(name);
61811767SAnurag.Maskey@Sun.COM 		ncu_data->ncu_enabled = B_TRUE;
61911767SAnurag.Maskey@Sun.COM 	} else {
62011767SAnurag.Maskey@Sun.COM 		if ((err = nwam_value_get_boolean(ncu_prop, &enablevalue)) !=
62111767SAnurag.Maskey@Sun.COM 		    NWAM_SUCCESS) {
62211767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwam_value_get_boolean ENABLED failed: "
62311767SAnurag.Maskey@Sun.COM 			    "%s", nwam_strerror(err));
62411767SAnurag.Maskey@Sun.COM 		} else {
62511767SAnurag.Maskey@Sun.COM 			ncu_data->ncu_enabled = enablevalue;
62611767SAnurag.Maskey@Sun.COM 		}
62711767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
62811767SAnurag.Maskey@Sun.COM 	}
62911767SAnurag.Maskey@Sun.COM 
63011767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &parent,
63111767SAnurag.Maskey@Sun.COM 	    &numvalues, NWAM_NCU_PROP_PARENT_NCP)) != NWAM_SUCCESS) {
63211767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwam_ncu_get_prop_value %s PARENT failed: %s",
63311767SAnurag.Maskey@Sun.COM 		    ncu_data->ncu_name, nwam_strerror(err));
63411767SAnurag.Maskey@Sun.COM 	} else {
63511767SAnurag.Maskey@Sun.COM 		(void) strlcpy(ncu_data->ncu_parent, parent[0],
63611767SAnurag.Maskey@Sun.COM 		    sizeof (ncu_data->ncu_parent));
63711767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
63811767SAnurag.Maskey@Sun.COM 	}
63911767SAnurag.Maskey@Sun.COM }
64011767SAnurag.Maskey@Sun.COM 
64111767SAnurag.Maskey@Sun.COM /*
64211767SAnurag.Maskey@Sun.COM  * Read in link properties.
64311767SAnurag.Maskey@Sun.COM  */
64411767SAnurag.Maskey@Sun.COM static void
populate_link_ncu_properties(nwam_ncu_handle_t ncuh,nwamd_ncu_t * ncu_data)64511767SAnurag.Maskey@Sun.COM populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
64611767SAnurag.Maskey@Sun.COM {
64711767SAnurag.Maskey@Sun.COM 	nwam_value_t ncu_prop;
64811767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
64911767SAnurag.Maskey@Sun.COM 	char **mac_addr;
65011767SAnurag.Maskey@Sun.COM 	uint64_t *uintval;
65111767SAnurag.Maskey@Sun.COM 	uint_t numvalues;
65211767SAnurag.Maskey@Sun.COM 
65311767SAnurag.Maskey@Sun.COM 	/* activation-mode */
65411767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues,
65511767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) {
65611767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR,
65711767SAnurag.Maskey@Sun.COM 		    "populate_link_ncu_properties: could not get %s value: %s",
65811767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_PROP_ACTIVATION_MODE, nwam_strerror(err));
65911767SAnurag.Maskey@Sun.COM 	} else {
66012576SAnurag.Maskey@Oracle.COM 		ncu_data->ncu_link.nwamd_link_activation_mode = uintval[0];
66111767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
66211767SAnurag.Maskey@Sun.COM 	}
66311767SAnurag.Maskey@Sun.COM 
66411767SAnurag.Maskey@Sun.COM 	/* priority-group and priority-mode for prioritized activation */
66512576SAnurag.Maskey@Oracle.COM 	if (ncu_data->ncu_link.nwamd_link_activation_mode ==
66611767SAnurag.Maskey@Sun.COM 	    NWAM_ACTIVATION_MODE_PRIORITIZED) {
66711767SAnurag.Maskey@Sun.COM 		/* ncus with prioritized activation are always enabled */
66811767SAnurag.Maskey@Sun.COM 		ncu_data->ncu_enabled = B_TRUE;
66911767SAnurag.Maskey@Sun.COM 		if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval,
67011767SAnurag.Maskey@Sun.COM 		    &numvalues, NWAM_NCU_PROP_PRIORITY_MODE))
67111767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS) {
67211767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "populate_link_ncu_properties: "
67311767SAnurag.Maskey@Sun.COM 			    "could not get %s value: %s",
67411767SAnurag.Maskey@Sun.COM 			    NWAM_NCU_PROP_PRIORITY_MODE, nwam_strerror(err));
67511767SAnurag.Maskey@Sun.COM 		} else {
67612576SAnurag.Maskey@Oracle.COM 			ncu_data->ncu_link.nwamd_link_priority_mode =
67711767SAnurag.Maskey@Sun.COM 			    uintval[0];
67811767SAnurag.Maskey@Sun.COM 			nwam_value_free(ncu_prop);
67911767SAnurag.Maskey@Sun.COM 		}
68011767SAnurag.Maskey@Sun.COM 
68111767SAnurag.Maskey@Sun.COM 		if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval,
68211767SAnurag.Maskey@Sun.COM 		    &numvalues, NWAM_NCU_PROP_PRIORITY_GROUP))
68311767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS) {
68411767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "populate_link_ncu_properties: "
68511767SAnurag.Maskey@Sun.COM 			    "could not get %s value: %s",
68611767SAnurag.Maskey@Sun.COM 			    NWAM_NCU_PROP_PRIORITY_GROUP, nwam_strerror(err));
68711767SAnurag.Maskey@Sun.COM 		} else {
68812576SAnurag.Maskey@Oracle.COM 			ncu_data->ncu_link.nwamd_link_priority_group =
68911767SAnurag.Maskey@Sun.COM 			    uintval[0];
69011767SAnurag.Maskey@Sun.COM 			nwam_value_free(ncu_prop);
69111767SAnurag.Maskey@Sun.COM 		}
69211767SAnurag.Maskey@Sun.COM 	}
69311767SAnurag.Maskey@Sun.COM 
69411767SAnurag.Maskey@Sun.COM 	/* link-mac-addr */
69511767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &mac_addr, &numvalues,
69611767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_LINK_MAC_ADDR)) != NWAM_SUCCESS) {
69711767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG,
69811767SAnurag.Maskey@Sun.COM 		    "populate_link_ncu_properties: could not get %s value: %s",
69911767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_PROP_LINK_MAC_ADDR, nwam_strerror(err));
70012576SAnurag.Maskey@Oracle.COM 		ncu_data->ncu_link.nwamd_link_mac_addr = NULL;
70111767SAnurag.Maskey@Sun.COM 	} else {
70212576SAnurag.Maskey@Oracle.COM 		ncu_data->ncu_link.nwamd_link_mac_addr = strdup(*mac_addr);
70312576SAnurag.Maskey@Oracle.COM 		ncu_data->ncu_link.nwamd_link_mac_addr_len = strlen(*mac_addr);
70411767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
70511767SAnurag.Maskey@Sun.COM 	}
70611767SAnurag.Maskey@Sun.COM 
70711767SAnurag.Maskey@Sun.COM 	/* link-mtu */
70811767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues,
70911767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_LINK_MTU)) != NWAM_SUCCESS) {
71011767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG,
71111767SAnurag.Maskey@Sun.COM 		    "populate_link_ncu_properties: could not get %s value: %s",
71211767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_PROP_LINK_MTU, nwam_strerror(err));
71312576SAnurag.Maskey@Oracle.COM 		ncu_data->ncu_link.nwamd_link_mtu = 0;
71411767SAnurag.Maskey@Sun.COM 	} else {
71512576SAnurag.Maskey@Oracle.COM 		ncu_data->ncu_link.nwamd_link_mtu = uintval[0];
71611767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
71711767SAnurag.Maskey@Sun.COM 	}
71811767SAnurag.Maskey@Sun.COM 
71911767SAnurag.Maskey@Sun.COM 	/* link-autopush */
72011767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop,
72112576SAnurag.Maskey@Oracle.COM 	    &ncu_data->ncu_link.nwamd_link_autopush,
72212576SAnurag.Maskey@Oracle.COM 	    &ncu_data->ncu_link.nwamd_link_num_autopush,
72311767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_LINK_AUTOPUSH)) != NWAM_SUCCESS) {
72411767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG,
72511767SAnurag.Maskey@Sun.COM 		    "populate_link_ncu_properties: could not get %s value: %s",
72611767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_PROP_LINK_AUTOPUSH, nwam_strerror(err));
72712576SAnurag.Maskey@Oracle.COM 		ncu_data->ncu_link.nwamd_link_num_autopush = 0;
72811767SAnurag.Maskey@Sun.COM 	}
72911767SAnurag.Maskey@Sun.COM }
73011767SAnurag.Maskey@Sun.COM 
73111767SAnurag.Maskey@Sun.COM static void
populate_ip_ncu_properties(nwam_ncu_handle_t ncuh,nwamd_ncu_t * ncu_data)73211767SAnurag.Maskey@Sun.COM populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
73311767SAnurag.Maskey@Sun.COM {
73412576SAnurag.Maskey@Oracle.COM 	nwamd_if_t *nif = &ncu_data->ncu_if;
73511767SAnurag.Maskey@Sun.COM 	struct nwamd_if_address **nifa, *nifai, *nifait;
73611767SAnurag.Maskey@Sun.COM 	boolean_t static_addr = B_FALSE;
73711767SAnurag.Maskey@Sun.COM 	uint64_t *addrsrcvalue;
73811767SAnurag.Maskey@Sun.COM 	nwam_value_t ncu_prop;
73911767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
74012576SAnurag.Maskey@Oracle.COM 	ipadm_addrobj_t ipaddr;
74112576SAnurag.Maskey@Oracle.COM 	ipadm_status_t ipstatus;
74211767SAnurag.Maskey@Sun.COM 	char **addrvalue;
74311767SAnurag.Maskey@Sun.COM 	uint_t numvalues;
74411767SAnurag.Maskey@Sun.COM 	uint64_t *ipversion;
74511767SAnurag.Maskey@Sun.COM 	int i;
74611767SAnurag.Maskey@Sun.COM 
74711767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_ipv4 = B_FALSE;
74811767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_ipv6 = B_FALSE;
74911767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_dhcp_requested = B_FALSE;
75011767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_stateful_requested = B_FALSE;
75111767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_stateless_requested = B_FALSE;
75211767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_ipv4_default_route_set = B_FALSE;
75311767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_ipv6_default_route_set = B_FALSE;
75411767SAnurag.Maskey@Sun.COM 
75511767SAnurag.Maskey@Sun.COM 	/* ip-version */
75611767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &ipversion, &numvalues,
75711767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_IP_VERSION)) != NWAM_SUCCESS) {
75811767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR,
75911767SAnurag.Maskey@Sun.COM 		    "populate_ip_ncu_properties: could not get %s value: %s",
76011767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_PROP_IP_VERSION, nwam_strerror(err));
76111767SAnurag.Maskey@Sun.COM 	} else {
76211767SAnurag.Maskey@Sun.COM 		for (i = 0; i < numvalues; i++) {
76311767SAnurag.Maskey@Sun.COM 			switch (ipversion[i]) {
76411767SAnurag.Maskey@Sun.COM 			case IPV4_VERSION:
76511767SAnurag.Maskey@Sun.COM 				nif->nwamd_if_ipv4 = B_TRUE;
76611767SAnurag.Maskey@Sun.COM 				break;
76711767SAnurag.Maskey@Sun.COM 			case IPV6_VERSION:
76811767SAnurag.Maskey@Sun.COM 				nif->nwamd_if_ipv6 = B_TRUE;
76911767SAnurag.Maskey@Sun.COM 				break;
77011767SAnurag.Maskey@Sun.COM 			default:
77111767SAnurag.Maskey@Sun.COM 				nlog(LOG_ERR, "bogus ip version %lld",
77211767SAnurag.Maskey@Sun.COM 				    ipversion[i]);
77311767SAnurag.Maskey@Sun.COM 				break;
77411767SAnurag.Maskey@Sun.COM 			}
77511767SAnurag.Maskey@Sun.COM 		}
77611767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
77711767SAnurag.Maskey@Sun.COM 	}
77811767SAnurag.Maskey@Sun.COM 
77911767SAnurag.Maskey@Sun.COM 	/* Free the old list. */
78011767SAnurag.Maskey@Sun.COM 	for (nifai = nif->nwamd_if_list; nifai != NULL; nifai = nifait) {
78111767SAnurag.Maskey@Sun.COM 		nifait = nifai->next;
78211767SAnurag.Maskey@Sun.COM 		nifai->next = NULL;
78312576SAnurag.Maskey@Oracle.COM 		ipadm_destroy_addrobj(nifai->ipaddr);
78411767SAnurag.Maskey@Sun.COM 		free(nifai);
78511767SAnurag.Maskey@Sun.COM 	}
78611767SAnurag.Maskey@Sun.COM 	nif->nwamd_if_list = NULL;
78711767SAnurag.Maskey@Sun.COM 	nifa = &(nif->nwamd_if_list);
78811767SAnurag.Maskey@Sun.COM 
78911767SAnurag.Maskey@Sun.COM 	if (!nif->nwamd_if_ipv4)
79011767SAnurag.Maskey@Sun.COM 		goto skip_ipv4;
79111767SAnurag.Maskey@Sun.COM 
79211767SAnurag.Maskey@Sun.COM 	/* ipv4-addrsrc */
79311767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue,
79411767SAnurag.Maskey@Sun.COM 	    &numvalues, NWAM_NCU_PROP_IPV4_ADDRSRC)) != NWAM_SUCCESS) {
79511767SAnurag.Maskey@Sun.COM 		nlog(nif->nwamd_if_ipv4 ? LOG_ERR : LOG_DEBUG,
79611767SAnurag.Maskey@Sun.COM 		    "populate_ip_ncu_properties: could not get %s value: %s",
79711767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_PROP_IPV4_ADDRSRC, nwam_strerror(err));
79811767SAnurag.Maskey@Sun.COM 	} else {
79911767SAnurag.Maskey@Sun.COM 		for (i = 0; i < numvalues; i++) {
80011767SAnurag.Maskey@Sun.COM 			switch (addrsrcvalue[i]) {
80111767SAnurag.Maskey@Sun.COM 			case NWAM_ADDRSRC_DHCP:
80211767SAnurag.Maskey@Sun.COM 				nif->nwamd_if_dhcp_requested = B_TRUE;
80311767SAnurag.Maskey@Sun.COM 				break;
80411767SAnurag.Maskey@Sun.COM 			case NWAM_ADDRSRC_STATIC:
80511767SAnurag.Maskey@Sun.COM 				static_addr = B_TRUE;
80611767SAnurag.Maskey@Sun.COM 				break;
80711767SAnurag.Maskey@Sun.COM 			default:
80811767SAnurag.Maskey@Sun.COM 				break;
80911767SAnurag.Maskey@Sun.COM 			}
81011767SAnurag.Maskey@Sun.COM 		}
81111767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
81211767SAnurag.Maskey@Sun.COM 	}
81311767SAnurag.Maskey@Sun.COM 	if (nif->nwamd_if_dhcp_requested) {
81412576SAnurag.Maskey@Oracle.COM 		ipstatus = ipadm_create_addrobj(IPADM_ADDR_DHCP,
81512576SAnurag.Maskey@Oracle.COM 		    ncu_data->ncu_name, &ipaddr);
81612576SAnurag.Maskey@Oracle.COM 		if (ipstatus != IPADM_SUCCESS) {
81712576SAnurag.Maskey@Oracle.COM 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
81812576SAnurag.Maskey@Oracle.COM 			    "ipadm_create_addrobj failed for v4 dhcp: %s",
81912576SAnurag.Maskey@Oracle.COM 			    ipadm_status2str(ipstatus));
82012576SAnurag.Maskey@Oracle.COM 			goto skip_ipv4_dhcp;
82112576SAnurag.Maskey@Oracle.COM 		}
82212576SAnurag.Maskey@Oracle.COM 
82312576SAnurag.Maskey@Oracle.COM 		ipstatus = ipadm_set_wait_time(ipaddr, ncu_wait_time);
82412576SAnurag.Maskey@Oracle.COM 		if (ipstatus != IPADM_SUCCESS) {
82512576SAnurag.Maskey@Oracle.COM 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
82612576SAnurag.Maskey@Oracle.COM 			    "ipadm_set_wait_time failed for v4 dhcp: %s",
82712576SAnurag.Maskey@Oracle.COM 			    ipadm_status2str(ipstatus));
82812576SAnurag.Maskey@Oracle.COM 			ipadm_destroy_addrobj(ipaddr);
82912576SAnurag.Maskey@Oracle.COM 			goto skip_ipv4_dhcp;
83012576SAnurag.Maskey@Oracle.COM 		}
83111767SAnurag.Maskey@Sun.COM 		if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
83212576SAnurag.Maskey@Oracle.COM 			(*nifa)->family = AF_INET;
83312576SAnurag.Maskey@Oracle.COM 			(*nifa)->ipaddr_atype = IPADM_ADDR_DHCP;
83412576SAnurag.Maskey@Oracle.COM 			(*nifa)->ipaddr = ipaddr;
83511767SAnurag.Maskey@Sun.COM 			nifa = &((*nifa)->next);
83611767SAnurag.Maskey@Sun.COM 			*nifa = NULL;
83712576SAnurag.Maskey@Oracle.COM 		} else {
83812576SAnurag.Maskey@Oracle.COM 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
83912576SAnurag.Maskey@Oracle.COM 			    "couldn't allocate nwamd address for v4 dhcp: %s",
84012576SAnurag.Maskey@Oracle.COM 			    strerror(errno));
84112576SAnurag.Maskey@Oracle.COM 			ipadm_destroy_addrobj(ipaddr);
84211767SAnurag.Maskey@Sun.COM 		}
84311767SAnurag.Maskey@Sun.COM 	}
84411767SAnurag.Maskey@Sun.COM 
84512576SAnurag.Maskey@Oracle.COM skip_ipv4_dhcp:
84611767SAnurag.Maskey@Sun.COM 	/* ipv4-addr */
84711767SAnurag.Maskey@Sun.COM 	if (static_addr) {
84811767SAnurag.Maskey@Sun.COM 		if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
84911767SAnurag.Maskey@Sun.COM 		    &numvalues, NWAM_NCU_PROP_IPV4_ADDR)) != NWAM_SUCCESS) {
85011767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
85111767SAnurag.Maskey@Sun.COM 			    "could not get %s value; %s",
85211767SAnurag.Maskey@Sun.COM 			    NWAM_NCU_PROP_IPV4_ADDR, nwam_strerror(err));
85311767SAnurag.Maskey@Sun.COM 		} else {
85411767SAnurag.Maskey@Sun.COM 			for (i = 0; i < numvalues; i++) {
85512576SAnurag.Maskey@Oracle.COM 				ipstatus = ipadm_create_addrobj(
85612576SAnurag.Maskey@Oracle.COM 				    IPADM_ADDR_STATIC, ncu_data->ncu_name,
85712576SAnurag.Maskey@Oracle.COM 				    &ipaddr);
85812576SAnurag.Maskey@Oracle.COM 				if (ipstatus != IPADM_SUCCESS) {
85912576SAnurag.Maskey@Oracle.COM 					nlog(LOG_ERR,
86012576SAnurag.Maskey@Oracle.COM 					    "populate_ip_ncu_properties: "
86112576SAnurag.Maskey@Oracle.COM 					    "ipadm_create_addrobj failed "
86212576SAnurag.Maskey@Oracle.COM 					    "for %s: %s", addrvalue[i],
86312576SAnurag.Maskey@Oracle.COM 					    ipadm_status2str(ipstatus));
86411767SAnurag.Maskey@Sun.COM 					continue;
86511767SAnurag.Maskey@Sun.COM 				}
86612576SAnurag.Maskey@Oracle.COM 				/* ipadm_set_addr takes <addr>[/<mask>] */
86712576SAnurag.Maskey@Oracle.COM 				ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
86812576SAnurag.Maskey@Oracle.COM 				    AF_INET);
86912576SAnurag.Maskey@Oracle.COM 				if (ipstatus != IPADM_SUCCESS) {
87012576SAnurag.Maskey@Oracle.COM 					nlog(LOG_ERR,
87112576SAnurag.Maskey@Oracle.COM 					    "populate_ip_ncu_properties: "
87212576SAnurag.Maskey@Oracle.COM 					    "ipadm_set_addr failed for %s: %s",
87312576SAnurag.Maskey@Oracle.COM 					    addrvalue[i],
87412576SAnurag.Maskey@Oracle.COM 					    ipadm_status2str(ipstatus));
87512576SAnurag.Maskey@Oracle.COM 					ipadm_destroy_addrobj(ipaddr);
87612576SAnurag.Maskey@Oracle.COM 					continue;
87711767SAnurag.Maskey@Sun.COM 				}
87812576SAnurag.Maskey@Oracle.COM 
87912576SAnurag.Maskey@Oracle.COM 				if ((*nifa = calloc(sizeof (**nifa), 1))
88012576SAnurag.Maskey@Oracle.COM 				    != NULL) {
88112576SAnurag.Maskey@Oracle.COM 					(*nifa)->family = AF_INET;
88212576SAnurag.Maskey@Oracle.COM 					(*nifa)->ipaddr_atype =
88312576SAnurag.Maskey@Oracle.COM 					    IPADM_ADDR_STATIC;
88412576SAnurag.Maskey@Oracle.COM 					(*nifa)->ipaddr = ipaddr;
88512576SAnurag.Maskey@Oracle.COM 					nifa = &((*nifa)->next);
88612576SAnurag.Maskey@Oracle.COM 				} else {
88712576SAnurag.Maskey@Oracle.COM 					nlog(LOG_ERR,
88812576SAnurag.Maskey@Oracle.COM 					    "populate_ip_ncu_properties: "
88912576SAnurag.Maskey@Oracle.COM 					    "couldn't allocate nwamd address "
89012576SAnurag.Maskey@Oracle.COM 					    "for %s: %s", addrvalue[i],
89112576SAnurag.Maskey@Oracle.COM 					    strerror(errno));
89212576SAnurag.Maskey@Oracle.COM 					ipadm_destroy_addrobj(ipaddr);
89312576SAnurag.Maskey@Oracle.COM 				}
89411767SAnurag.Maskey@Sun.COM 			}
89511767SAnurag.Maskey@Sun.COM 			*nifa = NULL;
89611767SAnurag.Maskey@Sun.COM 
89711767SAnurag.Maskey@Sun.COM 			nwam_value_free(ncu_prop);
89811767SAnurag.Maskey@Sun.COM 		}
89911767SAnurag.Maskey@Sun.COM 	}
90011767SAnurag.Maskey@Sun.COM 
90111767SAnurag.Maskey@Sun.COM 	/* get default route, if any */
90211767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
90311767SAnurag.Maskey@Sun.COM 	    &numvalues, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE)) == NWAM_SUCCESS) {
90411767SAnurag.Maskey@Sun.COM 		/* Only one default route is allowed. */
90511767SAnurag.Maskey@Sun.COM 		nif->nwamd_if_ipv4_default_route.sin_family = AF_INET;
90611767SAnurag.Maskey@Sun.COM 		(void) inet_pton(AF_INET, addrvalue[0],
90711767SAnurag.Maskey@Sun.COM 		    &(nif->nwamd_if_ipv4_default_route.sin_addr));
90811767SAnurag.Maskey@Sun.COM 		nif->nwamd_if_ipv4_default_route_set = B_TRUE;
90911767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
91011767SAnurag.Maskey@Sun.COM 	}
91111767SAnurag.Maskey@Sun.COM 
91211767SAnurag.Maskey@Sun.COM skip_ipv4:
91311767SAnurag.Maskey@Sun.COM 	if (!nif->nwamd_if_ipv6)
91411767SAnurag.Maskey@Sun.COM 		goto skip_ipv6;
91511767SAnurag.Maskey@Sun.COM 
91611767SAnurag.Maskey@Sun.COM 	/* ipv6-addrsrc */
91711767SAnurag.Maskey@Sun.COM 	static_addr = B_FALSE;
91811767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue,
91911767SAnurag.Maskey@Sun.COM 	    &numvalues, NWAM_NCU_PROP_IPV6_ADDRSRC)) != NWAM_SUCCESS) {
92011767SAnurag.Maskey@Sun.COM 		nlog(nif->nwamd_if_ipv6 ? LOG_ERR : LOG_DEBUG,
92111767SAnurag.Maskey@Sun.COM 		    "populate_ip_ncu_properties: could not get %s value: %s",
92211767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_PROP_IPV6_ADDRSRC, nwam_strerror(err));
92311767SAnurag.Maskey@Sun.COM 	} else {
92411767SAnurag.Maskey@Sun.COM 		for (i = 0; i < numvalues; i++) {
92511767SAnurag.Maskey@Sun.COM 			switch (addrsrcvalue[i]) {
92611767SAnurag.Maskey@Sun.COM 			case NWAM_ADDRSRC_DHCP:
92711767SAnurag.Maskey@Sun.COM 				nif->nwamd_if_stateful_requested = B_TRUE;
92811767SAnurag.Maskey@Sun.COM 				break;
92911767SAnurag.Maskey@Sun.COM 			case NWAM_ADDRSRC_AUTOCONF:
93011767SAnurag.Maskey@Sun.COM 				nif->nwamd_if_stateless_requested = B_TRUE;
93111767SAnurag.Maskey@Sun.COM 				break;
93211767SAnurag.Maskey@Sun.COM 			case NWAM_ADDRSRC_STATIC:
93311767SAnurag.Maskey@Sun.COM 				static_addr = B_TRUE;
93411767SAnurag.Maskey@Sun.COM 				break;
93511767SAnurag.Maskey@Sun.COM 			default:
93611767SAnurag.Maskey@Sun.COM 				break;
93711767SAnurag.Maskey@Sun.COM 			}
93811767SAnurag.Maskey@Sun.COM 		}
93911767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
94011767SAnurag.Maskey@Sun.COM 	}
94112576SAnurag.Maskey@Oracle.COM 	/*
94212576SAnurag.Maskey@Oracle.COM 	 * Both stateful and stateless share the same nwamd_if_address because
94312576SAnurag.Maskey@Oracle.COM 	 * only one ipaddr for both of these addresses can be created.
94412576SAnurag.Maskey@Oracle.COM 	 * ipadm_create_addr() adds both addresses from the same ipaddr.
94512576SAnurag.Maskey@Oracle.COM 	 */
94612576SAnurag.Maskey@Oracle.COM 	if (nif->nwamd_if_stateful_requested ||
94712576SAnurag.Maskey@Oracle.COM 	    nif->nwamd_if_stateless_requested) {
94812576SAnurag.Maskey@Oracle.COM 		ipstatus = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
94912576SAnurag.Maskey@Oracle.COM 		    ncu_data->ncu_name, &ipaddr);
95012576SAnurag.Maskey@Oracle.COM 		if (ipstatus != IPADM_SUCCESS) {
95112576SAnurag.Maskey@Oracle.COM 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
95212576SAnurag.Maskey@Oracle.COM 			    "ipadm_create_addrobj failed for v6 "
95312576SAnurag.Maskey@Oracle.COM 			    "stateless/stateful: %s",
95412576SAnurag.Maskey@Oracle.COM 			    ipadm_status2str(ipstatus));
95512576SAnurag.Maskey@Oracle.COM 			goto skip_ipv6_addrconf;
95612576SAnurag.Maskey@Oracle.COM 		}
95712576SAnurag.Maskey@Oracle.COM 		/* create_addrobj sets both stateless and stateful to B_TRUE */
95812576SAnurag.Maskey@Oracle.COM 		if (!nif->nwamd_if_stateful_requested) {
95912576SAnurag.Maskey@Oracle.COM 			ipstatus = ipadm_set_stateful(ipaddr, B_FALSE);
96012576SAnurag.Maskey@Oracle.COM 			if (ipstatus != IPADM_SUCCESS) {
96112576SAnurag.Maskey@Oracle.COM 				nlog(LOG_ERR, "populate_ip_ncu_properties: "
96212576SAnurag.Maskey@Oracle.COM 				    "ipadm_set_stateful failed for v6: %s",
96312576SAnurag.Maskey@Oracle.COM 				    ipadm_status2str(ipstatus));
96412576SAnurag.Maskey@Oracle.COM 				ipadm_destroy_addrobj(ipaddr);
96512576SAnurag.Maskey@Oracle.COM 				goto skip_ipv6_addrconf;
96612576SAnurag.Maskey@Oracle.COM 			}
96712576SAnurag.Maskey@Oracle.COM 		}
96812576SAnurag.Maskey@Oracle.COM 		if (!nif->nwamd_if_stateless_requested) {
96912576SAnurag.Maskey@Oracle.COM 			ipstatus = ipadm_set_stateless(ipaddr, B_FALSE);
97012576SAnurag.Maskey@Oracle.COM 			if (ipstatus != IPADM_SUCCESS) {
97112576SAnurag.Maskey@Oracle.COM 				nlog(LOG_ERR, "populate_ip_ncu_properties: "
97212576SAnurag.Maskey@Oracle.COM 				    "ipadm_set_stateless failed for v6: %s",
97312576SAnurag.Maskey@Oracle.COM 				    ipadm_status2str(ipstatus));
97412576SAnurag.Maskey@Oracle.COM 				ipadm_destroy_addrobj(ipaddr);
97512576SAnurag.Maskey@Oracle.COM 				goto skip_ipv6_addrconf;
97612576SAnurag.Maskey@Oracle.COM 			}
97712576SAnurag.Maskey@Oracle.COM 		}
97811767SAnurag.Maskey@Sun.COM 		if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
97912576SAnurag.Maskey@Oracle.COM 			(*nifa)->family = AF_INET6;
98012576SAnurag.Maskey@Oracle.COM 			(*nifa)->ipaddr_atype = IPADM_ADDR_IPV6_ADDRCONF;
98112576SAnurag.Maskey@Oracle.COM 			(*nifa)->ipaddr = ipaddr;
98211767SAnurag.Maskey@Sun.COM 			nifa = &((*nifa)->next);
98311767SAnurag.Maskey@Sun.COM 			*nifa = NULL;
98412576SAnurag.Maskey@Oracle.COM 		} else {
98512576SAnurag.Maskey@Oracle.COM 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
98612576SAnurag.Maskey@Oracle.COM 			    "couldn't allocate nwamd address for "
98712576SAnurag.Maskey@Oracle.COM 			    "v6 stateless/stateful: %s", strerror(errno));
98812576SAnurag.Maskey@Oracle.COM 			ipadm_destroy_addrobj(ipaddr);
98911767SAnurag.Maskey@Sun.COM 		}
99011767SAnurag.Maskey@Sun.COM 	}
99111767SAnurag.Maskey@Sun.COM 
99212576SAnurag.Maskey@Oracle.COM skip_ipv6_addrconf:
99311767SAnurag.Maskey@Sun.COM 	/* ipv6-addr */
99411767SAnurag.Maskey@Sun.COM 	if (static_addr) {
99511767SAnurag.Maskey@Sun.COM 		if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
99611767SAnurag.Maskey@Sun.COM 		    &numvalues, NWAM_NCU_PROP_IPV6_ADDR)) != NWAM_SUCCESS) {
99711767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
99811767SAnurag.Maskey@Sun.COM 			    "could not get %s value; %s",
99911767SAnurag.Maskey@Sun.COM 			    NWAM_NCU_PROP_IPV6_ADDR, nwam_strerror(err));
100011767SAnurag.Maskey@Sun.COM 		} else {
100111767SAnurag.Maskey@Sun.COM 			for (i = 0; i < numvalues; i++) {
100212576SAnurag.Maskey@Oracle.COM 				ipstatus = ipadm_create_addrobj(
100312576SAnurag.Maskey@Oracle.COM 				    IPADM_ADDR_STATIC, ncu_data->ncu_name,
100412576SAnurag.Maskey@Oracle.COM 				    &ipaddr);
100512576SAnurag.Maskey@Oracle.COM 				if (ipstatus != IPADM_SUCCESS) {
100612576SAnurag.Maskey@Oracle.COM 					nlog(LOG_ERR,
100712576SAnurag.Maskey@Oracle.COM 					    "populate_ip_ncu_properties: "
100812576SAnurag.Maskey@Oracle.COM 					    "ipadm_create_addrobj failed "
100912576SAnurag.Maskey@Oracle.COM 					    "for %s: %s", addrvalue[i],
101012576SAnurag.Maskey@Oracle.COM 					    ipadm_status2str(ipstatus));
101111767SAnurag.Maskey@Sun.COM 					continue;
101211767SAnurag.Maskey@Sun.COM 				}
101312576SAnurag.Maskey@Oracle.COM 				/* ipadm_set_addr takes <addr>[/<mask>] */
101412576SAnurag.Maskey@Oracle.COM 				ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
101512576SAnurag.Maskey@Oracle.COM 				    AF_INET6);
101612576SAnurag.Maskey@Oracle.COM 				if (ipstatus != IPADM_SUCCESS) {
101712576SAnurag.Maskey@Oracle.COM 					nlog(LOG_ERR,
101812576SAnurag.Maskey@Oracle.COM 					    "populate_ip_ncu_properties: "
101912576SAnurag.Maskey@Oracle.COM 					    "ipadm_set_addr failed for %s: %s",
102012576SAnurag.Maskey@Oracle.COM 					    addrvalue[i],
102112576SAnurag.Maskey@Oracle.COM 					    ipadm_status2str(ipstatus));
102212576SAnurag.Maskey@Oracle.COM 					ipadm_destroy_addrobj(ipaddr);
102312576SAnurag.Maskey@Oracle.COM 					continue;
102411767SAnurag.Maskey@Sun.COM 				}
102512576SAnurag.Maskey@Oracle.COM 
102612576SAnurag.Maskey@Oracle.COM 				if ((*nifa = calloc(sizeof (**nifa), 1))
102712576SAnurag.Maskey@Oracle.COM 				    != NULL) {
102812576SAnurag.Maskey@Oracle.COM 					(*nifa)->family = AF_INET6;
102912576SAnurag.Maskey@Oracle.COM 					(*nifa)->ipaddr_atype =
103012576SAnurag.Maskey@Oracle.COM 					    IPADM_ADDR_STATIC;
103112576SAnurag.Maskey@Oracle.COM 					(*nifa)->ipaddr = ipaddr;
103212576SAnurag.Maskey@Oracle.COM 					nifa = &((*nifa)->next);
103312576SAnurag.Maskey@Oracle.COM 				} else {
103412576SAnurag.Maskey@Oracle.COM 					nlog(LOG_ERR,
103512576SAnurag.Maskey@Oracle.COM 					    "populate_ip_ncu_properties: "
103612576SAnurag.Maskey@Oracle.COM 					    "couldn't allocate nwamd address "
103712576SAnurag.Maskey@Oracle.COM 					    "for %s: %s", addrvalue[i],
103812576SAnurag.Maskey@Oracle.COM 					    strerror(errno));
103912576SAnurag.Maskey@Oracle.COM 					ipadm_destroy_addrobj(ipaddr);
104012576SAnurag.Maskey@Oracle.COM 				}
104111767SAnurag.Maskey@Sun.COM 			}
104211767SAnurag.Maskey@Sun.COM 			*nifa = NULL;
104311767SAnurag.Maskey@Sun.COM 
104411767SAnurag.Maskey@Sun.COM 			nwam_value_free(ncu_prop);
104511767SAnurag.Maskey@Sun.COM 		}
104611767SAnurag.Maskey@Sun.COM 	}
104711767SAnurag.Maskey@Sun.COM 
104811767SAnurag.Maskey@Sun.COM 	/* get default route, if any */
104911767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
105011767SAnurag.Maskey@Sun.COM 	    &numvalues, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE)) == NWAM_SUCCESS) {
105111767SAnurag.Maskey@Sun.COM 		/* Only one default route is allowed. */
105211767SAnurag.Maskey@Sun.COM 		nif->nwamd_if_ipv6_default_route.sin6_family = AF_INET6;
105311767SAnurag.Maskey@Sun.COM 		(void) inet_pton(AF_INET6, addrvalue[0],
105411767SAnurag.Maskey@Sun.COM 		    &(nif->nwamd_if_ipv6_default_route.sin6_addr));
105511767SAnurag.Maskey@Sun.COM 		nif->nwamd_if_ipv6_default_route_set = B_TRUE;
105611767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncu_prop);
105711767SAnurag.Maskey@Sun.COM 	}
105811767SAnurag.Maskey@Sun.COM 
105911767SAnurag.Maskey@Sun.COM skip_ipv6:
106011767SAnurag.Maskey@Sun.COM 	;
106111767SAnurag.Maskey@Sun.COM }
106211767SAnurag.Maskey@Sun.COM 
106311767SAnurag.Maskey@Sun.COM static nwamd_ncu_t *
nwamd_ncu_init(nwam_ncu_type_t ncu_type,const char * name)106411767SAnurag.Maskey@Sun.COM nwamd_ncu_init(nwam_ncu_type_t ncu_type, const char *name)
106511767SAnurag.Maskey@Sun.COM {
106611767SAnurag.Maskey@Sun.COM 	nwamd_ncu_t *rv;
106711767SAnurag.Maskey@Sun.COM 
106811767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_ncu_init(%d, %s)", ncu_type, name);
106911767SAnurag.Maskey@Sun.COM 
107011767SAnurag.Maskey@Sun.COM 	if ((rv = calloc(1, sizeof (*rv))) == NULL)
107111767SAnurag.Maskey@Sun.COM 		return (NULL);
107211767SAnurag.Maskey@Sun.COM 
107311767SAnurag.Maskey@Sun.COM 	rv->ncu_type = ncu_type;
107411767SAnurag.Maskey@Sun.COM 	rv->ncu_name = strdup(name);
107511767SAnurag.Maskey@Sun.COM 	rv->ncu_enabled = B_FALSE;
107611767SAnurag.Maskey@Sun.COM 
107711767SAnurag.Maskey@Sun.COM 	/* Initialize link/interface-specific data */
107811767SAnurag.Maskey@Sun.COM 	if (rv->ncu_type == NWAM_NCU_TYPE_LINK) {
107912576SAnurag.Maskey@Oracle.COM 		(void) bzero(&rv->ncu_link, sizeof (nwamd_link_t));
108011767SAnurag.Maskey@Sun.COM 		(void) dladm_name2info(dld_handle, name,
108112576SAnurag.Maskey@Oracle.COM 		    &rv->ncu_link.nwamd_link_id, NULL, NULL,
108212576SAnurag.Maskey@Oracle.COM 		    &rv->ncu_link.nwamd_link_media);
108311767SAnurag.Maskey@Sun.COM 		(void) pthread_mutex_init(
108412576SAnurag.Maskey@Oracle.COM 		    &rv->ncu_link.nwamd_link_wifi_mutex, NULL);
108512576SAnurag.Maskey@Oracle.COM 		rv->ncu_link.nwamd_link_wifi_priority = MAXINT;
108611767SAnurag.Maskey@Sun.COM 	} else {
108712576SAnurag.Maskey@Oracle.COM 		(void) bzero(&rv->ncu_if, sizeof (nwamd_if_t));
108811767SAnurag.Maskey@Sun.COM 	}
108911767SAnurag.Maskey@Sun.COM 
109011767SAnurag.Maskey@Sun.COM 	return (rv);
109111767SAnurag.Maskey@Sun.COM }
109211767SAnurag.Maskey@Sun.COM 
109311767SAnurag.Maskey@Sun.COM void
nwamd_ncu_free(nwamd_ncu_t * ncu)109411767SAnurag.Maskey@Sun.COM nwamd_ncu_free(nwamd_ncu_t *ncu)
109511767SAnurag.Maskey@Sun.COM {
109611767SAnurag.Maskey@Sun.COM 	if (ncu != NULL) {
109711767SAnurag.Maskey@Sun.COM 		assert(ncu->ncu_type == NWAM_NCU_TYPE_LINK ||
109811767SAnurag.Maskey@Sun.COM 		    ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE);
109911767SAnurag.Maskey@Sun.COM 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
110012576SAnurag.Maskey@Oracle.COM 			struct nwamd_link *l = &ncu->ncu_link;
110111767SAnurag.Maskey@Sun.COM 			int i;
110211767SAnurag.Maskey@Sun.COM 
110311767SAnurag.Maskey@Sun.COM 			free(l->nwamd_link_wifi_key);
110411767SAnurag.Maskey@Sun.COM 			free(l->nwamd_link_mac_addr);
110511767SAnurag.Maskey@Sun.COM 			for (i = 0; i < l->nwamd_link_num_autopush; i++)
110611767SAnurag.Maskey@Sun.COM 				free(l->nwamd_link_autopush[i]);
110711767SAnurag.Maskey@Sun.COM 		} else if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) {
110811767SAnurag.Maskey@Sun.COM 			struct nwamd_if_address *nifa;
110911767SAnurag.Maskey@Sun.COM 
111012576SAnurag.Maskey@Oracle.COM 			nifa = ncu->ncu_if.nwamd_if_list;
111111767SAnurag.Maskey@Sun.COM 			while (nifa != NULL) {
111211767SAnurag.Maskey@Sun.COM 				struct nwamd_if_address *n;
111311767SAnurag.Maskey@Sun.COM 
111411767SAnurag.Maskey@Sun.COM 				n = nifa;
111511767SAnurag.Maskey@Sun.COM 				nifa = nifa->next;
111612576SAnurag.Maskey@Oracle.COM 				ipadm_destroy_addrobj(n->ipaddr);
111711767SAnurag.Maskey@Sun.COM 				free(n);
111811767SAnurag.Maskey@Sun.COM 			}
111911767SAnurag.Maskey@Sun.COM 		}
112011767SAnurag.Maskey@Sun.COM 		free(ncu->ncu_name);
112111767SAnurag.Maskey@Sun.COM 		free(ncu);
112211767SAnurag.Maskey@Sun.COM 	}
112311767SAnurag.Maskey@Sun.COM }
112411767SAnurag.Maskey@Sun.COM 
112511767SAnurag.Maskey@Sun.COM static int
nwamd_ncu_display(nwamd_object_t ncu_obj,void * data)112611767SAnurag.Maskey@Sun.COM nwamd_ncu_display(nwamd_object_t ncu_obj, void *data)
112711767SAnurag.Maskey@Sun.COM {
112811767SAnurag.Maskey@Sun.COM 	nwamd_ncu_t *ncu = (nwamd_ncu_t *)ncu_obj->nwamd_object_data;
112911767SAnurag.Maskey@Sun.COM 	data = data;
113011767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "NCU (%p) %s state %s, %s",
113111767SAnurag.Maskey@Sun.COM 	    (void *)ncu, ncu_obj->nwamd_object_name,
113211767SAnurag.Maskey@Sun.COM 	    nwam_state_to_string(ncu_obj->nwamd_object_state),
113311767SAnurag.Maskey@Sun.COM 	    nwam_aux_state_to_string(ncu_obj->nwamd_object_aux_state));
113411767SAnurag.Maskey@Sun.COM 	return (0);
113511767SAnurag.Maskey@Sun.COM }
113611767SAnurag.Maskey@Sun.COM 
113711767SAnurag.Maskey@Sun.COM void
nwamd_log_ncus(void)113811767SAnurag.Maskey@Sun.COM nwamd_log_ncus(void)
113911767SAnurag.Maskey@Sun.COM {
114011767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "NCP %s", active_ncp);
114111767SAnurag.Maskey@Sun.COM 	(void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, nwamd_ncu_display,
114211767SAnurag.Maskey@Sun.COM 	    NULL);
114311767SAnurag.Maskey@Sun.COM }
114411767SAnurag.Maskey@Sun.COM 
114511767SAnurag.Maskey@Sun.COM int
nwamd_ncu_action(const char * ncu,const char * parent,nwam_action_t action)114611767SAnurag.Maskey@Sun.COM nwamd_ncu_action(const char *ncu, const char *parent, nwam_action_t action)
114711767SAnurag.Maskey@Sun.COM {
114811767SAnurag.Maskey@Sun.COM 	nwamd_event_t ncu_event = nwamd_event_init_object_action
114911767SAnurag.Maskey@Sun.COM 	    (NWAM_OBJECT_TYPE_NCU, ncu, parent, action);
115011767SAnurag.Maskey@Sun.COM 	if (ncu_event == NULL)
115111767SAnurag.Maskey@Sun.COM 		return (1);
115211767SAnurag.Maskey@Sun.COM 	nwamd_event_enqueue(ncu_event);
115311767SAnurag.Maskey@Sun.COM 	return (0);
115411767SAnurag.Maskey@Sun.COM }
115511767SAnurag.Maskey@Sun.COM 
115611767SAnurag.Maskey@Sun.COM static void
add_phys_ncu_to_ncp(nwam_ncp_handle_t ncph,const char * name)115711767SAnurag.Maskey@Sun.COM add_phys_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name)
115811767SAnurag.Maskey@Sun.COM {
115911767SAnurag.Maskey@Sun.COM 	dladm_status_t dlrtn;
116011767SAnurag.Maskey@Sun.COM 	uint32_t media;
116111767SAnurag.Maskey@Sun.COM 	boolean_t is_wireless;
116211767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
116311767SAnurag.Maskey@Sun.COM 	nwam_ncu_handle_t ncuh;
116411767SAnurag.Maskey@Sun.COM 	uint64_t uintval;
116511767SAnurag.Maskey@Sun.COM 
116611767SAnurag.Maskey@Sun.COM 	if ((dlrtn = dladm_name2info(dld_handle, name, NULL, NULL, NULL,
116711767SAnurag.Maskey@Sun.COM 	    &media)) != DLADM_STATUS_OK) {
116811767SAnurag.Maskey@Sun.COM 		char errmsg[DLADM_STRSIZE];
116911767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "failed to get media type for %s: %s", name,
117011767SAnurag.Maskey@Sun.COM 		    dladm_status2str(dlrtn, errmsg));
117111767SAnurag.Maskey@Sun.COM 		return;
117211767SAnurag.Maskey@Sun.COM 	}
117311767SAnurag.Maskey@Sun.COM 	is_wireless = (media == DL_WIFI);
117411767SAnurag.Maskey@Sun.COM 
117511767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_LINK,
117611767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_CLASS_PHYS, &ncuh)) != NWAM_SUCCESS) {
117711767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "failed to create link ncu for %s: %s", name,
117811767SAnurag.Maskey@Sun.COM 		    nwam_strerror(err));
117911767SAnurag.Maskey@Sun.COM 		if (err == NWAM_ENTITY_READ_ONLY) {
118011767SAnurag.Maskey@Sun.COM 			nwamd_event_t retry_event;
118111767SAnurag.Maskey@Sun.COM 
118211767SAnurag.Maskey@Sun.COM 			/*
118311767SAnurag.Maskey@Sun.COM 			 * Root filesystem may be read-only, retry in
118411767SAnurag.Maskey@Sun.COM 			 * a few seconds.
118511767SAnurag.Maskey@Sun.COM 			 */
118611767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "Retrying addition of phys ncu for %s",
118711767SAnurag.Maskey@Sun.COM 			    name);
118811767SAnurag.Maskey@Sun.COM 			retry_event = nwamd_event_init_link_action(name,
118911767SAnurag.Maskey@Sun.COM 			    NWAM_ACTION_ADD);
119011767SAnurag.Maskey@Sun.COM 			if (retry_event != NULL) {
119111767SAnurag.Maskey@Sun.COM 				nwamd_event_enqueue_timed(retry_event,
119211767SAnurag.Maskey@Sun.COM 				    NWAMD_READONLY_RETRY_INTERVAL);
119311767SAnurag.Maskey@Sun.COM 			}
119411767SAnurag.Maskey@Sun.COM 		}
119511767SAnurag.Maskey@Sun.COM 		return;
119611767SAnurag.Maskey@Sun.COM 	}
119711767SAnurag.Maskey@Sun.COM 
119811767SAnurag.Maskey@Sun.COM 	uintval = NWAM_ACTIVATION_MODE_PRIORITIZED;
119911767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
120011767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) {
120111767SAnurag.Maskey@Sun.COM 		goto finish;
120211767SAnurag.Maskey@Sun.COM 	}
120311767SAnurag.Maskey@Sun.COM 
120411767SAnurag.Maskey@Sun.COM 	uintval = is_wireless ? 1 : 0;
120511767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
120611767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_PRIORITY_GROUP)) != NWAM_SUCCESS) {
120711767SAnurag.Maskey@Sun.COM 		goto finish;
120811767SAnurag.Maskey@Sun.COM 	}
120911767SAnurag.Maskey@Sun.COM 
121011767SAnurag.Maskey@Sun.COM 	uintval = is_wireless ? NWAM_PRIORITY_MODE_EXCLUSIVE :
121111767SAnurag.Maskey@Sun.COM 	    NWAM_PRIORITY_MODE_SHARED;
121211767SAnurag.Maskey@Sun.COM 	if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
121311767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_PROP_PRIORITY_MODE)) != NWAM_SUCCESS) {
121411767SAnurag.Maskey@Sun.COM 		goto finish;
121511767SAnurag.Maskey@Sun.COM 	}
121611767SAnurag.Maskey@Sun.COM 
121711767SAnurag.Maskey@Sun.COM 	err = nwam_ncu_commit(ncuh, 0);
121811767SAnurag.Maskey@Sun.COM 
121911767SAnurag.Maskey@Sun.COM finish:
122011767SAnurag.Maskey@Sun.COM 	nwam_ncu_free(ncuh);
122111767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
122211767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR,
122311767SAnurag.Maskey@Sun.COM 		    "failed to create automatic link ncu for %s: %s",
122411767SAnurag.Maskey@Sun.COM 		    name, nwam_strerror(err));
122511767SAnurag.Maskey@Sun.COM 	}
122611767SAnurag.Maskey@Sun.COM }
122711767SAnurag.Maskey@Sun.COM 
122811767SAnurag.Maskey@Sun.COM static void
add_ip_ncu_to_ncp(nwam_ncp_handle_t ncph,const char * name)122911767SAnurag.Maskey@Sun.COM add_ip_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name)
123011767SAnurag.Maskey@Sun.COM {
123111767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
123211767SAnurag.Maskey@Sun.COM 	nwam_ncu_handle_t ncuh;
123311767SAnurag.Maskey@Sun.COM 
123411767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_INTERFACE,
123511767SAnurag.Maskey@Sun.COM 	    NWAM_NCU_CLASS_IP, &ncuh)) != NWAM_SUCCESS) {
123611767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "failed to create ip ncu for %s: %s", name,
123711767SAnurag.Maskey@Sun.COM 		    nwam_strerror(err));
123811767SAnurag.Maskey@Sun.COM 		/*
123911767SAnurag.Maskey@Sun.COM 		 * Root filesystem may be read-only, but no need to
124011767SAnurag.Maskey@Sun.COM 		 * retry here since add_phys_ncu_to_ncp() enqueues
124111767SAnurag.Maskey@Sun.COM 		 * a retry event which will lead to add_ip_ncu_to_ncp()
124211767SAnurag.Maskey@Sun.COM 		 * being called.
124311767SAnurag.Maskey@Sun.COM 		 */
124411767SAnurag.Maskey@Sun.COM 		return;
124511767SAnurag.Maskey@Sun.COM 	}
124611767SAnurag.Maskey@Sun.COM 
124711767SAnurag.Maskey@Sun.COM 	/* IP NCU has the default values, so nothing else to do */
124811767SAnurag.Maskey@Sun.COM 	err = nwam_ncu_commit(ncuh, 0);
124911767SAnurag.Maskey@Sun.COM 
125011767SAnurag.Maskey@Sun.COM finish:
125111767SAnurag.Maskey@Sun.COM 	nwam_ncu_free(ncuh);
125211767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
125311767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR,
125411767SAnurag.Maskey@Sun.COM 		    "failed to create ip ncu for %s: %s", name,
125511767SAnurag.Maskey@Sun.COM 		    nwam_strerror(err));
125611767SAnurag.Maskey@Sun.COM 	}
125711767SAnurag.Maskey@Sun.COM }
125811767SAnurag.Maskey@Sun.COM 
125911767SAnurag.Maskey@Sun.COM static void
remove_ncu_from_ncp(nwam_ncp_handle_t ncph,const char * name,nwam_ncu_type_t type)126011767SAnurag.Maskey@Sun.COM remove_ncu_from_ncp(nwam_ncp_handle_t ncph, const char *name,
126111767SAnurag.Maskey@Sun.COM     nwam_ncu_type_t type)
126211767SAnurag.Maskey@Sun.COM {
126311767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
126411767SAnurag.Maskey@Sun.COM 	nwam_ncu_handle_t ncuh;
126511767SAnurag.Maskey@Sun.COM 
126611767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_read(ncph, name, type, 0, &ncuh)) != NWAM_SUCCESS) {
126711767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "failed to read automatic ncu %s: %s", name,
126811767SAnurag.Maskey@Sun.COM 		    nwam_strerror(err));
126911767SAnurag.Maskey@Sun.COM 		return;
127011767SAnurag.Maskey@Sun.COM 	}
127111767SAnurag.Maskey@Sun.COM 
127211767SAnurag.Maskey@Sun.COM 	err = nwam_ncu_destroy(ncuh, 0);
127311767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
127411767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "failed to delete automatic ncu %s: %s", name,
127511767SAnurag.Maskey@Sun.COM 		    nwam_strerror(err));
127611767SAnurag.Maskey@Sun.COM 	}
127711767SAnurag.Maskey@Sun.COM }
127811767SAnurag.Maskey@Sun.COM 
127911767SAnurag.Maskey@Sun.COM /*
128011767SAnurag.Maskey@Sun.COM  * Device represented by NCU has been added or removed for the active
128111767SAnurag.Maskey@Sun.COM  * User NCP.  If an associated NCU of the given type is found, transition it
128211767SAnurag.Maskey@Sun.COM  * to the appropriate state.
128311767SAnurag.Maskey@Sun.COM  */
128411767SAnurag.Maskey@Sun.COM void
ncu_action_change_state(nwam_action_t action,nwam_ncu_type_t type,const char * name)128511767SAnurag.Maskey@Sun.COM ncu_action_change_state(nwam_action_t action, nwam_ncu_type_t type,
128611767SAnurag.Maskey@Sun.COM     const char *name)
128711767SAnurag.Maskey@Sun.COM {
128811767SAnurag.Maskey@Sun.COM 	nwamd_object_t ncu_obj = NULL;
128911767SAnurag.Maskey@Sun.COM 	nwamd_ncu_t *ncu;
129011767SAnurag.Maskey@Sun.COM 
129111767SAnurag.Maskey@Sun.COM 	if ((ncu_obj = nwamd_ncu_object_find(type, name)) == NULL)
129211767SAnurag.Maskey@Sun.COM 		return;
129311767SAnurag.Maskey@Sun.COM 
129411767SAnurag.Maskey@Sun.COM 	ncu = ncu_obj->nwamd_object_data;
129511767SAnurag.Maskey@Sun.COM 
129611767SAnurag.Maskey@Sun.COM 	/*
129711767SAnurag.Maskey@Sun.COM 	 * If device has been added, transition from uninitialized to offline.
129811767SAnurag.Maskey@Sun.COM 	 * If device has been removed, transition to uninitialized (via online*
129911767SAnurag.Maskey@Sun.COM 	 * if the NCU is currently enabled in order to tear down config).
130011767SAnurag.Maskey@Sun.COM 	 */
130111767SAnurag.Maskey@Sun.COM 	if (action == NWAM_ACTION_ADD) {
130211767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
130311767SAnurag.Maskey@Sun.COM 		    ncu_obj->nwamd_object_name,
130411767SAnurag.Maskey@Sun.COM 		    NWAM_STATE_OFFLINE, NWAM_AUX_STATE_CONDITIONS_NOT_MET);
130511767SAnurag.Maskey@Sun.COM 	} else {
130611767SAnurag.Maskey@Sun.COM 		if (ncu->ncu_enabled) {
130711767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
130811767SAnurag.Maskey@Sun.COM 			    ncu_obj->nwamd_object_name,
130911767SAnurag.Maskey@Sun.COM 			    NWAM_STATE_ONLINE_TO_OFFLINE,
131011767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_NOT_FOUND);
131111767SAnurag.Maskey@Sun.COM 		} else {
131211767SAnurag.Maskey@Sun.COM 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
131311767SAnurag.Maskey@Sun.COM 			    ncu_obj->nwamd_object_name,
131411767SAnurag.Maskey@Sun.COM 			    NWAM_STATE_UNINITIALIZED,
131511767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_NOT_FOUND);
131611767SAnurag.Maskey@Sun.COM 		}
131711767SAnurag.Maskey@Sun.COM 	}
131811767SAnurag.Maskey@Sun.COM 	nwamd_object_release(ncu_obj);
131911767SAnurag.Maskey@Sun.COM }
132011767SAnurag.Maskey@Sun.COM 
132111767SAnurag.Maskey@Sun.COM /*
132211767SAnurag.Maskey@Sun.COM  * Called with hotplug sysevent or when nwam is started and walking the
132311767SAnurag.Maskey@Sun.COM  * physical interfaces.  Add/remove both link and interface NCUs from the
132411767SAnurag.Maskey@Sun.COM  * Automatic NCP.  Assumes that both link and interface NCUs don't exist.
132511767SAnurag.Maskey@Sun.COM  */
132611767SAnurag.Maskey@Sun.COM void
nwamd_ncu_handle_link_action_event(nwamd_event_t event)132711767SAnurag.Maskey@Sun.COM nwamd_ncu_handle_link_action_event(nwamd_event_t event)
132811767SAnurag.Maskey@Sun.COM {
132911767SAnurag.Maskey@Sun.COM 	nwam_ncp_handle_t ncph;
133011767SAnurag.Maskey@Sun.COM 	nwam_ncu_type_t type;
133111767SAnurag.Maskey@Sun.COM 	nwam_action_t action =
133211767SAnurag.Maskey@Sun.COM 	    event->event_msg->nwe_data.nwe_link_action.nwe_action;
133311767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
133411767SAnurag.Maskey@Sun.COM 	char *name;
133511767SAnurag.Maskey@Sun.COM 	boolean_t automatic_ncp_active = B_FALSE;
133611767SAnurag.Maskey@Sun.COM 
133711767SAnurag.Maskey@Sun.COM 	if (action != NWAM_ACTION_ADD && action != NWAM_ACTION_REMOVE) {
133811767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
133911767SAnurag.Maskey@Sun.COM 		    "invalid link action %s", nwam_action_to_string(action));
134011767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
134111767SAnurag.Maskey@Sun.COM 		return;
134211767SAnurag.Maskey@Sun.COM 	}
134311767SAnurag.Maskey@Sun.COM 
134411767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_ncu_handle_link_action_event: "
134511767SAnurag.Maskey@Sun.COM 	    "link action '%s' event on %s", nwam_action_to_string(action),
134611767SAnurag.Maskey@Sun.COM 	    event->event_object[0] == 0 ? "n/a" : event->event_object);
134711767SAnurag.Maskey@Sun.COM 
134811767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncu_typed_name_to_name(event->event_object, &type,
134911767SAnurag.Maskey@Sun.COM 	    &name)) != NWAM_SUCCESS) {
135011767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
135111767SAnurag.Maskey@Sun.COM 		    "translation from typedname error: %s", nwam_strerror(err));
135211767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
135311767SAnurag.Maskey@Sun.COM 		return;
135411767SAnurag.Maskey@Sun.COM 	}
135511767SAnurag.Maskey@Sun.COM 
135611767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_lock(&active_ncp_mutex);
135711767SAnurag.Maskey@Sun.COM 	if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 &&
135811767SAnurag.Maskey@Sun.COM 	    active_ncph != NULL) {
135911767SAnurag.Maskey@Sun.COM 		automatic_ncp_active = B_TRUE;
136011767SAnurag.Maskey@Sun.COM 	}
136111767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_unlock(&active_ncp_mutex);
136211767SAnurag.Maskey@Sun.COM 
136311767SAnurag.Maskey@Sun.COM 	/*
136411767SAnurag.Maskey@Sun.COM 	 * We could use active_ncph for cases where the Automatic NCP is active,
136511767SAnurag.Maskey@Sun.COM 	 * but that would involve holding the active_ncp_mutex for too long.
136611767SAnurag.Maskey@Sun.COM 	 */
136711767SAnurag.Maskey@Sun.COM 	if ((err = nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph))
136811767SAnurag.Maskey@Sun.COM 	    == NWAM_ENTITY_NOT_FOUND) {
136911767SAnurag.Maskey@Sun.COM 		/* Automatic NCP doesn't exist, create it */
137012371SAnurag.Maskey@Oracle.COM 		err = nwam_ncp_create(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph);
137111767SAnurag.Maskey@Sun.COM 	}
137212371SAnurag.Maskey@Oracle.COM 	if (err != NWAM_SUCCESS)
137312371SAnurag.Maskey@Oracle.COM 		goto fail;
137411767SAnurag.Maskey@Sun.COM 
137511767SAnurag.Maskey@Sun.COM 	/* add or remove NCUs from Automatic NCP */
137611767SAnurag.Maskey@Sun.COM 	if (action == NWAM_ACTION_ADD) {
137711767SAnurag.Maskey@Sun.COM 		add_phys_ncu_to_ncp(ncph, name);
137811767SAnurag.Maskey@Sun.COM 		add_ip_ncu_to_ncp(ncph, name);
137911767SAnurag.Maskey@Sun.COM 	} else {
138011767SAnurag.Maskey@Sun.COM 		/*
138111767SAnurag.Maskey@Sun.COM 		 * Order is important here, remove IP NCU first to prevent
138211767SAnurag.Maskey@Sun.COM 		 * propogation of down event from link to IP.  No need to
138311767SAnurag.Maskey@Sun.COM 		 * create REFRESH or DESTROY events.  They are generated by
138411767SAnurag.Maskey@Sun.COM 		 * nwam_ncu_commit() and nwam_ncu_destroy().
138511767SAnurag.Maskey@Sun.COM 		 */
138611767SAnurag.Maskey@Sun.COM 		remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_INTERFACE);
138711767SAnurag.Maskey@Sun.COM 		remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_LINK);
138811767SAnurag.Maskey@Sun.COM 	}
138911767SAnurag.Maskey@Sun.COM 	nwam_ncp_free(ncph);
139011767SAnurag.Maskey@Sun.COM 
139111767SAnurag.Maskey@Sun.COM 	/*
139211767SAnurag.Maskey@Sun.COM 	 * If the Automatic NCP is not active, and the associated NCUs
139311767SAnurag.Maskey@Sun.COM 	 * exist, they must be moved into the appropriate states given the
139411767SAnurag.Maskey@Sun.COM 	 * action that has occurred.
139511767SAnurag.Maskey@Sun.COM 	 */
139611767SAnurag.Maskey@Sun.COM 	if (!automatic_ncp_active) {
139711767SAnurag.Maskey@Sun.COM 		ncu_action_change_state(action, NWAM_NCU_TYPE_INTERFACE, name);
139811767SAnurag.Maskey@Sun.COM 		ncu_action_change_state(action, NWAM_NCU_TYPE_LINK, name);
139911767SAnurag.Maskey@Sun.COM 	}
140011767SAnurag.Maskey@Sun.COM 
140111767SAnurag.Maskey@Sun.COM 	/* Need NCU check to evaluate state in light of added/removed NCUs */
140211767SAnurag.Maskey@Sun.COM 	if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK,
140311767SAnurag.Maskey@Sun.COM 	    NWAM_OBJECT_TYPE_NCP, NULL)) {
140411767SAnurag.Maskey@Sun.COM 		nwamd_create_ncu_check_event(NEXT_FEW_SECONDS);
140511767SAnurag.Maskey@Sun.COM 	}
140611767SAnurag.Maskey@Sun.COM 
140712371SAnurag.Maskey@Oracle.COM fail:
140811767SAnurag.Maskey@Sun.COM 	free(name);
140912371SAnurag.Maskey@Oracle.COM 	if (err != NWAM_SUCCESS) {
141012371SAnurag.Maskey@Oracle.COM 		nwamd_event_t retry_event = nwamd_event_init_link_action(name,
141112371SAnurag.Maskey@Oracle.COM 		    action);
141212371SAnurag.Maskey@Oracle.COM 		if (retry_event == NULL) {
141312371SAnurag.Maskey@Oracle.COM 			nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
141412371SAnurag.Maskey@Oracle.COM 			    "could not create retry event to read/create "
141512371SAnurag.Maskey@Oracle.COM 			    "%s NCP", NWAM_NCP_NAME_AUTOMATIC);
141612371SAnurag.Maskey@Oracle.COM 			return;
141712371SAnurag.Maskey@Oracle.COM 		}
141812371SAnurag.Maskey@Oracle.COM 
141912371SAnurag.Maskey@Oracle.COM 		nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
142012371SAnurag.Maskey@Oracle.COM 		    "could not read/create %s NCP, retrying in %d seconds",
142112371SAnurag.Maskey@Oracle.COM 		    NWAM_NCP_NAME_AUTOMATIC, NWAMD_READONLY_RETRY_INTERVAL);
142212371SAnurag.Maskey@Oracle.COM 		nwamd_event_enqueue_timed(retry_event,
142312371SAnurag.Maskey@Oracle.COM 		    NWAMD_READONLY_RETRY_INTERVAL);
142412371SAnurag.Maskey@Oracle.COM 	}
142511767SAnurag.Maskey@Sun.COM }
142611767SAnurag.Maskey@Sun.COM 
142711767SAnurag.Maskey@Sun.COM /*
142811767SAnurag.Maskey@Sun.COM  * Figure out if this link is part of an aggregation.  This is fairly
142911767SAnurag.Maskey@Sun.COM  * inefficient since we generate this list for every query and search
143011767SAnurag.Maskey@Sun.COM  * linearly.  A better way would be to generate the list of links in an
143111767SAnurag.Maskey@Sun.COM  * aggregation once and then check each link against it.
143211767SAnurag.Maskey@Sun.COM  */
143311767SAnurag.Maskey@Sun.COM struct link_aggr_search_data {
143411767SAnurag.Maskey@Sun.COM 	datalink_id_t linkid;
143511767SAnurag.Maskey@Sun.COM 	boolean_t under;
143611767SAnurag.Maskey@Sun.COM };
143711767SAnurag.Maskey@Sun.COM 
143811767SAnurag.Maskey@Sun.COM static int
ncu_aggr_search(const char * name,void * data)143911767SAnurag.Maskey@Sun.COM ncu_aggr_search(const char *name, void *data)
144011767SAnurag.Maskey@Sun.COM {
144111767SAnurag.Maskey@Sun.COM 	struct link_aggr_search_data *lasd = data;
144211767SAnurag.Maskey@Sun.COM 	dladm_aggr_grp_attr_t ginfo;
144311767SAnurag.Maskey@Sun.COM 	datalink_id_t linkid;
144411767SAnurag.Maskey@Sun.COM 	int i;
144511767SAnurag.Maskey@Sun.COM 
144611767SAnurag.Maskey@Sun.COM 	if (dladm_name2info(dld_handle, name, &linkid, NULL, NULL, NULL) !=
144711767SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK)
144811767SAnurag.Maskey@Sun.COM 		return (DLADM_WALK_CONTINUE);
144911767SAnurag.Maskey@Sun.COM 	if (dladm_aggr_info(dld_handle, linkid, &ginfo, DLADM_OPT_ACTIVE)
145011767SAnurag.Maskey@Sun.COM 	    != DLADM_STATUS_OK || ginfo.lg_nports == 0)
145111767SAnurag.Maskey@Sun.COM 		return (DLADM_WALK_CONTINUE);
145211767SAnurag.Maskey@Sun.COM 
145311767SAnurag.Maskey@Sun.COM 	for (i = 0; i < ginfo.lg_nports; i++) {
145411767SAnurag.Maskey@Sun.COM 		if (lasd->linkid == ginfo.lg_ports[i].lp_linkid) {
145511767SAnurag.Maskey@Sun.COM 			lasd->under = B_TRUE;
145611767SAnurag.Maskey@Sun.COM 			return (DLADM_WALK_TERMINATE);
145711767SAnurag.Maskey@Sun.COM 		}
145811767SAnurag.Maskey@Sun.COM 	}
145911767SAnurag.Maskey@Sun.COM 	free(ginfo.lg_ports);
146011767SAnurag.Maskey@Sun.COM 	return (DLADM_WALK_CONTINUE);
146111767SAnurag.Maskey@Sun.COM }
146211767SAnurag.Maskey@Sun.COM 
146311767SAnurag.Maskey@Sun.COM static boolean_t
nwamd_link_belongs_to_an_aggr(const char * name)146411767SAnurag.Maskey@Sun.COM nwamd_link_belongs_to_an_aggr(const char *name)
146511767SAnurag.Maskey@Sun.COM {
146611767SAnurag.Maskey@Sun.COM 	struct link_aggr_search_data lasd;
146711767SAnurag.Maskey@Sun.COM 
146811767SAnurag.Maskey@Sun.COM 	if (dladm_name2info(dld_handle, name, &lasd.linkid, NULL, NULL, NULL)
146911767SAnurag.Maskey@Sun.COM 	    != DLADM_STATUS_OK)
147011767SAnurag.Maskey@Sun.COM 		return (B_FALSE);
147111767SAnurag.Maskey@Sun.COM 	lasd.under = B_FALSE;
147211767SAnurag.Maskey@Sun.COM 	(void) dladm_walk(ncu_aggr_search, dld_handle, &lasd,
147311767SAnurag.Maskey@Sun.COM 	    DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
147411767SAnurag.Maskey@Sun.COM 	return (lasd.under);
147511767SAnurag.Maskey@Sun.COM }
147611767SAnurag.Maskey@Sun.COM 
147711767SAnurag.Maskey@Sun.COM /*
147811767SAnurag.Maskey@Sun.COM  * If NCU doesn't exist for interface with given name, enqueue a ADD
147911767SAnurag.Maskey@Sun.COM  * LINK_ACTION event.
148011767SAnurag.Maskey@Sun.COM  */
148111767SAnurag.Maskey@Sun.COM static int
ncu_create_link_action_event(const char * name,void * data)148211767SAnurag.Maskey@Sun.COM ncu_create_link_action_event(const char *name, void *data)
148311767SAnurag.Maskey@Sun.COM {
148411767SAnurag.Maskey@Sun.COM 	nwam_ncp_handle_t ncph = data;
148511767SAnurag.Maskey@Sun.COM 	nwam_ncu_handle_t ncuh;
148611767SAnurag.Maskey@Sun.COM 	nwamd_event_t link_event;
148711767SAnurag.Maskey@Sun.COM 
148811767SAnurag.Maskey@Sun.COM 	/* Do not generate an event if this is a VirtualBox interface. */
148911767SAnurag.Maskey@Sun.COM 	if (strncmp(name, VBOX_IFACE_PREFIX, strlen(VBOX_IFACE_PREFIX)) == 0)
149011767SAnurag.Maskey@Sun.COM 		return (DLADM_WALK_CONTINUE);
149111767SAnurag.Maskey@Sun.COM 
149211767SAnurag.Maskey@Sun.COM 	/* Do not generate an event if this link belongs to another zone. */
149311767SAnurag.Maskey@Sun.COM 	if (!nwamd_link_belongs_to_this_zone(name))
149411767SAnurag.Maskey@Sun.COM 		return (DLADM_WALK_CONTINUE);
149511767SAnurag.Maskey@Sun.COM 
149611767SAnurag.Maskey@Sun.COM 	/* Do not generate an event if this link belongs to an aggregation. */
149711767SAnurag.Maskey@Sun.COM 	if (nwamd_link_belongs_to_an_aggr(name)) {
149811767SAnurag.Maskey@Sun.COM 		return (DLADM_WALK_CONTINUE);
149911767SAnurag.Maskey@Sun.COM 	}
150011767SAnurag.Maskey@Sun.COM 
150111767SAnurag.Maskey@Sun.COM 	/* Don't create an event if the NCU already exists. */
150211767SAnurag.Maskey@Sun.COM 	if (ncph != NULL && nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK, 0,
150311767SAnurag.Maskey@Sun.COM 	    &ncuh) == NWAM_SUCCESS) {
150411767SAnurag.Maskey@Sun.COM 		nwam_ncu_free(ncuh);
150511767SAnurag.Maskey@Sun.COM 		return (DLADM_WALK_CONTINUE);
150611767SAnurag.Maskey@Sun.COM 	}
150711767SAnurag.Maskey@Sun.COM 
150811767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "ncu_create_link_action_event: adding ncus for %s",
150911767SAnurag.Maskey@Sun.COM 	    name);
151011767SAnurag.Maskey@Sun.COM 
151111767SAnurag.Maskey@Sun.COM 	link_event = nwamd_event_init_link_action(name, NWAM_ACTION_ADD);
151211767SAnurag.Maskey@Sun.COM 	if (link_event != NULL)
151311767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue(link_event);
151411767SAnurag.Maskey@Sun.COM 
151511767SAnurag.Maskey@Sun.COM 	return (DLADM_WALK_CONTINUE);
151611767SAnurag.Maskey@Sun.COM }
151711767SAnurag.Maskey@Sun.COM 
151811767SAnurag.Maskey@Sun.COM /*
151911767SAnurag.Maskey@Sun.COM  * Check if interface exists for this NCU. If not, enqueue a REMOVE
152011767SAnurag.Maskey@Sun.COM  * LINK_ACTION event.
152111767SAnurag.Maskey@Sun.COM  */
152211767SAnurag.Maskey@Sun.COM /* ARGSUSED */
152311767SAnurag.Maskey@Sun.COM static int
nwamd_destroy_ncu(nwam_ncu_handle_t ncuh,void * data)152411767SAnurag.Maskey@Sun.COM nwamd_destroy_ncu(nwam_ncu_handle_t ncuh, void *data)
152511767SAnurag.Maskey@Sun.COM {
152611767SAnurag.Maskey@Sun.COM 	char *name;
152711767SAnurag.Maskey@Sun.COM 	uint32_t flags;
152811767SAnurag.Maskey@Sun.COM 	nwamd_event_t link_event;
152911767SAnurag.Maskey@Sun.COM 
153011767SAnurag.Maskey@Sun.COM 	if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) {
153111767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_destroy_ncu: could not get NCU name");
153211767SAnurag.Maskey@Sun.COM 		return (0);
153311767SAnurag.Maskey@Sun.COM 	}
153411767SAnurag.Maskey@Sun.COM 
153511767SAnurag.Maskey@Sun.COM 	/* Interfaces that exist return DLADM_OPT_ACTIVE flag */
153611767SAnurag.Maskey@Sun.COM 	if ((dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL)
153711767SAnurag.Maskey@Sun.COM 	    == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) &&
153811767SAnurag.Maskey@Sun.COM 	    !nwamd_link_belongs_to_an_aggr(name)) {
153911767SAnurag.Maskey@Sun.COM 		free(name);
154011767SAnurag.Maskey@Sun.COM 		return (0);
154111767SAnurag.Maskey@Sun.COM 	}
154211767SAnurag.Maskey@Sun.COM 
154311767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_destroy_ncu: destroying ncus for %s", name);
154411767SAnurag.Maskey@Sun.COM 
154511767SAnurag.Maskey@Sun.COM 	link_event = nwamd_event_init_link_action(name, NWAM_ACTION_REMOVE);
154611767SAnurag.Maskey@Sun.COM 	if (link_event != NULL)
154711767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue(link_event);
154811767SAnurag.Maskey@Sun.COM 	free(name);
154911767SAnurag.Maskey@Sun.COM 	return (0);
155011767SAnurag.Maskey@Sun.COM }
155111767SAnurag.Maskey@Sun.COM 
155211767SAnurag.Maskey@Sun.COM /*
155311767SAnurag.Maskey@Sun.COM  * Called when nwamd is starting up.
155411767SAnurag.Maskey@Sun.COM  *
155511767SAnurag.Maskey@Sun.COM  * Walk all NCUs and destroy any NCU from the Automatic NCP without an
155611767SAnurag.Maskey@Sun.COM  * underlying interface (assumption here is that the interface was removed
155711767SAnurag.Maskey@Sun.COM  * when nwam was disabled).
155811767SAnurag.Maskey@Sun.COM  *
155911767SAnurag.Maskey@Sun.COM  * Walk the physical interfaces and create ADD LINK_ACTION event, which
156011767SAnurag.Maskey@Sun.COM  * will create appropriate interface and link NCUs in the Automatic NCP.
156111767SAnurag.Maskey@Sun.COM  */
156211767SAnurag.Maskey@Sun.COM void
nwamd_walk_physical_configuration(void)156311767SAnurag.Maskey@Sun.COM nwamd_walk_physical_configuration(void)
156411767SAnurag.Maskey@Sun.COM {
156511767SAnurag.Maskey@Sun.COM 	nwam_ncp_handle_t ncph;
1566*12953SRishi.Srivatsavai@Sun.COM 	datalink_class_t dlclass = DATALINK_CLASS_PHYS;
1567*12953SRishi.Srivatsavai@Sun.COM 	zoneid_t zoneid = getzoneid();
156811767SAnurag.Maskey@Sun.COM 
156911767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_lock(&active_ncp_mutex);
157011767SAnurag.Maskey@Sun.COM 	if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 &&
157111767SAnurag.Maskey@Sun.COM 	    active_ncph != NULL) {
157211767SAnurag.Maskey@Sun.COM 		ncph = active_ncph;
157311767SAnurag.Maskey@Sun.COM 	} else {
157411767SAnurag.Maskey@Sun.COM 		if (nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph)
157511767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS) {
157611767SAnurag.Maskey@Sun.COM 			ncph = NULL;
157711767SAnurag.Maskey@Sun.COM 		}
157811767SAnurag.Maskey@Sun.COM 	}
157911767SAnurag.Maskey@Sun.COM 
158011767SAnurag.Maskey@Sun.COM 	/* destroy NCUs for interfaces that don't exist */
158111767SAnurag.Maskey@Sun.COM 	if (ncph != NULL) {
158211767SAnurag.Maskey@Sun.COM 		(void) nwam_ncp_walk_ncus(ncph, nwamd_destroy_ncu, NULL,
158311767SAnurag.Maskey@Sun.COM 		    NWAM_FLAG_NCU_TYPE_LINK, NULL);
158411767SAnurag.Maskey@Sun.COM 	}
158511767SAnurag.Maskey@Sun.COM 
1586*12953SRishi.Srivatsavai@Sun.COM 	/* In non-global zones NWAM can support VNICs */
1587*12953SRishi.Srivatsavai@Sun.COM 	if (zoneid != GLOBAL_ZONEID)
1588*12953SRishi.Srivatsavai@Sun.COM 		dlclass |= DATALINK_CLASS_VNIC;
1589*12953SRishi.Srivatsavai@Sun.COM 
159011767SAnurag.Maskey@Sun.COM 	/* create NCUs for interfaces without NCUs */
159111767SAnurag.Maskey@Sun.COM 	(void) dladm_walk(ncu_create_link_action_event, dld_handle, ncph,
1592*12953SRishi.Srivatsavai@Sun.COM 	    dlclass, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
159311767SAnurag.Maskey@Sun.COM 
159411767SAnurag.Maskey@Sun.COM 	if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) != 0 ||
159511767SAnurag.Maskey@Sun.COM 	    active_ncph == NULL) {
159611767SAnurag.Maskey@Sun.COM 		nwam_ncp_free(ncph);
159711767SAnurag.Maskey@Sun.COM 	}
159811767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_unlock(&active_ncp_mutex);
159911767SAnurag.Maskey@Sun.COM }
160011767SAnurag.Maskey@Sun.COM 
160111767SAnurag.Maskey@Sun.COM /*
160211767SAnurag.Maskey@Sun.COM  * Handle NCU initialization/refresh event.
160311767SAnurag.Maskey@Sun.COM  */
160411767SAnurag.Maskey@Sun.COM void
nwamd_ncu_handle_init_event(nwamd_event_t event)160511767SAnurag.Maskey@Sun.COM nwamd_ncu_handle_init_event(nwamd_event_t event)
160611767SAnurag.Maskey@Sun.COM {
160711767SAnurag.Maskey@Sun.COM 	nwamd_object_t object = NULL;
160811767SAnurag.Maskey@Sun.COM 	nwam_ncu_handle_t ncuh;
160911767SAnurag.Maskey@Sun.COM 	nwamd_ncu_t *ncu = NULL;
161011767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
161111767SAnurag.Maskey@Sun.COM 	nwam_ncu_type_t type;
161211767SAnurag.Maskey@Sun.COM 	char *name;
161311767SAnurag.Maskey@Sun.COM 	uint32_t flags;
161411767SAnurag.Maskey@Sun.COM 	boolean_t new = B_TRUE;
161511767SAnurag.Maskey@Sun.COM 
161611767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event(%s)",
161711767SAnurag.Maskey@Sun.COM 	    event->event_object);
161811767SAnurag.Maskey@Sun.COM 
161911767SAnurag.Maskey@Sun.COM 	/* Get base linkname rather than interface:linkname or link:linkname */
162011767SAnurag.Maskey@Sun.COM 	err = nwam_ncu_typed_name_to_name(event->event_object,
162111767SAnurag.Maskey@Sun.COM 	    &type, &name);
162211767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
162311767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_ncu_handle_init_event: "
162411767SAnurag.Maskey@Sun.COM 		    "nwam_ncu_typed_name_to_name returned %s",
162511767SAnurag.Maskey@Sun.COM 		    nwam_strerror(err));
162611767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
162711767SAnurag.Maskey@Sun.COM 		return;
162811767SAnurag.Maskey@Sun.COM 	}
162911767SAnurag.Maskey@Sun.COM 
163011767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_lock(&active_ncp_mutex);
163111767SAnurag.Maskey@Sun.COM 	if (active_ncph == NULL) {
163211767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG,
163311767SAnurag.Maskey@Sun.COM 		    "nwamd_ncu_handle_init_event: active NCP handle NULL");
163411767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
163512371SAnurag.Maskey@Oracle.COM 		free(name);
163611767SAnurag.Maskey@Sun.COM 		(void) pthread_mutex_unlock(&active_ncp_mutex);
163711767SAnurag.Maskey@Sun.COM 		return;
163811767SAnurag.Maskey@Sun.COM 	}
163911767SAnurag.Maskey@Sun.COM 	err = nwam_ncu_read(active_ncph, event->event_object,
164011767SAnurag.Maskey@Sun.COM 	    type, 0, &ncuh);
164111767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_unlock(&active_ncp_mutex);
164211767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
164311767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "nwamd_ncu_handle_init_event: "
164411767SAnurag.Maskey@Sun.COM 		    "could not read object '%s': %s",
164511767SAnurag.Maskey@Sun.COM 		    event->event_object, nwam_strerror(err));
164611767SAnurag.Maskey@Sun.COM 		free(name);
164711767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
164811767SAnurag.Maskey@Sun.COM 		return;
164911767SAnurag.Maskey@Sun.COM 	}
165011767SAnurag.Maskey@Sun.COM 
165111767SAnurag.Maskey@Sun.COM 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
165211767SAnurag.Maskey@Sun.COM 	    event->event_object)) != NULL)
165311767SAnurag.Maskey@Sun.COM 		new = B_FALSE;
165411767SAnurag.Maskey@Sun.COM 
165511767SAnurag.Maskey@Sun.COM 	/*
165611767SAnurag.Maskey@Sun.COM 	 * For new NCUs, or interface NCUs, we (re)initialize data from scratch.
165711767SAnurag.Maskey@Sun.COM 	 * For link NCUs, we want to retain object data.
165811767SAnurag.Maskey@Sun.COM 	 */
165911767SAnurag.Maskey@Sun.COM 	switch (type) {
166011767SAnurag.Maskey@Sun.COM 	case NWAM_NCU_TYPE_LINK:
166111767SAnurag.Maskey@Sun.COM 		if (new) {
166211767SAnurag.Maskey@Sun.COM 			ncu = nwamd_ncu_init(type, name);
166311767SAnurag.Maskey@Sun.COM 		} else {
166411767SAnurag.Maskey@Sun.COM 			ncu = object->nwamd_object_data;
166511767SAnurag.Maskey@Sun.COM 			nwam_ncu_free(object->nwamd_object_handle);
166611767SAnurag.Maskey@Sun.COM 		}
166711767SAnurag.Maskey@Sun.COM 		populate_common_ncu_properties(ncuh, ncu);
166811767SAnurag.Maskey@Sun.COM 		populate_link_ncu_properties(ncuh, ncu);
166911767SAnurag.Maskey@Sun.COM 		break;
167011767SAnurag.Maskey@Sun.COM 	case NWAM_NCU_TYPE_INTERFACE:
167111767SAnurag.Maskey@Sun.COM 		if (!new) {
167211767SAnurag.Maskey@Sun.COM 			nwam_ncu_free(object->nwamd_object_handle);
167311767SAnurag.Maskey@Sun.COM 			nwamd_ncu_free(object->nwamd_object_data);
167411767SAnurag.Maskey@Sun.COM 		}
167511767SAnurag.Maskey@Sun.COM 		ncu = nwamd_ncu_init(type, name);
167611767SAnurag.Maskey@Sun.COM 		populate_common_ncu_properties(ncuh, ncu);
167711767SAnurag.Maskey@Sun.COM 		populate_ip_ncu_properties(ncuh, ncu);
167811767SAnurag.Maskey@Sun.COM 		break;
167911767SAnurag.Maskey@Sun.COM 	default:
168011767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "unknown ncu type %d", type);
168111767SAnurag.Maskey@Sun.COM 		free(name);
168211767SAnurag.Maskey@Sun.COM 		nwam_ncu_free(ncuh);
168311767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
168411767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
168511767SAnurag.Maskey@Sun.COM 		return;
168611767SAnurag.Maskey@Sun.COM 	}
168711767SAnurag.Maskey@Sun.COM 
168811767SAnurag.Maskey@Sun.COM 	if (new) {
168911767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: didn't find "
169011767SAnurag.Maskey@Sun.COM 		    "ncu so create it %s", name);
169111767SAnurag.Maskey@Sun.COM 		object = nwamd_object_init(NWAM_OBJECT_TYPE_NCU,
169211767SAnurag.Maskey@Sun.COM 		    event->event_object, ncuh, ncu);
169311767SAnurag.Maskey@Sun.COM 	} else {
169411767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: refreshing "
169511767SAnurag.Maskey@Sun.COM 		    "ncu %s", name);
169611767SAnurag.Maskey@Sun.COM 		object->nwamd_object_data = ncu;
169711767SAnurag.Maskey@Sun.COM 		object->nwamd_object_handle = ncuh;
169811767SAnurag.Maskey@Sun.COM 	}
169911767SAnurag.Maskey@Sun.COM 
170011767SAnurag.Maskey@Sun.COM 	/*
170111767SAnurag.Maskey@Sun.COM 	 * If the physical link for this NCU doesn't exist in the system,
170211767SAnurag.Maskey@Sun.COM 	 * the state should be UNINITIALIZED/NOT_FOUND.  Interfaces that
170311767SAnurag.Maskey@Sun.COM 	 * exist return DLADM_OPT_ACTIVE flag.
170411767SAnurag.Maskey@Sun.COM 	 */
170511767SAnurag.Maskey@Sun.COM 	if (dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL)
170611767SAnurag.Maskey@Sun.COM 	    != DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) {
170711767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwam_ncu_handle_init_event: "
170811767SAnurag.Maskey@Sun.COM 		    "interface for NCU %s doesn't exist",
170911767SAnurag.Maskey@Sun.COM 		    event->event_object);
171011767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
171111767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name, NWAM_STATE_UNINITIALIZED,
171211767SAnurag.Maskey@Sun.COM 		    NWAM_AUX_STATE_NOT_FOUND);
171311767SAnurag.Maskey@Sun.COM 		free(name);
171411767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
171511767SAnurag.Maskey@Sun.COM 		return;
171611767SAnurag.Maskey@Sun.COM 	}
171711767SAnurag.Maskey@Sun.COM 
171811767SAnurag.Maskey@Sun.COM 	/*
171911767SAnurag.Maskey@Sun.COM 	 * If NCU is being initialized (rather than refreshed), the
172011767SAnurag.Maskey@Sun.COM 	 * object_state is INITIALIZED (from nwamd_object_init()).
172111767SAnurag.Maskey@Sun.COM 	 */
172211767SAnurag.Maskey@Sun.COM 	if (object->nwamd_object_state == NWAM_STATE_INITIALIZED) {
172311767SAnurag.Maskey@Sun.COM 		/*
172411767SAnurag.Maskey@Sun.COM 		 * If the NCU is disabled, initial state should be DISABLED.
172511767SAnurag.Maskey@Sun.COM 		 *
172611767SAnurag.Maskey@Sun.COM 		 * Otherwise, the initial state will be
172711767SAnurag.Maskey@Sun.COM 		 * OFFLINE/CONDITIONS_NOT_MET, and the link selection
172811767SAnurag.Maskey@Sun.COM 		 * algorithm will do the rest.
172911767SAnurag.Maskey@Sun.COM 		 */
173011767SAnurag.Maskey@Sun.COM 		if (!ncu->ncu_enabled) {
173111767SAnurag.Maskey@Sun.COM 			object->nwamd_object_state = NWAM_STATE_DISABLED;
173211767SAnurag.Maskey@Sun.COM 			object->nwamd_object_aux_state =
173311767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_MANUAL_DISABLE;
173411767SAnurag.Maskey@Sun.COM 		} else {
173511767SAnurag.Maskey@Sun.COM 			object->nwamd_object_state = NWAM_STATE_OFFLINE;
173611767SAnurag.Maskey@Sun.COM 			object->nwamd_object_aux_state =
173711767SAnurag.Maskey@Sun.COM 			    NWAM_AUX_STATE_CONDITIONS_NOT_MET;
173811767SAnurag.Maskey@Sun.COM 		}
173911767SAnurag.Maskey@Sun.COM 	} else {
174012576SAnurag.Maskey@Oracle.COM 		nwamd_link_t *link = &ncu->ncu_link;
174111767SAnurag.Maskey@Sun.COM 
174211767SAnurag.Maskey@Sun.COM 		/*
174311767SAnurag.Maskey@Sun.COM 		 * Refresh NCU.  Deal with disabled cases first, moving NCUs
174411767SAnurag.Maskey@Sun.COM 		 * that are not disabled - but have the enabled value set - to
174511767SAnurag.Maskey@Sun.COM 		 * the disabled state.  Then handle cases where the NCU was
174611767SAnurag.Maskey@Sun.COM 		 * disabled but is no longer.  Finally,  deal with refresh of
174711767SAnurag.Maskey@Sun.COM 		 * link and interface NCUs, as these are handled differently.
174811767SAnurag.Maskey@Sun.COM 		 */
174911767SAnurag.Maskey@Sun.COM 		if (!ncu->ncu_enabled) {
175011767SAnurag.Maskey@Sun.COM 			if (object->nwamd_object_state != NWAM_STATE_DISABLED) {
175111767SAnurag.Maskey@Sun.COM 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
175211767SAnurag.Maskey@Sun.COM 				    object->nwamd_object_name,
175311767SAnurag.Maskey@Sun.COM 				    NWAM_STATE_ONLINE_TO_OFFLINE,
175411767SAnurag.Maskey@Sun.COM 				    NWAM_AUX_STATE_MANUAL_DISABLE);
175511767SAnurag.Maskey@Sun.COM 			}
175611767SAnurag.Maskey@Sun.COM 			goto done;
175711767SAnurag.Maskey@Sun.COM 		} else {
175811767SAnurag.Maskey@Sun.COM 			if (object->nwamd_object_state == NWAM_STATE_DISABLED) {
175911767SAnurag.Maskey@Sun.COM 				int64_t c;
176011767SAnurag.Maskey@Sun.COM 
176111767SAnurag.Maskey@Sun.COM 				/*
176211767SAnurag.Maskey@Sun.COM 				 * Try to activate the NCU if manual or
176311767SAnurag.Maskey@Sun.COM 				 * prioritized (when priority <= current).
176411767SAnurag.Maskey@Sun.COM 				 */
176511767SAnurag.Maskey@Sun.COM 				(void) pthread_mutex_lock(&active_ncp_mutex);
176611767SAnurag.Maskey@Sun.COM 				c = current_ncu_priority_group;
176711767SAnurag.Maskey@Sun.COM 				(void) pthread_mutex_unlock(&active_ncp_mutex);
176811767SAnurag.Maskey@Sun.COM 				if (link->nwamd_link_activation_mode ==
176911767SAnurag.Maskey@Sun.COM 				    NWAM_ACTIVATION_MODE_MANUAL ||
177011767SAnurag.Maskey@Sun.COM 				    (link->nwamd_link_activation_mode ==
177111767SAnurag.Maskey@Sun.COM 				    NWAM_ACTIVATION_MODE_PRIORITIZED &&
177211767SAnurag.Maskey@Sun.COM 				    link->nwamd_link_priority_mode <= c)) {
177311767SAnurag.Maskey@Sun.COM 					nwamd_object_set_state
177411767SAnurag.Maskey@Sun.COM 					    (NWAM_OBJECT_TYPE_NCU,
177511767SAnurag.Maskey@Sun.COM 					    object->nwamd_object_name,
177611767SAnurag.Maskey@Sun.COM 					    NWAM_STATE_OFFLINE_TO_ONLINE,
177711767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_INITIALIZED);
177811767SAnurag.Maskey@Sun.COM 				} else {
177911767SAnurag.Maskey@Sun.COM 					nwamd_object_set_state
178011767SAnurag.Maskey@Sun.COM 					    (NWAM_OBJECT_TYPE_NCU,
178111767SAnurag.Maskey@Sun.COM 					    object->nwamd_object_name,
178211767SAnurag.Maskey@Sun.COM 					    NWAM_STATE_OFFLINE_TO_ONLINE,
178311767SAnurag.Maskey@Sun.COM 					    NWAM_AUX_STATE_INITIALIZED);
178411767SAnurag.Maskey@Sun.COM 				}
178511767SAnurag.Maskey@Sun.COM 				goto done;
178611767SAnurag.Maskey@Sun.COM 			}
178711767SAnurag.Maskey@Sun.COM 		}
178811767SAnurag.Maskey@Sun.COM 
178911767SAnurag.Maskey@Sun.COM 		switch (type) {
179011767SAnurag.Maskey@Sun.COM 		case NWAM_NCU_TYPE_LINK:
179112576SAnurag.Maskey@Oracle.COM 			if (ncu->ncu_link.nwamd_link_media == DL_WIFI) {
179211767SAnurag.Maskey@Sun.COM 				/*
179311767SAnurag.Maskey@Sun.COM 				 * Do rescan.  If the current state and the
179411767SAnurag.Maskey@Sun.COM 				 * active priority-group do not allow wireless
179511767SAnurag.Maskey@Sun.COM 				 * network selection, then it won't happen.
179611767SAnurag.Maskey@Sun.COM 				 */
179711767SAnurag.Maskey@Sun.COM 				(void) nwamd_wlan_scan(ncu->ncu_name);
179811767SAnurag.Maskey@Sun.COM 			}
179911767SAnurag.Maskey@Sun.COM 			break;
180011767SAnurag.Maskey@Sun.COM 		case NWAM_NCU_TYPE_INTERFACE:
180111767SAnurag.Maskey@Sun.COM 			/*
180211767SAnurag.Maskey@Sun.COM 			 * If interface NCU is offline*, online or in
180311767SAnurag.Maskey@Sun.COM 			 * maintenance, mark it down (from there, it will be
180411767SAnurag.Maskey@Sun.COM 			 * reinitialized to reapply addresses).
180511767SAnurag.Maskey@Sun.COM 			 */
180611767SAnurag.Maskey@Sun.COM 			if (object->nwamd_object_state != NWAM_STATE_OFFLINE) {
180711767SAnurag.Maskey@Sun.COM 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
180811767SAnurag.Maskey@Sun.COM 				    object->nwamd_object_name,
180911767SAnurag.Maskey@Sun.COM 				    NWAM_STATE_ONLINE_TO_OFFLINE,
181011767SAnurag.Maskey@Sun.COM 				    NWAM_AUX_STATE_DOWN);
181111767SAnurag.Maskey@Sun.COM 			} else {
181211767SAnurag.Maskey@Sun.COM 				object->nwamd_object_state = NWAM_STATE_OFFLINE;
181311767SAnurag.Maskey@Sun.COM 				object->nwamd_object_aux_state =
181411767SAnurag.Maskey@Sun.COM 				    NWAM_AUX_STATE_CONDITIONS_NOT_MET;
181511767SAnurag.Maskey@Sun.COM 			}
181611767SAnurag.Maskey@Sun.COM 			break;
181711767SAnurag.Maskey@Sun.COM 		}
181811767SAnurag.Maskey@Sun.COM 	}
181911767SAnurag.Maskey@Sun.COM 
182011767SAnurag.Maskey@Sun.COM done:
182111767SAnurag.Maskey@Sun.COM 	if (type == NWAM_NCU_TYPE_LINK &&
182211767SAnurag.Maskey@Sun.COM 	    !nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK,
182311767SAnurag.Maskey@Sun.COM 	    NWAM_OBJECT_TYPE_NCP, NULL)) {
182411767SAnurag.Maskey@Sun.COM 		nwamd_create_ncu_check_event(NEXT_FEW_SECONDS);
182511767SAnurag.Maskey@Sun.COM 	}
182611767SAnurag.Maskey@Sun.COM 	free(name);
182711767SAnurag.Maskey@Sun.COM 	nwamd_object_release(object);
182811767SAnurag.Maskey@Sun.COM }
182911767SAnurag.Maskey@Sun.COM 
183011767SAnurag.Maskey@Sun.COM void
nwamd_ncu_handle_fini_event(nwamd_event_t event)183111767SAnurag.Maskey@Sun.COM nwamd_ncu_handle_fini_event(nwamd_event_t event)
183211767SAnurag.Maskey@Sun.COM {
183311767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
183411767SAnurag.Maskey@Sun.COM 	nwamd_event_t state_event;
183511767SAnurag.Maskey@Sun.COM 
183611767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_ncu_handle_fini_event(%s)",
183711767SAnurag.Maskey@Sun.COM 	    event->event_object);
183811767SAnurag.Maskey@Sun.COM 
183911767SAnurag.Maskey@Sun.COM 	/*
184011767SAnurag.Maskey@Sun.COM 	 * Simulate a state event so that the state machine can correctly
184111767SAnurag.Maskey@Sun.COM 	 * disable the NCU.  Then free up allocated objects.
184211767SAnurag.Maskey@Sun.COM 	 */
184311767SAnurag.Maskey@Sun.COM 	state_event = nwamd_event_init_object_state(NWAM_OBJECT_TYPE_NCU,
184411767SAnurag.Maskey@Sun.COM 	    event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
184511767SAnurag.Maskey@Sun.COM 	    NWAM_AUX_STATE_UNINITIALIZED);
184611767SAnurag.Maskey@Sun.COM 	if (state_event == NULL) {
184711767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
184811767SAnurag.Maskey@Sun.COM 		return;
184911767SAnurag.Maskey@Sun.COM 	}
185011767SAnurag.Maskey@Sun.COM 	nwamd_ncu_handle_state_event(state_event);
185111767SAnurag.Maskey@Sun.COM 	nwamd_event_fini(state_event);
185211767SAnurag.Maskey@Sun.COM 
185311767SAnurag.Maskey@Sun.COM 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
185411767SAnurag.Maskey@Sun.COM 	    event->event_object)) == NULL) {
185512923SRenee.Sommerfeld@Oracle.COM 		nlog(LOG_INFO, "nwamd_ncu_handle_fini_event: "
185611767SAnurag.Maskey@Sun.COM 		    "ncu %s not found", event->event_object);
185711767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
185811767SAnurag.Maskey@Sun.COM 		return;
185911767SAnurag.Maskey@Sun.COM 	}
186011767SAnurag.Maskey@Sun.COM 	nwamd_object_release_and_destroy(object);
186111767SAnurag.Maskey@Sun.COM }
186211767SAnurag.Maskey@Sun.COM 
186311767SAnurag.Maskey@Sun.COM void
nwamd_ncu_handle_action_event(nwamd_event_t event)186411767SAnurag.Maskey@Sun.COM nwamd_ncu_handle_action_event(nwamd_event_t event)
186511767SAnurag.Maskey@Sun.COM {
186611767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
186711767SAnurag.Maskey@Sun.COM 
186811767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_lock(&active_ncp_mutex);
186911767SAnurag.Maskey@Sun.COM 	if (strcmp(event->event_msg->nwe_data.nwe_object_action.nwe_parent,
187011767SAnurag.Maskey@Sun.COM 	    active_ncp) != 0) {
187111767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: action for "
187211767SAnurag.Maskey@Sun.COM 		    "inactive NCP %s, nothing to do",
187311767SAnurag.Maskey@Sun.COM 		    event->event_msg->nwe_data.nwe_object_action.nwe_parent);
187411767SAnurag.Maskey@Sun.COM 		(void) pthread_mutex_unlock(&active_ncp_mutex);
187511767SAnurag.Maskey@Sun.COM 		return;
187611767SAnurag.Maskey@Sun.COM 	}
187711767SAnurag.Maskey@Sun.COM 	(void) pthread_mutex_unlock(&active_ncp_mutex);
187811767SAnurag.Maskey@Sun.COM 
187911767SAnurag.Maskey@Sun.COM 	switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) {
188011767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_ENABLE:
188111767SAnurag.Maskey@Sun.COM 		object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
188211767SAnurag.Maskey@Sun.COM 		    event->event_object);
188311767SAnurag.Maskey@Sun.COM 		if (object == NULL) {
188411767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_ncu_handle_action_event: "
188511767SAnurag.Maskey@Sun.COM 			    "could not find ncu %s", event->event_object);
188611767SAnurag.Maskey@Sun.COM 			nwamd_event_do_not_send(event);
188711767SAnurag.Maskey@Sun.COM 			return;
188811767SAnurag.Maskey@Sun.COM 		}
188911767SAnurag.Maskey@Sun.COM 		if (object->nwamd_object_state == NWAM_STATE_ONLINE) {
189011767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: "
189111767SAnurag.Maskey@Sun.COM 			    "ncu %s already online, nothing to do",
189211767SAnurag.Maskey@Sun.COM 			    event->event_object);
189311767SAnurag.Maskey@Sun.COM 			nwamd_object_release(object);
189411767SAnurag.Maskey@Sun.COM 			return;
189511767SAnurag.Maskey@Sun.COM 		}
189611767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
189711767SAnurag.Maskey@Sun.COM 
189811767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
189911767SAnurag.Maskey@Sun.COM 		    event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE,
190011767SAnurag.Maskey@Sun.COM 		    NWAM_AUX_STATE_INITIALIZED);
190111767SAnurag.Maskey@Sun.COM 		break;
190211767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_DISABLE:
190311767SAnurag.Maskey@Sun.COM 		object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
190411767SAnurag.Maskey@Sun.COM 		    event->event_object);
190511767SAnurag.Maskey@Sun.COM 		if (object == NULL) {
190611767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "nwamd_ncu_handle_action_event: "
190711767SAnurag.Maskey@Sun.COM 			    "could not find ncu %s", event->event_object);
190811767SAnurag.Maskey@Sun.COM 			nwamd_event_do_not_send(event);
190911767SAnurag.Maskey@Sun.COM 			return;
191011767SAnurag.Maskey@Sun.COM 		}
191111767SAnurag.Maskey@Sun.COM 		if (object->nwamd_object_state == NWAM_STATE_DISABLED) {
191211767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: "
191311767SAnurag.Maskey@Sun.COM 			    "ncu %s already disabled, nothing to do",
191411767SAnurag.Maskey@Sun.COM 			    event->event_object);
191511767SAnurag.Maskey@Sun.COM 			nwamd_object_release(object);
191611767SAnurag.Maskey@Sun.COM 			return;
191711767SAnurag.Maskey@Sun.COM 		}
191811767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
191911767SAnurag.Maskey@Sun.COM 
192011767SAnurag.Maskey@Sun.COM 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
192111767SAnurag.Maskey@Sun.COM 		    event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
192211767SAnurag.Maskey@Sun.COM 		    NWAM_AUX_STATE_MANUAL_DISABLE);
192311767SAnurag.Maskey@Sun.COM 		break;
192411767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_ADD:
192511767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_REFRESH:
192611767SAnurag.Maskey@Sun.COM 		nwamd_ncu_handle_init_event(event);
192711767SAnurag.Maskey@Sun.COM 		break;
192811767SAnurag.Maskey@Sun.COM 	case NWAM_ACTION_DESTROY:
192911767SAnurag.Maskey@Sun.COM 		nwamd_ncu_handle_fini_event(event);
193011767SAnurag.Maskey@Sun.COM 		break;
193111767SAnurag.Maskey@Sun.COM 	default:
193211767SAnurag.Maskey@Sun.COM 		nlog(LOG_INFO, "nwam_ncu_handle_action_event: "
193311767SAnurag.Maskey@Sun.COM 		    "unexpected action");
193411767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
193511767SAnurag.Maskey@Sun.COM 		break;
193611767SAnurag.Maskey@Sun.COM 	}
193711767SAnurag.Maskey@Sun.COM }
193811767SAnurag.Maskey@Sun.COM 
193911767SAnurag.Maskey@Sun.COM void
nwamd_ncu_handle_state_event(nwamd_event_t event)194011767SAnurag.Maskey@Sun.COM nwamd_ncu_handle_state_event(nwamd_event_t event)
194111767SAnurag.Maskey@Sun.COM {
194211767SAnurag.Maskey@Sun.COM 	nwamd_object_t object;
194311767SAnurag.Maskey@Sun.COM 	nwam_state_t old_state, new_state;
194411767SAnurag.Maskey@Sun.COM 	nwam_aux_state_t new_aux_state;
194511767SAnurag.Maskey@Sun.COM 	nwamd_ncu_t *ncu;
194611767SAnurag.Maskey@Sun.COM 	boolean_t is_link, enabled, prioritized = B_FALSE;
194711767SAnurag.Maskey@Sun.COM 	char linkname[NWAM_MAX_NAME_LEN];
194811767SAnurag.Maskey@Sun.COM 	nwam_event_t m = event->event_msg;
194911767SAnurag.Maskey@Sun.COM 
195011767SAnurag.Maskey@Sun.COM 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
195111767SAnurag.Maskey@Sun.COM 	    event->event_object)) == NULL) {
195212923SRenee.Sommerfeld@Oracle.COM 		nlog(LOG_INFO, "nwamd_ncu_handle_state_event %lld: "
195311767SAnurag.Maskey@Sun.COM 		    "state event for nonexistent NCU %s", event->event_id,
195411767SAnurag.Maskey@Sun.COM 		    event->event_object);
195511767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
195611767SAnurag.Maskey@Sun.COM 		return;
195711767SAnurag.Maskey@Sun.COM 	}
195811767SAnurag.Maskey@Sun.COM 	ncu = object->nwamd_object_data;
195911767SAnurag.Maskey@Sun.COM 	old_state = object->nwamd_object_state;
196011767SAnurag.Maskey@Sun.COM 	new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state;
196111767SAnurag.Maskey@Sun.COM 	new_aux_state =
196211767SAnurag.Maskey@Sun.COM 	    event->event_msg->nwe_data.nwe_object_state.nwe_aux_state;
196311767SAnurag.Maskey@Sun.COM 
196411767SAnurag.Maskey@Sun.COM 	/*
196511767SAnurag.Maskey@Sun.COM 	 * For NCU state changes, we need to supply the parent NCP name also,
196611767SAnurag.Maskey@Sun.COM 	 * regardless of whether the event is handled or not.  It is best to
196711767SAnurag.Maskey@Sun.COM 	 * fill this in here as we have the object lock - when we create
196811767SAnurag.Maskey@Sun.COM 	 * object state events we sometimes do not have the object lock, but
196911767SAnurag.Maskey@Sun.COM 	 * at this point in consuming the events (and prior to the associated
197011767SAnurag.Maskey@Sun.COM 	 * event message being sent out) we do.
197111767SAnurag.Maskey@Sun.COM 	 */
197211767SAnurag.Maskey@Sun.COM 	(void) strlcpy(m->nwe_data.nwe_object_state.nwe_parent, ncu->ncu_parent,
197311767SAnurag.Maskey@Sun.COM 	    sizeof (m->nwe_data.nwe_object_state.nwe_parent));
197411767SAnurag.Maskey@Sun.COM 
197511767SAnurag.Maskey@Sun.COM 	/*
197611767SAnurag.Maskey@Sun.COM 	 * If we receive a state change event moving this NCU to
197711767SAnurag.Maskey@Sun.COM 	 * DHCP_TIMED_OUT or UP state but this NCU is already ONLINE, then
197811767SAnurag.Maskey@Sun.COM 	 * ignore this state change event.
197911767SAnurag.Maskey@Sun.COM 	 */
198011767SAnurag.Maskey@Sun.COM 	if ((new_aux_state == NWAM_AUX_STATE_IF_DHCP_TIMED_OUT ||
198111767SAnurag.Maskey@Sun.COM 	    new_aux_state == NWAM_AUX_STATE_UP) &&
198211767SAnurag.Maskey@Sun.COM 	    object->nwamd_object_state == NWAM_STATE_ONLINE) {
198311767SAnurag.Maskey@Sun.COM 		nlog(LOG_INFO, "nwamd_ncu_handle_state_event: "
198411767SAnurag.Maskey@Sun.COM 		    "NCU %s already online, not going to '%s' state",
198511767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name,
198611767SAnurag.Maskey@Sun.COM 		    nwam_aux_state_to_string(new_aux_state));
198711767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
198811767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
198911767SAnurag.Maskey@Sun.COM 		return;
199011767SAnurag.Maskey@Sun.COM 	}
199111767SAnurag.Maskey@Sun.COM 
199211767SAnurag.Maskey@Sun.COM 	if (new_state == object->nwamd_object_state &&
199311767SAnurag.Maskey@Sun.COM 	    new_aux_state == object->nwamd_object_aux_state) {
199411767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
199511767SAnurag.Maskey@Sun.COM 		    "NCU %s already in state (%s, %s)",
199611767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name, nwam_state_to_string(new_state),
199711767SAnurag.Maskey@Sun.COM 		    nwam_aux_state_to_string(new_aux_state));
199811767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
199911767SAnurag.Maskey@Sun.COM 		return;
200011767SAnurag.Maskey@Sun.COM 	}
200111767SAnurag.Maskey@Sun.COM 
200211767SAnurag.Maskey@Sun.COM 	if (old_state == NWAM_STATE_MAINTENANCE &&
200311767SAnurag.Maskey@Sun.COM 	    (new_state == NWAM_STATE_ONLINE ||
200411767SAnurag.Maskey@Sun.COM 	    (new_state == NWAM_STATE_OFFLINE_TO_ONLINE &&
200511767SAnurag.Maskey@Sun.COM 	    new_aux_state != NWAM_AUX_STATE_INITIALIZED))) {
200611767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
200711767SAnurag.Maskey@Sun.COM 		    "NCU %s cannot transition from state %s to state (%s, %s)",
200811767SAnurag.Maskey@Sun.COM 		    object->nwamd_object_name, nwam_state_to_string(old_state),
200911767SAnurag.Maskey@Sun.COM 		    nwam_state_to_string(new_state),
201011767SAnurag.Maskey@Sun.COM 		    nwam_aux_state_to_string(new_aux_state));
201111767SAnurag.Maskey@Sun.COM 		nwamd_event_do_not_send(event);
201211767SAnurag.Maskey@Sun.COM 		nwamd_object_release(object);
201311767SAnurag.Maskey@Sun.COM 		return;
201411767SAnurag.Maskey@Sun.COM 	}
201511767SAnurag.Maskey@Sun.COM 
201611767SAnurag.Maskey@Sun.COM 	object->nwamd_object_state = new_state;
201711767SAnurag.Maskey@Sun.COM 	object->nwamd_object_aux_state = new_aux_state;
201811767SAnurag.Maskey@Sun.COM 
201911767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: changing state for NCU "
202011767SAnurag.Maskey@Sun.COM 	    "%s to (%s, %s)", object->nwamd_object_name,
202111767SAnurag.Maskey@Sun.COM 	    nwam_state_to_string(object->nwamd_object_state),
202211767SAnurag.Maskey@Sun.COM 	    nwam_aux_state_to_string(object->nwamd_object_aux_state));
202311767SAnurag.Maskey@Sun.COM 
202411767SAnurag.Maskey@Sun.COM 	is_link = (ncu->ncu_type == NWAM_NCU_TYPE_LINK);
202511767SAnurag.Maskey@Sun.COM 	if (is_link)
202611767SAnurag.Maskey@Sun.COM 		(void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
202711767SAnurag.Maskey@Sun.COM 	prioritized = (ncu->ncu_type == NWAM_NCU_TYPE_LINK &&
202812576SAnurag.Maskey@Oracle.COM 	    ncu->ncu_link.nwamd_link_activation_mode ==
202911767SAnurag.Maskey@Sun.COM 	    NWAM_ACTIVATION_MODE_PRIORITIZED);
203011767SAnurag.Maskey@Sun.COM 	enabled = ncu->ncu_enabled;
203111767SAnurag.Maskey@Sun.COM 
203211767SAnurag.Maskey@Sun.COM 	nwamd_object_release(object);
203311767SAnurag.Maskey@Sun.COM 
203411767SAnurag.Maskey@Sun.COM 	/*
203511767SAnurag.Maskey@Sun.COM 	 * State machine for NCUs
203611767SAnurag.Maskey@Sun.COM 	 */
203711767SAnurag.Maskey@Sun.COM 	switch (new_state) {
203811767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_OFFLINE_TO_ONLINE:
203911767SAnurag.Maskey@Sun.COM 		if (enabled) {
204011767SAnurag.Maskey@Sun.COM 			nwamd_ncu_state_machine(event->event_object);
204111767SAnurag.Maskey@Sun.COM 		} else {
204211767SAnurag.Maskey@Sun.COM 			nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
204311767SAnurag.Maskey@Sun.COM 			    "cannot move disabled NCU %s online",
204411767SAnurag.Maskey@Sun.COM 			    event->event_object);
204511767SAnurag.Maskey@Sun.COM 			nwamd_event_do_not_send(event);
204611767SAnurag.Maskey@Sun.COM 		}
204711767SAnurag.Maskey@Sun.COM 		break;
204811767SAnurag.Maskey@Sun.COM 
204911767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_ONLINE_TO_OFFLINE:
205011767SAnurag.Maskey@Sun.COM 		nwamd_ncu_state_machine(event->event_object);
205111767SAnurag.Maskey@Sun.COM 		break;
205211767SAnurag.Maskey@Sun.COM 
205311767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_ONLINE:
205411767SAnurag.Maskey@Sun.COM 		/*
205511767SAnurag.Maskey@Sun.COM 		 * We usually don't need to do anything when we're in the
205611767SAnurag.Maskey@Sun.COM 		 * ONLINE state.  However, for  WiFi we can be in INIT or
205711767SAnurag.Maskey@Sun.COM 		 * SCAN aux states while being ONLINE.
205811767SAnurag.Maskey@Sun.COM 		 */
205911767SAnurag.Maskey@Sun.COM 		nwamd_ncu_state_machine(event->event_object);
206011767SAnurag.Maskey@Sun.COM 		break;
206111767SAnurag.Maskey@Sun.COM 
206211767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_OFFLINE:
206311767SAnurag.Maskey@Sun.COM 		/* Reassess priority group now member is offline */
206411767SAnurag.Maskey@Sun.COM 		if (prioritized) {
206511767SAnurag.Maskey@Sun.COM 			nwamd_create_ncu_check_event(0);
206611767SAnurag.Maskey@Sun.COM 		}
206711767SAnurag.Maskey@Sun.COM 		break;
206811767SAnurag.Maskey@Sun.COM 
206911767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_DISABLED:
207011767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_UNINITIALIZED:
207111767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_MAINTENANCE:
207211767SAnurag.Maskey@Sun.COM 	case NWAM_STATE_DEGRADED:
207311767SAnurag.Maskey@Sun.COM 	default:
207411767SAnurag.Maskey@Sun.COM 		/* do nothing */
207511767SAnurag.Maskey@Sun.COM 		break;
207611767SAnurag.Maskey@Sun.COM 	}
207711767SAnurag.Maskey@Sun.COM 
207811767SAnurag.Maskey@Sun.COM 	if (is_link) {
207911767SAnurag.Maskey@Sun.COM 		if ((new_state == NWAM_STATE_ONLINE_TO_OFFLINE &&
208011767SAnurag.Maskey@Sun.COM 		    new_aux_state != NWAM_AUX_STATE_UNINITIALIZED &&
208111767SAnurag.Maskey@Sun.COM 		    new_aux_state != NWAM_AUX_STATE_NOT_FOUND) ||
208211767SAnurag.Maskey@Sun.COM 		    new_state == NWAM_STATE_DISABLED) {
208311767SAnurag.Maskey@Sun.COM 			/*
208411767SAnurag.Maskey@Sun.COM 			 * Going offline, propogate down event to IP NCU.  Do
208511767SAnurag.Maskey@Sun.COM 			 * not propogate event if new aux state is uninitialized
208611767SAnurag.Maskey@Sun.COM 			 * or not found as these auxiliary states signify
208711767SAnurag.Maskey@Sun.COM 			 * that an NCP switch/device removal is in progress.
208811767SAnurag.Maskey@Sun.COM 			 */
208911767SAnurag.Maskey@Sun.COM 			nwamd_propogate_link_up_down_to_ip(linkname, B_FALSE);
209011767SAnurag.Maskey@Sun.COM 		}
209111767SAnurag.Maskey@Sun.COM 		if (new_state == NWAM_STATE_ONLINE) {
209211767SAnurag.Maskey@Sun.COM 			/* gone online, propogate up event to IP NCU */
209311767SAnurag.Maskey@Sun.COM 			nwamd_propogate_link_up_down_to_ip(linkname, B_TRUE);
209411767SAnurag.Maskey@Sun.COM 		}
209511767SAnurag.Maskey@Sun.COM 	} else {
209611767SAnurag.Maskey@Sun.COM 		/* If IP NCU is online, reasses priority group */
209711767SAnurag.Maskey@Sun.COM 		if (new_state == NWAM_STATE_ONLINE)
209811767SAnurag.Maskey@Sun.COM 			nwamd_create_ncu_check_event(0);
209911767SAnurag.Maskey@Sun.COM 	}
210011767SAnurag.Maskey@Sun.COM }
2101