xref: /illumos-gate/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c (revision f689bed1)
16ba597c5SAnurag S. Maskey /*
26ba597c5SAnurag S. Maskey  * CDDL HEADER START
36ba597c5SAnurag S. Maskey  *
46ba597c5SAnurag S. Maskey  * The contents of this file are subject to the terms of the
56ba597c5SAnurag S. Maskey  * Common Development and Distribution License (the "License").
66ba597c5SAnurag S. Maskey  * You may not use this file except in compliance with the License.
76ba597c5SAnurag S. Maskey  *
86ba597c5SAnurag S. Maskey  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96ba597c5SAnurag S. Maskey  * or http://www.opensolaris.org/os/licensing.
106ba597c5SAnurag S. Maskey  * See the License for the specific language governing permissions
116ba597c5SAnurag S. Maskey  * and limitations under the License.
126ba597c5SAnurag S. Maskey  *
136ba597c5SAnurag S. Maskey  * When distributing Covered Code, include this CDDL HEADER in each
146ba597c5SAnurag S. Maskey  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156ba597c5SAnurag S. Maskey  * If applicable, add the following below this CDDL HEADER, with the
166ba597c5SAnurag S. Maskey  * fields enclosed by brackets "[]" replaced with your own identifying
176ba597c5SAnurag S. Maskey  * information: Portions Copyright [yyyy] [name of copyright owner]
186ba597c5SAnurag S. Maskey  *
196ba597c5SAnurag S. Maskey  * CDDL HEADER END
206ba597c5SAnurag S. Maskey  */
216ba597c5SAnurag S. Maskey 
226ba597c5SAnurag S. Maskey /*
2371ed50cfSAnurag S. Maskey  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
246ba597c5SAnurag S. Maskey  */
256ba597c5SAnurag S. Maskey 
266ba597c5SAnurag S. Maskey #include <arpa/inet.h>
276ba597c5SAnurag S. Maskey #include <assert.h>
286ba597c5SAnurag S. Maskey #include <libdlaggr.h>
296ba597c5SAnurag S. Maskey #include <libdllink.h>
306ba597c5SAnurag S. Maskey #include <libdlstat.h>
316ba597c5SAnurag S. Maskey #include <libnwam.h>
326ba597c5SAnurag S. Maskey #include <libscf.h>
336ba597c5SAnurag S. Maskey #include <netinet/in.h>
346ba597c5SAnurag S. Maskey #include <stdlib.h>
356ba597c5SAnurag S. Maskey #include <strings.h>
366ba597c5SAnurag S. Maskey #include <sys/socket.h>
376ba597c5SAnurag S. Maskey #include <sys/time.h>
386ba597c5SAnurag S. Maskey #include <sys/types.h>
396ba597c5SAnurag S. Maskey #include <values.h>
40*f689bed1SRishi Srivatsavai #include <zone.h>
416ba597c5SAnurag S. Maskey 
426ba597c5SAnurag S. Maskey #include "conditions.h"
436ba597c5SAnurag S. Maskey #include "events.h"
446ba597c5SAnurag S. Maskey #include "objects.h"
456ba597c5SAnurag S. Maskey #include "ncp.h"
466ba597c5SAnurag S. Maskey #include "util.h"
476ba597c5SAnurag S. Maskey 
486ba597c5SAnurag S. Maskey /*
496ba597c5SAnurag S. Maskey  * ncu.c - handles various NCU tasks - intialization/refresh, state machine
506ba597c5SAnurag S. Maskey  * for NCUs etc.
516ba597c5SAnurag S. Maskey  */
526ba597c5SAnurag S. Maskey 
536ba597c5SAnurag S. Maskey #define	VBOX_IFACE_PREFIX	"vboxnet"
546ba597c5SAnurag S. Maskey 
55f6da83d4SAnurag S. Maskey static void populate_ip_ncu_properties(nwam_ncu_handle_t, nwamd_ncu_t *);
56f6da83d4SAnurag S. Maskey 
576ba597c5SAnurag S. Maskey /*
586ba597c5SAnurag S. Maskey  * Find ncu of specified type for link/interface name.
596ba597c5SAnurag S. Maskey  */
606ba597c5SAnurag S. Maskey nwamd_object_t
616ba597c5SAnurag S. Maskey nwamd_ncu_object_find(nwam_ncu_type_t type, const char *name)
626ba597c5SAnurag S. Maskey {
636ba597c5SAnurag S. Maskey 	nwam_error_t err;
646ba597c5SAnurag S. Maskey 	char *object_name;
656ba597c5SAnurag S. Maskey 	nwamd_object_t ncu_obj = NULL;
666ba597c5SAnurag S. Maskey 
676ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_name_to_typed_name(name, type, &object_name))
686ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS) {
696ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_find: nwam_ncu_name_to_typed_name "
706ba597c5SAnurag S. Maskey 		    "returned %s", nwam_strerror(err));
716ba597c5SAnurag S. Maskey 		return (NULL);
726ba597c5SAnurag S. Maskey 	}
736ba597c5SAnurag S. Maskey 	ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name);
746ba597c5SAnurag S. Maskey 
756ba597c5SAnurag S. Maskey 	free(object_name);
766ba597c5SAnurag S. Maskey 	return (ncu_obj);
776ba597c5SAnurag S. Maskey }
786ba597c5SAnurag S. Maskey 
796ba597c5SAnurag S. Maskey nwam_error_t
806ba597c5SAnurag S. Maskey nwamd_set_ncu_string(nwam_ncu_handle_t ncuh, char **strval, uint_t cnt,
816ba597c5SAnurag S. Maskey     const char *prop)
826ba597c5SAnurag S. Maskey {
836ba597c5SAnurag S. Maskey 	nwam_error_t err;
846ba597c5SAnurag S. Maskey 	nwam_value_t val;
856ba597c5SAnurag S. Maskey 
866ba597c5SAnurag S. Maskey 	if ((err = nwam_value_create_string_array(strval, cnt, &val))
876ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
886ba597c5SAnurag S. Maskey 		return (err);
896ba597c5SAnurag S. Maskey 	err = nwam_ncu_set_prop_value(ncuh, prop, val);
906ba597c5SAnurag S. Maskey 	nwam_value_free(val);
916ba597c5SAnurag S. Maskey 	return (err);
926ba597c5SAnurag S. Maskey }
936ba597c5SAnurag S. Maskey 
946ba597c5SAnurag S. Maskey nwam_error_t
956ba597c5SAnurag S. Maskey nwamd_set_ncu_uint(nwam_ncu_handle_t ncuh, uint64_t *uintval, uint_t cnt,
966ba597c5SAnurag S. Maskey     const char *prop)
976ba597c5SAnurag S. Maskey {
986ba597c5SAnurag S. Maskey 	nwam_error_t err;
996ba597c5SAnurag S. Maskey 	nwam_value_t val;
1006ba597c5SAnurag S. Maskey 
1016ba597c5SAnurag S. Maskey 	if ((err = nwam_value_create_uint64_array(uintval, cnt, &val))
1026ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
1036ba597c5SAnurag S. Maskey 		return (err);
1046ba597c5SAnurag S. Maskey 	err = nwam_ncu_set_prop_value(ncuh, prop, val);
1056ba597c5SAnurag S. Maskey 	nwam_value_free(val);
1066ba597c5SAnurag S. Maskey 	return (err);
1076ba597c5SAnurag S. Maskey }
1086ba597c5SAnurag S. Maskey 
1096ba597c5SAnurag S. Maskey nwam_error_t
1106ba597c5SAnurag S. Maskey nwamd_get_ncu_string(nwam_ncu_handle_t ncuh, nwam_value_t *val, char ***strval,
1116ba597c5SAnurag S. Maskey     uint_t *cnt, const char *prop)
1126ba597c5SAnurag S. Maskey {
1136ba597c5SAnurag S. Maskey 	nwam_error_t err;
1146ba597c5SAnurag S. Maskey 
1156ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS)
1166ba597c5SAnurag S. Maskey 		return (err);
1176ba597c5SAnurag S. Maskey 	return (nwam_value_get_string_array(*val, strval, cnt));
1186ba597c5SAnurag S. Maskey }
1196ba597c5SAnurag S. Maskey 
1206ba597c5SAnurag S. Maskey nwam_error_t
1216ba597c5SAnurag S. Maskey nwamd_get_ncu_uint(nwam_ncu_handle_t ncuh, nwam_value_t *val,
1226ba597c5SAnurag S. Maskey     uint64_t **uintval, uint_t *cnt, const char *prop)
1236ba597c5SAnurag S. Maskey {
1246ba597c5SAnurag S. Maskey 	nwam_error_t err;
1256ba597c5SAnurag S. Maskey 
1266ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS)
1276ba597c5SAnurag S. Maskey 		return (err);
1286ba597c5SAnurag S. Maskey 	return (nwam_value_get_uint64_array(*val, uintval, cnt));
1296ba597c5SAnurag S. Maskey }
1306ba597c5SAnurag S. Maskey 
1316ba597c5SAnurag S. Maskey /*
1326ba597c5SAnurag S. Maskey  * Run link/interface state machine in response to a state change
1336ba597c5SAnurag S. Maskey  * or enable/disable action event.
1346ba597c5SAnurag S. Maskey  */
1356ba597c5SAnurag S. Maskey static void
1366ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(const char *object_name)
1376ba597c5SAnurag S. Maskey {
1386ba597c5SAnurag S. Maskey 	nwamd_object_t object;
1396ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu;
1406ba597c5SAnurag S. Maskey 	link_state_t link_state;
1416ba597c5SAnurag S. Maskey 	nwamd_event_t event;
1426ba597c5SAnurag S. Maskey 	nwam_wlan_t key_wlan, connected_wlan;
1436ba597c5SAnurag S. Maskey 	nwamd_link_t *link;
1446ba597c5SAnurag S. Maskey 	char linkname[NWAM_MAX_NAME_LEN];
1456ba597c5SAnurag S. Maskey 	boolean_t up;
1466ba597c5SAnurag S. Maskey 
1476ba597c5SAnurag S. Maskey 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name))
1486ba597c5SAnurag S. Maskey 	    == NULL) {
1496ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_state_machine: "
1506ba597c5SAnurag S. Maskey 		    "request for nonexistent NCU %s", object_name);
1516ba597c5SAnurag S. Maskey 		return;
1526ba597c5SAnurag S. Maskey 	}
1536ba597c5SAnurag S. Maskey 
1546ba597c5SAnurag S. Maskey 	ncu = object->nwamd_object_data;
155f6da83d4SAnurag S. Maskey 	link = &ncu->ncu_link;
1566ba597c5SAnurag S. Maskey 
1576ba597c5SAnurag S. Maskey 	switch (object->nwamd_object_aux_state) {
1586ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_INITIALIZED:
1596ba597c5SAnurag S. Maskey 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
1606ba597c5SAnurag S. Maskey 			/*
1616ba597c5SAnurag S. Maskey 			 * For wired/wireless links, need to get link
1626ba597c5SAnurag S. Maskey 			 * up/down events and even if these are not supported,
1636ba597c5SAnurag S. Maskey 			 * dlpi_open()ing the link prevents the driver from
1646ba597c5SAnurag S. Maskey 			 * being unloaded.
1656ba597c5SAnurag S. Maskey 			 */
1666ba597c5SAnurag S. Maskey 			nwamd_dlpi_add_link(object);
1676ba597c5SAnurag S. Maskey 
1686ba597c5SAnurag S. Maskey 			if (link->nwamd_link_media == DL_WIFI) {
1696ba597c5SAnurag S. Maskey 				/*
1706ba597c5SAnurag S. Maskey 				 * First, if we're unexpectedly connected,
1716ba597c5SAnurag S. Maskey 				 * disconnect.
1726ba597c5SAnurag S. Maskey 				 */
1736ba597c5SAnurag S. Maskey 				if (!link->nwamd_link_wifi_connected &&
1746ba597c5SAnurag S. Maskey 				    nwamd_wlan_connected(object)) {
1756ba597c5SAnurag S. Maskey 					nlog(LOG_DEBUG,
1766ba597c5SAnurag S. Maskey 					    "nwamd_ncu_state_machine: "
1776ba597c5SAnurag S. Maskey 					    "WiFi unexpectedly connected, "
1786ba597c5SAnurag S. Maskey 					    "disconnecting...");
1796ba597c5SAnurag S. Maskey 					(void) dladm_wlan_disconnect(dld_handle,
1806ba597c5SAnurag S. Maskey 					    link->nwamd_link_id);
1816ba597c5SAnurag S. Maskey 					nwamd_set_selected_connected(ncu,
1826ba597c5SAnurag S. Maskey 					    B_FALSE, B_FALSE);
1836ba597c5SAnurag S. Maskey 				}
1846ba597c5SAnurag S. Maskey 				/* move to scanning aux state */
1856ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1866ba597c5SAnurag S. Maskey 				    object_name, object->nwamd_object_state,
1876ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_LINK_WIFI_SCANNING);
1886ba597c5SAnurag S. Maskey 			} else {
1896ba597c5SAnurag S. Maskey 				/*
1906ba597c5SAnurag S. Maskey 				 * If initial wired link state is unknown, we
1916ba597c5SAnurag S. Maskey 				 * will need to assume the link is up, since
1926ba597c5SAnurag S. Maskey 				 * we won´t get DL_NOTE_LINK_UP/DOWN events.
1936ba597c5SAnurag S. Maskey 				 */
1946ba597c5SAnurag S. Maskey 				link_state = nwamd_get_link_state
1956ba597c5SAnurag S. Maskey 				    (ncu->ncu_name);
1966ba597c5SAnurag S. Maskey 				if (link_state == LINK_STATE_UP ||
1976ba597c5SAnurag S. Maskey 				    link_state == LINK_STATE_UNKNOWN) {
1986ba597c5SAnurag S. Maskey 					nwamd_object_set_state
1996ba597c5SAnurag S. Maskey 					    (NWAM_OBJECT_TYPE_NCU,
2006ba597c5SAnurag S. Maskey 					    object_name, NWAM_STATE_ONLINE,
2016ba597c5SAnurag S. Maskey 					    NWAM_AUX_STATE_UP);
2026ba597c5SAnurag S. Maskey 				} else {
2036ba597c5SAnurag S. Maskey 					nwamd_object_set_state
2046ba597c5SAnurag S. Maskey 					    (NWAM_OBJECT_TYPE_NCU,
2056ba597c5SAnurag S. Maskey 					    object_name,
2066ba597c5SAnurag S. Maskey 					    NWAM_STATE_ONLINE_TO_OFFLINE,
2076ba597c5SAnurag S. Maskey 					    NWAM_AUX_STATE_DOWN);
2086ba597c5SAnurag S. Maskey 				}
2096ba597c5SAnurag S. Maskey 			}
2106ba597c5SAnurag S. Maskey 		} else {
2116ba597c5SAnurag S. Maskey 			/*
2126ba597c5SAnurag S. Maskey 			 * In the current implementation, initialization has to
2136ba597c5SAnurag S. Maskey 			 * start from scratch since the complexity of minimizing
2146ba597c5SAnurag S. Maskey 			 * configuration change is considerable (e.g. if we
2156ba597c5SAnurag S. Maskey 			 * refresh and had DHCP running on the physical
2166ba597c5SAnurag S. Maskey 			 * interface, and now have changed to static assignment,
2176ba597c5SAnurag S. Maskey 			 * we need to remove DHCP etc).  To avoid all this,
2186ba597c5SAnurag S. Maskey 			 * unplumb before re-plumbing the protocols and
2196ba597c5SAnurag S. Maskey 			 * addresses we wish to configure.  In the future, it
2206ba597c5SAnurag S. Maskey 			 * would be good to try and minimize configuration
2216ba597c5SAnurag S. Maskey 			 * changes.
2226ba597c5SAnurag S. Maskey 			 */
223f6da83d4SAnurag S. Maskey 			nwamd_unplumb_interface(ncu, AF_INET);
224f6da83d4SAnurag S. Maskey 			nwamd_unplumb_interface(ncu, AF_INET6);
225f6da83d4SAnurag S. Maskey 
226f6da83d4SAnurag S. Maskey 			/*
227f6da83d4SAnurag S. Maskey 			 * We may be restarting the state machine.  Re-read
228f6da83d4SAnurag S. Maskey 			 * the IP NCU properties as the ipadm_addrobj_t in
229f6da83d4SAnurag S. Maskey 			 * nwamd_if_address should not be reused.
230f6da83d4SAnurag S. Maskey 			 */
231f6da83d4SAnurag S. Maskey 			populate_ip_ncu_properties(object->nwamd_object_handle,
232f6da83d4SAnurag S. Maskey 			    ncu);
2336ba597c5SAnurag S. Maskey 
2346ba597c5SAnurag S. Maskey 			/*
2356ba597c5SAnurag S. Maskey 			 * Enqueue a WAITING_FOR_ADDR aux state change so that
2366ba597c5SAnurag S. Maskey 			 * we are eligible to receive the IF_STATE events
2376ba597c5SAnurag S. Maskey 			 * associated with static, DHCP, DHCPv6 and autoconf
2386ba597c5SAnurag S. Maskey 			 * address assignment.  The latter two can happen
2396ba597c5SAnurag S. Maskey 			 * quite quickly after plumbing so we need to be ready.
2406ba597c5SAnurag S. Maskey 			 */
2416ba597c5SAnurag S. Maskey 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
2426ba597c5SAnurag S. Maskey 			    object_name, NWAM_STATE_OFFLINE_TO_ONLINE,
2436ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_IF_WAITING_FOR_ADDR);
2446ba597c5SAnurag S. Maskey 
245f6da83d4SAnurag S. Maskey 			if (ncu->ncu_if.nwamd_if_ipv4)
246f6da83d4SAnurag S. Maskey 				nwamd_plumb_interface(ncu, AF_INET);
2476ba597c5SAnurag S. Maskey 
248f6da83d4SAnurag S. Maskey 			if (ncu->ncu_if.nwamd_if_ipv6)
249f6da83d4SAnurag S. Maskey 				nwamd_plumb_interface(ncu, AF_INET6);
2506ba597c5SAnurag S. Maskey 
251f6da83d4SAnurag S. Maskey 			/* Configure addresses */
2526ba597c5SAnurag S. Maskey 			nwamd_configure_interface_addresses(ncu);
2536ba597c5SAnurag S. Maskey 		}
2546ba597c5SAnurag S. Maskey 		break;
2556ba597c5SAnurag S. Maskey 
2566ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_IF_DHCP_TIMED_OUT:
2576ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_IF_WAITING_FOR_ADDR:
2586ba597c5SAnurag S. Maskey 		/*
2596ba597c5SAnurag S. Maskey 		 * nothing to do here - RTM_NEWADDRs will trigger IF_STATE
2606ba597c5SAnurag S. Maskey 		 * events to move us online.
2616ba597c5SAnurag S. Maskey 		 */
2626ba597c5SAnurag S. Maskey 		break;
2636ba597c5SAnurag S. Maskey 
2646ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_SCANNING:
2656ba597c5SAnurag S. Maskey 		/* launch scan thread */
2666ba597c5SAnurag S. Maskey 		(void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
2676ba597c5SAnurag S. Maskey 		(void) nwamd_wlan_scan(linkname);
2686ba597c5SAnurag S. Maskey 		/* Create periodic scan event */
2696ba597c5SAnurag S. Maskey 		nwamd_ncu_create_periodic_scan_event(object);
2706ba597c5SAnurag S. Maskey 		break;
2716ba597c5SAnurag S. Maskey 
2726ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION:
2736ba597c5SAnurag S. Maskey 		/* send "need choice" event */
2746ba597c5SAnurag S. Maskey 		event = nwamd_event_init_wlan
2756ba597c5SAnurag S. Maskey 		    (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_CHOICE, B_FALSE,
2766ba597c5SAnurag S. Maskey 		    link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr,
2776ba597c5SAnurag S. Maskey 		    link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num);
2786ba597c5SAnurag S. Maskey 		if (event == NULL)
2796ba597c5SAnurag S. Maskey 			break;
2806ba597c5SAnurag S. Maskey 		nwamd_event_enqueue(event);
2816ba597c5SAnurag S. Maskey 		nwamd_set_selected_connected(ncu, B_FALSE, B_FALSE);
2826ba597c5SAnurag S. Maskey 		break;
2836ba597c5SAnurag S. Maskey 
2846ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_NEED_KEY:
2856ba597c5SAnurag S. Maskey 		/*
2866ba597c5SAnurag S. Maskey 		 * Send "need key" event.  Set selected to true, connected
2876ba597c5SAnurag S. Maskey 		 * and have_key to false.  Do not fill in WLAN details as
2886ba597c5SAnurag S. Maskey 		 * multiple WLANs may match the ESSID name, and each may
2896ba597c5SAnurag S. Maskey 		 * have a different speed and channel.
2906ba597c5SAnurag S. Maskey 		 */
2916ba597c5SAnurag S. Maskey 		bzero(&key_wlan, sizeof (key_wlan));
2926ba597c5SAnurag S. Maskey 		(void) strlcpy(key_wlan.nww_essid, link->nwamd_link_wifi_essid,
2936ba597c5SAnurag S. Maskey 		    sizeof (key_wlan.nww_essid));
2946ba597c5SAnurag S. Maskey 		(void) strlcpy(key_wlan.nww_bssid, link->nwamd_link_wifi_bssid,
2956ba597c5SAnurag S. Maskey 		    sizeof (key_wlan.nww_bssid));
2966ba597c5SAnurag S. Maskey 		key_wlan.nww_security_mode =
2976ba597c5SAnurag S. Maskey 		    link->nwamd_link_wifi_security_mode;
2986ba597c5SAnurag S. Maskey 		key_wlan.nww_selected = B_TRUE;
2996ba597c5SAnurag S. Maskey 		key_wlan.nww_connected = B_FALSE;
3006ba597c5SAnurag S. Maskey 		key_wlan.nww_have_key = B_FALSE;
3016ba597c5SAnurag S. Maskey 		event = nwamd_event_init_wlan
3026ba597c5SAnurag S. Maskey 		    (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_KEY, B_FALSE,
3036ba597c5SAnurag S. Maskey 		    &key_wlan, 1);
3046ba597c5SAnurag S. Maskey 		if (event == NULL)
3056ba597c5SAnurag S. Maskey 			break;
3066ba597c5SAnurag S. Maskey 		nwamd_event_enqueue(event);
3076ba597c5SAnurag S. Maskey 		break;
3086ba597c5SAnurag S. Maskey 
3096ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_CONNECTING:
3106ba597c5SAnurag S. Maskey 		(void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
3116ba597c5SAnurag S. Maskey 		nwamd_wlan_connect(linkname);
3126ba597c5SAnurag S. Maskey 		break;
3136ba597c5SAnurag S. Maskey 
3146ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_UP:
3156ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_DOWN:
3166ba597c5SAnurag S. Maskey 		up = (object->nwamd_object_aux_state == NWAM_AUX_STATE_UP);
3176ba597c5SAnurag S. Maskey 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
3186ba597c5SAnurag S. Maskey 			if (link->nwamd_link_media == DL_WIFI) {
3196ba597c5SAnurag S. Maskey 				/*
3206ba597c5SAnurag S. Maskey 				 * Connected/disconnected - send WLAN
3216ba597c5SAnurag S. Maskey 				 * connection report.
3226ba597c5SAnurag S. Maskey 				 */
3236ba597c5SAnurag S. Maskey 				link->nwamd_link_wifi_connected = up;
3246ba597c5SAnurag S. Maskey 				nwamd_set_selected_connected(ncu, B_TRUE, up);
3256ba597c5SAnurag S. Maskey 
3266ba597c5SAnurag S. Maskey 				(void) strlcpy(connected_wlan.nww_essid,
3276ba597c5SAnurag S. Maskey 				    link->nwamd_link_wifi_essid,
3286ba597c5SAnurag S. Maskey 				    sizeof (connected_wlan.nww_essid));
3296ba597c5SAnurag S. Maskey 				(void) strlcpy(connected_wlan.nww_bssid,
3306ba597c5SAnurag S. Maskey 				    link->nwamd_link_wifi_bssid,
3316ba597c5SAnurag S. Maskey 				    sizeof (connected_wlan.nww_bssid));
3326ba597c5SAnurag S. Maskey 				connected_wlan.nww_security_mode =
3336ba597c5SAnurag S. Maskey 				    link->nwamd_link_wifi_security_mode;
3346ba597c5SAnurag S. Maskey 				event = nwamd_event_init_wlan
3356ba597c5SAnurag S. Maskey 				    (ncu->ncu_name,
3366ba597c5SAnurag S. Maskey 				    NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT, up,
3376ba597c5SAnurag S. Maskey 				    &connected_wlan, 1);
3386ba597c5SAnurag S. Maskey 				if (event == NULL)
3396ba597c5SAnurag S. Maskey 					break;
3406ba597c5SAnurag S. Maskey 				nwamd_event_enqueue(event);
3416ba597c5SAnurag S. Maskey 
3426ba597c5SAnurag S. Maskey 				/*
3436ba597c5SAnurag S. Maskey 				 * If disconnected, restart the state machine
3446ba597c5SAnurag S. Maskey 				 * for the WiFi link (WiFi is always trying
3456ba597c5SAnurag S. Maskey 				 * to connect).
3466ba597c5SAnurag S. Maskey 				 *
3476ba597c5SAnurag S. Maskey 				 * If connected, start signal strength
3486ba597c5SAnurag S. Maskey 				 * monitoring thread.
3496ba597c5SAnurag S. Maskey 				 */
3506ba597c5SAnurag S. Maskey 				if (!up && ncu->ncu_enabled) {
3516ba597c5SAnurag S. Maskey 					nlog(LOG_DEBUG,
3526ba597c5SAnurag S. Maskey 					    "nwamd_ncu_state_machine: "
3536ba597c5SAnurag S. Maskey 					    "wifi disconnect - start over "
3546ba597c5SAnurag S. Maskey 					    "after %dsec interval",
3556ba597c5SAnurag S. Maskey 					    WIRELESS_RETRY_INTERVAL);
3566ba597c5SAnurag S. Maskey 					link->nwamd_link_wifi_connected =
3576ba597c5SAnurag S. Maskey 					    B_FALSE;
3586ba597c5SAnurag S. Maskey 					/* propogate down event to IP NCU */
3596ba597c5SAnurag S. Maskey 					nwamd_propogate_link_up_down_to_ip
3606ba597c5SAnurag S. Maskey 					    (ncu->ncu_name, B_FALSE);
3616ba597c5SAnurag S. Maskey 					nwamd_object_set_state_timed
3626ba597c5SAnurag S. Maskey 					    (NWAM_OBJECT_TYPE_NCU, object_name,
3636ba597c5SAnurag S. Maskey 					    NWAM_STATE_OFFLINE_TO_ONLINE,
3646ba597c5SAnurag S. Maskey 					    NWAM_AUX_STATE_INITIALIZED,
3656ba597c5SAnurag S. Maskey 					    WIRELESS_RETRY_INTERVAL);
3666ba597c5SAnurag S. Maskey 				} else {
3676ba597c5SAnurag S. Maskey 					nlog(LOG_DEBUG,
3686ba597c5SAnurag S. Maskey 					    "nwamd_ncu_state_machine: "
3696ba597c5SAnurag S. Maskey 					    "wifi connected, start monitoring");
3706ba597c5SAnurag S. Maskey 					(void) strlcpy(linkname, ncu->ncu_name,
3716ba597c5SAnurag S. Maskey 					    sizeof (linkname));
3726ba597c5SAnurag S. Maskey 					nwamd_wlan_monitor_signal(linkname);
3736ba597c5SAnurag S. Maskey 				}
3746ba597c5SAnurag S. Maskey 			}
3756ba597c5SAnurag S. Maskey 		}
3766ba597c5SAnurag S. Maskey 
3776ba597c5SAnurag S. Maskey 		/* If not in ONLINE/OFFLINE state yet, change state */
3786ba597c5SAnurag S. Maskey 		if ((up && object->nwamd_object_state != NWAM_STATE_ONLINE) ||
3796ba597c5SAnurag S. Maskey 		    (!up && object->nwamd_object_state != NWAM_STATE_OFFLINE)) {
3806ba597c5SAnurag S. Maskey 			nlog(LOG_DEBUG, "nwamd_ncu_state_machine: "
3816ba597c5SAnurag S. Maskey 			    "%s is moving %s", object_name,
3826ba597c5SAnurag S. Maskey 			    up ? "online" : "offline");
3836ba597c5SAnurag S. Maskey 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
3846ba597c5SAnurag S. Maskey 			    object_name,
3856ba597c5SAnurag S. Maskey 			    up ? NWAM_STATE_ONLINE : NWAM_STATE_OFFLINE,
3866ba597c5SAnurag S. Maskey 			    up ? NWAM_AUX_STATE_UP : NWAM_AUX_STATE_DOWN);
3876ba597c5SAnurag S. Maskey 
3886ba597c5SAnurag S. Maskey 			if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) {
3896ba597c5SAnurag S. Maskey 				if (up) {
3906ba597c5SAnurag S. Maskey 					/*
3916ba597c5SAnurag S. Maskey 					 * Moving online, add v4/v6 default
3926ba597c5SAnurag S. Maskey 					 * routes (if any).
3936ba597c5SAnurag S. Maskey 					 */
3946ba597c5SAnurag S. Maskey 					nwamd_add_default_routes(ncu);
3956ba597c5SAnurag S. Maskey 				} else {
3966ba597c5SAnurag S. Maskey 					/*
3976ba597c5SAnurag S. Maskey 					 * If this is an interface NCU and we
3986ba597c5SAnurag S. Maskey 					 * got a down event, it is a consequence
3996ba597c5SAnurag S. Maskey 					 * of NCU refresh, so reapply addresses
4006ba597c5SAnurag S. Maskey 					 * by reinitializing.
4016ba597c5SAnurag S. Maskey 					 */
4026ba597c5SAnurag S. Maskey 					nwamd_object_set_state
4036ba597c5SAnurag S. Maskey 					    (NWAM_OBJECT_TYPE_NCU, object_name,
4046ba597c5SAnurag S. Maskey 					    NWAM_STATE_OFFLINE_TO_ONLINE,
4056ba597c5SAnurag S. Maskey 					    NWAM_AUX_STATE_INITIALIZED);
4066ba597c5SAnurag S. Maskey 				}
4076ba597c5SAnurag S. Maskey 			}
4086ba597c5SAnurag S. Maskey 		} else {
4096ba597c5SAnurag S. Maskey 			nlog(LOG_DEBUG, "nwamd_ncu_state_machine: "
4106ba597c5SAnurag S. Maskey 			    "%s is %s", object_name,
4116ba597c5SAnurag S. Maskey 			    up ? "online" : "offline");
4126ba597c5SAnurag S. Maskey 		}
4136ba597c5SAnurag S. Maskey 		/*
4146ba597c5SAnurag S. Maskey 		 * NCU is UP or DOWN, trigger all condition checking, even if
4156ba597c5SAnurag S. Maskey 		 * the NCU is already in the ONLINE state - an ENM may depend
4166ba597c5SAnurag S. Maskey 		 * on NCU activity.
4176ba597c5SAnurag S. Maskey 		 */
4186ba597c5SAnurag S. Maskey 		nwamd_create_triggered_condition_check_event(NEXT_FEW_SECONDS);
4196ba597c5SAnurag S. Maskey 		break;
4206ba597c5SAnurag S. Maskey 
4216ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_CONDITIONS_NOT_MET:
4226ba597c5SAnurag S. Maskey 		/*
4236ba597c5SAnurag S. Maskey 		 * Link/interface is moving offline.  Nothing to do except
4246ba597c5SAnurag S. Maskey 		 * for WiFi, where we disconnect.  Don't unplumb IP on
4256ba597c5SAnurag S. Maskey 		 * a link since it may be a transient change.
4266ba597c5SAnurag S. Maskey 		 */
4276ba597c5SAnurag S. Maskey 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
4286ba597c5SAnurag S. Maskey 			if (link->nwamd_link_media == DL_WIFI) {
4296ba597c5SAnurag S. Maskey 				(void) dladm_wlan_disconnect(dld_handle,
4306ba597c5SAnurag S. Maskey 				    link->nwamd_link_id);
4316ba597c5SAnurag S. Maskey 				link->nwamd_link_wifi_connected = B_FALSE;
4326ba597c5SAnurag S. Maskey 				nwamd_set_selected_connected(ncu, B_FALSE,
4336ba597c5SAnurag S. Maskey 				    B_FALSE);
4346ba597c5SAnurag S. Maskey 			}
4356ba597c5SAnurag S. Maskey 		} else {
4366ba597c5SAnurag S. Maskey 			/*
4376ba597c5SAnurag S. Maskey 			 * Unplumb here. In the future we may elaborate on
4386ba597c5SAnurag S. Maskey 			 * the approach used and not unplumb for WiFi
4396ba597c5SAnurag S. Maskey 			 * until we reconnect to a different WLAN (i.e. with
4406ba597c5SAnurag S. Maskey 			 * a different ESSID).
4416ba597c5SAnurag S. Maskey 			 */
442f6da83d4SAnurag S. Maskey 			nwamd_unplumb_interface(ncu, AF_INET);
443f6da83d4SAnurag S. Maskey 			nwamd_unplumb_interface(ncu, AF_INET6);
4446ba597c5SAnurag S. Maskey 		}
4456ba597c5SAnurag S. Maskey 		if (object->nwamd_object_state != NWAM_STATE_OFFLINE) {
4466ba597c5SAnurag S. Maskey 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4476ba597c5SAnurag S. Maskey 			    object_name, NWAM_STATE_OFFLINE,
4486ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_CONDITIONS_NOT_MET);
4496ba597c5SAnurag S. Maskey 		}
4506ba597c5SAnurag S. Maskey 		break;
4516ba597c5SAnurag S. Maskey 
4526ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_MANUAL_DISABLE:
4536ba597c5SAnurag S. Maskey 		/* Manual disable, set enabled state appropriately. */
4546ba597c5SAnurag S. Maskey 		ncu->ncu_enabled = B_FALSE;
4556ba597c5SAnurag S. Maskey 		/* FALLTHROUGH */
4566ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_UNINITIALIZED:
4576ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_NOT_FOUND:
4586ba597c5SAnurag S. Maskey 		/*
4596ba597c5SAnurag S. Maskey 		 * Link/interface NCU has been disabled/deactivated/removed.
4606ba597c5SAnurag S. Maskey 		 * For WiFi links disconnect, and for IP interfaces we unplumb.
4616ba597c5SAnurag S. Maskey 		 */
4626ba597c5SAnurag S. Maskey 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
4636ba597c5SAnurag S. Maskey 			if (link->nwamd_link_media == DL_WIFI) {
4646ba597c5SAnurag S. Maskey 				(void) dladm_wlan_disconnect(dld_handle,
4656ba597c5SAnurag S. Maskey 				    link->nwamd_link_id);
4666ba597c5SAnurag S. Maskey 				link->nwamd_link_wifi_connected = B_FALSE;
4676ba597c5SAnurag S. Maskey 				nwamd_set_selected_connected(ncu, B_FALSE,
4686ba597c5SAnurag S. Maskey 				    B_FALSE);
4696ba597c5SAnurag S. Maskey 			}
4706ba597c5SAnurag S. Maskey 			nwamd_dlpi_delete_link(object);
4716ba597c5SAnurag S. Maskey 		} else {
4726ba597c5SAnurag S. Maskey 			/* Unplumb here. */
473f6da83d4SAnurag S. Maskey 			if (ncu->ncu_if.nwamd_if_ipv4) {
474f6da83d4SAnurag S. Maskey 				nwamd_unplumb_interface(ncu, AF_INET);
4756ba597c5SAnurag S. Maskey 			}
476f6da83d4SAnurag S. Maskey 			if (ncu->ncu_if.nwamd_if_ipv6) {
477f6da83d4SAnurag S. Maskey 				nwamd_unplumb_interface(ncu, AF_INET6);
4786ba597c5SAnurag S. Maskey 			}
4796ba597c5SAnurag S. Maskey 			/* trigger location condition checking */
4806ba597c5SAnurag S. Maskey 			nwamd_create_triggered_condition_check_event(0);
4816ba597c5SAnurag S. Maskey 		}
4826ba597c5SAnurag S. Maskey 
4836ba597c5SAnurag S. Maskey 		switch (object->nwamd_object_aux_state) {
4846ba597c5SAnurag S. Maskey 		case NWAM_AUX_STATE_MANUAL_DISABLE:
4856ba597c5SAnurag S. Maskey 			/* Change state to DISABLED if manually disabled */
4866ba597c5SAnurag S. Maskey 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4876ba597c5SAnurag S. Maskey 			    object_name, NWAM_STATE_DISABLED,
4886ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_MANUAL_DISABLE);
4896ba597c5SAnurag S. Maskey 			/* Note that NCU has been disabled */
4906ba597c5SAnurag S. Maskey 			ncu->ncu_enabled = B_FALSE;
4916ba597c5SAnurag S. Maskey 			break;
4926ba597c5SAnurag S. Maskey 		case NWAM_AUX_STATE_NOT_FOUND:
4936ba597c5SAnurag S. Maskey 			/* Change state to UNINITIALIZED for device removal */
4946ba597c5SAnurag S. Maskey 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
4956ba597c5SAnurag S. Maskey 			    object_name, NWAM_STATE_UNINITIALIZED,
4966ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_NOT_FOUND);
4976ba597c5SAnurag S. Maskey 			break;
4986ba597c5SAnurag S. Maskey 		default:
4996ba597c5SAnurag S. Maskey 			break;
5006ba597c5SAnurag S. Maskey 		}
5016ba597c5SAnurag S. Maskey 		break;
5026ba597c5SAnurag S. Maskey 	default:
5036ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_state_machine: unexpected state");
5046ba597c5SAnurag S. Maskey 		break;
5056ba597c5SAnurag S. Maskey 	}
5066ba597c5SAnurag S. Maskey 
5076ba597c5SAnurag S. Maskey 	nwamd_object_release(object);
5086ba597c5SAnurag S. Maskey }
5096ba597c5SAnurag S. Maskey 
5106ba597c5SAnurag S. Maskey static int
5116ba597c5SAnurag S. Maskey ncu_create_init_fini_event(nwam_ncu_handle_t ncuh, void *data)
5126ba597c5SAnurag S. Maskey {
5136ba597c5SAnurag S. Maskey 	boolean_t *init = data;
5146ba597c5SAnurag S. Maskey 	char *name, *typedname;
5156ba597c5SAnurag S. Maskey 	nwam_error_t err;
5166ba597c5SAnurag S. Maskey 	nwam_value_t typeval = NULL;
5176ba597c5SAnurag S. Maskey 	uint64_t *type;
5186ba597c5SAnurag S. Maskey 	uint_t numvalues;
5196ba597c5SAnurag S. Maskey 	nwamd_event_t ncu_event;
5206ba597c5SAnurag S. Maskey 
5216ba597c5SAnurag S. Maskey 	if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) {
5226ba597c5SAnurag S. Maskey 		nlog(LOG_ERR,
5236ba597c5SAnurag S. Maskey 		    "ncu_create_init_fini_event: could not get NCU name");
5246ba597c5SAnurag S. Maskey 		return (0);
5256ba597c5SAnurag S. Maskey 	}
5266ba597c5SAnurag S. Maskey 
5276ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "ncu_create_init_fini_event(%s, %p)", name, data);
5286ba597c5SAnurag S. Maskey 
5296ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_uint(ncuh, &typeval, &type, &numvalues,
5306ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_TYPE)) != NWAM_SUCCESS) {
5316ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "ncu_create_init_fini_event: "
5326ba597c5SAnurag S. Maskey 		    "could not get NCU type: %s", nwam_strerror(err));
5336ba597c5SAnurag S. Maskey 		free(name);
5346ba597c5SAnurag S. Maskey 		nwam_value_free(typeval);
5356ba597c5SAnurag S. Maskey 		return (0);
5366ba597c5SAnurag S. Maskey 	}
5376ba597c5SAnurag S. Maskey 
5386ba597c5SAnurag S. Maskey 	/* convert name to typedname for event */
5396ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_name_to_typed_name(name, *type, &typedname))
5406ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS) {
5416ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "ncu_create_init_fini_event: "
5426ba597c5SAnurag S. Maskey 		    "NCU name translation failed: %s", nwam_strerror(err));
5436ba597c5SAnurag S. Maskey 		free(name);
5446ba597c5SAnurag S. Maskey 		return (0);
5456ba597c5SAnurag S. Maskey 	}
5466ba597c5SAnurag S. Maskey 	free(name);
5476ba597c5SAnurag S. Maskey 	nwam_value_free(typeval);
5486ba597c5SAnurag S. Maskey 
5496ba597c5SAnurag S. Maskey 	ncu_event = nwamd_event_init(*init ?
5506ba597c5SAnurag S. Maskey 	    NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI,
5516ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_NCU, 0, typedname);
5526ba597c5SAnurag S. Maskey 	if (ncu_event != NULL)
5536ba597c5SAnurag S. Maskey 		nwamd_event_enqueue(ncu_event);
5546ba597c5SAnurag S. Maskey 	free(typedname);
5556ba597c5SAnurag S. Maskey 
5566ba597c5SAnurag S. Maskey 	return (0);
5576ba597c5SAnurag S. Maskey }
5586ba597c5SAnurag S. Maskey 
5596ba597c5SAnurag S. Maskey /*
5606ba597c5SAnurag S. Maskey  * Initialization - walk the NCUs, creating initialization events for each
5616ba597c5SAnurag S. Maskey  * NCU.  nwamd_ncu_handle_init_event() will check if the associated
5626ba597c5SAnurag S. Maskey  * physical link exists or not.
5636ba597c5SAnurag S. Maskey  */
5646ba597c5SAnurag S. Maskey void
5656ba597c5SAnurag S. Maskey nwamd_init_ncus(void)
5666ba597c5SAnurag S. Maskey {
5676ba597c5SAnurag S. Maskey 	boolean_t init = B_TRUE;
5686ba597c5SAnurag S. Maskey 
5696ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
5706ba597c5SAnurag S. Maskey 	if (active_ncph != NULL) {
5716ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_init_ncus: "
5726ba597c5SAnurag S. Maskey 		    "(re)intializing NCUs for NCP %s", active_ncp);
5736ba597c5SAnurag S. Maskey 		(void) nwam_ncp_walk_ncus(active_ncph,
5746ba597c5SAnurag S. Maskey 		    ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL,
5756ba597c5SAnurag S. Maskey 		    NULL);
5766ba597c5SAnurag S. Maskey 	}
5776ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
5786ba597c5SAnurag S. Maskey }
5796ba597c5SAnurag S. Maskey 
5806ba597c5SAnurag S. Maskey void
5816ba597c5SAnurag S. Maskey nwamd_fini_ncus(void)
5826ba597c5SAnurag S. Maskey {
5836ba597c5SAnurag S. Maskey 	boolean_t init = B_FALSE;
5846ba597c5SAnurag S. Maskey 
5856ba597c5SAnurag S. Maskey 	/* We may not have an active NCP on initialization, so skip fini */
5866ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
5876ba597c5SAnurag S. Maskey 	if (active_ncph != NULL) {
5886ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_fini_ncus: deinitializing NCUs for %s",
5896ba597c5SAnurag S. Maskey 		    active_ncp);
5906ba597c5SAnurag S. Maskey 		(void) nwam_ncp_walk_ncus(active_ncph,
5916ba597c5SAnurag S. Maskey 		    ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL,
5926ba597c5SAnurag S. Maskey 		    NULL);
5936ba597c5SAnurag S. Maskey 	}
5946ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
5956ba597c5SAnurag S. Maskey }
5966ba597c5SAnurag S. Maskey 
5976ba597c5SAnurag S. Maskey /*
5986ba597c5SAnurag S. Maskey  * Most properties of this type don't need to be cached locally.  Only those
5996ba597c5SAnurag S. Maskey  * interesting to the daemon are stored in an nwamd_ncu_t.
6006ba597c5SAnurag S. Maskey  */
6016ba597c5SAnurag S. Maskey static void
6026ba597c5SAnurag S. Maskey populate_common_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
6036ba597c5SAnurag S. Maskey {
6046ba597c5SAnurag S. Maskey 	nwam_value_t ncu_prop;
6056ba597c5SAnurag S. Maskey 	nwam_error_t err;
6066ba597c5SAnurag S. Maskey 	boolean_t enablevalue;
6076ba597c5SAnurag S. Maskey 	uint_t numvalues;
6086ba597c5SAnurag S. Maskey 	char **parent;
6096ba597c5SAnurag S. Maskey 
6106ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED,
6116ba597c5SAnurag S. Maskey 	    &ncu_prop)) != NWAM_SUCCESS) {
6126ba597c5SAnurag S. Maskey 		char *name;
6136ba597c5SAnurag S. Maskey 		(void) nwam_ncu_name_to_typed_name(ncu_data->ncu_name,
6146ba597c5SAnurag S. Maskey 		    ncu_data->ncu_type, &name);
6156ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwam_ncu_get_prop_value %s ENABLED failed: %s",
6166ba597c5SAnurag S. Maskey 		    name, nwam_strerror(err));
6176ba597c5SAnurag S. Maskey 		free(name);
6186ba597c5SAnurag S. Maskey 		ncu_data->ncu_enabled = B_TRUE;
6196ba597c5SAnurag S. Maskey 	} else {
6206ba597c5SAnurag S. Maskey 		if ((err = nwam_value_get_boolean(ncu_prop, &enablevalue)) !=
6216ba597c5SAnurag S. Maskey 		    NWAM_SUCCESS) {
6226ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "nwam_value_get_boolean ENABLED failed: "
6236ba597c5SAnurag S. Maskey 			    "%s", nwam_strerror(err));
6246ba597c5SAnurag S. Maskey 		} else {
6256ba597c5SAnurag S. Maskey 			ncu_data->ncu_enabled = enablevalue;
6266ba597c5SAnurag S. Maskey 		}
6276ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
6286ba597c5SAnurag S. Maskey 	}
6296ba597c5SAnurag S. Maskey 
6306ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &parent,
6316ba597c5SAnurag S. Maskey 	    &numvalues, NWAM_NCU_PROP_PARENT_NCP)) != NWAM_SUCCESS) {
6326ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwam_ncu_get_prop_value %s PARENT failed: %s",
6336ba597c5SAnurag S. Maskey 		    ncu_data->ncu_name, nwam_strerror(err));
6346ba597c5SAnurag S. Maskey 	} else {
6356ba597c5SAnurag S. Maskey 		(void) strlcpy(ncu_data->ncu_parent, parent[0],
6366ba597c5SAnurag S. Maskey 		    sizeof (ncu_data->ncu_parent));
6376ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
6386ba597c5SAnurag S. Maskey 	}
6396ba597c5SAnurag S. Maskey }
6406ba597c5SAnurag S. Maskey 
6416ba597c5SAnurag S. Maskey /*
6426ba597c5SAnurag S. Maskey  * Read in link properties.
6436ba597c5SAnurag S. Maskey  */
6446ba597c5SAnurag S. Maskey static void
6456ba597c5SAnurag S. Maskey populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
6466ba597c5SAnurag S. Maskey {
6476ba597c5SAnurag S. Maskey 	nwam_value_t ncu_prop;
6486ba597c5SAnurag S. Maskey 	nwam_error_t err;
6496ba597c5SAnurag S. Maskey 	char **mac_addr;
6506ba597c5SAnurag S. Maskey 	uint64_t *uintval;
6516ba597c5SAnurag S. Maskey 	uint_t numvalues;
6526ba597c5SAnurag S. Maskey 
6536ba597c5SAnurag S. Maskey 	/* activation-mode */
6546ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues,
6556ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) {
6566ba597c5SAnurag S. Maskey 		nlog(LOG_ERR,
6576ba597c5SAnurag S. Maskey 		    "populate_link_ncu_properties: could not get %s value: %s",
6586ba597c5SAnurag S. Maskey 		    NWAM_NCU_PROP_ACTIVATION_MODE, nwam_strerror(err));
6596ba597c5SAnurag S. Maskey 	} else {
660f6da83d4SAnurag S. Maskey 		ncu_data->ncu_link.nwamd_link_activation_mode = uintval[0];
6616ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
6626ba597c5SAnurag S. Maskey 	}
6636ba597c5SAnurag S. Maskey 
6646ba597c5SAnurag S. Maskey 	/* priority-group and priority-mode for prioritized activation */
665f6da83d4SAnurag S. Maskey 	if (ncu_data->ncu_link.nwamd_link_activation_mode ==
6666ba597c5SAnurag S. Maskey 	    NWAM_ACTIVATION_MODE_PRIORITIZED) {
6676ba597c5SAnurag S. Maskey 		/* ncus with prioritized activation are always enabled */
6686ba597c5SAnurag S. Maskey 		ncu_data->ncu_enabled = B_TRUE;
6696ba597c5SAnurag S. Maskey 		if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval,
6706ba597c5SAnurag S. Maskey 		    &numvalues, NWAM_NCU_PROP_PRIORITY_MODE))
6716ba597c5SAnurag S. Maskey 		    != NWAM_SUCCESS) {
6726ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "populate_link_ncu_properties: "
6736ba597c5SAnurag S. Maskey 			    "could not get %s value: %s",
6746ba597c5SAnurag S. Maskey 			    NWAM_NCU_PROP_PRIORITY_MODE, nwam_strerror(err));
6756ba597c5SAnurag S. Maskey 		} else {
676f6da83d4SAnurag S. Maskey 			ncu_data->ncu_link.nwamd_link_priority_mode =
6776ba597c5SAnurag S. Maskey 			    uintval[0];
6786ba597c5SAnurag S. Maskey 			nwam_value_free(ncu_prop);
6796ba597c5SAnurag S. Maskey 		}
6806ba597c5SAnurag S. Maskey 
6816ba597c5SAnurag S. Maskey 		if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval,
6826ba597c5SAnurag S. Maskey 		    &numvalues, NWAM_NCU_PROP_PRIORITY_GROUP))
6836ba597c5SAnurag S. Maskey 		    != NWAM_SUCCESS) {
6846ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "populate_link_ncu_properties: "
6856ba597c5SAnurag S. Maskey 			    "could not get %s value: %s",
6866ba597c5SAnurag S. Maskey 			    NWAM_NCU_PROP_PRIORITY_GROUP, nwam_strerror(err));
6876ba597c5SAnurag S. Maskey 		} else {
688f6da83d4SAnurag S. Maskey 			ncu_data->ncu_link.nwamd_link_priority_group =
6896ba597c5SAnurag S. Maskey 			    uintval[0];
6906ba597c5SAnurag S. Maskey 			nwam_value_free(ncu_prop);
6916ba597c5SAnurag S. Maskey 		}
6926ba597c5SAnurag S. Maskey 	}
6936ba597c5SAnurag S. Maskey 
6946ba597c5SAnurag S. Maskey 	/* link-mac-addr */
6956ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &mac_addr, &numvalues,
6966ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_LINK_MAC_ADDR)) != NWAM_SUCCESS) {
6976ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG,
6986ba597c5SAnurag S. Maskey 		    "populate_link_ncu_properties: could not get %s value: %s",
6996ba597c5SAnurag S. Maskey 		    NWAM_NCU_PROP_LINK_MAC_ADDR, nwam_strerror(err));
700f6da83d4SAnurag S. Maskey 		ncu_data->ncu_link.nwamd_link_mac_addr = NULL;
7016ba597c5SAnurag S. Maskey 	} else {
702f6da83d4SAnurag S. Maskey 		ncu_data->ncu_link.nwamd_link_mac_addr = strdup(*mac_addr);
703f6da83d4SAnurag S. Maskey 		ncu_data->ncu_link.nwamd_link_mac_addr_len = strlen(*mac_addr);
7046ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
7056ba597c5SAnurag S. Maskey 	}
7066ba597c5SAnurag S. Maskey 
7076ba597c5SAnurag S. Maskey 	/* link-mtu */
7086ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues,
7096ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_LINK_MTU)) != NWAM_SUCCESS) {
7106ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG,
7116ba597c5SAnurag S. Maskey 		    "populate_link_ncu_properties: could not get %s value: %s",
7126ba597c5SAnurag S. Maskey 		    NWAM_NCU_PROP_LINK_MTU, nwam_strerror(err));
713f6da83d4SAnurag S. Maskey 		ncu_data->ncu_link.nwamd_link_mtu = 0;
7146ba597c5SAnurag S. Maskey 	} else {
715f6da83d4SAnurag S. Maskey 		ncu_data->ncu_link.nwamd_link_mtu = uintval[0];
7166ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
7176ba597c5SAnurag S. Maskey 	}
7186ba597c5SAnurag S. Maskey 
7196ba597c5SAnurag S. Maskey 	/* link-autopush */
7206ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop,
721f6da83d4SAnurag S. Maskey 	    &ncu_data->ncu_link.nwamd_link_autopush,
722f6da83d4SAnurag S. Maskey 	    &ncu_data->ncu_link.nwamd_link_num_autopush,
7236ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_LINK_AUTOPUSH)) != NWAM_SUCCESS) {
7246ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG,
7256ba597c5SAnurag S. Maskey 		    "populate_link_ncu_properties: could not get %s value: %s",
7266ba597c5SAnurag S. Maskey 		    NWAM_NCU_PROP_LINK_AUTOPUSH, nwam_strerror(err));
727f6da83d4SAnurag S. Maskey 		ncu_data->ncu_link.nwamd_link_num_autopush = 0;
7286ba597c5SAnurag S. Maskey 	}
7296ba597c5SAnurag S. Maskey }
7306ba597c5SAnurag S. Maskey 
7316ba597c5SAnurag S. Maskey static void
7326ba597c5SAnurag S. Maskey populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
7336ba597c5SAnurag S. Maskey {
734f6da83d4SAnurag S. Maskey 	nwamd_if_t *nif = &ncu_data->ncu_if;
7356ba597c5SAnurag S. Maskey 	struct nwamd_if_address **nifa, *nifai, *nifait;
7366ba597c5SAnurag S. Maskey 	boolean_t static_addr = B_FALSE;
7376ba597c5SAnurag S. Maskey 	uint64_t *addrsrcvalue;
7386ba597c5SAnurag S. Maskey 	nwam_value_t ncu_prop;
7396ba597c5SAnurag S. Maskey 	nwam_error_t err;
740f6da83d4SAnurag S. Maskey 	ipadm_addrobj_t ipaddr;
741f6da83d4SAnurag S. Maskey 	ipadm_status_t ipstatus;
7426ba597c5SAnurag S. Maskey 	char **addrvalue;
7436ba597c5SAnurag S. Maskey 	uint_t numvalues;
7446ba597c5SAnurag S. Maskey 	uint64_t *ipversion;
7456ba597c5SAnurag S. Maskey 	int i;
7466ba597c5SAnurag S. Maskey 
7476ba597c5SAnurag S. Maskey 	nif->nwamd_if_ipv4 = B_FALSE;
7486ba597c5SAnurag S. Maskey 	nif->nwamd_if_ipv6 = B_FALSE;
7496ba597c5SAnurag S. Maskey 	nif->nwamd_if_dhcp_requested = B_FALSE;
7506ba597c5SAnurag S. Maskey 	nif->nwamd_if_stateful_requested = B_FALSE;
7516ba597c5SAnurag S. Maskey 	nif->nwamd_if_stateless_requested = B_FALSE;
7526ba597c5SAnurag S. Maskey 	nif->nwamd_if_ipv4_default_route_set = B_FALSE;
7536ba597c5SAnurag S. Maskey 	nif->nwamd_if_ipv6_default_route_set = B_FALSE;
7546ba597c5SAnurag S. Maskey 
7556ba597c5SAnurag S. Maskey 	/* ip-version */
7566ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &ipversion, &numvalues,
7576ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_IP_VERSION)) != NWAM_SUCCESS) {
7586ba597c5SAnurag S. Maskey 		nlog(LOG_ERR,
7596ba597c5SAnurag S. Maskey 		    "populate_ip_ncu_properties: could not get %s value: %s",
7606ba597c5SAnurag S. Maskey 		    NWAM_NCU_PROP_IP_VERSION, nwam_strerror(err));
7616ba597c5SAnurag S. Maskey 	} else {
7626ba597c5SAnurag S. Maskey 		for (i = 0; i < numvalues; i++) {
7636ba597c5SAnurag S. Maskey 			switch (ipversion[i]) {
7646ba597c5SAnurag S. Maskey 			case IPV4_VERSION:
7656ba597c5SAnurag S. Maskey 				nif->nwamd_if_ipv4 = B_TRUE;
7666ba597c5SAnurag S. Maskey 				break;
7676ba597c5SAnurag S. Maskey 			case IPV6_VERSION:
7686ba597c5SAnurag S. Maskey 				nif->nwamd_if_ipv6 = B_TRUE;
7696ba597c5SAnurag S. Maskey 				break;
7706ba597c5SAnurag S. Maskey 			default:
7716ba597c5SAnurag S. Maskey 				nlog(LOG_ERR, "bogus ip version %lld",
7726ba597c5SAnurag S. Maskey 				    ipversion[i]);
7736ba597c5SAnurag S. Maskey 				break;
7746ba597c5SAnurag S. Maskey 			}
7756ba597c5SAnurag S. Maskey 		}
7766ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
7776ba597c5SAnurag S. Maskey 	}
7786ba597c5SAnurag S. Maskey 
7796ba597c5SAnurag S. Maskey 	/* Free the old list. */
7806ba597c5SAnurag S. Maskey 	for (nifai = nif->nwamd_if_list; nifai != NULL; nifai = nifait) {
7816ba597c5SAnurag S. Maskey 		nifait = nifai->next;
7826ba597c5SAnurag S. Maskey 		nifai->next = NULL;
783f6da83d4SAnurag S. Maskey 		ipadm_destroy_addrobj(nifai->ipaddr);
7846ba597c5SAnurag S. Maskey 		free(nifai);
7856ba597c5SAnurag S. Maskey 	}
7866ba597c5SAnurag S. Maskey 	nif->nwamd_if_list = NULL;
7876ba597c5SAnurag S. Maskey 	nifa = &(nif->nwamd_if_list);
7886ba597c5SAnurag S. Maskey 
7896ba597c5SAnurag S. Maskey 	if (!nif->nwamd_if_ipv4)
7906ba597c5SAnurag S. Maskey 		goto skip_ipv4;
7916ba597c5SAnurag S. Maskey 
7926ba597c5SAnurag S. Maskey 	/* ipv4-addrsrc */
7936ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue,
7946ba597c5SAnurag S. Maskey 	    &numvalues, NWAM_NCU_PROP_IPV4_ADDRSRC)) != NWAM_SUCCESS) {
7956ba597c5SAnurag S. Maskey 		nlog(nif->nwamd_if_ipv4 ? LOG_ERR : LOG_DEBUG,
7966ba597c5SAnurag S. Maskey 		    "populate_ip_ncu_properties: could not get %s value: %s",
7976ba597c5SAnurag S. Maskey 		    NWAM_NCU_PROP_IPV4_ADDRSRC, nwam_strerror(err));
7986ba597c5SAnurag S. Maskey 	} else {
7996ba597c5SAnurag S. Maskey 		for (i = 0; i < numvalues; i++) {
8006ba597c5SAnurag S. Maskey 			switch (addrsrcvalue[i]) {
8016ba597c5SAnurag S. Maskey 			case NWAM_ADDRSRC_DHCP:
8026ba597c5SAnurag S. Maskey 				nif->nwamd_if_dhcp_requested = B_TRUE;
8036ba597c5SAnurag S. Maskey 				break;
8046ba597c5SAnurag S. Maskey 			case NWAM_ADDRSRC_STATIC:
8056ba597c5SAnurag S. Maskey 				static_addr = B_TRUE;
8066ba597c5SAnurag S. Maskey 				break;
8076ba597c5SAnurag S. Maskey 			default:
8086ba597c5SAnurag S. Maskey 				break;
8096ba597c5SAnurag S. Maskey 			}
8106ba597c5SAnurag S. Maskey 		}
8116ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
8126ba597c5SAnurag S. Maskey 	}
8136ba597c5SAnurag S. Maskey 	if (nif->nwamd_if_dhcp_requested) {
814f6da83d4SAnurag S. Maskey 		ipstatus = ipadm_create_addrobj(IPADM_ADDR_DHCP,
815f6da83d4SAnurag S. Maskey 		    ncu_data->ncu_name, &ipaddr);
816f6da83d4SAnurag S. Maskey 		if (ipstatus != IPADM_SUCCESS) {
817f6da83d4SAnurag S. Maskey 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
818f6da83d4SAnurag S. Maskey 			    "ipadm_create_addrobj failed for v4 dhcp: %s",
819f6da83d4SAnurag S. Maskey 			    ipadm_status2str(ipstatus));
820f6da83d4SAnurag S. Maskey 			goto skip_ipv4_dhcp;
821f6da83d4SAnurag S. Maskey 		}
822f6da83d4SAnurag S. Maskey 
823f6da83d4SAnurag S. Maskey 		ipstatus = ipadm_set_wait_time(ipaddr, ncu_wait_time);
824f6da83d4SAnurag S. Maskey 		if (ipstatus != IPADM_SUCCESS) {
825f6da83d4SAnurag S. Maskey 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
826f6da83d4SAnurag S. Maskey 			    "ipadm_set_wait_time failed for v4 dhcp: %s",
827f6da83d4SAnurag S. Maskey 			    ipadm_status2str(ipstatus));
828f6da83d4SAnurag S. Maskey 			ipadm_destroy_addrobj(ipaddr);
829f6da83d4SAnurag S. Maskey 			goto skip_ipv4_dhcp;
830f6da83d4SAnurag S. Maskey 		}
8316ba597c5SAnurag S. Maskey 		if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
832f6da83d4SAnurag S. Maskey 			(*nifa)->family = AF_INET;
833f6da83d4SAnurag S. Maskey 			(*nifa)->ipaddr_atype = IPADM_ADDR_DHCP;
834f6da83d4SAnurag S. Maskey 			(*nifa)->ipaddr = ipaddr;
8356ba597c5SAnurag S. Maskey 			nifa = &((*nifa)->next);
8366ba597c5SAnurag S. Maskey 			*nifa = NULL;
837f6da83d4SAnurag S. Maskey 		} else {
838f6da83d4SAnurag S. Maskey 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
839f6da83d4SAnurag S. Maskey 			    "couldn't allocate nwamd address for v4 dhcp: %s",
840f6da83d4SAnurag S. Maskey 			    strerror(errno));
841f6da83d4SAnurag S. Maskey 			ipadm_destroy_addrobj(ipaddr);
8426ba597c5SAnurag S. Maskey 		}
8436ba597c5SAnurag S. Maskey 	}
8446ba597c5SAnurag S. Maskey 
845f6da83d4SAnurag S. Maskey skip_ipv4_dhcp:
8466ba597c5SAnurag S. Maskey 	/* ipv4-addr */
8476ba597c5SAnurag S. Maskey 	if (static_addr) {
8486ba597c5SAnurag S. Maskey 		if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
8496ba597c5SAnurag S. Maskey 		    &numvalues, NWAM_NCU_PROP_IPV4_ADDR)) != NWAM_SUCCESS) {
8506ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
8516ba597c5SAnurag S. Maskey 			    "could not get %s value; %s",
8526ba597c5SAnurag S. Maskey 			    NWAM_NCU_PROP_IPV4_ADDR, nwam_strerror(err));
8536ba597c5SAnurag S. Maskey 		} else {
8546ba597c5SAnurag S. Maskey 			for (i = 0; i < numvalues; i++) {
855f6da83d4SAnurag S. Maskey 				ipstatus = ipadm_create_addrobj(
856f6da83d4SAnurag S. Maskey 				    IPADM_ADDR_STATIC, ncu_data->ncu_name,
857f6da83d4SAnurag S. Maskey 				    &ipaddr);
858f6da83d4SAnurag S. Maskey 				if (ipstatus != IPADM_SUCCESS) {
859f6da83d4SAnurag S. Maskey 					nlog(LOG_ERR,
860f6da83d4SAnurag S. Maskey 					    "populate_ip_ncu_properties: "
861f6da83d4SAnurag S. Maskey 					    "ipadm_create_addrobj failed "
862f6da83d4SAnurag S. Maskey 					    "for %s: %s", addrvalue[i],
863f6da83d4SAnurag S. Maskey 					    ipadm_status2str(ipstatus));
8646ba597c5SAnurag S. Maskey 					continue;
8656ba597c5SAnurag S. Maskey 				}
866f6da83d4SAnurag S. Maskey 				/* ipadm_set_addr takes <addr>[/<mask>] */
867f6da83d4SAnurag S. Maskey 				ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
868f6da83d4SAnurag S. Maskey 				    AF_INET);
869f6da83d4SAnurag S. Maskey 				if (ipstatus != IPADM_SUCCESS) {
870f6da83d4SAnurag S. Maskey 					nlog(LOG_ERR,
871f6da83d4SAnurag S. Maskey 					    "populate_ip_ncu_properties: "
872f6da83d4SAnurag S. Maskey 					    "ipadm_set_addr failed for %s: %s",
873f6da83d4SAnurag S. Maskey 					    addrvalue[i],
874f6da83d4SAnurag S. Maskey 					    ipadm_status2str(ipstatus));
875f6da83d4SAnurag S. Maskey 					ipadm_destroy_addrobj(ipaddr);
876f6da83d4SAnurag S. Maskey 					continue;
8776ba597c5SAnurag S. Maskey 				}
878f6da83d4SAnurag S. Maskey 
879f6da83d4SAnurag S. Maskey 				if ((*nifa = calloc(sizeof (**nifa), 1))
880f6da83d4SAnurag S. Maskey 				    != NULL) {
881f6da83d4SAnurag S. Maskey 					(*nifa)->family = AF_INET;
882f6da83d4SAnurag S. Maskey 					(*nifa)->ipaddr_atype =
883f6da83d4SAnurag S. Maskey 					    IPADM_ADDR_STATIC;
884f6da83d4SAnurag S. Maskey 					(*nifa)->ipaddr = ipaddr;
8856ba597c5SAnurag S. Maskey 					nifa = &((*nifa)->next);
886f6da83d4SAnurag S. Maskey 				} else {
887f6da83d4SAnurag S. Maskey 					nlog(LOG_ERR,
888f6da83d4SAnurag S. Maskey 					    "populate_ip_ncu_properties: "
889f6da83d4SAnurag S. Maskey 					    "couldn't allocate nwamd address "
890f6da83d4SAnurag S. Maskey 					    "for %s: %s", addrvalue[i],
891f6da83d4SAnurag S. Maskey 					    strerror(errno));
892f6da83d4SAnurag S. Maskey 					ipadm_destroy_addrobj(ipaddr);
893f6da83d4SAnurag S. Maskey 				}
8946ba597c5SAnurag S. Maskey 			}
8956ba597c5SAnurag S. Maskey 			*nifa = NULL;
8966ba597c5SAnurag S. Maskey 
8976ba597c5SAnurag S. Maskey 			nwam_value_free(ncu_prop);
8986ba597c5SAnurag S. Maskey 		}
8996ba597c5SAnurag S. Maskey 	}
9006ba597c5SAnurag S. Maskey 
9016ba597c5SAnurag S. Maskey 	/* get default route, if any */
9026ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
9036ba597c5SAnurag S. Maskey 	    &numvalues, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE)) == NWAM_SUCCESS) {
9046ba597c5SAnurag S. Maskey 		/* Only one default route is allowed. */
9056ba597c5SAnurag S. Maskey 		nif->nwamd_if_ipv4_default_route.sin_family = AF_INET;
9066ba597c5SAnurag S. Maskey 		(void) inet_pton(AF_INET, addrvalue[0],
9076ba597c5SAnurag S. Maskey 		    &(nif->nwamd_if_ipv4_default_route.sin_addr));
9086ba597c5SAnurag S. Maskey 		nif->nwamd_if_ipv4_default_route_set = B_TRUE;
9096ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
9106ba597c5SAnurag S. Maskey 	}
9116ba597c5SAnurag S. Maskey 
9126ba597c5SAnurag S. Maskey skip_ipv4:
9136ba597c5SAnurag S. Maskey 	if (!nif->nwamd_if_ipv6)
9146ba597c5SAnurag S. Maskey 		goto skip_ipv6;
9156ba597c5SAnurag S. Maskey 
9166ba597c5SAnurag S. Maskey 	/* ipv6-addrsrc */
9176ba597c5SAnurag S. Maskey 	static_addr = B_FALSE;
9186ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue,
9196ba597c5SAnurag S. Maskey 	    &numvalues, NWAM_NCU_PROP_IPV6_ADDRSRC)) != NWAM_SUCCESS) {
9206ba597c5SAnurag S. Maskey 		nlog(nif->nwamd_if_ipv6 ? LOG_ERR : LOG_DEBUG,
9216ba597c5SAnurag S. Maskey 		    "populate_ip_ncu_properties: could not get %s value: %s",
9226ba597c5SAnurag S. Maskey 		    NWAM_NCU_PROP_IPV6_ADDRSRC, nwam_strerror(err));
9236ba597c5SAnurag S. Maskey 	} else {
9246ba597c5SAnurag S. Maskey 		for (i = 0; i < numvalues; i++) {
9256ba597c5SAnurag S. Maskey 			switch (addrsrcvalue[i]) {
9266ba597c5SAnurag S. Maskey 			case NWAM_ADDRSRC_DHCP:
9276ba597c5SAnurag S. Maskey 				nif->nwamd_if_stateful_requested = B_TRUE;
9286ba597c5SAnurag S. Maskey 				break;
9296ba597c5SAnurag S. Maskey 			case NWAM_ADDRSRC_AUTOCONF:
9306ba597c5SAnurag S. Maskey 				nif->nwamd_if_stateless_requested = B_TRUE;
9316ba597c5SAnurag S. Maskey 				break;
9326ba597c5SAnurag S. Maskey 			case NWAM_ADDRSRC_STATIC:
9336ba597c5SAnurag S. Maskey 				static_addr = B_TRUE;
9346ba597c5SAnurag S. Maskey 				break;
9356ba597c5SAnurag S. Maskey 			default:
9366ba597c5SAnurag S. Maskey 				break;
9376ba597c5SAnurag S. Maskey 			}
9386ba597c5SAnurag S. Maskey 		}
9396ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
9406ba597c5SAnurag S. Maskey 	}
941f6da83d4SAnurag S. Maskey 	/*
942f6da83d4SAnurag S. Maskey 	 * Both stateful and stateless share the same nwamd_if_address because
943f6da83d4SAnurag S. Maskey 	 * only one ipaddr for both of these addresses can be created.
944f6da83d4SAnurag S. Maskey 	 * ipadm_create_addr() adds both addresses from the same ipaddr.
945f6da83d4SAnurag S. Maskey 	 */
946f6da83d4SAnurag S. Maskey 	if (nif->nwamd_if_stateful_requested ||
947f6da83d4SAnurag S. Maskey 	    nif->nwamd_if_stateless_requested) {
948f6da83d4SAnurag S. Maskey 		ipstatus = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
949f6da83d4SAnurag S. Maskey 		    ncu_data->ncu_name, &ipaddr);
950f6da83d4SAnurag S. Maskey 		if (ipstatus != IPADM_SUCCESS) {
951f6da83d4SAnurag S. Maskey 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
952f6da83d4SAnurag S. Maskey 			    "ipadm_create_addrobj failed for v6 "
953f6da83d4SAnurag S. Maskey 			    "stateless/stateful: %s",
954f6da83d4SAnurag S. Maskey 			    ipadm_status2str(ipstatus));
955f6da83d4SAnurag S. Maskey 			goto skip_ipv6_addrconf;
956f6da83d4SAnurag S. Maskey 		}
957f6da83d4SAnurag S. Maskey 		/* create_addrobj sets both stateless and stateful to B_TRUE */
958f6da83d4SAnurag S. Maskey 		if (!nif->nwamd_if_stateful_requested) {
959f6da83d4SAnurag S. Maskey 			ipstatus = ipadm_set_stateful(ipaddr, B_FALSE);
960f6da83d4SAnurag S. Maskey 			if (ipstatus != IPADM_SUCCESS) {
961f6da83d4SAnurag S. Maskey 				nlog(LOG_ERR, "populate_ip_ncu_properties: "
962f6da83d4SAnurag S. Maskey 				    "ipadm_set_stateful failed for v6: %s",
963f6da83d4SAnurag S. Maskey 				    ipadm_status2str(ipstatus));
964f6da83d4SAnurag S. Maskey 				ipadm_destroy_addrobj(ipaddr);
965f6da83d4SAnurag S. Maskey 				goto skip_ipv6_addrconf;
9666ba597c5SAnurag S. Maskey 			}
9676ba597c5SAnurag S. Maskey 		}
968f6da83d4SAnurag S. Maskey 		if (!nif->nwamd_if_stateless_requested) {
969f6da83d4SAnurag S. Maskey 			ipstatus = ipadm_set_stateless(ipaddr, B_FALSE);
970f6da83d4SAnurag S. Maskey 			if (ipstatus != IPADM_SUCCESS) {
971f6da83d4SAnurag S. Maskey 				nlog(LOG_ERR, "populate_ip_ncu_properties: "
972f6da83d4SAnurag S. Maskey 				    "ipadm_set_stateless failed for v6: %s",
973f6da83d4SAnurag S. Maskey 				    ipadm_status2str(ipstatus));
974f6da83d4SAnurag S. Maskey 				ipadm_destroy_addrobj(ipaddr);
975f6da83d4SAnurag S. Maskey 				goto skip_ipv6_addrconf;
976f6da83d4SAnurag S. Maskey 			}
977f6da83d4SAnurag S. Maskey 		}
9786ba597c5SAnurag S. Maskey 		if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
979f6da83d4SAnurag S. Maskey 			(*nifa)->family = AF_INET6;
980f6da83d4SAnurag S. Maskey 			(*nifa)->ipaddr_atype = IPADM_ADDR_IPV6_ADDRCONF;
981f6da83d4SAnurag S. Maskey 			(*nifa)->ipaddr = ipaddr;
9826ba597c5SAnurag S. Maskey 			nifa = &((*nifa)->next);
9836ba597c5SAnurag S. Maskey 			*nifa = NULL;
984f6da83d4SAnurag S. Maskey 		} else {
985f6da83d4SAnurag S. Maskey 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
986f6da83d4SAnurag S. Maskey 			    "couldn't allocate nwamd address for "
987f6da83d4SAnurag S. Maskey 			    "v6 stateless/stateful: %s", strerror(errno));
988f6da83d4SAnurag S. Maskey 			ipadm_destroy_addrobj(ipaddr);
9896ba597c5SAnurag S. Maskey 		}
9906ba597c5SAnurag S. Maskey 	}
9916ba597c5SAnurag S. Maskey 
992f6da83d4SAnurag S. Maskey skip_ipv6_addrconf:
9936ba597c5SAnurag S. Maskey 	/* ipv6-addr */
9946ba597c5SAnurag S. Maskey 	if (static_addr) {
9956ba597c5SAnurag S. Maskey 		if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
9966ba597c5SAnurag S. Maskey 		    &numvalues, NWAM_NCU_PROP_IPV6_ADDR)) != NWAM_SUCCESS) {
9976ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "populate_ip_ncu_properties: "
9986ba597c5SAnurag S. Maskey 			    "could not get %s value; %s",
9996ba597c5SAnurag S. Maskey 			    NWAM_NCU_PROP_IPV6_ADDR, nwam_strerror(err));
10006ba597c5SAnurag S. Maskey 		} else {
10016ba597c5SAnurag S. Maskey 			for (i = 0; i < numvalues; i++) {
1002f6da83d4SAnurag S. Maskey 				ipstatus = ipadm_create_addrobj(
1003f6da83d4SAnurag S. Maskey 				    IPADM_ADDR_STATIC, ncu_data->ncu_name,
1004f6da83d4SAnurag S. Maskey 				    &ipaddr);
1005f6da83d4SAnurag S. Maskey 				if (ipstatus != IPADM_SUCCESS) {
1006f6da83d4SAnurag S. Maskey 					nlog(LOG_ERR,
1007f6da83d4SAnurag S. Maskey 					    "populate_ip_ncu_properties: "
1008f6da83d4SAnurag S. Maskey 					    "ipadm_create_addrobj failed "
1009f6da83d4SAnurag S. Maskey 					    "for %s: %s", addrvalue[i],
1010f6da83d4SAnurag S. Maskey 					    ipadm_status2str(ipstatus));
10116ba597c5SAnurag S. Maskey 					continue;
10126ba597c5SAnurag S. Maskey 				}
1013f6da83d4SAnurag S. Maskey 				/* ipadm_set_addr takes <addr>[/<mask>] */
1014f6da83d4SAnurag S. Maskey 				ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
1015f6da83d4SAnurag S. Maskey 				    AF_INET6);
1016f6da83d4SAnurag S. Maskey 				if (ipstatus != IPADM_SUCCESS) {
1017f6da83d4SAnurag S. Maskey 					nlog(LOG_ERR,
1018f6da83d4SAnurag S. Maskey 					    "populate_ip_ncu_properties: "
1019f6da83d4SAnurag S. Maskey 					    "ipadm_set_addr failed for %s: %s",
1020f6da83d4SAnurag S. Maskey 					    addrvalue[i],
1021f6da83d4SAnurag S. Maskey 					    ipadm_status2str(ipstatus));
1022f6da83d4SAnurag S. Maskey 					ipadm_destroy_addrobj(ipaddr);
1023f6da83d4SAnurag S. Maskey 					continue;
10246ba597c5SAnurag S. Maskey 				}
1025f6da83d4SAnurag S. Maskey 
1026f6da83d4SAnurag S. Maskey 				if ((*nifa = calloc(sizeof (**nifa), 1))
1027f6da83d4SAnurag S. Maskey 				    != NULL) {
1028f6da83d4SAnurag S. Maskey 					(*nifa)->family = AF_INET6;
1029f6da83d4SAnurag S. Maskey 					(*nifa)->ipaddr_atype =
1030f6da83d4SAnurag S. Maskey 					    IPADM_ADDR_STATIC;
1031f6da83d4SAnurag S. Maskey 					(*nifa)->ipaddr = ipaddr;
10326ba597c5SAnurag S. Maskey 					nifa = &((*nifa)->next);
1033f6da83d4SAnurag S. Maskey 				} else {
1034f6da83d4SAnurag S. Maskey 					nlog(LOG_ERR,
1035f6da83d4SAnurag S. Maskey 					    "populate_ip_ncu_properties: "
1036f6da83d4SAnurag S. Maskey 					    "couldn't allocate nwamd address "
1037f6da83d4SAnurag S. Maskey 					    "for %s: %s", addrvalue[i],
1038f6da83d4SAnurag S. Maskey 					    strerror(errno));
1039f6da83d4SAnurag S. Maskey 					ipadm_destroy_addrobj(ipaddr);
1040f6da83d4SAnurag S. Maskey 				}
10416ba597c5SAnurag S. Maskey 			}
10426ba597c5SAnurag S. Maskey 			*nifa = NULL;
10436ba597c5SAnurag S. Maskey 
10446ba597c5SAnurag S. Maskey 			nwam_value_free(ncu_prop);
10456ba597c5SAnurag S. Maskey 		}
10466ba597c5SAnurag S. Maskey 	}
10476ba597c5SAnurag S. Maskey 
10486ba597c5SAnurag S. Maskey 	/* get default route, if any */
10496ba597c5SAnurag S. Maskey 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
10506ba597c5SAnurag S. Maskey 	    &numvalues, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE)) == NWAM_SUCCESS) {
10516ba597c5SAnurag S. Maskey 		/* Only one default route is allowed. */
10526ba597c5SAnurag S. Maskey 		nif->nwamd_if_ipv6_default_route.sin6_family = AF_INET6;
10536ba597c5SAnurag S. Maskey 		(void) inet_pton(AF_INET6, addrvalue[0],
10546ba597c5SAnurag S. Maskey 		    &(nif->nwamd_if_ipv6_default_route.sin6_addr));
10556ba597c5SAnurag S. Maskey 		nif->nwamd_if_ipv6_default_route_set = B_TRUE;
10566ba597c5SAnurag S. Maskey 		nwam_value_free(ncu_prop);
10576ba597c5SAnurag S. Maskey 	}
10586ba597c5SAnurag S. Maskey 
10596ba597c5SAnurag S. Maskey skip_ipv6:
10606ba597c5SAnurag S. Maskey 	;
10616ba597c5SAnurag S. Maskey }
10626ba597c5SAnurag S. Maskey 
10636ba597c5SAnurag S. Maskey static nwamd_ncu_t *
10646ba597c5SAnurag S. Maskey nwamd_ncu_init(nwam_ncu_type_t ncu_type, const char *name)
10656ba597c5SAnurag S. Maskey {
10666ba597c5SAnurag S. Maskey 	nwamd_ncu_t *rv;
10676ba597c5SAnurag S. Maskey 
10686ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncu_init(%d, %s)", ncu_type, name);
10696ba597c5SAnurag S. Maskey 
10706ba597c5SAnurag S. Maskey 	if ((rv = calloc(1, sizeof (*rv))) == NULL)
10716ba597c5SAnurag S. Maskey 		return (NULL);
10726ba597c5SAnurag S. Maskey 
10736ba597c5SAnurag S. Maskey 	rv->ncu_type = ncu_type;
10746ba597c5SAnurag S. Maskey 	rv->ncu_name = strdup(name);
10756ba597c5SAnurag S. Maskey 	rv->ncu_enabled = B_FALSE;
10766ba597c5SAnurag S. Maskey 
10776ba597c5SAnurag S. Maskey 	/* Initialize link/interface-specific data */
10786ba597c5SAnurag S. Maskey 	if (rv->ncu_type == NWAM_NCU_TYPE_LINK) {
1079f6da83d4SAnurag S. Maskey 		(void) bzero(&rv->ncu_link, sizeof (nwamd_link_t));
10806ba597c5SAnurag S. Maskey 		(void) dladm_name2info(dld_handle, name,
1081f6da83d4SAnurag S. Maskey 		    &rv->ncu_link.nwamd_link_id, NULL, NULL,
1082f6da83d4SAnurag S. Maskey 		    &rv->ncu_link.nwamd_link_media);
10836ba597c5SAnurag S. Maskey 		(void) pthread_mutex_init(
1084f6da83d4SAnurag S. Maskey 		    &rv->ncu_link.nwamd_link_wifi_mutex, NULL);
1085f6da83d4SAnurag S. Maskey 		rv->ncu_link.nwamd_link_wifi_priority = MAXINT;
10866ba597c5SAnurag S. Maskey 	} else {
1087f6da83d4SAnurag S. Maskey 		(void) bzero(&rv->ncu_if, sizeof (nwamd_if_t));
10886ba597c5SAnurag S. Maskey 	}
10896ba597c5SAnurag S. Maskey 
10906ba597c5SAnurag S. Maskey 	return (rv);
10916ba597c5SAnurag S. Maskey }
10926ba597c5SAnurag S. Maskey 
10936ba597c5SAnurag S. Maskey void
10946ba597c5SAnurag S. Maskey nwamd_ncu_free(nwamd_ncu_t *ncu)
10956ba597c5SAnurag S. Maskey {
10966ba597c5SAnurag S. Maskey 	if (ncu != NULL) {
10976ba597c5SAnurag S. Maskey 		assert(ncu->ncu_type == NWAM_NCU_TYPE_LINK ||
10986ba597c5SAnurag S. Maskey 		    ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE);
10996ba597c5SAnurag S. Maskey 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
1100f6da83d4SAnurag S. Maskey 			struct nwamd_link *l = &ncu->ncu_link;
11016ba597c5SAnurag S. Maskey 			int i;
11026ba597c5SAnurag S. Maskey 
11036ba597c5SAnurag S. Maskey 			free(l->nwamd_link_wifi_key);
11046ba597c5SAnurag S. Maskey 			free(l->nwamd_link_mac_addr);
11056ba597c5SAnurag S. Maskey 			for (i = 0; i < l->nwamd_link_num_autopush; i++)
11066ba597c5SAnurag S. Maskey 				free(l->nwamd_link_autopush[i]);
11076ba597c5SAnurag S. Maskey 		} else if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) {
11086ba597c5SAnurag S. Maskey 			struct nwamd_if_address *nifa;
11096ba597c5SAnurag S. Maskey 
1110f6da83d4SAnurag S. Maskey 			nifa = ncu->ncu_if.nwamd_if_list;
11116ba597c5SAnurag S. Maskey 			while (nifa != NULL) {
11126ba597c5SAnurag S. Maskey 				struct nwamd_if_address *n;
11136ba597c5SAnurag S. Maskey 
11146ba597c5SAnurag S. Maskey 				n = nifa;
11156ba597c5SAnurag S. Maskey 				nifa = nifa->next;
1116f6da83d4SAnurag S. Maskey 				ipadm_destroy_addrobj(n->ipaddr);
11176ba597c5SAnurag S. Maskey 				free(n);
11186ba597c5SAnurag S. Maskey 			}
11196ba597c5SAnurag S. Maskey 		}
11206ba597c5SAnurag S. Maskey 		free(ncu->ncu_name);
11216ba597c5SAnurag S. Maskey 		free(ncu);
11226ba597c5SAnurag S. Maskey 	}
11236ba597c5SAnurag S. Maskey }
11246ba597c5SAnurag S. Maskey 
11256ba597c5SAnurag S. Maskey static int
11266ba597c5SAnurag S. Maskey nwamd_ncu_display(nwamd_object_t ncu_obj, void *data)
11276ba597c5SAnurag S. Maskey {
11286ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu = (nwamd_ncu_t *)ncu_obj->nwamd_object_data;
11296ba597c5SAnurag S. Maskey 	data = data;
11306ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "NCU (%p) %s state %s, %s",
11316ba597c5SAnurag S. Maskey 	    (void *)ncu, ncu_obj->nwamd_object_name,
11326ba597c5SAnurag S. Maskey 	    nwam_state_to_string(ncu_obj->nwamd_object_state),
11336ba597c5SAnurag S. Maskey 	    nwam_aux_state_to_string(ncu_obj->nwamd_object_aux_state));
11346ba597c5SAnurag S. Maskey 	return (0);
11356ba597c5SAnurag S. Maskey }
11366ba597c5SAnurag S. Maskey 
11376ba597c5SAnurag S. Maskey void
11386ba597c5SAnurag S. Maskey nwamd_log_ncus(void)
11396ba597c5SAnurag S. Maskey {
11406ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "NCP %s", active_ncp);
11416ba597c5SAnurag S. Maskey 	(void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, nwamd_ncu_display,
11426ba597c5SAnurag S. Maskey 	    NULL);
11436ba597c5SAnurag S. Maskey }
11446ba597c5SAnurag S. Maskey 
11456ba597c5SAnurag S. Maskey int
11466ba597c5SAnurag S. Maskey nwamd_ncu_action(const char *ncu, const char *parent, nwam_action_t action)
11476ba597c5SAnurag S. Maskey {
11486ba597c5SAnurag S. Maskey 	nwamd_event_t ncu_event = nwamd_event_init_object_action
11496ba597c5SAnurag S. Maskey 	    (NWAM_OBJECT_TYPE_NCU, ncu, parent, action);
11506ba597c5SAnurag S. Maskey 	if (ncu_event == NULL)
11516ba597c5SAnurag S. Maskey 		return (1);
11526ba597c5SAnurag S. Maskey 	nwamd_event_enqueue(ncu_event);
11536ba597c5SAnurag S. Maskey 	return (0);
11546ba597c5SAnurag S. Maskey }
11556ba597c5SAnurag S. Maskey 
11566ba597c5SAnurag S. Maskey static void
11576ba597c5SAnurag S. Maskey add_phys_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name)
11586ba597c5SAnurag S. Maskey {
11596ba597c5SAnurag S. Maskey 	dladm_status_t dlrtn;
11606ba597c5SAnurag S. Maskey 	uint32_t media;
11616ba597c5SAnurag S. Maskey 	boolean_t is_wireless;
11626ba597c5SAnurag S. Maskey 	nwam_error_t err;
11636ba597c5SAnurag S. Maskey 	nwam_ncu_handle_t ncuh;
11646ba597c5SAnurag S. Maskey 	uint64_t uintval;
11656ba597c5SAnurag S. Maskey 
11666ba597c5SAnurag S. Maskey 	if ((dlrtn = dladm_name2info(dld_handle, name, NULL, NULL, NULL,
11676ba597c5SAnurag S. Maskey 	    &media)) != DLADM_STATUS_OK) {
11686ba597c5SAnurag S. Maskey 		char errmsg[DLADM_STRSIZE];
11696ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "failed to get media type for %s: %s", name,
11706ba597c5SAnurag S. Maskey 		    dladm_status2str(dlrtn, errmsg));
11716ba597c5SAnurag S. Maskey 		return;
11726ba597c5SAnurag S. Maskey 	}
11736ba597c5SAnurag S. Maskey 	is_wireless = (media == DL_WIFI);
11746ba597c5SAnurag S. Maskey 
11756ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_LINK,
11766ba597c5SAnurag S. Maskey 	    NWAM_NCU_CLASS_PHYS, &ncuh)) != NWAM_SUCCESS) {
11776ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "failed to create link ncu for %s: %s", name,
11786ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
11796ba597c5SAnurag S. Maskey 		if (err == NWAM_ENTITY_READ_ONLY) {
11806ba597c5SAnurag S. Maskey 			nwamd_event_t retry_event;
11816ba597c5SAnurag S. Maskey 
11826ba597c5SAnurag S. Maskey 			/*
11836ba597c5SAnurag S. Maskey 			 * Root filesystem may be read-only, retry in
11846ba597c5SAnurag S. Maskey 			 * a few seconds.
11856ba597c5SAnurag S. Maskey 			 */
11866ba597c5SAnurag S. Maskey 			nlog(LOG_DEBUG, "Retrying addition of phys ncu for %s",
11876ba597c5SAnurag S. Maskey 			    name);
11886ba597c5SAnurag S. Maskey 			retry_event = nwamd_event_init_link_action(name,
11896ba597c5SAnurag S. Maskey 			    NWAM_ACTION_ADD);
11906ba597c5SAnurag S. Maskey 			if (retry_event != NULL) {
11916ba597c5SAnurag S. Maskey 				nwamd_event_enqueue_timed(retry_event,
11926ba597c5SAnurag S. Maskey 				    NWAMD_READONLY_RETRY_INTERVAL);
11936ba597c5SAnurag S. Maskey 			}
11946ba597c5SAnurag S. Maskey 		}
11956ba597c5SAnurag S. Maskey 		return;
11966ba597c5SAnurag S. Maskey 	}
11976ba597c5SAnurag S. Maskey 
11986ba597c5SAnurag S. Maskey 	uintval = NWAM_ACTIVATION_MODE_PRIORITIZED;
11996ba597c5SAnurag S. Maskey 	if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
12006ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) {
12016ba597c5SAnurag S. Maskey 		goto finish;
12026ba597c5SAnurag S. Maskey 	}
12036ba597c5SAnurag S. Maskey 
12046ba597c5SAnurag S. Maskey 	uintval = is_wireless ? 1 : 0;
12056ba597c5SAnurag S. Maskey 	if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
12066ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_PRIORITY_GROUP)) != NWAM_SUCCESS) {
12076ba597c5SAnurag S. Maskey 		goto finish;
12086ba597c5SAnurag S. Maskey 	}
12096ba597c5SAnurag S. Maskey 
12106ba597c5SAnurag S. Maskey 	uintval = is_wireless ? NWAM_PRIORITY_MODE_EXCLUSIVE :
12116ba597c5SAnurag S. Maskey 	    NWAM_PRIORITY_MODE_SHARED;
12126ba597c5SAnurag S. Maskey 	if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
12136ba597c5SAnurag S. Maskey 	    NWAM_NCU_PROP_PRIORITY_MODE)) != NWAM_SUCCESS) {
12146ba597c5SAnurag S. Maskey 		goto finish;
12156ba597c5SAnurag S. Maskey 	}
12166ba597c5SAnurag S. Maskey 
12176ba597c5SAnurag S. Maskey 	err = nwam_ncu_commit(ncuh, 0);
12186ba597c5SAnurag S. Maskey 
12196ba597c5SAnurag S. Maskey finish:
12206ba597c5SAnurag S. Maskey 	nwam_ncu_free(ncuh);
12216ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
12226ba597c5SAnurag S. Maskey 		nlog(LOG_ERR,
12236ba597c5SAnurag S. Maskey 		    "failed to create automatic link ncu for %s: %s",
12246ba597c5SAnurag S. Maskey 		    name, nwam_strerror(err));
12256ba597c5SAnurag S. Maskey 	}
12266ba597c5SAnurag S. Maskey }
12276ba597c5SAnurag S. Maskey 
12286ba597c5SAnurag S. Maskey static void
12296ba597c5SAnurag S. Maskey add_ip_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name)
12306ba597c5SAnurag S. Maskey {
12316ba597c5SAnurag S. Maskey 	nwam_error_t err;
12326ba597c5SAnurag S. Maskey 	nwam_ncu_handle_t ncuh;
12336ba597c5SAnurag S. Maskey 
12346ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_INTERFACE,
12356ba597c5SAnurag S. Maskey 	    NWAM_NCU_CLASS_IP, &ncuh)) != NWAM_SUCCESS) {
12366ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "failed to create ip ncu for %s: %s", name,
12376ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
12386ba597c5SAnurag S. Maskey 		/*
12396ba597c5SAnurag S. Maskey 		 * Root filesystem may be read-only, but no need to
12406ba597c5SAnurag S. Maskey 		 * retry here since add_phys_ncu_to_ncp() enqueues
12416ba597c5SAnurag S. Maskey 		 * a retry event which will lead to add_ip_ncu_to_ncp()
12426ba597c5SAnurag S. Maskey 		 * being called.
12436ba597c5SAnurag S. Maskey 		 */
12446ba597c5SAnurag S. Maskey 		return;
12456ba597c5SAnurag S. Maskey 	}
12466ba597c5SAnurag S. Maskey 
12476ba597c5SAnurag S. Maskey 	/* IP NCU has the default values, so nothing else to do */
12486ba597c5SAnurag S. Maskey 	err = nwam_ncu_commit(ncuh, 0);
12496ba597c5SAnurag S. Maskey 
12506ba597c5SAnurag S. Maskey finish:
12516ba597c5SAnurag S. Maskey 	nwam_ncu_free(ncuh);
12526ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
12536ba597c5SAnurag S. Maskey 		nlog(LOG_ERR,
12546ba597c5SAnurag S. Maskey 		    "failed to create ip ncu for %s: %s", name,
12556ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
12566ba597c5SAnurag S. Maskey 	}
12576ba597c5SAnurag S. Maskey }
12586ba597c5SAnurag S. Maskey 
12596ba597c5SAnurag S. Maskey static void
12606ba597c5SAnurag S. Maskey remove_ncu_from_ncp(nwam_ncp_handle_t ncph, const char *name,
12616ba597c5SAnurag S. Maskey     nwam_ncu_type_t type)
12626ba597c5SAnurag S. Maskey {
12636ba597c5SAnurag S. Maskey 	nwam_error_t err;
12646ba597c5SAnurag S. Maskey 	nwam_ncu_handle_t ncuh;
12656ba597c5SAnurag S. Maskey 
12666ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_read(ncph, name, type, 0, &ncuh)) != NWAM_SUCCESS) {
12676ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "failed to read automatic ncu %s: %s", name,
12686ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
12696ba597c5SAnurag S. Maskey 		return;
12706ba597c5SAnurag S. Maskey 	}
12716ba597c5SAnurag S. Maskey 
12726ba597c5SAnurag S. Maskey 	err = nwam_ncu_destroy(ncuh, 0);
12736ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
12746ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "failed to delete automatic ncu %s: %s", name,
12756ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
12766ba597c5SAnurag S. Maskey 	}
12776ba597c5SAnurag S. Maskey }
12786ba597c5SAnurag S. Maskey 
12796ba597c5SAnurag S. Maskey /*
12806ba597c5SAnurag S. Maskey  * Device represented by NCU has been added or removed for the active
12816ba597c5SAnurag S. Maskey  * User NCP.  If an associated NCU of the given type is found, transition it
12826ba597c5SAnurag S. Maskey  * to the appropriate state.
12836ba597c5SAnurag S. Maskey  */
12846ba597c5SAnurag S. Maskey void
12856ba597c5SAnurag S. Maskey ncu_action_change_state(nwam_action_t action, nwam_ncu_type_t type,
12866ba597c5SAnurag S. Maskey     const char *name)
12876ba597c5SAnurag S. Maskey {
12886ba597c5SAnurag S. Maskey 	nwamd_object_t ncu_obj = NULL;
12896ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu;
12906ba597c5SAnurag S. Maskey 
12916ba597c5SAnurag S. Maskey 	if ((ncu_obj = nwamd_ncu_object_find(type, name)) == NULL)
12926ba597c5SAnurag S. Maskey 		return;
12936ba597c5SAnurag S. Maskey 
12946ba597c5SAnurag S. Maskey 	ncu = ncu_obj->nwamd_object_data;
12956ba597c5SAnurag S. Maskey 
12966ba597c5SAnurag S. Maskey 	/*
12976ba597c5SAnurag S. Maskey 	 * If device has been added, transition from uninitialized to offline.
12986ba597c5SAnurag S. Maskey 	 * If device has been removed, transition to uninitialized (via online*
12996ba597c5SAnurag S. Maskey 	 * if the NCU is currently enabled in order to tear down config).
13006ba597c5SAnurag S. Maskey 	 */
13016ba597c5SAnurag S. Maskey 	if (action == NWAM_ACTION_ADD) {
13026ba597c5SAnurag S. Maskey 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
13036ba597c5SAnurag S. Maskey 		    ncu_obj->nwamd_object_name,
13046ba597c5SAnurag S. Maskey 		    NWAM_STATE_OFFLINE, NWAM_AUX_STATE_CONDITIONS_NOT_MET);
13056ba597c5SAnurag S. Maskey 	} else {
13066ba597c5SAnurag S. Maskey 		if (ncu->ncu_enabled) {
13076ba597c5SAnurag S. Maskey 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
13086ba597c5SAnurag S. Maskey 			    ncu_obj->nwamd_object_name,
13096ba597c5SAnurag S. Maskey 			    NWAM_STATE_ONLINE_TO_OFFLINE,
13106ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_NOT_FOUND);
13116ba597c5SAnurag S. Maskey 		} else {
13126ba597c5SAnurag S. Maskey 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
13136ba597c5SAnurag S. Maskey 			    ncu_obj->nwamd_object_name,
13146ba597c5SAnurag S. Maskey 			    NWAM_STATE_UNINITIALIZED,
13156ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_NOT_FOUND);
13166ba597c5SAnurag S. Maskey 		}
13176ba597c5SAnurag S. Maskey 	}
13186ba597c5SAnurag S. Maskey 	nwamd_object_release(ncu_obj);
13196ba597c5SAnurag S. Maskey }
13206ba597c5SAnurag S. Maskey 
13216ba597c5SAnurag S. Maskey /*
13226ba597c5SAnurag S. Maskey  * Called with hotplug sysevent or when nwam is started and walking the
13236ba597c5SAnurag S. Maskey  * physical interfaces.  Add/remove both link and interface NCUs from the
13246ba597c5SAnurag S. Maskey  * Automatic NCP.  Assumes that both link and interface NCUs don't exist.
13256ba597c5SAnurag S. Maskey  */
13266ba597c5SAnurag S. Maskey void
13276ba597c5SAnurag S. Maskey nwamd_ncu_handle_link_action_event(nwamd_event_t event)
13286ba597c5SAnurag S. Maskey {
13296ba597c5SAnurag S. Maskey 	nwam_ncp_handle_t ncph;
13306ba597c5SAnurag S. Maskey 	nwam_ncu_type_t type;
13316ba597c5SAnurag S. Maskey 	nwam_action_t action =
13326ba597c5SAnurag S. Maskey 	    event->event_msg->nwe_data.nwe_link_action.nwe_action;
13336ba597c5SAnurag S. Maskey 	nwam_error_t err;
13346ba597c5SAnurag S. Maskey 	char *name;
13356ba597c5SAnurag S. Maskey 	boolean_t automatic_ncp_active = B_FALSE;
13366ba597c5SAnurag S. Maskey 
13376ba597c5SAnurag S. Maskey 	if (action != NWAM_ACTION_ADD && action != NWAM_ACTION_REMOVE) {
13386ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
13396ba597c5SAnurag S. Maskey 		    "invalid link action %s", nwam_action_to_string(action));
13406ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
13416ba597c5SAnurag S. Maskey 		return;
13426ba597c5SAnurag S. Maskey 	}
13436ba597c5SAnurag S. Maskey 
13446ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncu_handle_link_action_event: "
13456ba597c5SAnurag S. Maskey 	    "link action '%s' event on %s", nwam_action_to_string(action),
13466ba597c5SAnurag S. Maskey 	    event->event_object[0] == 0 ? "n/a" : event->event_object);
13476ba597c5SAnurag S. Maskey 
13486ba597c5SAnurag S. Maskey 	if ((err = nwam_ncu_typed_name_to_name(event->event_object, &type,
13496ba597c5SAnurag S. Maskey 	    &name)) != NWAM_SUCCESS) {
13506ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
13516ba597c5SAnurag S. Maskey 		    "translation from typedname error: %s", nwam_strerror(err));
13526ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
13536ba597c5SAnurag S. Maskey 		return;
13546ba597c5SAnurag S. Maskey 	}
13556ba597c5SAnurag S. Maskey 
13566ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
13576ba597c5SAnurag S. Maskey 	if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 &&
13586ba597c5SAnurag S. Maskey 	    active_ncph != NULL) {
13596ba597c5SAnurag S. Maskey 		automatic_ncp_active = B_TRUE;
13606ba597c5SAnurag S. Maskey 	}
13616ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
13626ba597c5SAnurag S. Maskey 
13636ba597c5SAnurag S. Maskey 	/*
13646ba597c5SAnurag S. Maskey 	 * We could use active_ncph for cases where the Automatic NCP is active,
13656ba597c5SAnurag S. Maskey 	 * but that would involve holding the active_ncp_mutex for too long.
13666ba597c5SAnurag S. Maskey 	 */
13676ba597c5SAnurag S. Maskey 	if ((err = nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph))
13686ba597c5SAnurag S. Maskey 	    == NWAM_ENTITY_NOT_FOUND) {
13696ba597c5SAnurag S. Maskey 		/* Automatic NCP doesn't exist, create it */
137071ed50cfSAnurag S. Maskey 		err = nwam_ncp_create(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph);
13716ba597c5SAnurag S. Maskey 	}
137271ed50cfSAnurag S. Maskey 	if (err != NWAM_SUCCESS)
137371ed50cfSAnurag S. Maskey 		goto fail;
13746ba597c5SAnurag S. Maskey 
13756ba597c5SAnurag S. Maskey 	/* add or remove NCUs from Automatic NCP */
13766ba597c5SAnurag S. Maskey 	if (action == NWAM_ACTION_ADD) {
13776ba597c5SAnurag S. Maskey 		add_phys_ncu_to_ncp(ncph, name);
13786ba597c5SAnurag S. Maskey 		add_ip_ncu_to_ncp(ncph, name);
13796ba597c5SAnurag S. Maskey 	} else {
13806ba597c5SAnurag S. Maskey 		/*
13816ba597c5SAnurag S. Maskey 		 * Order is important here, remove IP NCU first to prevent
13826ba597c5SAnurag S. Maskey 		 * propogation of down event from link to IP.  No need to
13836ba597c5SAnurag S. Maskey 		 * create REFRESH or DESTROY events.  They are generated by
13846ba597c5SAnurag S. Maskey 		 * nwam_ncu_commit() and nwam_ncu_destroy().
13856ba597c5SAnurag S. Maskey 		 */
13866ba597c5SAnurag S. Maskey 		remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_INTERFACE);
13876ba597c5SAnurag S. Maskey 		remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_LINK);
13886ba597c5SAnurag S. Maskey 	}
13896ba597c5SAnurag S. Maskey 	nwam_ncp_free(ncph);
13906ba597c5SAnurag S. Maskey 
13916ba597c5SAnurag S. Maskey 	/*
13926ba597c5SAnurag S. Maskey 	 * If the Automatic NCP is not active, and the associated NCUs
13936ba597c5SAnurag S. Maskey 	 * exist, they must be moved into the appropriate states given the
13946ba597c5SAnurag S. Maskey 	 * action that has occurred.
13956ba597c5SAnurag S. Maskey 	 */
13966ba597c5SAnurag S. Maskey 	if (!automatic_ncp_active) {
13976ba597c5SAnurag S. Maskey 		ncu_action_change_state(action, NWAM_NCU_TYPE_INTERFACE, name);
13986ba597c5SAnurag S. Maskey 		ncu_action_change_state(action, NWAM_NCU_TYPE_LINK, name);
13996ba597c5SAnurag S. Maskey 	}
14006ba597c5SAnurag S. Maskey 
14016ba597c5SAnurag S. Maskey 	/* Need NCU check to evaluate state in light of added/removed NCUs */
14026ba597c5SAnurag S. Maskey 	if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK,
14036ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_NCP, NULL)) {
14046ba597c5SAnurag S. Maskey 		nwamd_create_ncu_check_event(NEXT_FEW_SECONDS);
14056ba597c5SAnurag S. Maskey 	}
14066ba597c5SAnurag S. Maskey 
140771ed50cfSAnurag S. Maskey fail:
14086ba597c5SAnurag S. Maskey 	free(name);
140971ed50cfSAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
141071ed50cfSAnurag S. Maskey 		nwamd_event_t retry_event = nwamd_event_init_link_action(name,
141171ed50cfSAnurag S. Maskey 		    action);
141271ed50cfSAnurag S. Maskey 		if (retry_event == NULL) {
141371ed50cfSAnurag S. Maskey 			nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
141471ed50cfSAnurag S. Maskey 			    "could not create retry event to read/create "
141571ed50cfSAnurag S. Maskey 			    "%s NCP", NWAM_NCP_NAME_AUTOMATIC);
141671ed50cfSAnurag S. Maskey 			return;
141771ed50cfSAnurag S. Maskey 		}
141871ed50cfSAnurag S. Maskey 
141971ed50cfSAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
142071ed50cfSAnurag S. Maskey 		    "could not read/create %s NCP, retrying in %d seconds",
142171ed50cfSAnurag S. Maskey 		    NWAM_NCP_NAME_AUTOMATIC, NWAMD_READONLY_RETRY_INTERVAL);
142271ed50cfSAnurag S. Maskey 		nwamd_event_enqueue_timed(retry_event,
142371ed50cfSAnurag S. Maskey 		    NWAMD_READONLY_RETRY_INTERVAL);
142471ed50cfSAnurag S. Maskey 	}
14256ba597c5SAnurag S. Maskey }
14266ba597c5SAnurag S. Maskey 
14276ba597c5SAnurag S. Maskey /*
14286ba597c5SAnurag S. Maskey  * Figure out if this link is part of an aggregation.  This is fairly
14296ba597c5SAnurag S. Maskey  * inefficient since we generate this list for every query and search
14306ba597c5SAnurag S. Maskey  * linearly.  A better way would be to generate the list of links in an
14316ba597c5SAnurag S. Maskey  * aggregation once and then check each link against it.
14326ba597c5SAnurag S. Maskey  */
14336ba597c5SAnurag S. Maskey struct link_aggr_search_data {
14346ba597c5SAnurag S. Maskey 	datalink_id_t linkid;
14356ba597c5SAnurag S. Maskey 	boolean_t under;
14366ba597c5SAnurag S. Maskey };
14376ba597c5SAnurag S. Maskey 
14386ba597c5SAnurag S. Maskey static int
14396ba597c5SAnurag S. Maskey ncu_aggr_search(const char *name, void *data)
14406ba597c5SAnurag S. Maskey {
14416ba597c5SAnurag S. Maskey 	struct link_aggr_search_data *lasd = data;
14426ba597c5SAnurag S. Maskey 	dladm_aggr_grp_attr_t ginfo;
14436ba597c5SAnurag S. Maskey 	datalink_id_t linkid;
14446ba597c5SAnurag S. Maskey 	int i;
14456ba597c5SAnurag S. Maskey 
14466ba597c5SAnurag S. Maskey 	if (dladm_name2info(dld_handle, name, &linkid, NULL, NULL, NULL) !=
14476ba597c5SAnurag S. Maskey 	    DLADM_STATUS_OK)
14486ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
14496ba597c5SAnurag S. Maskey 	if (dladm_aggr_info(dld_handle, linkid, &ginfo, DLADM_OPT_ACTIVE)
14506ba597c5SAnurag S. Maskey 	    != DLADM_STATUS_OK || ginfo.lg_nports == 0)
14516ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
14526ba597c5SAnurag S. Maskey 
14536ba597c5SAnurag S. Maskey 	for (i = 0; i < ginfo.lg_nports; i++) {
14546ba597c5SAnurag S. Maskey 		if (lasd->linkid == ginfo.lg_ports[i].lp_linkid) {
14556ba597c5SAnurag S. Maskey 			lasd->under = B_TRUE;
14566ba597c5SAnurag S. Maskey 			return (DLADM_WALK_TERMINATE);
14576ba597c5SAnurag S. Maskey 		}
14586ba597c5SAnurag S. Maskey 	}
14596ba597c5SAnurag S. Maskey 	free(ginfo.lg_ports);
14606ba597c5SAnurag S. Maskey 	return (DLADM_WALK_CONTINUE);
14616ba597c5SAnurag S. Maskey }
14626ba597c5SAnurag S. Maskey 
14636ba597c5SAnurag S. Maskey static boolean_t
14646ba597c5SAnurag S. Maskey nwamd_link_belongs_to_an_aggr(const char *name)
14656ba597c5SAnurag S. Maskey {
14666ba597c5SAnurag S. Maskey 	struct link_aggr_search_data lasd;
14676ba597c5SAnurag S. Maskey 
14686ba597c5SAnurag S. Maskey 	if (dladm_name2info(dld_handle, name, &lasd.linkid, NULL, NULL, NULL)
14696ba597c5SAnurag S. Maskey 	    != DLADM_STATUS_OK)
14706ba597c5SAnurag S. Maskey 		return (B_FALSE);
14716ba597c5SAnurag S. Maskey 	lasd.under = B_FALSE;
14726ba597c5SAnurag S. Maskey 	(void) dladm_walk(ncu_aggr_search, dld_handle, &lasd,
14736ba597c5SAnurag S. Maskey 	    DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
14746ba597c5SAnurag S. Maskey 	return (lasd.under);
14756ba597c5SAnurag S. Maskey }
14766ba597c5SAnurag S. Maskey 
14776ba597c5SAnurag S. Maskey /*
14786ba597c5SAnurag S. Maskey  * If NCU doesn't exist for interface with given name, enqueue a ADD
14796ba597c5SAnurag S. Maskey  * LINK_ACTION event.
14806ba597c5SAnurag S. Maskey  */
14816ba597c5SAnurag S. Maskey static int
14826ba597c5SAnurag S. Maskey ncu_create_link_action_event(const char *name, void *data)
14836ba597c5SAnurag S. Maskey {
14846ba597c5SAnurag S. Maskey 	nwam_ncp_handle_t ncph = data;
14856ba597c5SAnurag S. Maskey 	nwam_ncu_handle_t ncuh;
14866ba597c5SAnurag S. Maskey 	nwamd_event_t link_event;
14876ba597c5SAnurag S. Maskey 
14886ba597c5SAnurag S. Maskey 	/* Do not generate an event if this is a VirtualBox interface. */
14896ba597c5SAnurag S. Maskey 	if (strncmp(name, VBOX_IFACE_PREFIX, strlen(VBOX_IFACE_PREFIX)) == 0)
14906ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
14916ba597c5SAnurag S. Maskey 
14926ba597c5SAnurag S. Maskey 	/* Do not generate an event if this link belongs to another zone. */
14936ba597c5SAnurag S. Maskey 	if (!nwamd_link_belongs_to_this_zone(name))
14946ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
14956ba597c5SAnurag S. Maskey 
14966ba597c5SAnurag S. Maskey 	/* Do not generate an event if this link belongs to an aggregation. */
14976ba597c5SAnurag S. Maskey 	if (nwamd_link_belongs_to_an_aggr(name)) {
14986ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
14996ba597c5SAnurag S. Maskey 	}
15006ba597c5SAnurag S. Maskey 
15016ba597c5SAnurag S. Maskey 	/* Don't create an event if the NCU already exists. */
15026ba597c5SAnurag S. Maskey 	if (ncph != NULL && nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK, 0,
15036ba597c5SAnurag S. Maskey 	    &ncuh) == NWAM_SUCCESS) {
15046ba597c5SAnurag S. Maskey 		nwam_ncu_free(ncuh);
15056ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
15066ba597c5SAnurag S. Maskey 	}
15076ba597c5SAnurag S. Maskey 
15086ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "ncu_create_link_action_event: adding ncus for %s",
15096ba597c5SAnurag S. Maskey 	    name);
15106ba597c5SAnurag S. Maskey 
15116ba597c5SAnurag S. Maskey 	link_event = nwamd_event_init_link_action(name, NWAM_ACTION_ADD);
15126ba597c5SAnurag S. Maskey 	if (link_event != NULL)
15136ba597c5SAnurag S. Maskey 		nwamd_event_enqueue(link_event);
15146ba597c5SAnurag S. Maskey 
15156ba597c5SAnurag S. Maskey 	return (DLADM_WALK_CONTINUE);
15166ba597c5SAnurag S. Maskey }
15176ba597c5SAnurag S. Maskey 
15186ba597c5SAnurag S. Maskey /*
15196ba597c5SAnurag S. Maskey  * Check if interface exists for this NCU. If not, enqueue a REMOVE
15206ba597c5SAnurag S. Maskey  * LINK_ACTION event.
15216ba597c5SAnurag S. Maskey  */
15226ba597c5SAnurag S. Maskey /* ARGSUSED */
15236ba597c5SAnurag S. Maskey static int
15246ba597c5SAnurag S. Maskey nwamd_destroy_ncu(nwam_ncu_handle_t ncuh, void *data)
15256ba597c5SAnurag S. Maskey {
15266ba597c5SAnurag S. Maskey 	char *name;
15276ba597c5SAnurag S. Maskey 	uint32_t flags;
15286ba597c5SAnurag S. Maskey 	nwamd_event_t link_event;
15296ba597c5SAnurag S. Maskey 
15306ba597c5SAnurag S. Maskey 	if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) {
15316ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_destroy_ncu: could not get NCU name");
15326ba597c5SAnurag S. Maskey 		return (0);
15336ba597c5SAnurag S. Maskey 	}
15346ba597c5SAnurag S. Maskey 
15356ba597c5SAnurag S. Maskey 	/* Interfaces that exist return DLADM_OPT_ACTIVE flag */
15366ba597c5SAnurag S. Maskey 	if ((dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL)
15376ba597c5SAnurag S. Maskey 	    == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) &&
15386ba597c5SAnurag S. Maskey 	    !nwamd_link_belongs_to_an_aggr(name)) {
15396ba597c5SAnurag S. Maskey 		free(name);
15406ba597c5SAnurag S. Maskey 		return (0);
15416ba597c5SAnurag S. Maskey 	}
15426ba597c5SAnurag S. Maskey 
15436ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_destroy_ncu: destroying ncus for %s", name);
15446ba597c5SAnurag S. Maskey 
15456ba597c5SAnurag S. Maskey 	link_event = nwamd_event_init_link_action(name, NWAM_ACTION_REMOVE);
15466ba597c5SAnurag S. Maskey 	if (link_event != NULL)
15476ba597c5SAnurag S. Maskey 		nwamd_event_enqueue(link_event);
15486ba597c5SAnurag S. Maskey 	free(name);
15496ba597c5SAnurag S. Maskey 	return (0);
15506ba597c5SAnurag S. Maskey }
15516ba597c5SAnurag S. Maskey 
15526ba597c5SAnurag S. Maskey /*
15536ba597c5SAnurag S. Maskey  * Called when nwamd is starting up.
15546ba597c5SAnurag S. Maskey  *
15556ba597c5SAnurag S. Maskey  * Walk all NCUs and destroy any NCU from the Automatic NCP without an
15566ba597c5SAnurag S. Maskey  * underlying interface (assumption here is that the interface was removed
15576ba597c5SAnurag S. Maskey  * when nwam was disabled).
15586ba597c5SAnurag S. Maskey  *
15596ba597c5SAnurag S. Maskey  * Walk the physical interfaces and create ADD LINK_ACTION event, which
15606ba597c5SAnurag S. Maskey  * will create appropriate interface and link NCUs in the Automatic NCP.
15616ba597c5SAnurag S. Maskey  */
15626ba597c5SAnurag S. Maskey void
15636ba597c5SAnurag S. Maskey nwamd_walk_physical_configuration(void)
15646ba597c5SAnurag S. Maskey {
15656ba597c5SAnurag S. Maskey 	nwam_ncp_handle_t ncph;
1566*f689bed1SRishi Srivatsavai 	datalink_class_t dlclass = DATALINK_CLASS_PHYS;
1567*f689bed1SRishi Srivatsavai 	zoneid_t zoneid = getzoneid();
15686ba597c5SAnurag S. Maskey 
15696ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
15706ba597c5SAnurag S. Maskey 	if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 &&
15716ba597c5SAnurag S. Maskey 	    active_ncph != NULL) {
15726ba597c5SAnurag S. Maskey 		ncph = active_ncph;
15736ba597c5SAnurag S. Maskey 	} else {
15746ba597c5SAnurag S. Maskey 		if (nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph)
15756ba597c5SAnurag S. Maskey 		    != NWAM_SUCCESS) {
15766ba597c5SAnurag S. Maskey 			ncph = NULL;
15776ba597c5SAnurag S. Maskey 		}
15786ba597c5SAnurag S. Maskey 	}
15796ba597c5SAnurag S. Maskey 
15806ba597c5SAnurag S. Maskey 	/* destroy NCUs for interfaces that don't exist */
15816ba597c5SAnurag S. Maskey 	if (ncph != NULL) {
15826ba597c5SAnurag S. Maskey 		(void) nwam_ncp_walk_ncus(ncph, nwamd_destroy_ncu, NULL,
15836ba597c5SAnurag S. Maskey 		    NWAM_FLAG_NCU_TYPE_LINK, NULL);
15846ba597c5SAnurag S. Maskey 	}
15856ba597c5SAnurag S. Maskey 
1586*f689bed1SRishi Srivatsavai 	/* In non-global zones NWAM can support VNICs */
1587*f689bed1SRishi Srivatsavai 	if (zoneid != GLOBAL_ZONEID)
1588*f689bed1SRishi Srivatsavai 		dlclass |= DATALINK_CLASS_VNIC;
1589*f689bed1SRishi Srivatsavai 
15906ba597c5SAnurag S. Maskey 	/* create NCUs for interfaces without NCUs */
15916ba597c5SAnurag S. Maskey 	(void) dladm_walk(ncu_create_link_action_event, dld_handle, ncph,
1592*f689bed1SRishi Srivatsavai 	    dlclass, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
15936ba597c5SAnurag S. Maskey 
15946ba597c5SAnurag S. Maskey 	if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) != 0 ||
15956ba597c5SAnurag S. Maskey 	    active_ncph == NULL) {
15966ba597c5SAnurag S. Maskey 		nwam_ncp_free(ncph);
15976ba597c5SAnurag S. Maskey 	}
15986ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
15996ba597c5SAnurag S. Maskey }
16006ba597c5SAnurag S. Maskey 
16016ba597c5SAnurag S. Maskey /*
16026ba597c5SAnurag S. Maskey  * Handle NCU initialization/refresh event.
16036ba597c5SAnurag S. Maskey  */
16046ba597c5SAnurag S. Maskey void
16056ba597c5SAnurag S. Maskey nwamd_ncu_handle_init_event(nwamd_event_t event)
16066ba597c5SAnurag S. Maskey {
16076ba597c5SAnurag S. Maskey 	nwamd_object_t object = NULL;
16086ba597c5SAnurag S. Maskey 	nwam_ncu_handle_t ncuh;
16096ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu = NULL;
16106ba597c5SAnurag S. Maskey 	nwam_error_t err;
16116ba597c5SAnurag S. Maskey 	nwam_ncu_type_t type;
16126ba597c5SAnurag S. Maskey 	char *name;
16136ba597c5SAnurag S. Maskey 	uint32_t flags;
16146ba597c5SAnurag S. Maskey 	boolean_t new = B_TRUE;
16156ba597c5SAnurag S. Maskey 
16166ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event(%s)",
16176ba597c5SAnurag S. Maskey 	    event->event_object);
16186ba597c5SAnurag S. Maskey 
16196ba597c5SAnurag S. Maskey 	/* Get base linkname rather than interface:linkname or link:linkname */
16206ba597c5SAnurag S. Maskey 	err = nwam_ncu_typed_name_to_name(event->event_object,
16216ba597c5SAnurag S. Maskey 	    &type, &name);
16226ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
16236ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_handle_init_event: "
16246ba597c5SAnurag S. Maskey 		    "nwam_ncu_typed_name_to_name returned %s",
16256ba597c5SAnurag S. Maskey 		    nwam_strerror(err));
16266ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
16276ba597c5SAnurag S. Maskey 		return;
16286ba597c5SAnurag S. Maskey 	}
16296ba597c5SAnurag S. Maskey 
16306ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
16316ba597c5SAnurag S. Maskey 	if (active_ncph == NULL) {
16326ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG,
16336ba597c5SAnurag S. Maskey 		    "nwamd_ncu_handle_init_event: active NCP handle NULL");
16346ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
163571ed50cfSAnurag S. Maskey 		free(name);
16366ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&active_ncp_mutex);
16376ba597c5SAnurag S. Maskey 		return;
16386ba597c5SAnurag S. Maskey 	}
16396ba597c5SAnurag S. Maskey 	err = nwam_ncu_read(active_ncph, event->event_object,
16406ba597c5SAnurag S. Maskey 	    type, 0, &ncuh);
16416ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
16426ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS) {
16436ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_ncu_handle_init_event: "
16446ba597c5SAnurag S. Maskey 		    "could not read object '%s': %s",
16456ba597c5SAnurag S. Maskey 		    event->event_object, nwam_strerror(err));
16466ba597c5SAnurag S. Maskey 		free(name);
16476ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
16486ba597c5SAnurag S. Maskey 		return;
16496ba597c5SAnurag S. Maskey 	}
16506ba597c5SAnurag S. Maskey 
16516ba597c5SAnurag S. Maskey 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
16526ba597c5SAnurag S. Maskey 	    event->event_object)) != NULL)
16536ba597c5SAnurag S. Maskey 		new = B_FALSE;
16546ba597c5SAnurag S. Maskey 
16556ba597c5SAnurag S. Maskey 	/*
16566ba597c5SAnurag S. Maskey 	 * For new NCUs, or interface NCUs, we (re)initialize data from scratch.
16576ba597c5SAnurag S. Maskey 	 * For link NCUs, we want to retain object data.
16586ba597c5SAnurag S. Maskey 	 */
16596ba597c5SAnurag S. Maskey 	switch (type) {
16606ba597c5SAnurag S. Maskey 	case NWAM_NCU_TYPE_LINK:
16616ba597c5SAnurag S. Maskey 		if (new) {
16626ba597c5SAnurag S. Maskey 			ncu = nwamd_ncu_init(type, name);
16636ba597c5SAnurag S. Maskey 		} else {
16646ba597c5SAnurag S. Maskey 			ncu = object->nwamd_object_data;
16656ba597c5SAnurag S. Maskey 			nwam_ncu_free(object->nwamd_object_handle);
16666ba597c5SAnurag S. Maskey 		}
16676ba597c5SAnurag S. Maskey 		populate_common_ncu_properties(ncuh, ncu);
16686ba597c5SAnurag S. Maskey 		populate_link_ncu_properties(ncuh, ncu);
16696ba597c5SAnurag S. Maskey 		break;
16706ba597c5SAnurag S. Maskey 	case NWAM_NCU_TYPE_INTERFACE:
16716ba597c5SAnurag S. Maskey 		if (!new) {
16726ba597c5SAnurag S. Maskey 			nwam_ncu_free(object->nwamd_object_handle);
16736ba597c5SAnurag S. Maskey 			nwamd_ncu_free(object->nwamd_object_data);
16746ba597c5SAnurag S. Maskey 		}
16756ba597c5SAnurag S. Maskey 		ncu = nwamd_ncu_init(type, name);
16766ba597c5SAnurag S. Maskey 		populate_common_ncu_properties(ncuh, ncu);
16776ba597c5SAnurag S. Maskey 		populate_ip_ncu_properties(ncuh, ncu);
16786ba597c5SAnurag S. Maskey 		break;
16796ba597c5SAnurag S. Maskey 	default:
16806ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "unknown ncu type %d", type);
16816ba597c5SAnurag S. Maskey 		free(name);
16826ba597c5SAnurag S. Maskey 		nwam_ncu_free(ncuh);
16836ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
16846ba597c5SAnurag S. Maskey 		nwamd_object_release(object);
16856ba597c5SAnurag S. Maskey 		return;
16866ba597c5SAnurag S. Maskey 	}
16876ba597c5SAnurag S. Maskey 
16886ba597c5SAnurag S. Maskey 	if (new) {
16896ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: didn't find "
16906ba597c5SAnurag S. Maskey 		    "ncu so create it %s", name);
16916ba597c5SAnurag S. Maskey 		object = nwamd_object_init(NWAM_OBJECT_TYPE_NCU,
16926ba597c5SAnurag S. Maskey 		    event->event_object, ncuh, ncu);
16936ba597c5SAnurag S. Maskey 	} else {
16946ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: refreshing "
16956ba597c5SAnurag S. Maskey 		    "ncu %s", name);
16966ba597c5SAnurag S. Maskey 		object->nwamd_object_data = ncu;
16976ba597c5SAnurag S. Maskey 		object->nwamd_object_handle = ncuh;
16986ba597c5SAnurag S. Maskey 	}
16996ba597c5SAnurag S. Maskey 
17006ba597c5SAnurag S. Maskey 	/*
17016ba597c5SAnurag S. Maskey 	 * If the physical link for this NCU doesn't exist in the system,
17026ba597c5SAnurag S. Maskey 	 * the state should be UNINITIALIZED/NOT_FOUND.  Interfaces that
17036ba597c5SAnurag S. Maskey 	 * exist return DLADM_OPT_ACTIVE flag.
17046ba597c5SAnurag S. Maskey 	 */
17056ba597c5SAnurag S. Maskey 	if (dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL)
17066ba597c5SAnurag S. Maskey 	    != DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) {
17076ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwam_ncu_handle_init_event: "
17086ba597c5SAnurag S. Maskey 		    "interface for NCU %s doesn't exist",
17096ba597c5SAnurag S. Maskey 		    event->event_object);
17106ba597c5SAnurag S. Maskey 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
17116ba597c5SAnurag S. Maskey 		    object->nwamd_object_name, NWAM_STATE_UNINITIALIZED,
17126ba597c5SAnurag S. Maskey 		    NWAM_AUX_STATE_NOT_FOUND);
17136ba597c5SAnurag S. Maskey 		free(name);
17146ba597c5SAnurag S. Maskey 		nwamd_object_release(object);
17156ba597c5SAnurag S. Maskey 		return;
17166ba597c5SAnurag S. Maskey 	}
17176ba597c5SAnurag S. Maskey 
17186ba597c5SAnurag S. Maskey 	/*
17196ba597c5SAnurag S. Maskey 	 * If NCU is being initialized (rather than refreshed), the
17206ba597c5SAnurag S. Maskey 	 * object_state is INITIALIZED (from nwamd_object_init()).
17216ba597c5SAnurag S. Maskey 	 */
17226ba597c5SAnurag S. Maskey 	if (object->nwamd_object_state == NWAM_STATE_INITIALIZED) {
17236ba597c5SAnurag S. Maskey 		/*
17246ba597c5SAnurag S. Maskey 		 * If the NCU is disabled, initial state should be DISABLED.
17256ba597c5SAnurag S. Maskey 		 *
17266ba597c5SAnurag S. Maskey 		 * Otherwise, the initial state will be
17276ba597c5SAnurag S. Maskey 		 * OFFLINE/CONDITIONS_NOT_MET, and the link selection
17286ba597c5SAnurag S. Maskey 		 * algorithm will do the rest.
17296ba597c5SAnurag S. Maskey 		 */
17306ba597c5SAnurag S. Maskey 		if (!ncu->ncu_enabled) {
17316ba597c5SAnurag S. Maskey 			object->nwamd_object_state = NWAM_STATE_DISABLED;
17326ba597c5SAnurag S. Maskey 			object->nwamd_object_aux_state =
17336ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_MANUAL_DISABLE;
17346ba597c5SAnurag S. Maskey 		} else {
17356ba597c5SAnurag S. Maskey 			object->nwamd_object_state = NWAM_STATE_OFFLINE;
17366ba597c5SAnurag S. Maskey 			object->nwamd_object_aux_state =
17376ba597c5SAnurag S. Maskey 			    NWAM_AUX_STATE_CONDITIONS_NOT_MET;
17386ba597c5SAnurag S. Maskey 		}
17396ba597c5SAnurag S. Maskey 	} else {
1740f6da83d4SAnurag S. Maskey 		nwamd_link_t *link = &ncu->ncu_link;
17416ba597c5SAnurag S. Maskey 
17426ba597c5SAnurag S. Maskey 		/*
17436ba597c5SAnurag S. Maskey 		 * Refresh NCU.  Deal with disabled cases first, moving NCUs
17446ba597c5SAnurag S. Maskey 		 * that are not disabled - but have the enabled value set - to
17456ba597c5SAnurag S. Maskey 		 * the disabled state.  Then handle cases where the NCU was
17466ba597c5SAnurag S. Maskey 		 * disabled but is no longer.  Finally,  deal with refresh of
17476ba597c5SAnurag S. Maskey 		 * link and interface NCUs, as these are handled differently.
17486ba597c5SAnurag S. Maskey 		 */
17496ba597c5SAnurag S. Maskey 		if (!ncu->ncu_enabled) {
17506ba597c5SAnurag S. Maskey 			if (object->nwamd_object_state != NWAM_STATE_DISABLED) {
17516ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
17526ba597c5SAnurag S. Maskey 				    object->nwamd_object_name,
17536ba597c5SAnurag S. Maskey 				    NWAM_STATE_ONLINE_TO_OFFLINE,
17546ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_MANUAL_DISABLE);
17556ba597c5SAnurag S. Maskey 			}
17566ba597c5SAnurag S. Maskey 			goto done;
17576ba597c5SAnurag S. Maskey 		} else {
17586ba597c5SAnurag S. Maskey 			if (object->nwamd_object_state == NWAM_STATE_DISABLED) {
17596ba597c5SAnurag S. Maskey 				int64_t c;
17606ba597c5SAnurag S. Maskey 
17616ba597c5SAnurag S. Maskey 				/*
17626ba597c5SAnurag S. Maskey 				 * Try to activate the NCU if manual or
17636ba597c5SAnurag S. Maskey 				 * prioritized (when priority <= current).
17646ba597c5SAnurag S. Maskey 				 */
17656ba597c5SAnurag S. Maskey 				(void) pthread_mutex_lock(&active_ncp_mutex);
17666ba597c5SAnurag S. Maskey 				c = current_ncu_priority_group;
17676ba597c5SAnurag S. Maskey 				(void) pthread_mutex_unlock(&active_ncp_mutex);
17686ba597c5SAnurag S. Maskey 				if (link->nwamd_link_activation_mode ==
17696ba597c5SAnurag S. Maskey 				    NWAM_ACTIVATION_MODE_MANUAL ||
17706ba597c5SAnurag S. Maskey 				    (link->nwamd_link_activation_mode ==
17716ba597c5SAnurag S. Maskey 				    NWAM_ACTIVATION_MODE_PRIORITIZED &&
17726ba597c5SAnurag S. Maskey 				    link->nwamd_link_priority_mode <= c)) {
17736ba597c5SAnurag S. Maskey 					nwamd_object_set_state
17746ba597c5SAnurag S. Maskey 					    (NWAM_OBJECT_TYPE_NCU,
17756ba597c5SAnurag S. Maskey 					    object->nwamd_object_name,
17766ba597c5SAnurag S. Maskey 					    NWAM_STATE_OFFLINE_TO_ONLINE,
17776ba597c5SAnurag S. Maskey 					    NWAM_AUX_STATE_INITIALIZED);
17786ba597c5SAnurag S. Maskey 				} else {
17796ba597c5SAnurag S. Maskey 					nwamd_object_set_state
17806ba597c5SAnurag S. Maskey 					    (NWAM_OBJECT_TYPE_NCU,
17816ba597c5SAnurag S. Maskey 					    object->nwamd_object_name,
17826ba597c5SAnurag S. Maskey 					    NWAM_STATE_OFFLINE_TO_ONLINE,
17836ba597c5SAnurag S. Maskey 					    NWAM_AUX_STATE_INITIALIZED);
17846ba597c5SAnurag S. Maskey 				}
17856ba597c5SAnurag S. Maskey 				goto done;
17866ba597c5SAnurag S. Maskey 			}
17876ba597c5SAnurag S. Maskey 		}
17886ba597c5SAnurag S. Maskey 
17896ba597c5SAnurag S. Maskey 		switch (type) {
17906ba597c5SAnurag S. Maskey 		case NWAM_NCU_TYPE_LINK:
1791f6da83d4SAnurag S. Maskey 			if (ncu->ncu_link.nwamd_link_media == DL_WIFI) {
17926ba597c5SAnurag S. Maskey 				/*
17936ba597c5SAnurag S. Maskey 				 * Do rescan.  If the current state and the
17946ba597c5SAnurag S. Maskey 				 * active priority-group do not allow wireless
17956ba597c5SAnurag S. Maskey 				 * network selection, then it won't happen.
17966ba597c5SAnurag S. Maskey 				 */
17976ba597c5SAnurag S. Maskey 				(void) nwamd_wlan_scan(ncu->ncu_name);
17986ba597c5SAnurag S. Maskey 			}
17996ba597c5SAnurag S. Maskey 			break;
18006ba597c5SAnurag S. Maskey 		case NWAM_NCU_TYPE_INTERFACE:
18016ba597c5SAnurag S. Maskey 			/*
18026ba597c5SAnurag S. Maskey 			 * If interface NCU is offline*, online or in
18036ba597c5SAnurag S. Maskey 			 * maintenance, mark it down (from there, it will be
18046ba597c5SAnurag S. Maskey 			 * reinitialized to reapply addresses).
18056ba597c5SAnurag S. Maskey 			 */
18066ba597c5SAnurag S. Maskey 			if (object->nwamd_object_state != NWAM_STATE_OFFLINE) {
18076ba597c5SAnurag S. Maskey 				nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
18086ba597c5SAnurag S. Maskey 				    object->nwamd_object_name,
18096ba597c5SAnurag S. Maskey 				    NWAM_STATE_ONLINE_TO_OFFLINE,
18106ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_DOWN);
18116ba597c5SAnurag S. Maskey 			} else {
18126ba597c5SAnurag S. Maskey 				object->nwamd_object_state = NWAM_STATE_OFFLINE;
18136ba597c5SAnurag S. Maskey 				object->nwamd_object_aux_state =
18146ba597c5SAnurag S. Maskey 				    NWAM_AUX_STATE_CONDITIONS_NOT_MET;
18156ba597c5SAnurag S. Maskey 			}
18166ba597c5SAnurag S. Maskey 			break;
18176ba597c5SAnurag S. Maskey 		}
18186ba597c5SAnurag S. Maskey 	}
18196ba597c5SAnurag S. Maskey 
18206ba597c5SAnurag S. Maskey done:
18216ba597c5SAnurag S. Maskey 	if (type == NWAM_NCU_TYPE_LINK &&
18226ba597c5SAnurag S. Maskey 	    !nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK,
18236ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_NCP, NULL)) {
18246ba597c5SAnurag S. Maskey 		nwamd_create_ncu_check_event(NEXT_FEW_SECONDS);
18256ba597c5SAnurag S. Maskey 	}
18266ba597c5SAnurag S. Maskey 	free(name);
18276ba597c5SAnurag S. Maskey 	nwamd_object_release(object);
18286ba597c5SAnurag S. Maskey }
18296ba597c5SAnurag S. Maskey 
18306ba597c5SAnurag S. Maskey void
18316ba597c5SAnurag S. Maskey nwamd_ncu_handle_fini_event(nwamd_event_t event)
18326ba597c5SAnurag S. Maskey {
18336ba597c5SAnurag S. Maskey 	nwamd_object_t object;
18346ba597c5SAnurag S. Maskey 	nwamd_event_t state_event;
18356ba597c5SAnurag S. Maskey 
18366ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncu_handle_fini_event(%s)",
18376ba597c5SAnurag S. Maskey 	    event->event_object);
18386ba597c5SAnurag S. Maskey 
18396ba597c5SAnurag S. Maskey 	/*
18406ba597c5SAnurag S. Maskey 	 * Simulate a state event so that the state machine can correctly
18416ba597c5SAnurag S. Maskey 	 * disable the NCU.  Then free up allocated objects.
18426ba597c5SAnurag S. Maskey 	 */
18436ba597c5SAnurag S. Maskey 	state_event = nwamd_event_init_object_state(NWAM_OBJECT_TYPE_NCU,
18446ba597c5SAnurag S. Maskey 	    event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
18456ba597c5SAnurag S. Maskey 	    NWAM_AUX_STATE_UNINITIALIZED);
18466ba597c5SAnurag S. Maskey 	if (state_event == NULL) {
18476ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
18486ba597c5SAnurag S. Maskey 		return;
18496ba597c5SAnurag S. Maskey 	}
18506ba597c5SAnurag S. Maskey 	nwamd_ncu_handle_state_event(state_event);
18516ba597c5SAnurag S. Maskey 	nwamd_event_fini(state_event);
18526ba597c5SAnurag S. Maskey 
18536ba597c5SAnurag S. Maskey 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
18546ba597c5SAnurag S. Maskey 	    event->event_object)) == NULL) {
1855f6904bc3SRenee Danson Sommerfeld 		nlog(LOG_INFO, "nwamd_ncu_handle_fini_event: "
18566ba597c5SAnurag S. Maskey 		    "ncu %s not found", event->event_object);
18576ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
18586ba597c5SAnurag S. Maskey 		return;
18596ba597c5SAnurag S. Maskey 	}
18606ba597c5SAnurag S. Maskey 	nwamd_object_release_and_destroy(object);
18616ba597c5SAnurag S. Maskey }
18626ba597c5SAnurag S. Maskey 
18636ba597c5SAnurag S. Maskey void
18646ba597c5SAnurag S. Maskey nwamd_ncu_handle_action_event(nwamd_event_t event)
18656ba597c5SAnurag S. Maskey {
18666ba597c5SAnurag S. Maskey 	nwamd_object_t object;
18676ba597c5SAnurag S. Maskey 
18686ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
18696ba597c5SAnurag S. Maskey 	if (strcmp(event->event_msg->nwe_data.nwe_object_action.nwe_parent,
18706ba597c5SAnurag S. Maskey 	    active_ncp) != 0) {
18716ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: action for "
18726ba597c5SAnurag S. Maskey 		    "inactive NCP %s, nothing to do",
18736ba597c5SAnurag S. Maskey 		    event->event_msg->nwe_data.nwe_object_action.nwe_parent);
18746ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&active_ncp_mutex);
18756ba597c5SAnurag S. Maskey 		return;
18766ba597c5SAnurag S. Maskey 	}
18776ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
18786ba597c5SAnurag S. Maskey 
18796ba597c5SAnurag S. Maskey 	switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) {
18806ba597c5SAnurag S. Maskey 	case NWAM_ACTION_ENABLE:
18816ba597c5SAnurag S. Maskey 		object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
18826ba597c5SAnurag S. Maskey 		    event->event_object);
18836ba597c5SAnurag S. Maskey 		if (object == NULL) {
18846ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "nwamd_ncu_handle_action_event: "
18856ba597c5SAnurag S. Maskey 			    "could not find ncu %s", event->event_object);
18866ba597c5SAnurag S. Maskey 			nwamd_event_do_not_send(event);
18876ba597c5SAnurag S. Maskey 			return;
18886ba597c5SAnurag S. Maskey 		}
18896ba597c5SAnurag S. Maskey 		if (object->nwamd_object_state == NWAM_STATE_ONLINE) {
18906ba597c5SAnurag S. Maskey 			nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: "
18916ba597c5SAnurag S. Maskey 			    "ncu %s already online, nothing to do",
18926ba597c5SAnurag S. Maskey 			    event->event_object);
18936ba597c5SAnurag S. Maskey 			nwamd_object_release(object);
18946ba597c5SAnurag S. Maskey 			return;
18956ba597c5SAnurag S. Maskey 		}
18966ba597c5SAnurag S. Maskey 		nwamd_object_release(object);
18976ba597c5SAnurag S. Maskey 
18986ba597c5SAnurag S. Maskey 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
18996ba597c5SAnurag S. Maskey 		    event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE,
19006ba597c5SAnurag S. Maskey 		    NWAM_AUX_STATE_INITIALIZED);
19016ba597c5SAnurag S. Maskey 		break;
19026ba597c5SAnurag S. Maskey 	case NWAM_ACTION_DISABLE:
19036ba597c5SAnurag S. Maskey 		object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
19046ba597c5SAnurag S. Maskey 		    event->event_object);
19056ba597c5SAnurag S. Maskey 		if (object == NULL) {
19066ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "nwamd_ncu_handle_action_event: "
19076ba597c5SAnurag S. Maskey 			    "could not find ncu %s", event->event_object);
19086ba597c5SAnurag S. Maskey 			nwamd_event_do_not_send(event);
19096ba597c5SAnurag S. Maskey 			return;
19106ba597c5SAnurag S. Maskey 		}
19116ba597c5SAnurag S. Maskey 		if (object->nwamd_object_state == NWAM_STATE_DISABLED) {
19126ba597c5SAnurag S. Maskey 			nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: "
19136ba597c5SAnurag S. Maskey 			    "ncu %s already disabled, nothing to do",
19146ba597c5SAnurag S. Maskey 			    event->event_object);
19156ba597c5SAnurag S. Maskey 			nwamd_object_release(object);
19166ba597c5SAnurag S. Maskey 			return;
19176ba597c5SAnurag S. Maskey 		}
19186ba597c5SAnurag S. Maskey 		nwamd_object_release(object);
19196ba597c5SAnurag S. Maskey 
19206ba597c5SAnurag S. Maskey 		nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
19216ba597c5SAnurag S. Maskey 		    event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
19226ba597c5SAnurag S. Maskey 		    NWAM_AUX_STATE_MANUAL_DISABLE);
19236ba597c5SAnurag S. Maskey 		break;
19246ba597c5SAnurag S. Maskey 	case NWAM_ACTION_ADD:
19256ba597c5SAnurag S. Maskey 	case NWAM_ACTION_REFRESH:
19266ba597c5SAnurag S. Maskey 		nwamd_ncu_handle_init_event(event);
19276ba597c5SAnurag S. Maskey 		break;
19286ba597c5SAnurag S. Maskey 	case NWAM_ACTION_DESTROY:
19296ba597c5SAnurag S. Maskey 		nwamd_ncu_handle_fini_event(event);
19306ba597c5SAnurag S. Maskey 		break;
19316ba597c5SAnurag S. Maskey 	default:
19326ba597c5SAnurag S. Maskey 		nlog(LOG_INFO, "nwam_ncu_handle_action_event: "
19336ba597c5SAnurag S. Maskey 		    "unexpected action");
19346ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
19356ba597c5SAnurag S. Maskey 		break;
19366ba597c5SAnurag S. Maskey 	}
19376ba597c5SAnurag S. Maskey }
19386ba597c5SAnurag S. Maskey 
19396ba597c5SAnurag S. Maskey void
19406ba597c5SAnurag S. Maskey nwamd_ncu_handle_state_event(nwamd_event_t event)
19416ba597c5SAnurag S. Maskey {
19426ba597c5SAnurag S. Maskey 	nwamd_object_t object;
19436ba597c5SAnurag S. Maskey 	nwam_state_t old_state, new_state;
19446ba597c5SAnurag S. Maskey 	nwam_aux_state_t new_aux_state;
19456ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu;
19466ba597c5SAnurag S. Maskey 	boolean_t is_link, enabled, prioritized = B_FALSE;
19476ba597c5SAnurag S. Maskey 	char linkname[NWAM_MAX_NAME_LEN];
19486ba597c5SAnurag S. Maskey 	nwam_event_t m = event->event_msg;
19496ba597c5SAnurag S. Maskey 
19506ba597c5SAnurag S. Maskey 	if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
19516ba597c5SAnurag S. Maskey 	    event->event_object)) == NULL) {
1952f6904bc3SRenee Danson Sommerfeld 		nlog(LOG_INFO, "nwamd_ncu_handle_state_event %lld: "
19536ba597c5SAnurag S. Maskey 		    "state event for nonexistent NCU %s", event->event_id,
19546ba597c5SAnurag S. Maskey 		    event->event_object);
19556ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
19566ba597c5SAnurag S. Maskey 		return;
19576ba597c5SAnurag S. Maskey 	}
19586ba597c5SAnurag S. Maskey 	ncu = object->nwamd_object_data;
19596ba597c5SAnurag S. Maskey 	old_state = object->nwamd_object_state;
19606ba597c5SAnurag S. Maskey 	new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state;
19616ba597c5SAnurag S. Maskey 	new_aux_state =
19626ba597c5SAnurag S. Maskey 	    event->event_msg->nwe_data.nwe_object_state.nwe_aux_state;
19636ba597c5SAnurag S. Maskey 
19646ba597c5SAnurag S. Maskey 	/*
19656ba597c5SAnurag S. Maskey 	 * For NCU state changes, we need to supply the parent NCP name also,
19666ba597c5SAnurag S. Maskey 	 * regardless of whether the event is handled or not.  It is best to
19676ba597c5SAnurag S. Maskey 	 * fill this in here as we have the object lock - when we create
19686ba597c5SAnurag S. Maskey 	 * object state events we sometimes do not have the object lock, but
19696ba597c5SAnurag S. Maskey 	 * at this point in consuming the events (and prior to the associated
19706ba597c5SAnurag S. Maskey 	 * event message being sent out) we do.
19716ba597c5SAnurag S. Maskey 	 */
19726ba597c5SAnurag S. Maskey 	(void) strlcpy(m->nwe_data.nwe_object_state.nwe_parent, ncu->ncu_parent,
19736ba597c5SAnurag S. Maskey 	    sizeof (m->nwe_data.nwe_object_state.nwe_parent));
19746ba597c5SAnurag S. Maskey 
19756ba597c5SAnurag S. Maskey 	/*
19766ba597c5SAnurag S. Maskey 	 * If we receive a state change event moving this NCU to
19776ba597c5SAnurag S. Maskey 	 * DHCP_TIMED_OUT or UP state but this NCU is already ONLINE, then
19786ba597c5SAnurag S. Maskey 	 * ignore this state change event.
19796ba597c5SAnurag S. Maskey 	 */
19806ba597c5SAnurag S. Maskey 	if ((new_aux_state == NWAM_AUX_STATE_IF_DHCP_TIMED_OUT ||
19816ba597c5SAnurag S. Maskey 	    new_aux_state == NWAM_AUX_STATE_UP) &&
19826ba597c5SAnurag S. Maskey 	    object->nwamd_object_state == NWAM_STATE_ONLINE) {
19836ba597c5SAnurag S. Maskey 		nlog(LOG_INFO, "nwamd_ncu_handle_state_event: "
19846ba597c5SAnurag S. Maskey 		    "NCU %s already online, not going to '%s' state",
19856ba597c5SAnurag S. Maskey 		    object->nwamd_object_name,
19866ba597c5SAnurag S. Maskey 		    nwam_aux_state_to_string(new_aux_state));
19876ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
19886ba597c5SAnurag S. Maskey 		nwamd_object_release(object);
19896ba597c5SAnurag S. Maskey 		return;
19906ba597c5SAnurag S. Maskey 	}
19916ba597c5SAnurag S. Maskey 
19926ba597c5SAnurag S. Maskey 	if (new_state == object->nwamd_object_state &&
19936ba597c5SAnurag S. Maskey 	    new_aux_state == object->nwamd_object_aux_state) {
19946ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
19956ba597c5SAnurag S. Maskey 		    "NCU %s already in state (%s, %s)",
19966ba597c5SAnurag S. Maskey 		    object->nwamd_object_name, nwam_state_to_string(new_state),
19976ba597c5SAnurag S. Maskey 		    nwam_aux_state_to_string(new_aux_state));
19986ba597c5SAnurag S. Maskey 		nwamd_object_release(object);
19996ba597c5SAnurag S. Maskey 		return;
20006ba597c5SAnurag S. Maskey 	}
20016ba597c5SAnurag S. Maskey 
20026ba597c5SAnurag S. Maskey 	if (old_state == NWAM_STATE_MAINTENANCE &&
20036ba597c5SAnurag S. Maskey 	    (new_state == NWAM_STATE_ONLINE ||
20046ba597c5SAnurag S. Maskey 	    (new_state == NWAM_STATE_OFFLINE_TO_ONLINE &&
20056ba597c5SAnurag S. Maskey 	    new_aux_state != NWAM_AUX_STATE_INITIALIZED))) {
20066ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
20076ba597c5SAnurag S. Maskey 		    "NCU %s cannot transition from state %s to state (%s, %s)",
20086ba597c5SAnurag S. Maskey 		    object->nwamd_object_name, nwam_state_to_string(old_state),
20096ba597c5SAnurag S. Maskey 		    nwam_state_to_string(new_state),
20106ba597c5SAnurag S. Maskey 		    nwam_aux_state_to_string(new_aux_state));
20116ba597c5SAnurag S. Maskey 		nwamd_event_do_not_send(event);
20126ba597c5SAnurag S. Maskey 		nwamd_object_release(object);
20136ba597c5SAnurag S. Maskey 		return;
20146ba597c5SAnurag S. Maskey 	}
20156ba597c5SAnurag S. Maskey 
20166ba597c5SAnurag S. Maskey 	object->nwamd_object_state = new_state;
20176ba597c5SAnurag S. Maskey 	object->nwamd_object_aux_state = new_aux_state;
20186ba597c5SAnurag S. Maskey 
20196ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: changing state for NCU "
20206ba597c5SAnurag S. Maskey 	    "%s to (%s, %s)", object->nwamd_object_name,
20216ba597c5SAnurag S. Maskey 	    nwam_state_to_string(object->nwamd_object_state),
20226ba597c5SAnurag S. Maskey 	    nwam_aux_state_to_string(object->nwamd_object_aux_state));
20236ba597c5SAnurag S. Maskey 
20246ba597c5SAnurag S. Maskey 	is_link = (ncu->ncu_type == NWAM_NCU_TYPE_LINK);
20256ba597c5SAnurag S. Maskey 	if (is_link)
20266ba597c5SAnurag S. Maskey 		(void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
20276ba597c5SAnurag S. Maskey 	prioritized = (ncu->ncu_type == NWAM_NCU_TYPE_LINK &&
2028f6da83d4SAnurag S. Maskey 	    ncu->ncu_link.nwamd_link_activation_mode ==
20296ba597c5SAnurag S. Maskey 	    NWAM_ACTIVATION_MODE_PRIORITIZED);
20306ba597c5SAnurag S. Maskey 	enabled = ncu->ncu_enabled;
20316ba597c5SAnurag S. Maskey 
20326ba597c5SAnurag S. Maskey 	nwamd_object_release(object);
20336ba597c5SAnurag S. Maskey 
20346ba597c5SAnurag S. Maskey 	/*
20356ba597c5SAnurag S. Maskey 	 * State machine for NCUs
20366ba597c5SAnurag S. Maskey 	 */
20376ba597c5SAnurag S. Maskey 	switch (new_state) {
20386ba597c5SAnurag S. Maskey 	case NWAM_STATE_OFFLINE_TO_ONLINE:
20396ba597c5SAnurag S. Maskey 		if (enabled) {
20406ba597c5SAnurag S. Maskey 			nwamd_ncu_state_machine(event->event_object);
20416ba597c5SAnurag S. Maskey 		} else {
20426ba597c5SAnurag S. Maskey 			nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
20436ba597c5SAnurag S. Maskey 			    "cannot move disabled NCU %s online",
20446ba597c5SAnurag S. Maskey 			    event->event_object);
20456ba597c5SAnurag S. Maskey 			nwamd_event_do_not_send(event);
20466ba597c5SAnurag S. Maskey 		}
20476ba597c5SAnurag S. Maskey 		break;
20486ba597c5SAnurag S. Maskey 
20496ba597c5SAnurag S. Maskey 	case NWAM_STATE_ONLINE_TO_OFFLINE:
20506ba597c5SAnurag S. Maskey 		nwamd_ncu_state_machine(event->event_object);
20516ba597c5SAnurag S. Maskey 		break;
20526ba597c5SAnurag S. Maskey 
20536ba597c5SAnurag S. Maskey 	case NWAM_STATE_ONLINE:
20546ba597c5SAnurag S. Maskey 		/*
20556ba597c5SAnurag S. Maskey 		 * We usually don't need to do anything when we're in the
20566ba597c5SAnurag S. Maskey 		 * ONLINE state.  However, for  WiFi we can be in INIT or
20576ba597c5SAnurag S. Maskey 		 * SCAN aux states while being ONLINE.
20586ba597c5SAnurag S. Maskey 		 */
20596ba597c5SAnurag S. Maskey 		nwamd_ncu_state_machine(event->event_object);
20606ba597c5SAnurag S. Maskey 		break;
20616ba597c5SAnurag S. Maskey 
20626ba597c5SAnurag S. Maskey 	case NWAM_STATE_OFFLINE:
20636ba597c5SAnurag S. Maskey 		/* Reassess priority group now member is offline */
20646ba597c5SAnurag S. Maskey 		if (prioritized) {
20656ba597c5SAnurag S. Maskey 			nwamd_create_ncu_check_event(0);
20666ba597c5SAnurag S. Maskey 		}
20676ba597c5SAnurag S. Maskey 		break;
20686ba597c5SAnurag S. Maskey 
20696ba597c5SAnurag S. Maskey 	case NWAM_STATE_DISABLED:
20706ba597c5SAnurag S. Maskey 	case NWAM_STATE_UNINITIALIZED:
20716ba597c5SAnurag S. Maskey 	case NWAM_STATE_MAINTENANCE:
20726ba597c5SAnurag S. Maskey 	case NWAM_STATE_DEGRADED:
20736ba597c5SAnurag S. Maskey 	default:
20746ba597c5SAnurag S. Maskey 		/* do nothing */
20756ba597c5SAnurag S. Maskey 		break;
20766ba597c5SAnurag S. Maskey 	}
20776ba597c5SAnurag S. Maskey 
20786ba597c5SAnurag S. Maskey 	if (is_link) {
20796ba597c5SAnurag S. Maskey 		if ((new_state == NWAM_STATE_ONLINE_TO_OFFLINE &&
20806ba597c5SAnurag S. Maskey 		    new_aux_state != NWAM_AUX_STATE_UNINITIALIZED &&
20816ba597c5SAnurag S. Maskey 		    new_aux_state != NWAM_AUX_STATE_NOT_FOUND) ||
20826ba597c5SAnurag S. Maskey 		    new_state == NWAM_STATE_DISABLED) {
20836ba597c5SAnurag S. Maskey 			/*
20846ba597c5SAnurag S. Maskey 			 * Going offline, propogate down event to IP NCU.  Do
20856ba597c5SAnurag S. Maskey 			 * not propogate event if new aux state is uninitialized
20866ba597c5SAnurag S. Maskey 			 * or not found as these auxiliary states signify
20876ba597c5SAnurag S. Maskey 			 * that an NCP switch/device removal is in progress.
20886ba597c5SAnurag S. Maskey 			 */
20896ba597c5SAnurag S. Maskey 			nwamd_propogate_link_up_down_to_ip(linkname, B_FALSE);
20906ba597c5SAnurag S. Maskey 		}
20916ba597c5SAnurag S. Maskey 		if (new_state == NWAM_STATE_ONLINE) {
20926ba597c5SAnurag S. Maskey 			/* gone online, propogate up event to IP NCU */
20936ba597c5SAnurag S. Maskey 			nwamd_propogate_link_up_down_to_ip(linkname, B_TRUE);
20946ba597c5SAnurag S. Maskey 		}
20956ba597c5SAnurag S. Maskey 	} else {
20966ba597c5SAnurag S. Maskey 		/* If IP NCU is online, reasses priority group */
20976ba597c5SAnurag S. Maskey 		if (new_state == NWAM_STATE_ONLINE)
20986ba597c5SAnurag S. Maskey 			nwamd_create_ncu_check_event(0);
20996ba597c5SAnurag S. Maskey 	}
21006ba597c5SAnurag S. Maskey }
2101