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 /* 23*71ed50cfSAnurag 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> 406ba597c5SAnurag S. Maskey 416ba597c5SAnurag S. Maskey #include "conditions.h" 426ba597c5SAnurag S. Maskey #include "events.h" 436ba597c5SAnurag S. Maskey #include "objects.h" 446ba597c5SAnurag S. Maskey #include "ncp.h" 456ba597c5SAnurag S. Maskey #include "util.h" 466ba597c5SAnurag S. Maskey 476ba597c5SAnurag S. Maskey /* 486ba597c5SAnurag S. Maskey * ncu.c - handles various NCU tasks - intialization/refresh, state machine 496ba597c5SAnurag S. Maskey * for NCUs etc. 506ba597c5SAnurag S. Maskey */ 516ba597c5SAnurag S. Maskey 526ba597c5SAnurag S. Maskey #define VBOX_IFACE_PREFIX "vboxnet" 536ba597c5SAnurag S. Maskey 546ba597c5SAnurag S. Maskey /* 556ba597c5SAnurag S. Maskey * Find ncu of specified type for link/interface name. 566ba597c5SAnurag S. Maskey */ 576ba597c5SAnurag S. Maskey nwamd_object_t 586ba597c5SAnurag S. Maskey nwamd_ncu_object_find(nwam_ncu_type_t type, const char *name) 596ba597c5SAnurag S. Maskey { 606ba597c5SAnurag S. Maskey nwam_error_t err; 616ba597c5SAnurag S. Maskey char *object_name; 626ba597c5SAnurag S. Maskey nwamd_object_t ncu_obj = NULL; 636ba597c5SAnurag S. Maskey 646ba597c5SAnurag S. Maskey if ((err = nwam_ncu_name_to_typed_name(name, type, &object_name)) 656ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 666ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_find: nwam_ncu_name_to_typed_name " 676ba597c5SAnurag S. Maskey "returned %s", nwam_strerror(err)); 686ba597c5SAnurag S. Maskey return (NULL); 696ba597c5SAnurag S. Maskey } 706ba597c5SAnurag S. Maskey ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name); 716ba597c5SAnurag S. Maskey 726ba597c5SAnurag S. Maskey free(object_name); 736ba597c5SAnurag S. Maskey return (ncu_obj); 746ba597c5SAnurag S. Maskey } 756ba597c5SAnurag S. Maskey 766ba597c5SAnurag S. Maskey nwam_error_t 776ba597c5SAnurag S. Maskey nwamd_set_ncu_string(nwam_ncu_handle_t ncuh, char **strval, uint_t cnt, 786ba597c5SAnurag S. Maskey const char *prop) 796ba597c5SAnurag S. Maskey { 806ba597c5SAnurag S. Maskey nwam_error_t err; 816ba597c5SAnurag S. Maskey nwam_value_t val; 826ba597c5SAnurag S. Maskey 836ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string_array(strval, cnt, &val)) 846ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 856ba597c5SAnurag S. Maskey return (err); 866ba597c5SAnurag S. Maskey err = nwam_ncu_set_prop_value(ncuh, prop, val); 876ba597c5SAnurag S. Maskey nwam_value_free(val); 886ba597c5SAnurag S. Maskey return (err); 896ba597c5SAnurag S. Maskey } 906ba597c5SAnurag S. Maskey 916ba597c5SAnurag S. Maskey nwam_error_t 926ba597c5SAnurag S. Maskey nwamd_set_ncu_uint(nwam_ncu_handle_t ncuh, uint64_t *uintval, uint_t cnt, 936ba597c5SAnurag S. Maskey const char *prop) 946ba597c5SAnurag S. Maskey { 956ba597c5SAnurag S. Maskey nwam_error_t err; 966ba597c5SAnurag S. Maskey nwam_value_t val; 976ba597c5SAnurag S. Maskey 986ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64_array(uintval, cnt, &val)) 996ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 1006ba597c5SAnurag S. Maskey return (err); 1016ba597c5SAnurag S. Maskey err = nwam_ncu_set_prop_value(ncuh, prop, val); 1026ba597c5SAnurag S. Maskey nwam_value_free(val); 1036ba597c5SAnurag S. Maskey return (err); 1046ba597c5SAnurag S. Maskey } 1056ba597c5SAnurag S. Maskey 1066ba597c5SAnurag S. Maskey nwam_error_t 1076ba597c5SAnurag S. Maskey nwamd_get_ncu_string(nwam_ncu_handle_t ncuh, nwam_value_t *val, char ***strval, 1086ba597c5SAnurag S. Maskey uint_t *cnt, const char *prop) 1096ba597c5SAnurag S. Maskey { 1106ba597c5SAnurag S. Maskey nwam_error_t err; 1116ba597c5SAnurag S. Maskey 1126ba597c5SAnurag S. Maskey if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS) 1136ba597c5SAnurag S. Maskey return (err); 1146ba597c5SAnurag S. Maskey return (nwam_value_get_string_array(*val, strval, cnt)); 1156ba597c5SAnurag S. Maskey } 1166ba597c5SAnurag S. Maskey 1176ba597c5SAnurag S. Maskey nwam_error_t 1186ba597c5SAnurag S. Maskey nwamd_get_ncu_uint(nwam_ncu_handle_t ncuh, nwam_value_t *val, 1196ba597c5SAnurag S. Maskey uint64_t **uintval, uint_t *cnt, const char *prop) 1206ba597c5SAnurag S. Maskey { 1216ba597c5SAnurag S. Maskey nwam_error_t err; 1226ba597c5SAnurag S. Maskey 1236ba597c5SAnurag S. Maskey if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS) 1246ba597c5SAnurag S. Maskey return (err); 1256ba597c5SAnurag S. Maskey return (nwam_value_get_uint64_array(*val, uintval, cnt)); 1266ba597c5SAnurag S. Maskey } 1276ba597c5SAnurag S. Maskey 1286ba597c5SAnurag S. Maskey /* 1296ba597c5SAnurag S. Maskey * Run link/interface state machine in response to a state change 1306ba597c5SAnurag S. Maskey * or enable/disable action event. 1316ba597c5SAnurag S. Maskey */ 1326ba597c5SAnurag S. Maskey static void 1336ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(const char *object_name) 1346ba597c5SAnurag S. Maskey { 1356ba597c5SAnurag S. Maskey nwamd_object_t object; 1366ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu; 1376ba597c5SAnurag S. Maskey link_state_t link_state; 1386ba597c5SAnurag S. Maskey nwamd_event_t event; 1396ba597c5SAnurag S. Maskey nwam_wlan_t key_wlan, connected_wlan; 1406ba597c5SAnurag S. Maskey nwamd_link_t *link; 1416ba597c5SAnurag S. Maskey char linkname[NWAM_MAX_NAME_LEN]; 1426ba597c5SAnurag S. Maskey boolean_t up; 1436ba597c5SAnurag S. Maskey 1446ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name)) 1456ba597c5SAnurag S. Maskey == NULL) { 1466ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_state_machine: " 1476ba597c5SAnurag S. Maskey "request for nonexistent NCU %s", object_name); 1486ba597c5SAnurag S. Maskey return; 1496ba597c5SAnurag S. Maskey } 1506ba597c5SAnurag S. Maskey 1516ba597c5SAnurag S. Maskey ncu = object->nwamd_object_data; 1526ba597c5SAnurag S. Maskey link = &ncu->ncu_node.u_link; 1536ba597c5SAnurag S. Maskey 1546ba597c5SAnurag S. Maskey switch (object->nwamd_object_aux_state) { 1556ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_INITIALIZED: 1566ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 1576ba597c5SAnurag S. Maskey /* 1586ba597c5SAnurag S. Maskey * For wired/wireless links, need to get link 1596ba597c5SAnurag S. Maskey * up/down events and even if these are not supported, 1606ba597c5SAnurag S. Maskey * dlpi_open()ing the link prevents the driver from 1616ba597c5SAnurag S. Maskey * being unloaded. 1626ba597c5SAnurag S. Maskey */ 1636ba597c5SAnurag S. Maskey nwamd_dlpi_add_link(object); 1646ba597c5SAnurag S. Maskey 1656ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 1666ba597c5SAnurag S. Maskey /* 1676ba597c5SAnurag S. Maskey * First, if we're unexpectedly connected, 1686ba597c5SAnurag S. Maskey * disconnect. 1696ba597c5SAnurag S. Maskey */ 1706ba597c5SAnurag S. Maskey if (!link->nwamd_link_wifi_connected && 1716ba597c5SAnurag S. Maskey nwamd_wlan_connected(object)) { 1726ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 1736ba597c5SAnurag S. Maskey "nwamd_ncu_state_machine: " 1746ba597c5SAnurag S. Maskey "WiFi unexpectedly connected, " 1756ba597c5SAnurag S. Maskey "disconnecting..."); 1766ba597c5SAnurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, 1776ba597c5SAnurag S. Maskey link->nwamd_link_id); 1786ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, 1796ba597c5SAnurag S. Maskey B_FALSE, B_FALSE); 1806ba597c5SAnurag S. Maskey } 1816ba597c5SAnurag S. Maskey /* move to scanning aux state */ 1826ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1836ba597c5SAnurag S. Maskey object_name, object->nwamd_object_state, 1846ba597c5SAnurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_SCANNING); 1856ba597c5SAnurag S. Maskey } else { 1866ba597c5SAnurag S. Maskey /* 1876ba597c5SAnurag S. Maskey * If initial wired link state is unknown, we 1886ba597c5SAnurag S. Maskey * will need to assume the link is up, since 1896ba597c5SAnurag S. Maskey * we won´t get DL_NOTE_LINK_UP/DOWN events. 1906ba597c5SAnurag S. Maskey */ 1916ba597c5SAnurag S. Maskey link_state = nwamd_get_link_state 1926ba597c5SAnurag S. Maskey (ncu->ncu_name); 1936ba597c5SAnurag S. Maskey if (link_state == LINK_STATE_UP || 1946ba597c5SAnurag S. Maskey link_state == LINK_STATE_UNKNOWN) { 1956ba597c5SAnurag S. Maskey nwamd_object_set_state 1966ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 1976ba597c5SAnurag S. Maskey object_name, NWAM_STATE_ONLINE, 1986ba597c5SAnurag S. Maskey NWAM_AUX_STATE_UP); 1996ba597c5SAnurag S. Maskey } else { 2006ba597c5SAnurag S. Maskey nwamd_object_set_state 2016ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 2026ba597c5SAnurag S. Maskey object_name, 2036ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 2046ba597c5SAnurag S. Maskey NWAM_AUX_STATE_DOWN); 2056ba597c5SAnurag S. Maskey } 2066ba597c5SAnurag S. Maskey } 2076ba597c5SAnurag S. Maskey } else { 2086ba597c5SAnurag S. Maskey /* 2096ba597c5SAnurag S. Maskey * In the current implementation, initialization has to 2106ba597c5SAnurag S. Maskey * start from scratch since the complexity of minimizing 2116ba597c5SAnurag S. Maskey * configuration change is considerable (e.g. if we 2126ba597c5SAnurag S. Maskey * refresh and had DHCP running on the physical 2136ba597c5SAnurag S. Maskey * interface, and now have changed to static assignment, 2146ba597c5SAnurag S. Maskey * we need to remove DHCP etc). To avoid all this, 2156ba597c5SAnurag S. Maskey * unplumb before re-plumbing the protocols and 2166ba597c5SAnurag S. Maskey * addresses we wish to configure. In the future, it 2176ba597c5SAnurag S. Maskey * would be good to try and minimize configuration 2186ba597c5SAnurag S. Maskey * changes. 2196ba597c5SAnurag S. Maskey */ 2206ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET); 2216ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET6); 2226ba597c5SAnurag S. Maskey 2236ba597c5SAnurag S. Maskey /* 2246ba597c5SAnurag S. Maskey * Enqueue a WAITING_FOR_ADDR aux state change so that 2256ba597c5SAnurag S. Maskey * we are eligible to receive the IF_STATE events 2266ba597c5SAnurag S. Maskey * associated with static, DHCP, DHCPv6 and autoconf 2276ba597c5SAnurag S. Maskey * address assignment. The latter two can happen 2286ba597c5SAnurag S. Maskey * quite quickly after plumbing so we need to be ready. 2296ba597c5SAnurag S. Maskey */ 2306ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 2316ba597c5SAnurag S. Maskey object_name, NWAM_STATE_OFFLINE_TO_ONLINE, 2326ba597c5SAnurag S. Maskey NWAM_AUX_STATE_IF_WAITING_FOR_ADDR); 2336ba597c5SAnurag S. Maskey 2346ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv4) 2356ba597c5SAnurag S. Maskey nwamd_plumb_interface(ncu, 0, AF_INET); 2366ba597c5SAnurag S. Maskey 2376ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv6) 2386ba597c5SAnurag S. Maskey nwamd_plumb_interface(ncu, 0, AF_INET6); 2396ba597c5SAnurag S. Maskey 2406ba597c5SAnurag S. Maskey /* 2416ba597c5SAnurag S. Maskey * Configure addresses. Configure any static addresses 2426ba597c5SAnurag S. Maskey * and start DHCP if required. If DHCP is not required, 2436ba597c5SAnurag S. Maskey * do a DHCPINFORM to get other networking config 2446ba597c5SAnurag S. Maskey * parameters. RTM_NEWADDRs - translated into IF_STATE 2456ba597c5SAnurag S. Maskey * events - will then finish the job of bringing us 2466ba597c5SAnurag S. Maskey * online. 2476ba597c5SAnurag S. Maskey */ 2486ba597c5SAnurag S. Maskey nwamd_configure_interface_addresses(ncu); 2496ba597c5SAnurag S. Maskey 2506ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_dhcp_requested) 2516ba597c5SAnurag S. Maskey nwamd_start_dhcp(ncu); 2526ba597c5SAnurag S. Maskey else 2536ba597c5SAnurag S. Maskey nwamd_dhcp_inform(ncu); 2546ba597c5SAnurag S. Maskey } 2556ba597c5SAnurag S. Maskey break; 2566ba597c5SAnurag S. Maskey 2576ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_IF_DHCP_TIMED_OUT: 2586ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_IF_WAITING_FOR_ADDR: 2596ba597c5SAnurag S. Maskey /* 2606ba597c5SAnurag S. Maskey * nothing to do here - RTM_NEWADDRs will trigger IF_STATE 2616ba597c5SAnurag S. Maskey * events to move us online. 2626ba597c5SAnurag S. Maskey */ 2636ba597c5SAnurag S. Maskey break; 2646ba597c5SAnurag S. Maskey 2656ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_SCANNING: 2666ba597c5SAnurag S. Maskey /* launch scan thread */ 2676ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname)); 2686ba597c5SAnurag S. Maskey (void) nwamd_wlan_scan(linkname); 2696ba597c5SAnurag S. Maskey /* Create periodic scan event */ 2706ba597c5SAnurag S. Maskey nwamd_ncu_create_periodic_scan_event(object); 2716ba597c5SAnurag S. Maskey break; 2726ba597c5SAnurag S. Maskey 2736ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION: 2746ba597c5SAnurag S. Maskey /* send "need choice" event */ 2756ba597c5SAnurag S. Maskey event = nwamd_event_init_wlan 2766ba597c5SAnurag S. Maskey (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_CHOICE, B_FALSE, 2776ba597c5SAnurag S. Maskey link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr, 2786ba597c5SAnurag S. Maskey link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num); 2796ba597c5SAnurag S. Maskey if (event == NULL) 2806ba597c5SAnurag S. Maskey break; 2816ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 2826ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_FALSE, B_FALSE); 2836ba597c5SAnurag S. Maskey break; 2846ba597c5SAnurag S. Maskey 2856ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_NEED_KEY: 2866ba597c5SAnurag S. Maskey /* 2876ba597c5SAnurag S. Maskey * Send "need key" event. Set selected to true, connected 2886ba597c5SAnurag S. Maskey * and have_key to false. Do not fill in WLAN details as 2896ba597c5SAnurag S. Maskey * multiple WLANs may match the ESSID name, and each may 2906ba597c5SAnurag S. Maskey * have a different speed and channel. 2916ba597c5SAnurag S. Maskey */ 2926ba597c5SAnurag S. Maskey bzero(&key_wlan, sizeof (key_wlan)); 2936ba597c5SAnurag S. Maskey (void) strlcpy(key_wlan.nww_essid, link->nwamd_link_wifi_essid, 2946ba597c5SAnurag S. Maskey sizeof (key_wlan.nww_essid)); 2956ba597c5SAnurag S. Maskey (void) strlcpy(key_wlan.nww_bssid, link->nwamd_link_wifi_bssid, 2966ba597c5SAnurag S. Maskey sizeof (key_wlan.nww_bssid)); 2976ba597c5SAnurag S. Maskey key_wlan.nww_security_mode = 2986ba597c5SAnurag S. Maskey link->nwamd_link_wifi_security_mode; 2996ba597c5SAnurag S. Maskey key_wlan.nww_selected = B_TRUE; 3006ba597c5SAnurag S. Maskey key_wlan.nww_connected = B_FALSE; 3016ba597c5SAnurag S. Maskey key_wlan.nww_have_key = B_FALSE; 3026ba597c5SAnurag S. Maskey event = nwamd_event_init_wlan 3036ba597c5SAnurag S. Maskey (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_KEY, B_FALSE, 3046ba597c5SAnurag S. Maskey &key_wlan, 1); 3056ba597c5SAnurag S. Maskey if (event == NULL) 3066ba597c5SAnurag S. Maskey break; 3076ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 3086ba597c5SAnurag S. Maskey break; 3096ba597c5SAnurag S. Maskey 3106ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_CONNECTING: 3116ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname)); 3126ba597c5SAnurag S. Maskey nwamd_wlan_connect(linkname); 3136ba597c5SAnurag S. Maskey break; 3146ba597c5SAnurag S. Maskey 3156ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_UP: 3166ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_DOWN: 3176ba597c5SAnurag S. Maskey up = (object->nwamd_object_aux_state == NWAM_AUX_STATE_UP); 3186ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 3196ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 3206ba597c5SAnurag S. Maskey /* 3216ba597c5SAnurag S. Maskey * Connected/disconnected - send WLAN 3226ba597c5SAnurag S. Maskey * connection report. 3236ba597c5SAnurag S. Maskey */ 3246ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = up; 3256ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_TRUE, up); 3266ba597c5SAnurag S. Maskey 3276ba597c5SAnurag S. Maskey (void) strlcpy(connected_wlan.nww_essid, 3286ba597c5SAnurag S. Maskey link->nwamd_link_wifi_essid, 3296ba597c5SAnurag S. Maskey sizeof (connected_wlan.nww_essid)); 3306ba597c5SAnurag S. Maskey (void) strlcpy(connected_wlan.nww_bssid, 3316ba597c5SAnurag S. Maskey link->nwamd_link_wifi_bssid, 3326ba597c5SAnurag S. Maskey sizeof (connected_wlan.nww_bssid)); 3336ba597c5SAnurag S. Maskey connected_wlan.nww_security_mode = 3346ba597c5SAnurag S. Maskey link->nwamd_link_wifi_security_mode; 3356ba597c5SAnurag S. Maskey event = nwamd_event_init_wlan 3366ba597c5SAnurag S. Maskey (ncu->ncu_name, 3376ba597c5SAnurag S. Maskey NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT, up, 3386ba597c5SAnurag S. Maskey &connected_wlan, 1); 3396ba597c5SAnurag S. Maskey if (event == NULL) 3406ba597c5SAnurag S. Maskey break; 3416ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 3426ba597c5SAnurag S. Maskey 3436ba597c5SAnurag S. Maskey /* 3446ba597c5SAnurag S. Maskey * If disconnected, restart the state machine 3456ba597c5SAnurag S. Maskey * for the WiFi link (WiFi is always trying 3466ba597c5SAnurag S. Maskey * to connect). 3476ba597c5SAnurag S. Maskey * 3486ba597c5SAnurag S. Maskey * If connected, start signal strength 3496ba597c5SAnurag S. Maskey * monitoring thread. 3506ba597c5SAnurag S. Maskey */ 3516ba597c5SAnurag S. Maskey if (!up && ncu->ncu_enabled) { 3526ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 3536ba597c5SAnurag S. Maskey "nwamd_ncu_state_machine: " 3546ba597c5SAnurag S. Maskey "wifi disconnect - start over " 3556ba597c5SAnurag S. Maskey "after %dsec interval", 3566ba597c5SAnurag S. Maskey WIRELESS_RETRY_INTERVAL); 3576ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = 3586ba597c5SAnurag S. Maskey B_FALSE; 3596ba597c5SAnurag S. Maskey /* propogate down event to IP NCU */ 3606ba597c5SAnurag S. Maskey nwamd_propogate_link_up_down_to_ip 3616ba597c5SAnurag S. Maskey (ncu->ncu_name, B_FALSE); 3626ba597c5SAnurag S. Maskey nwamd_object_set_state_timed 3636ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, object_name, 3646ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 3656ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED, 3666ba597c5SAnurag S. Maskey WIRELESS_RETRY_INTERVAL); 3676ba597c5SAnurag S. Maskey } else { 3686ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 3696ba597c5SAnurag S. Maskey "nwamd_ncu_state_machine: " 3706ba597c5SAnurag S. Maskey "wifi connected, start monitoring"); 3716ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, 3726ba597c5SAnurag S. Maskey sizeof (linkname)); 3736ba597c5SAnurag S. Maskey nwamd_wlan_monitor_signal(linkname); 3746ba597c5SAnurag S. Maskey } 3756ba597c5SAnurag S. Maskey } 3766ba597c5SAnurag S. Maskey } 3776ba597c5SAnurag S. Maskey 3786ba597c5SAnurag S. Maskey /* If not in ONLINE/OFFLINE state yet, change state */ 3796ba597c5SAnurag S. Maskey if ((up && object->nwamd_object_state != NWAM_STATE_ONLINE) || 3806ba597c5SAnurag S. Maskey (!up && object->nwamd_object_state != NWAM_STATE_OFFLINE)) { 3816ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_state_machine: " 3826ba597c5SAnurag S. Maskey "%s is moving %s", object_name, 3836ba597c5SAnurag S. Maskey up ? "online" : "offline"); 3846ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 3856ba597c5SAnurag S. Maskey object_name, 3866ba597c5SAnurag S. Maskey up ? NWAM_STATE_ONLINE : NWAM_STATE_OFFLINE, 3876ba597c5SAnurag S. Maskey up ? NWAM_AUX_STATE_UP : NWAM_AUX_STATE_DOWN); 3886ba597c5SAnurag S. Maskey 3896ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) { 3906ba597c5SAnurag S. Maskey if (up) { 3916ba597c5SAnurag S. Maskey /* 3926ba597c5SAnurag S. Maskey * Moving online, add v4/v6 default 3936ba597c5SAnurag S. Maskey * routes (if any). 3946ba597c5SAnurag S. Maskey */ 3956ba597c5SAnurag S. Maskey nwamd_add_default_routes(ncu); 3966ba597c5SAnurag S. Maskey } else { 3976ba597c5SAnurag S. Maskey /* 3986ba597c5SAnurag S. Maskey * If this is an interface NCU and we 3996ba597c5SAnurag S. Maskey * got a down event, it is a consequence 4006ba597c5SAnurag S. Maskey * of NCU refresh, so reapply addresses 4016ba597c5SAnurag S. Maskey * by reinitializing. 4026ba597c5SAnurag S. Maskey */ 4036ba597c5SAnurag S. Maskey nwamd_object_set_state 4046ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, object_name, 4056ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 4066ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 4076ba597c5SAnurag S. Maskey } 4086ba597c5SAnurag S. Maskey } 4096ba597c5SAnurag S. Maskey } else { 4106ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_state_machine: " 4116ba597c5SAnurag S. Maskey "%s is %s", object_name, 4126ba597c5SAnurag S. Maskey up ? "online" : "offline"); 4136ba597c5SAnurag S. Maskey } 4146ba597c5SAnurag S. Maskey /* 4156ba597c5SAnurag S. Maskey * NCU is UP or DOWN, trigger all condition checking, even if 4166ba597c5SAnurag S. Maskey * the NCU is already in the ONLINE state - an ENM may depend 4176ba597c5SAnurag S. Maskey * on NCU activity. 4186ba597c5SAnurag S. Maskey */ 4196ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(NEXT_FEW_SECONDS); 4206ba597c5SAnurag S. Maskey break; 4216ba597c5SAnurag S. Maskey 4226ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_CONDITIONS_NOT_MET: 4236ba597c5SAnurag S. Maskey /* 4246ba597c5SAnurag S. Maskey * Link/interface is moving offline. Nothing to do except 4256ba597c5SAnurag S. Maskey * for WiFi, where we disconnect. Don't unplumb IP on 4266ba597c5SAnurag S. Maskey * a link since it may be a transient change. 4276ba597c5SAnurag S. Maskey */ 4286ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 4296ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 4306ba597c5SAnurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, 4316ba597c5SAnurag S. Maskey link->nwamd_link_id); 4326ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = B_FALSE; 4336ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_FALSE, 4346ba597c5SAnurag S. Maskey B_FALSE); 4356ba597c5SAnurag S. Maskey } 4366ba597c5SAnurag S. Maskey } else { 4376ba597c5SAnurag S. Maskey /* 4386ba597c5SAnurag S. Maskey * Unplumb here. In the future we may elaborate on 4396ba597c5SAnurag S. Maskey * the approach used and not unplumb for WiFi 4406ba597c5SAnurag S. Maskey * until we reconnect to a different WLAN (i.e. with 4416ba597c5SAnurag S. Maskey * a different ESSID). 4426ba597c5SAnurag S. Maskey */ 4436ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET); 4446ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET6); 4456ba597c5SAnurag S. Maskey } 4466ba597c5SAnurag S. Maskey if (object->nwamd_object_state != NWAM_STATE_OFFLINE) { 4476ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 4486ba597c5SAnurag S. Maskey object_name, NWAM_STATE_OFFLINE, 4496ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 4506ba597c5SAnurag S. Maskey } 4516ba597c5SAnurag S. Maskey break; 4526ba597c5SAnurag S. Maskey 4536ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_MANUAL_DISABLE: 4546ba597c5SAnurag S. Maskey /* Manual disable, set enabled state appropriately. */ 4556ba597c5SAnurag S. Maskey ncu->ncu_enabled = B_FALSE; 4566ba597c5SAnurag S. Maskey /* FALLTHROUGH */ 4576ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_UNINITIALIZED: 4586ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_NOT_FOUND: 4596ba597c5SAnurag S. Maskey /* 4606ba597c5SAnurag S. Maskey * Link/interface NCU has been disabled/deactivated/removed. 4616ba597c5SAnurag S. Maskey * For WiFi links disconnect, and for IP interfaces we unplumb. 4626ba597c5SAnurag S. Maskey */ 4636ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 4646ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 4656ba597c5SAnurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, 4666ba597c5SAnurag S. Maskey link->nwamd_link_id); 4676ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = B_FALSE; 4686ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_FALSE, 4696ba597c5SAnurag S. Maskey B_FALSE); 4706ba597c5SAnurag S. Maskey } 4716ba597c5SAnurag S. Maskey nwamd_dlpi_delete_link(object); 4726ba597c5SAnurag S. Maskey } else { 4736ba597c5SAnurag S. Maskey /* Unplumb here. */ 4746ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv4) { 4756ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET); 4766ba597c5SAnurag S. Maskey } 4776ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv6) { 4786ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET6); 4796ba597c5SAnurag S. Maskey } 4806ba597c5SAnurag S. Maskey /* trigger location condition checking */ 4816ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(0); 4826ba597c5SAnurag S. Maskey } 4836ba597c5SAnurag S. Maskey 4846ba597c5SAnurag S. Maskey switch (object->nwamd_object_aux_state) { 4856ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_MANUAL_DISABLE: 4866ba597c5SAnurag S. Maskey /* Change state to DISABLED if manually disabled */ 4876ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 4886ba597c5SAnurag S. Maskey object_name, NWAM_STATE_DISABLED, 4896ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 4906ba597c5SAnurag S. Maskey /* Note that NCU has been disabled */ 4916ba597c5SAnurag S. Maskey ncu->ncu_enabled = B_FALSE; 4926ba597c5SAnurag S. Maskey break; 4936ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_NOT_FOUND: 4946ba597c5SAnurag S. Maskey /* Change state to UNINITIALIZED for device removal */ 4956ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 4966ba597c5SAnurag S. Maskey object_name, NWAM_STATE_UNINITIALIZED, 4976ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 4986ba597c5SAnurag S. Maskey break; 4996ba597c5SAnurag S. Maskey default: 5006ba597c5SAnurag S. Maskey break; 5016ba597c5SAnurag S. Maskey } 5026ba597c5SAnurag S. Maskey break; 5036ba597c5SAnurag S. Maskey default: 5046ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_state_machine: unexpected state"); 5056ba597c5SAnurag S. Maskey break; 5066ba597c5SAnurag S. Maskey } 5076ba597c5SAnurag S. Maskey 5086ba597c5SAnurag S. Maskey nwamd_object_release(object); 5096ba597c5SAnurag S. Maskey } 5106ba597c5SAnurag S. Maskey 5116ba597c5SAnurag S. Maskey static int 5126ba597c5SAnurag S. Maskey ncu_create_init_fini_event(nwam_ncu_handle_t ncuh, void *data) 5136ba597c5SAnurag S. Maskey { 5146ba597c5SAnurag S. Maskey boolean_t *init = data; 5156ba597c5SAnurag S. Maskey char *name, *typedname; 5166ba597c5SAnurag S. Maskey nwam_error_t err; 5176ba597c5SAnurag S. Maskey nwam_value_t typeval = NULL; 5186ba597c5SAnurag S. Maskey uint64_t *type; 5196ba597c5SAnurag S. Maskey uint_t numvalues; 5206ba597c5SAnurag S. Maskey nwamd_event_t ncu_event; 5216ba597c5SAnurag S. Maskey 5226ba597c5SAnurag S. Maskey if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) { 5236ba597c5SAnurag S. Maskey nlog(LOG_ERR, 5246ba597c5SAnurag S. Maskey "ncu_create_init_fini_event: could not get NCU name"); 5256ba597c5SAnurag S. Maskey return (0); 5266ba597c5SAnurag S. Maskey } 5276ba597c5SAnurag S. Maskey 5286ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "ncu_create_init_fini_event(%s, %p)", name, data); 5296ba597c5SAnurag S. Maskey 5306ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &typeval, &type, &numvalues, 5316ba597c5SAnurag S. Maskey NWAM_NCU_PROP_TYPE)) != NWAM_SUCCESS) { 5326ba597c5SAnurag S. Maskey nlog(LOG_ERR, "ncu_create_init_fini_event: " 5336ba597c5SAnurag S. Maskey "could not get NCU type: %s", nwam_strerror(err)); 5346ba597c5SAnurag S. Maskey free(name); 5356ba597c5SAnurag S. Maskey nwam_value_free(typeval); 5366ba597c5SAnurag S. Maskey return (0); 5376ba597c5SAnurag S. Maskey } 5386ba597c5SAnurag S. Maskey 5396ba597c5SAnurag S. Maskey /* convert name to typedname for event */ 5406ba597c5SAnurag S. Maskey if ((err = nwam_ncu_name_to_typed_name(name, *type, &typedname)) 5416ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 5426ba597c5SAnurag S. Maskey nlog(LOG_ERR, "ncu_create_init_fini_event: " 5436ba597c5SAnurag S. Maskey "NCU name translation failed: %s", nwam_strerror(err)); 5446ba597c5SAnurag S. Maskey free(name); 5456ba597c5SAnurag S. Maskey return (0); 5466ba597c5SAnurag S. Maskey } 5476ba597c5SAnurag S. Maskey free(name); 5486ba597c5SAnurag S. Maskey nwam_value_free(typeval); 5496ba597c5SAnurag S. Maskey 5506ba597c5SAnurag S. Maskey ncu_event = nwamd_event_init(*init ? 5516ba597c5SAnurag S. Maskey NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI, 5526ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_NCU, 0, typedname); 5536ba597c5SAnurag S. Maskey if (ncu_event != NULL) 5546ba597c5SAnurag S. Maskey nwamd_event_enqueue(ncu_event); 5556ba597c5SAnurag S. Maskey free(typedname); 5566ba597c5SAnurag S. Maskey 5576ba597c5SAnurag S. Maskey return (0); 5586ba597c5SAnurag S. Maskey } 5596ba597c5SAnurag S. Maskey 5606ba597c5SAnurag S. Maskey /* 5616ba597c5SAnurag S. Maskey * Initialization - walk the NCUs, creating initialization events for each 5626ba597c5SAnurag S. Maskey * NCU. nwamd_ncu_handle_init_event() will check if the associated 5636ba597c5SAnurag S. Maskey * physical link exists or not. 5646ba597c5SAnurag S. Maskey */ 5656ba597c5SAnurag S. Maskey void 5666ba597c5SAnurag S. Maskey nwamd_init_ncus(void) 5676ba597c5SAnurag S. Maskey { 5686ba597c5SAnurag S. Maskey boolean_t init = B_TRUE; 5696ba597c5SAnurag S. Maskey 5706ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 5716ba597c5SAnurag S. Maskey if (active_ncph != NULL) { 5726ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_init_ncus: " 5736ba597c5SAnurag S. Maskey "(re)intializing NCUs for NCP %s", active_ncp); 5746ba597c5SAnurag S. Maskey (void) nwam_ncp_walk_ncus(active_ncph, 5756ba597c5SAnurag S. Maskey ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL, 5766ba597c5SAnurag S. Maskey NULL); 5776ba597c5SAnurag S. Maskey } 5786ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 5796ba597c5SAnurag S. Maskey } 5806ba597c5SAnurag S. Maskey 5816ba597c5SAnurag S. Maskey void 5826ba597c5SAnurag S. Maskey nwamd_fini_ncus(void) 5836ba597c5SAnurag S. Maskey { 5846ba597c5SAnurag S. Maskey boolean_t init = B_FALSE; 5856ba597c5SAnurag S. Maskey 5866ba597c5SAnurag S. Maskey /* We may not have an active NCP on initialization, so skip fini */ 5876ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 5886ba597c5SAnurag S. Maskey if (active_ncph != NULL) { 5896ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_fini_ncus: deinitializing NCUs for %s", 5906ba597c5SAnurag S. Maskey active_ncp); 5916ba597c5SAnurag S. Maskey (void) nwam_ncp_walk_ncus(active_ncph, 5926ba597c5SAnurag S. Maskey ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL, 5936ba597c5SAnurag S. Maskey NULL); 5946ba597c5SAnurag S. Maskey } 5956ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 5966ba597c5SAnurag S. Maskey } 5976ba597c5SAnurag S. Maskey 5986ba597c5SAnurag S. Maskey /* 5996ba597c5SAnurag S. Maskey * Most properties of this type don't need to be cached locally. Only those 6006ba597c5SAnurag S. Maskey * interesting to the daemon are stored in an nwamd_ncu_t. 6016ba597c5SAnurag S. Maskey */ 6026ba597c5SAnurag S. Maskey static void 6036ba597c5SAnurag S. Maskey populate_common_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) 6046ba597c5SAnurag S. Maskey { 6056ba597c5SAnurag S. Maskey nwam_value_t ncu_prop; 6066ba597c5SAnurag S. Maskey nwam_error_t err; 6076ba597c5SAnurag S. Maskey boolean_t enablevalue; 6086ba597c5SAnurag S. Maskey uint_t numvalues; 6096ba597c5SAnurag S. Maskey char **parent; 6106ba597c5SAnurag S. Maskey 6116ba597c5SAnurag S. Maskey if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED, 6126ba597c5SAnurag S. Maskey &ncu_prop)) != NWAM_SUCCESS) { 6136ba597c5SAnurag S. Maskey char *name; 6146ba597c5SAnurag S. Maskey (void) nwam_ncu_name_to_typed_name(ncu_data->ncu_name, 6156ba597c5SAnurag S. Maskey ncu_data->ncu_type, &name); 6166ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwam_ncu_get_prop_value %s ENABLED failed: %s", 6176ba597c5SAnurag S. Maskey name, nwam_strerror(err)); 6186ba597c5SAnurag S. Maskey free(name); 6196ba597c5SAnurag S. Maskey ncu_data->ncu_enabled = B_TRUE; 6206ba597c5SAnurag S. Maskey } else { 6216ba597c5SAnurag S. Maskey if ((err = nwam_value_get_boolean(ncu_prop, &enablevalue)) != 6226ba597c5SAnurag S. Maskey NWAM_SUCCESS) { 6236ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwam_value_get_boolean ENABLED failed: " 6246ba597c5SAnurag S. Maskey "%s", nwam_strerror(err)); 6256ba597c5SAnurag S. Maskey } else { 6266ba597c5SAnurag S. Maskey ncu_data->ncu_enabled = enablevalue; 6276ba597c5SAnurag S. Maskey } 6286ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 6296ba597c5SAnurag S. Maskey } 6306ba597c5SAnurag S. Maskey 6316ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &parent, 6326ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_PARENT_NCP)) != NWAM_SUCCESS) { 6336ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwam_ncu_get_prop_value %s PARENT failed: %s", 6346ba597c5SAnurag S. Maskey ncu_data->ncu_name, nwam_strerror(err)); 6356ba597c5SAnurag S. Maskey } else { 6366ba597c5SAnurag S. Maskey (void) strlcpy(ncu_data->ncu_parent, parent[0], 6376ba597c5SAnurag S. Maskey sizeof (ncu_data->ncu_parent)); 6386ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 6396ba597c5SAnurag S. Maskey } 6406ba597c5SAnurag S. Maskey } 6416ba597c5SAnurag S. Maskey 6426ba597c5SAnurag S. Maskey /* 6436ba597c5SAnurag S. Maskey * Read in link properties. 6446ba597c5SAnurag S. Maskey */ 6456ba597c5SAnurag S. Maskey static void 6466ba597c5SAnurag S. Maskey populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) 6476ba597c5SAnurag S. Maskey { 6486ba597c5SAnurag S. Maskey nwam_value_t ncu_prop; 6496ba597c5SAnurag S. Maskey nwam_error_t err; 6506ba597c5SAnurag S. Maskey char **mac_addr; 6516ba597c5SAnurag S. Maskey uint64_t *uintval; 6526ba597c5SAnurag S. Maskey uint_t numvalues; 6536ba597c5SAnurag S. Maskey 6546ba597c5SAnurag S. Maskey /* activation-mode */ 6556ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues, 6566ba597c5SAnurag S. Maskey NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) { 6576ba597c5SAnurag S. Maskey nlog(LOG_ERR, 6586ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 6596ba597c5SAnurag S. Maskey NWAM_NCU_PROP_ACTIVATION_MODE, nwam_strerror(err)); 6606ba597c5SAnurag S. Maskey } else { 6616ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_activation_mode = 6626ba597c5SAnurag S. Maskey uintval[0]; 6636ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 6646ba597c5SAnurag S. Maskey } 6656ba597c5SAnurag S. Maskey 6666ba597c5SAnurag S. Maskey /* priority-group and priority-mode for prioritized activation */ 6676ba597c5SAnurag S. Maskey if (ncu_data->ncu_node.u_link.nwamd_link_activation_mode == 6686ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED) { 6696ba597c5SAnurag S. Maskey /* ncus with prioritized activation are always enabled */ 6706ba597c5SAnurag S. Maskey ncu_data->ncu_enabled = B_TRUE; 6716ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, 6726ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_PRIORITY_MODE)) 6736ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 6746ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_link_ncu_properties: " 6756ba597c5SAnurag S. Maskey "could not get %s value: %s", 6766ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_MODE, nwam_strerror(err)); 6776ba597c5SAnurag S. Maskey } else { 6786ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_priority_mode = 6796ba597c5SAnurag S. Maskey uintval[0]; 6806ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 6816ba597c5SAnurag S. Maskey } 6826ba597c5SAnurag S. Maskey 6836ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, 6846ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_PRIORITY_GROUP)) 6856ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 6866ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_link_ncu_properties: " 6876ba597c5SAnurag S. Maskey "could not get %s value: %s", 6886ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_GROUP, nwam_strerror(err)); 6896ba597c5SAnurag S. Maskey } else { 6906ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_priority_group = 6916ba597c5SAnurag S. Maskey uintval[0]; 6926ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 6936ba597c5SAnurag S. Maskey } 6946ba597c5SAnurag S. Maskey } 6956ba597c5SAnurag S. Maskey 6966ba597c5SAnurag S. Maskey /* link-mac-addr */ 6976ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &mac_addr, &numvalues, 6986ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MAC_ADDR)) != NWAM_SUCCESS) { 6996ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 7006ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 7016ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MAC_ADDR, nwam_strerror(err)); 7026ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mac_addr = NULL; 7036ba597c5SAnurag S. Maskey } else { 7046ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mac_addr = 7056ba597c5SAnurag S. Maskey strdup(*mac_addr); 7066ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mac_addr_len = 7076ba597c5SAnurag S. Maskey strlen(*mac_addr); 7086ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 7096ba597c5SAnurag S. Maskey } 7106ba597c5SAnurag S. Maskey 7116ba597c5SAnurag S. Maskey /* link-mtu */ 7126ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues, 7136ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MTU)) != NWAM_SUCCESS) { 7146ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 7156ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 7166ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MTU, nwam_strerror(err)); 7176ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mtu = 0; 7186ba597c5SAnurag S. Maskey } else { 7196ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mtu = uintval[0]; 7206ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 7216ba597c5SAnurag S. Maskey } 7226ba597c5SAnurag S. Maskey 7236ba597c5SAnurag S. Maskey /* link-autopush */ 7246ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, 7256ba597c5SAnurag S. Maskey &ncu_data->ncu_node.u_link.nwamd_link_autopush, 7266ba597c5SAnurag S. Maskey &ncu_data->ncu_node.u_link.nwamd_link_num_autopush, 7276ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_AUTOPUSH)) != NWAM_SUCCESS) { 7286ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 7296ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 7306ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_AUTOPUSH, nwam_strerror(err)); 7316ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_num_autopush = 0; 7326ba597c5SAnurag S. Maskey } 7336ba597c5SAnurag S. Maskey } 7346ba597c5SAnurag S. Maskey 7356ba597c5SAnurag S. Maskey static void 7366ba597c5SAnurag S. Maskey populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) 7376ba597c5SAnurag S. Maskey { 7386ba597c5SAnurag S. Maskey nwamd_if_t *nif = &ncu_data->ncu_node.u_if; 7396ba597c5SAnurag S. Maskey struct nwamd_if_address **nifa, *nifai, *nifait; 7406ba597c5SAnurag S. Maskey char *prefix; 7416ba597c5SAnurag S. Maskey boolean_t static_addr = B_FALSE; 7426ba597c5SAnurag S. Maskey uint64_t *addrsrcvalue; 7436ba597c5SAnurag S. Maskey nwam_value_t ncu_prop; 7446ba597c5SAnurag S. Maskey nwam_error_t err; 7456ba597c5SAnurag S. Maskey char **addrvalue; 7466ba597c5SAnurag S. Maskey uint_t numvalues; 7476ba597c5SAnurag S. Maskey uint64_t *ipversion; 7486ba597c5SAnurag S. Maskey int i; 7496ba597c5SAnurag S. Maskey 7506ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4 = B_FALSE; 7516ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6 = B_FALSE; 7526ba597c5SAnurag S. Maskey nif->nwamd_if_dhcp_requested = B_FALSE; 7536ba597c5SAnurag S. Maskey nif->nwamd_if_stateful_requested = B_FALSE; 7546ba597c5SAnurag S. Maskey nif->nwamd_if_stateless_requested = B_FALSE; 7556ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4_default_route_set = B_FALSE; 7566ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6_default_route_set = B_FALSE; 7576ba597c5SAnurag S. Maskey 7586ba597c5SAnurag S. Maskey /* ip-version */ 7596ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &ipversion, &numvalues, 7606ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IP_VERSION)) != NWAM_SUCCESS) { 7616ba597c5SAnurag S. Maskey nlog(LOG_ERR, 7626ba597c5SAnurag S. Maskey "populate_ip_ncu_properties: could not get %s value: %s", 7636ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IP_VERSION, nwam_strerror(err)); 7646ba597c5SAnurag S. Maskey } else { 7656ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 7666ba597c5SAnurag S. Maskey switch (ipversion[i]) { 7676ba597c5SAnurag S. Maskey case IPV4_VERSION: 7686ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4 = B_TRUE; 7696ba597c5SAnurag S. Maskey break; 7706ba597c5SAnurag S. Maskey case IPV6_VERSION: 7716ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6 = B_TRUE; 7726ba597c5SAnurag S. Maskey break; 7736ba597c5SAnurag S. Maskey default: 7746ba597c5SAnurag S. Maskey nlog(LOG_ERR, "bogus ip version %lld", 7756ba597c5SAnurag S. Maskey ipversion[i]); 7766ba597c5SAnurag S. Maskey break; 7776ba597c5SAnurag S. Maskey } 7786ba597c5SAnurag S. Maskey } 7796ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 7806ba597c5SAnurag S. Maskey } 7816ba597c5SAnurag S. Maskey 7826ba597c5SAnurag S. Maskey /* Free the old list. */ 7836ba597c5SAnurag S. Maskey for (nifai = nif->nwamd_if_list; nifai != NULL; nifai = nifait) { 7846ba597c5SAnurag S. Maskey nifait = nifai->next; 7856ba597c5SAnurag S. Maskey nifai->next = NULL; 7866ba597c5SAnurag S. Maskey free(nifai); 7876ba597c5SAnurag S. Maskey } 7886ba597c5SAnurag S. Maskey nif->nwamd_if_list = NULL; 7896ba597c5SAnurag S. Maskey nifa = &(nif->nwamd_if_list); 7906ba597c5SAnurag S. Maskey 7916ba597c5SAnurag S. Maskey if (!nif->nwamd_if_ipv4) 7926ba597c5SAnurag S. Maskey goto skip_ipv4; 7936ba597c5SAnurag S. Maskey 7946ba597c5SAnurag S. Maskey /* ipv4-addrsrc */ 7956ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue, 7966ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV4_ADDRSRC)) != NWAM_SUCCESS) { 7976ba597c5SAnurag S. Maskey nlog(nif->nwamd_if_ipv4 ? LOG_ERR : LOG_DEBUG, 7986ba597c5SAnurag S. Maskey "populate_ip_ncu_properties: could not get %s value: %s", 7996ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV4_ADDRSRC, nwam_strerror(err)); 8006ba597c5SAnurag S. Maskey } else { 8016ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 8026ba597c5SAnurag S. Maskey switch (addrsrcvalue[i]) { 8036ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_DHCP: 8046ba597c5SAnurag S. Maskey nif->nwamd_if_dhcp_requested = B_TRUE; 8056ba597c5SAnurag S. Maskey break; 8066ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_STATIC: 8076ba597c5SAnurag S. Maskey static_addr = B_TRUE; 8086ba597c5SAnurag S. Maskey break; 8096ba597c5SAnurag S. Maskey default: 8106ba597c5SAnurag S. Maskey break; 8116ba597c5SAnurag S. Maskey } 8126ba597c5SAnurag S. Maskey } 8136ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 8146ba597c5SAnurag S. Maskey } 8156ba597c5SAnurag S. Maskey if (nif->nwamd_if_dhcp_requested) { 8166ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { 8176ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET; 8186ba597c5SAnurag S. Maskey (*nifa)->dhcp_if = B_TRUE; 8196ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 8206ba597c5SAnurag S. Maskey *nifa = NULL; 8216ba597c5SAnurag S. Maskey } 8226ba597c5SAnurag S. Maskey } 8236ba597c5SAnurag S. Maskey 8246ba597c5SAnurag S. Maskey /* ipv4-addr */ 8256ba597c5SAnurag S. Maskey if (static_addr) { 8266ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 8276ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV4_ADDR)) != NWAM_SUCCESS) { 8286ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_ip_ncu_properties: " 8296ba597c5SAnurag S. Maskey "could not get %s value; %s", 8306ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV4_ADDR, nwam_strerror(err)); 8316ba597c5SAnurag S. Maskey } else { 8326ba597c5SAnurag S. Maskey struct sockaddr_in *s; 8336ba597c5SAnurag S. Maskey 8346ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 8356ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) 8366ba597c5SAnurag S. Maskey == NULL) { 8376ba597c5SAnurag S. Maskey nlog(LOG_ERR, "couldn't allocate nwamd" 8386ba597c5SAnurag S. Maskey "address"); 8396ba597c5SAnurag S. Maskey continue; 8406ba597c5SAnurag S. Maskey } 8416ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET; 8426ba597c5SAnurag S. Maskey /*LINTED*/ 8436ba597c5SAnurag S. Maskey s = (struct sockaddr_in *)&(*nifa)->address; 8446ba597c5SAnurag S. Maskey s->sin_family = AF_INET; 8456ba597c5SAnurag S. Maskey s->sin_port = 0; 8466ba597c5SAnurag S. Maskey prefix = strchr(addrvalue[i], '/'); 8476ba597c5SAnurag S. Maskey if (prefix != NULL) { 8486ba597c5SAnurag S. Maskey *prefix++ = 0; 8496ba597c5SAnurag S. Maskey (*nifa)->prefix = atoi(prefix); 8506ba597c5SAnurag S. Maskey } 8516ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET, addrvalue[i], 8526ba597c5SAnurag S. Maskey &(s->sin_addr)); 8536ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 8546ba597c5SAnurag S. Maskey } 8556ba597c5SAnurag S. Maskey *nifa = NULL; 8566ba597c5SAnurag S. Maskey 8576ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 8586ba597c5SAnurag S. Maskey } 8596ba597c5SAnurag S. Maskey } 8606ba597c5SAnurag S. Maskey 8616ba597c5SAnurag S. Maskey /* get default route, if any */ 8626ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 8636ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE)) == NWAM_SUCCESS) { 8646ba597c5SAnurag S. Maskey /* Only one default route is allowed. */ 8656ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4_default_route.sin_family = AF_INET; 8666ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET, addrvalue[0], 8676ba597c5SAnurag S. Maskey &(nif->nwamd_if_ipv4_default_route.sin_addr)); 8686ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4_default_route_set = B_TRUE; 8696ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 8706ba597c5SAnurag S. Maskey } 8716ba597c5SAnurag S. Maskey 8726ba597c5SAnurag S. Maskey skip_ipv4: 8736ba597c5SAnurag S. Maskey 8746ba597c5SAnurag S. Maskey if (!nif->nwamd_if_ipv6) 8756ba597c5SAnurag S. Maskey goto skip_ipv6; 8766ba597c5SAnurag S. Maskey 8776ba597c5SAnurag S. Maskey /* ipv6-addrsrc */ 8786ba597c5SAnurag S. Maskey static_addr = B_FALSE; 8796ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue, 8806ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV6_ADDRSRC)) != NWAM_SUCCESS) { 8816ba597c5SAnurag S. Maskey nlog(nif->nwamd_if_ipv6 ? LOG_ERR : LOG_DEBUG, 8826ba597c5SAnurag S. Maskey "populate_ip_ncu_properties: could not get %s value: %s", 8836ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV6_ADDRSRC, nwam_strerror(err)); 8846ba597c5SAnurag S. Maskey } else { 8856ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 8866ba597c5SAnurag S. Maskey switch (addrsrcvalue[i]) { 8876ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_DHCP: 8886ba597c5SAnurag S. Maskey nif->nwamd_if_stateful_requested = B_TRUE; 8896ba597c5SAnurag S. Maskey break; 8906ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_AUTOCONF: 8916ba597c5SAnurag S. Maskey nif->nwamd_if_stateless_requested = B_TRUE; 8926ba597c5SAnurag S. Maskey break; 8936ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_STATIC: 8946ba597c5SAnurag S. Maskey static_addr = B_TRUE; 8956ba597c5SAnurag S. Maskey break; 8966ba597c5SAnurag S. Maskey default: 8976ba597c5SAnurag S. Maskey break; 8986ba597c5SAnurag S. Maskey } 8996ba597c5SAnurag S. Maskey } 9006ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 9016ba597c5SAnurag S. Maskey } 9026ba597c5SAnurag S. Maskey if (nif->nwamd_if_stateful_requested) { 9036ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { 9046ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET6; 9056ba597c5SAnurag S. Maskey (*nifa)->dhcp_if = B_TRUE; 9066ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 9076ba597c5SAnurag S. Maskey *nifa = NULL; 9086ba597c5SAnurag S. Maskey } 9096ba597c5SAnurag S. Maskey } 9106ba597c5SAnurag S. Maskey if (nif->nwamd_if_stateless_requested) { 9116ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { 9126ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET6; 9136ba597c5SAnurag S. Maskey (*nifa)->stateless_if = B_TRUE; 9146ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 9156ba597c5SAnurag S. Maskey *nifa = NULL; 9166ba597c5SAnurag S. Maskey } 9176ba597c5SAnurag S. Maskey } 9186ba597c5SAnurag S. Maskey 9196ba597c5SAnurag S. Maskey /* ipv6-addr */ 9206ba597c5SAnurag S. Maskey if (static_addr) { 9216ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 9226ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV6_ADDR)) != NWAM_SUCCESS) { 9236ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_ip_ncu_properties: " 9246ba597c5SAnurag S. Maskey "could not get %s value; %s", 9256ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV6_ADDR, nwam_strerror(err)); 9266ba597c5SAnurag S. Maskey } else { 9276ba597c5SAnurag S. Maskey struct sockaddr_in6 *s; 9286ba597c5SAnurag S. Maskey 9296ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 9306ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) 9316ba597c5SAnurag S. Maskey == NULL) { 9326ba597c5SAnurag S. Maskey nlog(LOG_ERR, "couldn't allocate nwamd" 9336ba597c5SAnurag S. Maskey "address"); 9346ba597c5SAnurag S. Maskey continue; 9356ba597c5SAnurag S. Maskey } 9366ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET6; 9376ba597c5SAnurag S. Maskey /*LINTED*/ 9386ba597c5SAnurag S. Maskey s = (struct sockaddr_in6 *)&(*nifa)->address; 9396ba597c5SAnurag S. Maskey s->sin6_family = AF_INET6; 9406ba597c5SAnurag S. Maskey s->sin6_port = 0; 9416ba597c5SAnurag S. Maskey prefix = strchr(addrvalue[i], '/'); 9426ba597c5SAnurag S. Maskey if (prefix != NULL) { 9436ba597c5SAnurag S. Maskey *prefix++ = 0; 9446ba597c5SAnurag S. Maskey (*nifa)->prefix = atoi(prefix); 9456ba597c5SAnurag S. Maskey } 9466ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET6, addrvalue[i], 9476ba597c5SAnurag S. Maskey &(s->sin6_addr)); 9486ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 9496ba597c5SAnurag S. Maskey } 9506ba597c5SAnurag S. Maskey *nifa = NULL; 9516ba597c5SAnurag S. Maskey 9526ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 9536ba597c5SAnurag S. Maskey } 9546ba597c5SAnurag S. Maskey } 9556ba597c5SAnurag S. Maskey 9566ba597c5SAnurag S. Maskey /* get default route, if any */ 9576ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 9586ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE)) == NWAM_SUCCESS) { 9596ba597c5SAnurag S. Maskey /* Only one default route is allowed. */ 9606ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6_default_route.sin6_family = AF_INET6; 9616ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET6, addrvalue[0], 9626ba597c5SAnurag S. Maskey &(nif->nwamd_if_ipv6_default_route.sin6_addr)); 9636ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6_default_route_set = B_TRUE; 9646ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 9656ba597c5SAnurag S. Maskey } 9666ba597c5SAnurag S. Maskey 9676ba597c5SAnurag S. Maskey skip_ipv6: 9686ba597c5SAnurag S. Maskey ; 9696ba597c5SAnurag S. Maskey } 9706ba597c5SAnurag S. Maskey 9716ba597c5SAnurag S. Maskey static nwamd_ncu_t * 9726ba597c5SAnurag S. Maskey nwamd_ncu_init(nwam_ncu_type_t ncu_type, const char *name) 9736ba597c5SAnurag S. Maskey { 9746ba597c5SAnurag S. Maskey nwamd_ncu_t *rv; 9756ba597c5SAnurag S. Maskey 9766ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_init(%d, %s)", ncu_type, name); 9776ba597c5SAnurag S. Maskey 9786ba597c5SAnurag S. Maskey if ((rv = calloc(1, sizeof (*rv))) == NULL) 9796ba597c5SAnurag S. Maskey return (NULL); 9806ba597c5SAnurag S. Maskey 9816ba597c5SAnurag S. Maskey rv->ncu_type = ncu_type; 9826ba597c5SAnurag S. Maskey rv->ncu_name = strdup(name); 9836ba597c5SAnurag S. Maskey rv->ncu_enabled = B_FALSE; 9846ba597c5SAnurag S. Maskey 9856ba597c5SAnurag S. Maskey /* Initialize link/interface-specific data */ 9866ba597c5SAnurag S. Maskey if (rv->ncu_type == NWAM_NCU_TYPE_LINK) { 9876ba597c5SAnurag S. Maskey (void) bzero(&rv->ncu_node.u_link, sizeof (nwamd_link_t)); 9886ba597c5SAnurag S. Maskey (void) dladm_name2info(dld_handle, name, 9896ba597c5SAnurag S. Maskey &rv->ncu_node.u_link.nwamd_link_id, NULL, NULL, 9906ba597c5SAnurag S. Maskey &rv->ncu_node.u_link.nwamd_link_media); 9916ba597c5SAnurag S. Maskey (void) pthread_mutex_init( 9926ba597c5SAnurag S. Maskey &rv->ncu_node.u_link.nwamd_link_wifi_mutex, NULL); 9936ba597c5SAnurag S. Maskey rv->ncu_node.u_link.nwamd_link_wifi_priority = MAXINT; 9946ba597c5SAnurag S. Maskey } else { 9956ba597c5SAnurag S. Maskey (void) bzero(&rv->ncu_node.u_if, sizeof (nwamd_if_t)); 9966ba597c5SAnurag S. Maskey } 9976ba597c5SAnurag S. Maskey 9986ba597c5SAnurag S. Maskey return (rv); 9996ba597c5SAnurag S. Maskey } 10006ba597c5SAnurag S. Maskey 10016ba597c5SAnurag S. Maskey void 10026ba597c5SAnurag S. Maskey nwamd_ncu_free(nwamd_ncu_t *ncu) 10036ba597c5SAnurag S. Maskey { 10046ba597c5SAnurag S. Maskey if (ncu != NULL) { 10056ba597c5SAnurag S. Maskey assert(ncu->ncu_type == NWAM_NCU_TYPE_LINK || 10066ba597c5SAnurag S. Maskey ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE); 10076ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 10086ba597c5SAnurag S. Maskey struct nwamd_link *l = &ncu->ncu_node.u_link; 10096ba597c5SAnurag S. Maskey int i; 10106ba597c5SAnurag S. Maskey 10116ba597c5SAnurag S. Maskey free(l->nwamd_link_wifi_key); 10126ba597c5SAnurag S. Maskey free(l->nwamd_link_mac_addr); 10136ba597c5SAnurag S. Maskey for (i = 0; i < l->nwamd_link_num_autopush; i++) 10146ba597c5SAnurag S. Maskey free(l->nwamd_link_autopush[i]); 10156ba597c5SAnurag S. Maskey } else if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) { 10166ba597c5SAnurag S. Maskey struct nwamd_if_address *nifa; 10176ba597c5SAnurag S. Maskey 10186ba597c5SAnurag S. Maskey nifa = ncu->ncu_node.u_if.nwamd_if_list; 10196ba597c5SAnurag S. Maskey while (nifa != NULL) { 10206ba597c5SAnurag S. Maskey struct nwamd_if_address *n; 10216ba597c5SAnurag S. Maskey 10226ba597c5SAnurag S. Maskey n = nifa; 10236ba597c5SAnurag S. Maskey nifa = nifa->next; 10246ba597c5SAnurag S. Maskey free(n); 10256ba597c5SAnurag S. Maskey } 10266ba597c5SAnurag S. Maskey } 10276ba597c5SAnurag S. Maskey free(ncu->ncu_name); 10286ba597c5SAnurag S. Maskey free(ncu); 10296ba597c5SAnurag S. Maskey } 10306ba597c5SAnurag S. Maskey } 10316ba597c5SAnurag S. Maskey 10326ba597c5SAnurag S. Maskey static int 10336ba597c5SAnurag S. Maskey nwamd_ncu_display(nwamd_object_t ncu_obj, void *data) 10346ba597c5SAnurag S. Maskey { 10356ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu = (nwamd_ncu_t *)ncu_obj->nwamd_object_data; 10366ba597c5SAnurag S. Maskey data = data; 10376ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "NCU (%p) %s state %s, %s", 10386ba597c5SAnurag S. Maskey (void *)ncu, ncu_obj->nwamd_object_name, 10396ba597c5SAnurag S. Maskey nwam_state_to_string(ncu_obj->nwamd_object_state), 10406ba597c5SAnurag S. Maskey nwam_aux_state_to_string(ncu_obj->nwamd_object_aux_state)); 10416ba597c5SAnurag S. Maskey return (0); 10426ba597c5SAnurag S. Maskey } 10436ba597c5SAnurag S. Maskey 10446ba597c5SAnurag S. Maskey void 10456ba597c5SAnurag S. Maskey nwamd_log_ncus(void) 10466ba597c5SAnurag S. Maskey { 10476ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "NCP %s", active_ncp); 10486ba597c5SAnurag S. Maskey (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, nwamd_ncu_display, 10496ba597c5SAnurag S. Maskey NULL); 10506ba597c5SAnurag S. Maskey } 10516ba597c5SAnurag S. Maskey 10526ba597c5SAnurag S. Maskey int 10536ba597c5SAnurag S. Maskey nwamd_ncu_action(const char *ncu, const char *parent, nwam_action_t action) 10546ba597c5SAnurag S. Maskey { 10556ba597c5SAnurag S. Maskey nwamd_event_t ncu_event = nwamd_event_init_object_action 10566ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, ncu, parent, action); 10576ba597c5SAnurag S. Maskey if (ncu_event == NULL) 10586ba597c5SAnurag S. Maskey return (1); 10596ba597c5SAnurag S. Maskey nwamd_event_enqueue(ncu_event); 10606ba597c5SAnurag S. Maskey return (0); 10616ba597c5SAnurag S. Maskey } 10626ba597c5SAnurag S. Maskey 10636ba597c5SAnurag S. Maskey static void 10646ba597c5SAnurag S. Maskey add_phys_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name) 10656ba597c5SAnurag S. Maskey { 10666ba597c5SAnurag S. Maskey dladm_status_t dlrtn; 10676ba597c5SAnurag S. Maskey uint32_t media; 10686ba597c5SAnurag S. Maskey boolean_t is_wireless; 10696ba597c5SAnurag S. Maskey nwam_error_t err; 10706ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 10716ba597c5SAnurag S. Maskey uint64_t uintval; 10726ba597c5SAnurag S. Maskey 10736ba597c5SAnurag S. Maskey if ((dlrtn = dladm_name2info(dld_handle, name, NULL, NULL, NULL, 10746ba597c5SAnurag S. Maskey &media)) != DLADM_STATUS_OK) { 10756ba597c5SAnurag S. Maskey char errmsg[DLADM_STRSIZE]; 10766ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to get media type for %s: %s", name, 10776ba597c5SAnurag S. Maskey dladm_status2str(dlrtn, errmsg)); 10786ba597c5SAnurag S. Maskey return; 10796ba597c5SAnurag S. Maskey } 10806ba597c5SAnurag S. Maskey is_wireless = (media == DL_WIFI); 10816ba597c5SAnurag S. Maskey 10826ba597c5SAnurag S. Maskey if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_LINK, 10836ba597c5SAnurag S. Maskey NWAM_NCU_CLASS_PHYS, &ncuh)) != NWAM_SUCCESS) { 10846ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to create link ncu for %s: %s", name, 10856ba597c5SAnurag S. Maskey nwam_strerror(err)); 10866ba597c5SAnurag S. Maskey if (err == NWAM_ENTITY_READ_ONLY) { 10876ba597c5SAnurag S. Maskey nwamd_event_t retry_event; 10886ba597c5SAnurag S. Maskey 10896ba597c5SAnurag S. Maskey /* 10906ba597c5SAnurag S. Maskey * Root filesystem may be read-only, retry in 10916ba597c5SAnurag S. Maskey * a few seconds. 10926ba597c5SAnurag S. Maskey */ 10936ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "Retrying addition of phys ncu for %s", 10946ba597c5SAnurag S. Maskey name); 10956ba597c5SAnurag S. Maskey retry_event = nwamd_event_init_link_action(name, 10966ba597c5SAnurag S. Maskey NWAM_ACTION_ADD); 10976ba597c5SAnurag S. Maskey if (retry_event != NULL) { 10986ba597c5SAnurag S. Maskey nwamd_event_enqueue_timed(retry_event, 10996ba597c5SAnurag S. Maskey NWAMD_READONLY_RETRY_INTERVAL); 11006ba597c5SAnurag S. Maskey } 11016ba597c5SAnurag S. Maskey } 11026ba597c5SAnurag S. Maskey return; 11036ba597c5SAnurag S. Maskey } 11046ba597c5SAnurag S. Maskey 11056ba597c5SAnurag S. Maskey uintval = NWAM_ACTIVATION_MODE_PRIORITIZED; 11066ba597c5SAnurag S. Maskey if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1, 11076ba597c5SAnurag S. Maskey NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) { 11086ba597c5SAnurag S. Maskey goto finish; 11096ba597c5SAnurag S. Maskey } 11106ba597c5SAnurag S. Maskey 11116ba597c5SAnurag S. Maskey uintval = is_wireless ? 1 : 0; 11126ba597c5SAnurag S. Maskey if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1, 11136ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_GROUP)) != NWAM_SUCCESS) { 11146ba597c5SAnurag S. Maskey goto finish; 11156ba597c5SAnurag S. Maskey } 11166ba597c5SAnurag S. Maskey 11176ba597c5SAnurag S. Maskey uintval = is_wireless ? NWAM_PRIORITY_MODE_EXCLUSIVE : 11186ba597c5SAnurag S. Maskey NWAM_PRIORITY_MODE_SHARED; 11196ba597c5SAnurag S. Maskey if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1, 11206ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_MODE)) != NWAM_SUCCESS) { 11216ba597c5SAnurag S. Maskey goto finish; 11226ba597c5SAnurag S. Maskey } 11236ba597c5SAnurag S. Maskey 11246ba597c5SAnurag S. Maskey err = nwam_ncu_commit(ncuh, 0); 11256ba597c5SAnurag S. Maskey 11266ba597c5SAnurag S. Maskey finish: 11276ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 11286ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 11296ba597c5SAnurag S. Maskey nlog(LOG_ERR, 11306ba597c5SAnurag S. Maskey "failed to create automatic link ncu for %s: %s", 11316ba597c5SAnurag S. Maskey name, nwam_strerror(err)); 11326ba597c5SAnurag S. Maskey } 11336ba597c5SAnurag S. Maskey } 11346ba597c5SAnurag S. Maskey 11356ba597c5SAnurag S. Maskey static void 11366ba597c5SAnurag S. Maskey add_ip_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name) 11376ba597c5SAnurag S. Maskey { 11386ba597c5SAnurag S. Maskey nwam_error_t err; 11396ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 11406ba597c5SAnurag S. Maskey 11416ba597c5SAnurag S. Maskey if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_INTERFACE, 11426ba597c5SAnurag S. Maskey NWAM_NCU_CLASS_IP, &ncuh)) != NWAM_SUCCESS) { 11436ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to create ip ncu for %s: %s", name, 11446ba597c5SAnurag S. Maskey nwam_strerror(err)); 11456ba597c5SAnurag S. Maskey /* 11466ba597c5SAnurag S. Maskey * Root filesystem may be read-only, but no need to 11476ba597c5SAnurag S. Maskey * retry here since add_phys_ncu_to_ncp() enqueues 11486ba597c5SAnurag S. Maskey * a retry event which will lead to add_ip_ncu_to_ncp() 11496ba597c5SAnurag S. Maskey * being called. 11506ba597c5SAnurag S. Maskey */ 11516ba597c5SAnurag S. Maskey return; 11526ba597c5SAnurag S. Maskey } 11536ba597c5SAnurag S. Maskey 11546ba597c5SAnurag S. Maskey /* IP NCU has the default values, so nothing else to do */ 11556ba597c5SAnurag S. Maskey err = nwam_ncu_commit(ncuh, 0); 11566ba597c5SAnurag S. Maskey 11576ba597c5SAnurag S. Maskey finish: 11586ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 11596ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 11606ba597c5SAnurag S. Maskey nlog(LOG_ERR, 11616ba597c5SAnurag S. Maskey "failed to create ip ncu for %s: %s", name, 11626ba597c5SAnurag S. Maskey nwam_strerror(err)); 11636ba597c5SAnurag S. Maskey } 11646ba597c5SAnurag S. Maskey } 11656ba597c5SAnurag S. Maskey 11666ba597c5SAnurag S. Maskey static void 11676ba597c5SAnurag S. Maskey remove_ncu_from_ncp(nwam_ncp_handle_t ncph, const char *name, 11686ba597c5SAnurag S. Maskey nwam_ncu_type_t type) 11696ba597c5SAnurag S. Maskey { 11706ba597c5SAnurag S. Maskey nwam_error_t err; 11716ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 11726ba597c5SAnurag S. Maskey 11736ba597c5SAnurag S. Maskey if ((err = nwam_ncu_read(ncph, name, type, 0, &ncuh)) != NWAM_SUCCESS) { 11746ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to read automatic ncu %s: %s", name, 11756ba597c5SAnurag S. Maskey nwam_strerror(err)); 11766ba597c5SAnurag S. Maskey return; 11776ba597c5SAnurag S. Maskey } 11786ba597c5SAnurag S. Maskey 11796ba597c5SAnurag S. Maskey err = nwam_ncu_destroy(ncuh, 0); 11806ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 11816ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to delete automatic ncu %s: %s", name, 11826ba597c5SAnurag S. Maskey nwam_strerror(err)); 11836ba597c5SAnurag S. Maskey } 11846ba597c5SAnurag S. Maskey } 11856ba597c5SAnurag S. Maskey 11866ba597c5SAnurag S. Maskey /* 11876ba597c5SAnurag S. Maskey * Device represented by NCU has been added or removed for the active 11886ba597c5SAnurag S. Maskey * User NCP. If an associated NCU of the given type is found, transition it 11896ba597c5SAnurag S. Maskey * to the appropriate state. 11906ba597c5SAnurag S. Maskey */ 11916ba597c5SAnurag S. Maskey void 11926ba597c5SAnurag S. Maskey ncu_action_change_state(nwam_action_t action, nwam_ncu_type_t type, 11936ba597c5SAnurag S. Maskey const char *name) 11946ba597c5SAnurag S. Maskey { 11956ba597c5SAnurag S. Maskey nwamd_object_t ncu_obj = NULL; 11966ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu; 11976ba597c5SAnurag S. Maskey 11986ba597c5SAnurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(type, name)) == NULL) 11996ba597c5SAnurag S. Maskey return; 12006ba597c5SAnurag S. Maskey 12016ba597c5SAnurag S. Maskey ncu = ncu_obj->nwamd_object_data; 12026ba597c5SAnurag S. Maskey 12036ba597c5SAnurag S. Maskey /* 12046ba597c5SAnurag S. Maskey * If device has been added, transition from uninitialized to offline. 12056ba597c5SAnurag S. Maskey * If device has been removed, transition to uninitialized (via online* 12066ba597c5SAnurag S. Maskey * if the NCU is currently enabled in order to tear down config). 12076ba597c5SAnurag S. Maskey */ 12086ba597c5SAnurag S. Maskey if (action == NWAM_ACTION_ADD) { 12096ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 12106ba597c5SAnurag S. Maskey ncu_obj->nwamd_object_name, 12116ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE, NWAM_AUX_STATE_CONDITIONS_NOT_MET); 12126ba597c5SAnurag S. Maskey } else { 12136ba597c5SAnurag S. Maskey if (ncu->ncu_enabled) { 12146ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 12156ba597c5SAnurag S. Maskey ncu_obj->nwamd_object_name, 12166ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 12176ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 12186ba597c5SAnurag S. Maskey } else { 12196ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 12206ba597c5SAnurag S. Maskey ncu_obj->nwamd_object_name, 12216ba597c5SAnurag S. Maskey NWAM_STATE_UNINITIALIZED, 12226ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 12236ba597c5SAnurag S. Maskey } 12246ba597c5SAnurag S. Maskey } 12256ba597c5SAnurag S. Maskey nwamd_object_release(ncu_obj); 12266ba597c5SAnurag S. Maskey } 12276ba597c5SAnurag S. Maskey 12286ba597c5SAnurag S. Maskey /* 12296ba597c5SAnurag S. Maskey * Called with hotplug sysevent or when nwam is started and walking the 12306ba597c5SAnurag S. Maskey * physical interfaces. Add/remove both link and interface NCUs from the 12316ba597c5SAnurag S. Maskey * Automatic NCP. Assumes that both link and interface NCUs don't exist. 12326ba597c5SAnurag S. Maskey */ 12336ba597c5SAnurag S. Maskey void 12346ba597c5SAnurag S. Maskey nwamd_ncu_handle_link_action_event(nwamd_event_t event) 12356ba597c5SAnurag S. Maskey { 12366ba597c5SAnurag S. Maskey nwam_ncp_handle_t ncph; 12376ba597c5SAnurag S. Maskey nwam_ncu_type_t type; 12386ba597c5SAnurag S. Maskey nwam_action_t action = 12396ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_link_action.nwe_action; 12406ba597c5SAnurag S. Maskey nwam_error_t err; 12416ba597c5SAnurag S. Maskey char *name; 12426ba597c5SAnurag S. Maskey boolean_t automatic_ncp_active = B_FALSE; 12436ba597c5SAnurag S. Maskey 12446ba597c5SAnurag S. Maskey if (action != NWAM_ACTION_ADD && action != NWAM_ACTION_REMOVE) { 12456ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: " 12466ba597c5SAnurag S. Maskey "invalid link action %s", nwam_action_to_string(action)); 12476ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 12486ba597c5SAnurag S. Maskey return; 12496ba597c5SAnurag S. Maskey } 12506ba597c5SAnurag S. Maskey 12516ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_link_action_event: " 12526ba597c5SAnurag S. Maskey "link action '%s' event on %s", nwam_action_to_string(action), 12536ba597c5SAnurag S. Maskey event->event_object[0] == 0 ? "n/a" : event->event_object); 12546ba597c5SAnurag S. Maskey 12556ba597c5SAnurag S. Maskey if ((err = nwam_ncu_typed_name_to_name(event->event_object, &type, 12566ba597c5SAnurag S. Maskey &name)) != NWAM_SUCCESS) { 12576ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: " 12586ba597c5SAnurag S. Maskey "translation from typedname error: %s", nwam_strerror(err)); 12596ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 12606ba597c5SAnurag S. Maskey return; 12616ba597c5SAnurag S. Maskey } 12626ba597c5SAnurag S. Maskey 12636ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 12646ba597c5SAnurag S. Maskey if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 && 12656ba597c5SAnurag S. Maskey active_ncph != NULL) { 12666ba597c5SAnurag S. Maskey automatic_ncp_active = B_TRUE; 12676ba597c5SAnurag S. Maskey } 12686ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 12696ba597c5SAnurag S. Maskey 12706ba597c5SAnurag S. Maskey /* 12716ba597c5SAnurag S. Maskey * We could use active_ncph for cases where the Automatic NCP is active, 12726ba597c5SAnurag S. Maskey * but that would involve holding the active_ncp_mutex for too long. 12736ba597c5SAnurag S. Maskey */ 12746ba597c5SAnurag S. Maskey if ((err = nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph)) 12756ba597c5SAnurag S. Maskey == NWAM_ENTITY_NOT_FOUND) { 12766ba597c5SAnurag S. Maskey /* Automatic NCP doesn't exist, create it */ 1277*71ed50cfSAnurag S. Maskey err = nwam_ncp_create(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph); 12786ba597c5SAnurag S. Maskey } 1279*71ed50cfSAnurag S. Maskey if (err != NWAM_SUCCESS) 1280*71ed50cfSAnurag S. Maskey goto fail; 12816ba597c5SAnurag S. Maskey 12826ba597c5SAnurag S. Maskey /* add or remove NCUs from Automatic NCP */ 12836ba597c5SAnurag S. Maskey if (action == NWAM_ACTION_ADD) { 12846ba597c5SAnurag S. Maskey add_phys_ncu_to_ncp(ncph, name); 12856ba597c5SAnurag S. Maskey add_ip_ncu_to_ncp(ncph, name); 12866ba597c5SAnurag S. Maskey } else { 12876ba597c5SAnurag S. Maskey /* 12886ba597c5SAnurag S. Maskey * Order is important here, remove IP NCU first to prevent 12896ba597c5SAnurag S. Maskey * propogation of down event from link to IP. No need to 12906ba597c5SAnurag S. Maskey * create REFRESH or DESTROY events. They are generated by 12916ba597c5SAnurag S. Maskey * nwam_ncu_commit() and nwam_ncu_destroy(). 12926ba597c5SAnurag S. Maskey */ 12936ba597c5SAnurag S. Maskey remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_INTERFACE); 12946ba597c5SAnurag S. Maskey remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_LINK); 12956ba597c5SAnurag S. Maskey } 12966ba597c5SAnurag S. Maskey nwam_ncp_free(ncph); 12976ba597c5SAnurag S. Maskey 12986ba597c5SAnurag S. Maskey /* 12996ba597c5SAnurag S. Maskey * If the Automatic NCP is not active, and the associated NCUs 13006ba597c5SAnurag S. Maskey * exist, they must be moved into the appropriate states given the 13016ba597c5SAnurag S. Maskey * action that has occurred. 13026ba597c5SAnurag S. Maskey */ 13036ba597c5SAnurag S. Maskey if (!automatic_ncp_active) { 13046ba597c5SAnurag S. Maskey ncu_action_change_state(action, NWAM_NCU_TYPE_INTERFACE, name); 13056ba597c5SAnurag S. Maskey ncu_action_change_state(action, NWAM_NCU_TYPE_LINK, name); 13066ba597c5SAnurag S. Maskey } 13076ba597c5SAnurag S. Maskey 13086ba597c5SAnurag S. Maskey /* Need NCU check to evaluate state in light of added/removed NCUs */ 13096ba597c5SAnurag S. Maskey if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK, 13106ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_NCP, NULL)) { 13116ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(NEXT_FEW_SECONDS); 13126ba597c5SAnurag S. Maskey } 13136ba597c5SAnurag S. Maskey 1314*71ed50cfSAnurag S. Maskey fail: 13156ba597c5SAnurag S. Maskey free(name); 1316*71ed50cfSAnurag S. Maskey if (err != NWAM_SUCCESS) { 1317*71ed50cfSAnurag S. Maskey nwamd_event_t retry_event = nwamd_event_init_link_action(name, 1318*71ed50cfSAnurag S. Maskey action); 1319*71ed50cfSAnurag S. Maskey if (retry_event == NULL) { 1320*71ed50cfSAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: " 1321*71ed50cfSAnurag S. Maskey "could not create retry event to read/create " 1322*71ed50cfSAnurag S. Maskey "%s NCP", NWAM_NCP_NAME_AUTOMATIC); 1323*71ed50cfSAnurag S. Maskey return; 1324*71ed50cfSAnurag S. Maskey } 1325*71ed50cfSAnurag S. Maskey 1326*71ed50cfSAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: " 1327*71ed50cfSAnurag S. Maskey "could not read/create %s NCP, retrying in %d seconds", 1328*71ed50cfSAnurag S. Maskey NWAM_NCP_NAME_AUTOMATIC, NWAMD_READONLY_RETRY_INTERVAL); 1329*71ed50cfSAnurag S. Maskey nwamd_event_enqueue_timed(retry_event, 1330*71ed50cfSAnurag S. Maskey NWAMD_READONLY_RETRY_INTERVAL); 1331*71ed50cfSAnurag S. Maskey } 13326ba597c5SAnurag S. Maskey } 13336ba597c5SAnurag S. Maskey 13346ba597c5SAnurag S. Maskey /* 13356ba597c5SAnurag S. Maskey * Figure out if this link is part of an aggregation. This is fairly 13366ba597c5SAnurag S. Maskey * inefficient since we generate this list for every query and search 13376ba597c5SAnurag S. Maskey * linearly. A better way would be to generate the list of links in an 13386ba597c5SAnurag S. Maskey * aggregation once and then check each link against it. 13396ba597c5SAnurag S. Maskey */ 13406ba597c5SAnurag S. Maskey struct link_aggr_search_data { 13416ba597c5SAnurag S. Maskey datalink_id_t linkid; 13426ba597c5SAnurag S. Maskey boolean_t under; 13436ba597c5SAnurag S. Maskey }; 13446ba597c5SAnurag S. Maskey 13456ba597c5SAnurag S. Maskey static int 13466ba597c5SAnurag S. Maskey ncu_aggr_search(const char *name, void *data) 13476ba597c5SAnurag S. Maskey { 13486ba597c5SAnurag S. Maskey struct link_aggr_search_data *lasd = data; 13496ba597c5SAnurag S. Maskey dladm_aggr_grp_attr_t ginfo; 13506ba597c5SAnurag S. Maskey datalink_id_t linkid; 13516ba597c5SAnurag S. Maskey int i; 13526ba597c5SAnurag S. Maskey 13536ba597c5SAnurag S. Maskey if (dladm_name2info(dld_handle, name, &linkid, NULL, NULL, NULL) != 13546ba597c5SAnurag S. Maskey DLADM_STATUS_OK) 13556ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 13566ba597c5SAnurag S. Maskey if (dladm_aggr_info(dld_handle, linkid, &ginfo, DLADM_OPT_ACTIVE) 13576ba597c5SAnurag S. Maskey != DLADM_STATUS_OK || ginfo.lg_nports == 0) 13586ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 13596ba597c5SAnurag S. Maskey 13606ba597c5SAnurag S. Maskey for (i = 0; i < ginfo.lg_nports; i++) { 13616ba597c5SAnurag S. Maskey if (lasd->linkid == ginfo.lg_ports[i].lp_linkid) { 13626ba597c5SAnurag S. Maskey lasd->under = B_TRUE; 13636ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 13646ba597c5SAnurag S. Maskey } 13656ba597c5SAnurag S. Maskey } 13666ba597c5SAnurag S. Maskey free(ginfo.lg_ports); 13676ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 13686ba597c5SAnurag S. Maskey } 13696ba597c5SAnurag S. Maskey 13706ba597c5SAnurag S. Maskey static boolean_t 13716ba597c5SAnurag S. Maskey nwamd_link_belongs_to_an_aggr(const char *name) 13726ba597c5SAnurag S. Maskey { 13736ba597c5SAnurag S. Maskey struct link_aggr_search_data lasd; 13746ba597c5SAnurag S. Maskey 13756ba597c5SAnurag S. Maskey if (dladm_name2info(dld_handle, name, &lasd.linkid, NULL, NULL, NULL) 13766ba597c5SAnurag S. Maskey != DLADM_STATUS_OK) 13776ba597c5SAnurag S. Maskey return (B_FALSE); 13786ba597c5SAnurag S. Maskey lasd.under = B_FALSE; 13796ba597c5SAnurag S. Maskey (void) dladm_walk(ncu_aggr_search, dld_handle, &lasd, 13806ba597c5SAnurag S. Maskey DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 13816ba597c5SAnurag S. Maskey return (lasd.under); 13826ba597c5SAnurag S. Maskey } 13836ba597c5SAnurag S. Maskey 13846ba597c5SAnurag S. Maskey /* 13856ba597c5SAnurag S. Maskey * If NCU doesn't exist for interface with given name, enqueue a ADD 13866ba597c5SAnurag S. Maskey * LINK_ACTION event. 13876ba597c5SAnurag S. Maskey */ 13886ba597c5SAnurag S. Maskey static int 13896ba597c5SAnurag S. Maskey ncu_create_link_action_event(const char *name, void *data) 13906ba597c5SAnurag S. Maskey { 13916ba597c5SAnurag S. Maskey nwam_ncp_handle_t ncph = data; 13926ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 13936ba597c5SAnurag S. Maskey nwamd_event_t link_event; 13946ba597c5SAnurag S. Maskey 13956ba597c5SAnurag S. Maskey /* Do not generate an event if this is a VirtualBox interface. */ 13966ba597c5SAnurag S. Maskey if (strncmp(name, VBOX_IFACE_PREFIX, strlen(VBOX_IFACE_PREFIX)) == 0) 13976ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 13986ba597c5SAnurag S. Maskey 13996ba597c5SAnurag S. Maskey /* Do not generate an event if this link belongs to another zone. */ 14006ba597c5SAnurag S. Maskey if (!nwamd_link_belongs_to_this_zone(name)) 14016ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 14026ba597c5SAnurag S. Maskey 14036ba597c5SAnurag S. Maskey /* Do not generate an event if this link belongs to an aggregation. */ 14046ba597c5SAnurag S. Maskey if (nwamd_link_belongs_to_an_aggr(name)) { 14056ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 14066ba597c5SAnurag S. Maskey } 14076ba597c5SAnurag S. Maskey 14086ba597c5SAnurag S. Maskey /* Don't create an event if the NCU already exists. */ 14096ba597c5SAnurag S. Maskey if (ncph != NULL && nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK, 0, 14106ba597c5SAnurag S. Maskey &ncuh) == NWAM_SUCCESS) { 14116ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 14126ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 14136ba597c5SAnurag S. Maskey } 14146ba597c5SAnurag S. Maskey 14156ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "ncu_create_link_action_event: adding ncus for %s", 14166ba597c5SAnurag S. Maskey name); 14176ba597c5SAnurag S. Maskey 14186ba597c5SAnurag S. Maskey link_event = nwamd_event_init_link_action(name, NWAM_ACTION_ADD); 14196ba597c5SAnurag S. Maskey if (link_event != NULL) 14206ba597c5SAnurag S. Maskey nwamd_event_enqueue(link_event); 14216ba597c5SAnurag S. Maskey 14226ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 14236ba597c5SAnurag S. Maskey } 14246ba597c5SAnurag S. Maskey 14256ba597c5SAnurag S. Maskey /* 14266ba597c5SAnurag S. Maskey * Check if interface exists for this NCU. If not, enqueue a REMOVE 14276ba597c5SAnurag S. Maskey * LINK_ACTION event. 14286ba597c5SAnurag S. Maskey */ 14296ba597c5SAnurag S. Maskey /* ARGSUSED */ 14306ba597c5SAnurag S. Maskey static int 14316ba597c5SAnurag S. Maskey nwamd_destroy_ncu(nwam_ncu_handle_t ncuh, void *data) 14326ba597c5SAnurag S. Maskey { 14336ba597c5SAnurag S. Maskey char *name; 14346ba597c5SAnurag S. Maskey uint32_t flags; 14356ba597c5SAnurag S. Maskey nwamd_event_t link_event; 14366ba597c5SAnurag S. Maskey 14376ba597c5SAnurag S. Maskey if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) { 14386ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_destroy_ncu: could not get NCU name"); 14396ba597c5SAnurag S. Maskey return (0); 14406ba597c5SAnurag S. Maskey } 14416ba597c5SAnurag S. Maskey 14426ba597c5SAnurag S. Maskey /* Interfaces that exist return DLADM_OPT_ACTIVE flag */ 14436ba597c5SAnurag S. Maskey if ((dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL) 14446ba597c5SAnurag S. Maskey == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) && 14456ba597c5SAnurag S. Maskey !nwamd_link_belongs_to_an_aggr(name)) { 14466ba597c5SAnurag S. Maskey free(name); 14476ba597c5SAnurag S. Maskey return (0); 14486ba597c5SAnurag S. Maskey } 14496ba597c5SAnurag S. Maskey 14506ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_destroy_ncu: destroying ncus for %s", name); 14516ba597c5SAnurag S. Maskey 14526ba597c5SAnurag S. Maskey link_event = nwamd_event_init_link_action(name, NWAM_ACTION_REMOVE); 14536ba597c5SAnurag S. Maskey if (link_event != NULL) 14546ba597c5SAnurag S. Maskey nwamd_event_enqueue(link_event); 14556ba597c5SAnurag S. Maskey free(name); 14566ba597c5SAnurag S. Maskey return (0); 14576ba597c5SAnurag S. Maskey } 14586ba597c5SAnurag S. Maskey 14596ba597c5SAnurag S. Maskey /* 14606ba597c5SAnurag S. Maskey * Called when nwamd is starting up. 14616ba597c5SAnurag S. Maskey * 14626ba597c5SAnurag S. Maskey * Walk all NCUs and destroy any NCU from the Automatic NCP without an 14636ba597c5SAnurag S. Maskey * underlying interface (assumption here is that the interface was removed 14646ba597c5SAnurag S. Maskey * when nwam was disabled). 14656ba597c5SAnurag S. Maskey * 14666ba597c5SAnurag S. Maskey * Walk the physical interfaces and create ADD LINK_ACTION event, which 14676ba597c5SAnurag S. Maskey * will create appropriate interface and link NCUs in the Automatic NCP. 14686ba597c5SAnurag S. Maskey */ 14696ba597c5SAnurag S. Maskey void 14706ba597c5SAnurag S. Maskey nwamd_walk_physical_configuration(void) 14716ba597c5SAnurag S. Maskey { 14726ba597c5SAnurag S. Maskey nwam_ncp_handle_t ncph; 14736ba597c5SAnurag S. Maskey 14746ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 14756ba597c5SAnurag S. Maskey if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 && 14766ba597c5SAnurag S. Maskey active_ncph != NULL) { 14776ba597c5SAnurag S. Maskey ncph = active_ncph; 14786ba597c5SAnurag S. Maskey } else { 14796ba597c5SAnurag S. Maskey if (nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph) 14806ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 14816ba597c5SAnurag S. Maskey ncph = NULL; 14826ba597c5SAnurag S. Maskey } 14836ba597c5SAnurag S. Maskey } 14846ba597c5SAnurag S. Maskey 14856ba597c5SAnurag S. Maskey /* destroy NCUs for interfaces that don't exist */ 14866ba597c5SAnurag S. Maskey if (ncph != NULL) { 14876ba597c5SAnurag S. Maskey (void) nwam_ncp_walk_ncus(ncph, nwamd_destroy_ncu, NULL, 14886ba597c5SAnurag S. Maskey NWAM_FLAG_NCU_TYPE_LINK, NULL); 14896ba597c5SAnurag S. Maskey } 14906ba597c5SAnurag S. Maskey 14916ba597c5SAnurag S. Maskey /* create NCUs for interfaces without NCUs */ 14926ba597c5SAnurag S. Maskey (void) dladm_walk(ncu_create_link_action_event, dld_handle, ncph, 14936ba597c5SAnurag S. Maskey DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 14946ba597c5SAnurag S. Maskey 14956ba597c5SAnurag S. Maskey if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) != 0 || 14966ba597c5SAnurag S. Maskey active_ncph == NULL) { 14976ba597c5SAnurag S. Maskey nwam_ncp_free(ncph); 14986ba597c5SAnurag S. Maskey } 14996ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 15006ba597c5SAnurag S. Maskey } 15016ba597c5SAnurag S. Maskey 15026ba597c5SAnurag S. Maskey /* 15036ba597c5SAnurag S. Maskey * Handle NCU initialization/refresh event. 15046ba597c5SAnurag S. Maskey */ 15056ba597c5SAnurag S. Maskey void 15066ba597c5SAnurag S. Maskey nwamd_ncu_handle_init_event(nwamd_event_t event) 15076ba597c5SAnurag S. Maskey { 15086ba597c5SAnurag S. Maskey nwamd_object_t object = NULL; 15096ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 15106ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu = NULL; 15116ba597c5SAnurag S. Maskey nwam_error_t err; 15126ba597c5SAnurag S. Maskey nwam_ncu_type_t type; 15136ba597c5SAnurag S. Maskey char *name; 15146ba597c5SAnurag S. Maskey uint32_t flags; 15156ba597c5SAnurag S. Maskey boolean_t new = B_TRUE; 15166ba597c5SAnurag S. Maskey 15176ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event(%s)", 15186ba597c5SAnurag S. Maskey event->event_object); 15196ba597c5SAnurag S. Maskey 15206ba597c5SAnurag S. Maskey /* Get base linkname rather than interface:linkname or link:linkname */ 15216ba597c5SAnurag S. Maskey err = nwam_ncu_typed_name_to_name(event->event_object, 15226ba597c5SAnurag S. Maskey &type, &name); 15236ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 15246ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_init_event: " 15256ba597c5SAnurag S. Maskey "nwam_ncu_typed_name_to_name returned %s", 15266ba597c5SAnurag S. Maskey nwam_strerror(err)); 15276ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 15286ba597c5SAnurag S. Maskey return; 15296ba597c5SAnurag S. Maskey } 15306ba597c5SAnurag S. Maskey 15316ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 15326ba597c5SAnurag S. Maskey if (active_ncph == NULL) { 15336ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 15346ba597c5SAnurag S. Maskey "nwamd_ncu_handle_init_event: active NCP handle NULL"); 15356ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1536*71ed50cfSAnurag S. Maskey free(name); 15376ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 15386ba597c5SAnurag S. Maskey return; 15396ba597c5SAnurag S. Maskey } 15406ba597c5SAnurag S. Maskey err = nwam_ncu_read(active_ncph, event->event_object, 15416ba597c5SAnurag S. Maskey type, 0, &ncuh); 15426ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 15436ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 15446ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_init_event: " 15456ba597c5SAnurag S. Maskey "could not read object '%s': %s", 15466ba597c5SAnurag S. Maskey event->event_object, nwam_strerror(err)); 15476ba597c5SAnurag S. Maskey free(name); 15486ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 15496ba597c5SAnurag S. Maskey return; 15506ba597c5SAnurag S. Maskey } 15516ba597c5SAnurag S. Maskey 15526ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 15536ba597c5SAnurag S. Maskey event->event_object)) != NULL) 15546ba597c5SAnurag S. Maskey new = B_FALSE; 15556ba597c5SAnurag S. Maskey 15566ba597c5SAnurag S. Maskey /* 15576ba597c5SAnurag S. Maskey * For new NCUs, or interface NCUs, we (re)initialize data from scratch. 15586ba597c5SAnurag S. Maskey * For link NCUs, we want to retain object data. 15596ba597c5SAnurag S. Maskey */ 15606ba597c5SAnurag S. Maskey switch (type) { 15616ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_LINK: 15626ba597c5SAnurag S. Maskey if (new) { 15636ba597c5SAnurag S. Maskey ncu = nwamd_ncu_init(type, name); 15646ba597c5SAnurag S. Maskey } else { 15656ba597c5SAnurag S. Maskey ncu = object->nwamd_object_data; 15666ba597c5SAnurag S. Maskey nwam_ncu_free(object->nwamd_object_handle); 15676ba597c5SAnurag S. Maskey } 15686ba597c5SAnurag S. Maskey populate_common_ncu_properties(ncuh, ncu); 15696ba597c5SAnurag S. Maskey populate_link_ncu_properties(ncuh, ncu); 15706ba597c5SAnurag S. Maskey break; 15716ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_INTERFACE: 15726ba597c5SAnurag S. Maskey if (!new) { 15736ba597c5SAnurag S. Maskey nwam_ncu_free(object->nwamd_object_handle); 15746ba597c5SAnurag S. Maskey nwamd_ncu_free(object->nwamd_object_data); 15756ba597c5SAnurag S. Maskey } 15766ba597c5SAnurag S. Maskey ncu = nwamd_ncu_init(type, name); 15776ba597c5SAnurag S. Maskey populate_common_ncu_properties(ncuh, ncu); 15786ba597c5SAnurag S. Maskey populate_ip_ncu_properties(ncuh, ncu); 15796ba597c5SAnurag S. Maskey break; 15806ba597c5SAnurag S. Maskey default: 15816ba597c5SAnurag S. Maskey nlog(LOG_ERR, "unknown ncu type %d", type); 15826ba597c5SAnurag S. Maskey free(name); 15836ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 15846ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 15856ba597c5SAnurag S. Maskey nwamd_object_release(object); 15866ba597c5SAnurag S. Maskey return; 15876ba597c5SAnurag S. Maskey } 15886ba597c5SAnurag S. Maskey 15896ba597c5SAnurag S. Maskey if (new) { 15906ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: didn't find " 15916ba597c5SAnurag S. Maskey "ncu so create it %s", name); 15926ba597c5SAnurag S. Maskey object = nwamd_object_init(NWAM_OBJECT_TYPE_NCU, 15936ba597c5SAnurag S. Maskey event->event_object, ncuh, ncu); 15946ba597c5SAnurag S. Maskey } else { 15956ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: refreshing " 15966ba597c5SAnurag S. Maskey "ncu %s", name); 15976ba597c5SAnurag S. Maskey object->nwamd_object_data = ncu; 15986ba597c5SAnurag S. Maskey object->nwamd_object_handle = ncuh; 15996ba597c5SAnurag S. Maskey } 16006ba597c5SAnurag S. Maskey 16016ba597c5SAnurag S. Maskey /* 16026ba597c5SAnurag S. Maskey * If the physical link for this NCU doesn't exist in the system, 16036ba597c5SAnurag S. Maskey * the state should be UNINITIALIZED/NOT_FOUND. Interfaces that 16046ba597c5SAnurag S. Maskey * exist return DLADM_OPT_ACTIVE flag. 16056ba597c5SAnurag S. Maskey */ 16066ba597c5SAnurag S. Maskey if (dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL) 16076ba597c5SAnurag S. Maskey != DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) { 16086ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwam_ncu_handle_init_event: " 16096ba597c5SAnurag S. Maskey "interface for NCU %s doesn't exist", 16106ba597c5SAnurag S. Maskey event->event_object); 16116ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 16126ba597c5SAnurag S. Maskey object->nwamd_object_name, NWAM_STATE_UNINITIALIZED, 16136ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 16146ba597c5SAnurag S. Maskey free(name); 16156ba597c5SAnurag S. Maskey nwamd_object_release(object); 16166ba597c5SAnurag S. Maskey return; 16176ba597c5SAnurag S. Maskey } 16186ba597c5SAnurag S. Maskey 16196ba597c5SAnurag S. Maskey /* 16206ba597c5SAnurag S. Maskey * If NCU is being initialized (rather than refreshed), the 16216ba597c5SAnurag S. Maskey * object_state is INITIALIZED (from nwamd_object_init()). 16226ba597c5SAnurag S. Maskey */ 16236ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_INITIALIZED) { 16246ba597c5SAnurag S. Maskey /* 16256ba597c5SAnurag S. Maskey * If the NCU is disabled, initial state should be DISABLED. 16266ba597c5SAnurag S. Maskey * 16276ba597c5SAnurag S. Maskey * Otherwise, the initial state will be 16286ba597c5SAnurag S. Maskey * OFFLINE/CONDITIONS_NOT_MET, and the link selection 16296ba597c5SAnurag S. Maskey * algorithm will do the rest. 16306ba597c5SAnurag S. Maskey */ 16316ba597c5SAnurag S. Maskey if (!ncu->ncu_enabled) { 16326ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_DISABLED; 16336ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 16346ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE; 16356ba597c5SAnurag S. Maskey } else { 16366ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_OFFLINE; 16376ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 16386ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET; 16396ba597c5SAnurag S. Maskey } 16406ba597c5SAnurag S. Maskey } else { 16416ba597c5SAnurag S. Maskey nwamd_link_t *link = &ncu->ncu_node.u_link; 16426ba597c5SAnurag S. Maskey 16436ba597c5SAnurag S. Maskey /* 16446ba597c5SAnurag S. Maskey * Refresh NCU. Deal with disabled cases first, moving NCUs 16456ba597c5SAnurag S. Maskey * that are not disabled - but have the enabled value set - to 16466ba597c5SAnurag S. Maskey * the disabled state. Then handle cases where the NCU was 16476ba597c5SAnurag S. Maskey * disabled but is no longer. Finally, deal with refresh of 16486ba597c5SAnurag S. Maskey * link and interface NCUs, as these are handled differently. 16496ba597c5SAnurag S. Maskey */ 16506ba597c5SAnurag S. Maskey if (!ncu->ncu_enabled) { 16516ba597c5SAnurag S. Maskey if (object->nwamd_object_state != NWAM_STATE_DISABLED) { 16526ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 16536ba597c5SAnurag S. Maskey object->nwamd_object_name, 16546ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 16556ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 16566ba597c5SAnurag S. Maskey } 16576ba597c5SAnurag S. Maskey goto done; 16586ba597c5SAnurag S. Maskey } else { 16596ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_DISABLED) { 16606ba597c5SAnurag S. Maskey int64_t c; 16616ba597c5SAnurag S. Maskey 16626ba597c5SAnurag S. Maskey /* 16636ba597c5SAnurag S. Maskey * Try to activate the NCU if manual or 16646ba597c5SAnurag S. Maskey * prioritized (when priority <= current). 16656ba597c5SAnurag S. Maskey */ 16666ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 16676ba597c5SAnurag S. Maskey c = current_ncu_priority_group; 16686ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 16696ba597c5SAnurag S. Maskey if (link->nwamd_link_activation_mode == 16706ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_MANUAL || 16716ba597c5SAnurag S. Maskey (link->nwamd_link_activation_mode == 16726ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED && 16736ba597c5SAnurag S. Maskey link->nwamd_link_priority_mode <= c)) { 16746ba597c5SAnurag S. Maskey nwamd_object_set_state 16756ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 16766ba597c5SAnurag S. Maskey object->nwamd_object_name, 16776ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 16786ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 16796ba597c5SAnurag S. Maskey } else { 16806ba597c5SAnurag S. Maskey nwamd_object_set_state 16816ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 16826ba597c5SAnurag S. Maskey object->nwamd_object_name, 16836ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 16846ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 16856ba597c5SAnurag S. Maskey } 16866ba597c5SAnurag S. Maskey goto done; 16876ba597c5SAnurag S. Maskey } 16886ba597c5SAnurag S. Maskey } 16896ba597c5SAnurag S. Maskey 16906ba597c5SAnurag S. Maskey switch (type) { 16916ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_LINK: 16926ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_link.nwamd_link_media == DL_WIFI) { 16936ba597c5SAnurag S. Maskey /* 16946ba597c5SAnurag S. Maskey * Do rescan. If the current state and the 16956ba597c5SAnurag S. Maskey * active priority-group do not allow wireless 16966ba597c5SAnurag S. Maskey * network selection, then it won't happen. 16976ba597c5SAnurag S. Maskey */ 16986ba597c5SAnurag S. Maskey (void) nwamd_wlan_scan(ncu->ncu_name); 16996ba597c5SAnurag S. Maskey } 17006ba597c5SAnurag S. Maskey break; 17016ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_INTERFACE: 17026ba597c5SAnurag S. Maskey /* 17036ba597c5SAnurag S. Maskey * If interface NCU is offline*, online or in 17046ba597c5SAnurag S. Maskey * maintenance, mark it down (from there, it will be 17056ba597c5SAnurag S. Maskey * reinitialized to reapply addresses). 17066ba597c5SAnurag S. Maskey */ 17076ba597c5SAnurag S. Maskey if (object->nwamd_object_state != NWAM_STATE_OFFLINE) { 17086ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 17096ba597c5SAnurag S. Maskey object->nwamd_object_name, 17106ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 17116ba597c5SAnurag S. Maskey NWAM_AUX_STATE_DOWN); 17126ba597c5SAnurag S. Maskey } else { 17136ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_OFFLINE; 17146ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 17156ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET; 17166ba597c5SAnurag S. Maskey } 17176ba597c5SAnurag S. Maskey break; 17186ba597c5SAnurag S. Maskey } 17196ba597c5SAnurag S. Maskey } 17206ba597c5SAnurag S. Maskey 17216ba597c5SAnurag S. Maskey done: 17226ba597c5SAnurag S. Maskey if (type == NWAM_NCU_TYPE_LINK && 17236ba597c5SAnurag S. Maskey !nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK, 17246ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_NCP, NULL)) { 17256ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(NEXT_FEW_SECONDS); 17266ba597c5SAnurag S. Maskey } 17276ba597c5SAnurag S. Maskey free(name); 17286ba597c5SAnurag S. Maskey nwamd_object_release(object); 17296ba597c5SAnurag S. Maskey } 17306ba597c5SAnurag S. Maskey 17316ba597c5SAnurag S. Maskey void 17326ba597c5SAnurag S. Maskey nwamd_ncu_handle_fini_event(nwamd_event_t event) 17336ba597c5SAnurag S. Maskey { 17346ba597c5SAnurag S. Maskey nwamd_object_t object; 17356ba597c5SAnurag S. Maskey nwamd_event_t state_event; 17366ba597c5SAnurag S. Maskey 17376ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_fini_event(%s)", 17386ba597c5SAnurag S. Maskey event->event_object); 17396ba597c5SAnurag S. Maskey 17406ba597c5SAnurag S. Maskey /* 17416ba597c5SAnurag S. Maskey * Simulate a state event so that the state machine can correctly 17426ba597c5SAnurag S. Maskey * disable the NCU. Then free up allocated objects. 17436ba597c5SAnurag S. Maskey */ 17446ba597c5SAnurag S. Maskey state_event = nwamd_event_init_object_state(NWAM_OBJECT_TYPE_NCU, 17456ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE, 17466ba597c5SAnurag S. Maskey NWAM_AUX_STATE_UNINITIALIZED); 17476ba597c5SAnurag S. Maskey if (state_event == NULL) { 17486ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 17496ba597c5SAnurag S. Maskey return; 17506ba597c5SAnurag S. Maskey } 17516ba597c5SAnurag S. Maskey nwamd_ncu_handle_state_event(state_event); 17526ba597c5SAnurag S. Maskey nwamd_event_fini(state_event); 17536ba597c5SAnurag S. Maskey 17546ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 17556ba597c5SAnurag S. Maskey event->event_object)) == NULL) { 17566ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_fini_event: " 17576ba597c5SAnurag S. Maskey "ncu %s not found", event->event_object); 17586ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 17596ba597c5SAnurag S. Maskey return; 17606ba597c5SAnurag S. Maskey } 17616ba597c5SAnurag S. Maskey nwamd_object_release_and_destroy(object); 17626ba597c5SAnurag S. Maskey } 17636ba597c5SAnurag S. Maskey 17646ba597c5SAnurag S. Maskey void 17656ba597c5SAnurag S. Maskey nwamd_ncu_handle_action_event(nwamd_event_t event) 17666ba597c5SAnurag S. Maskey { 17676ba597c5SAnurag S. Maskey nwamd_object_t object; 17686ba597c5SAnurag S. Maskey 17696ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 17706ba597c5SAnurag S. Maskey if (strcmp(event->event_msg->nwe_data.nwe_object_action.nwe_parent, 17716ba597c5SAnurag S. Maskey active_ncp) != 0) { 17726ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: action for " 17736ba597c5SAnurag S. Maskey "inactive NCP %s, nothing to do", 17746ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_object_action.nwe_parent); 17756ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 17766ba597c5SAnurag S. Maskey return; 17776ba597c5SAnurag S. Maskey } 17786ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 17796ba597c5SAnurag S. Maskey 17806ba597c5SAnurag S. Maskey switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) { 17816ba597c5SAnurag S. Maskey case NWAM_ACTION_ENABLE: 17826ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 17836ba597c5SAnurag S. Maskey event->event_object); 17846ba597c5SAnurag S. Maskey if (object == NULL) { 17856ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_action_event: " 17866ba597c5SAnurag S. Maskey "could not find ncu %s", event->event_object); 17876ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 17886ba597c5SAnurag S. Maskey return; 17896ba597c5SAnurag S. Maskey } 17906ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_ONLINE) { 17916ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: " 17926ba597c5SAnurag S. Maskey "ncu %s already online, nothing to do", 17936ba597c5SAnurag S. Maskey event->event_object); 17946ba597c5SAnurag S. Maskey nwamd_object_release(object); 17956ba597c5SAnurag S. Maskey return; 17966ba597c5SAnurag S. Maskey } 17976ba597c5SAnurag S. Maskey nwamd_object_release(object); 17986ba597c5SAnurag S. Maskey 17996ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 18006ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE, 18016ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 18026ba597c5SAnurag S. Maskey break; 18036ba597c5SAnurag S. Maskey case NWAM_ACTION_DISABLE: 18046ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 18056ba597c5SAnurag S. Maskey event->event_object); 18066ba597c5SAnurag S. Maskey if (object == NULL) { 18076ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_action_event: " 18086ba597c5SAnurag S. Maskey "could not find ncu %s", event->event_object); 18096ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 18106ba597c5SAnurag S. Maskey return; 18116ba597c5SAnurag S. Maskey } 18126ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_DISABLED) { 18136ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: " 18146ba597c5SAnurag S. Maskey "ncu %s already disabled, nothing to do", 18156ba597c5SAnurag S. Maskey event->event_object); 18166ba597c5SAnurag S. Maskey nwamd_object_release(object); 18176ba597c5SAnurag S. Maskey return; 18186ba597c5SAnurag S. Maskey } 18196ba597c5SAnurag S. Maskey nwamd_object_release(object); 18206ba597c5SAnurag S. Maskey 18216ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 18226ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE, 18236ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 18246ba597c5SAnurag S. Maskey break; 18256ba597c5SAnurag S. Maskey case NWAM_ACTION_ADD: 18266ba597c5SAnurag S. Maskey case NWAM_ACTION_REFRESH: 18276ba597c5SAnurag S. Maskey nwamd_ncu_handle_init_event(event); 18286ba597c5SAnurag S. Maskey break; 18296ba597c5SAnurag S. Maskey case NWAM_ACTION_DESTROY: 18306ba597c5SAnurag S. Maskey nwamd_ncu_handle_fini_event(event); 18316ba597c5SAnurag S. Maskey break; 18326ba597c5SAnurag S. Maskey default: 18336ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwam_ncu_handle_action_event: " 18346ba597c5SAnurag S. Maskey "unexpected action"); 18356ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 18366ba597c5SAnurag S. Maskey break; 18376ba597c5SAnurag S. Maskey } 18386ba597c5SAnurag S. Maskey } 18396ba597c5SAnurag S. Maskey 18406ba597c5SAnurag S. Maskey void 18416ba597c5SAnurag S. Maskey nwamd_ncu_handle_state_event(nwamd_event_t event) 18426ba597c5SAnurag S. Maskey { 18436ba597c5SAnurag S. Maskey nwamd_object_t object; 18446ba597c5SAnurag S. Maskey nwam_state_t old_state, new_state; 18456ba597c5SAnurag S. Maskey nwam_aux_state_t new_aux_state; 18466ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu; 18476ba597c5SAnurag S. Maskey boolean_t is_link, enabled, prioritized = B_FALSE; 18486ba597c5SAnurag S. Maskey char linkname[NWAM_MAX_NAME_LEN]; 18496ba597c5SAnurag S. Maskey nwam_event_t m = event->event_msg; 18506ba597c5SAnurag S. Maskey 18516ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 18526ba597c5SAnurag S. Maskey event->event_object)) == NULL) { 18536ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_state_event %lld: " 18546ba597c5SAnurag S. Maskey "state event for nonexistent NCU %s", event->event_id, 18556ba597c5SAnurag S. Maskey event->event_object); 18566ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 18576ba597c5SAnurag S. Maskey return; 18586ba597c5SAnurag S. Maskey } 18596ba597c5SAnurag S. Maskey ncu = object->nwamd_object_data; 18606ba597c5SAnurag S. Maskey old_state = object->nwamd_object_state; 18616ba597c5SAnurag S. Maskey new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state; 18626ba597c5SAnurag S. Maskey new_aux_state = 18636ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_object_state.nwe_aux_state; 18646ba597c5SAnurag S. Maskey 18656ba597c5SAnurag S. Maskey /* 18666ba597c5SAnurag S. Maskey * For NCU state changes, we need to supply the parent NCP name also, 18676ba597c5SAnurag S. Maskey * regardless of whether the event is handled or not. It is best to 18686ba597c5SAnurag S. Maskey * fill this in here as we have the object lock - when we create 18696ba597c5SAnurag S. Maskey * object state events we sometimes do not have the object lock, but 18706ba597c5SAnurag S. Maskey * at this point in consuming the events (and prior to the associated 18716ba597c5SAnurag S. Maskey * event message being sent out) we do. 18726ba597c5SAnurag S. Maskey */ 18736ba597c5SAnurag S. Maskey (void) strlcpy(m->nwe_data.nwe_object_state.nwe_parent, ncu->ncu_parent, 18746ba597c5SAnurag S. Maskey sizeof (m->nwe_data.nwe_object_state.nwe_parent)); 18756ba597c5SAnurag S. Maskey 18766ba597c5SAnurag S. Maskey /* 18776ba597c5SAnurag S. Maskey * If we receive a state change event moving this NCU to 18786ba597c5SAnurag S. Maskey * DHCP_TIMED_OUT or UP state but this NCU is already ONLINE, then 18796ba597c5SAnurag S. Maskey * ignore this state change event. 18806ba597c5SAnurag S. Maskey */ 18816ba597c5SAnurag S. Maskey if ((new_aux_state == NWAM_AUX_STATE_IF_DHCP_TIMED_OUT || 18826ba597c5SAnurag S. Maskey new_aux_state == NWAM_AUX_STATE_UP) && 18836ba597c5SAnurag S. Maskey object->nwamd_object_state == NWAM_STATE_ONLINE) { 18846ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_ncu_handle_state_event: " 18856ba597c5SAnurag S. Maskey "NCU %s already online, not going to '%s' state", 18866ba597c5SAnurag S. Maskey object->nwamd_object_name, 18876ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 18886ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 18896ba597c5SAnurag S. Maskey nwamd_object_release(object); 18906ba597c5SAnurag S. Maskey return; 18916ba597c5SAnurag S. Maskey } 18926ba597c5SAnurag S. Maskey 18936ba597c5SAnurag S. Maskey if (new_state == object->nwamd_object_state && 18946ba597c5SAnurag S. Maskey new_aux_state == object->nwamd_object_aux_state) { 18956ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: " 18966ba597c5SAnurag S. Maskey "NCU %s already in state (%s, %s)", 18976ba597c5SAnurag S. Maskey object->nwamd_object_name, nwam_state_to_string(new_state), 18986ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 18996ba597c5SAnurag S. Maskey nwamd_object_release(object); 19006ba597c5SAnurag S. Maskey return; 19016ba597c5SAnurag S. Maskey } 19026ba597c5SAnurag S. Maskey 19036ba597c5SAnurag S. Maskey if (old_state == NWAM_STATE_MAINTENANCE && 19046ba597c5SAnurag S. Maskey (new_state == NWAM_STATE_ONLINE || 19056ba597c5SAnurag S. Maskey (new_state == NWAM_STATE_OFFLINE_TO_ONLINE && 19066ba597c5SAnurag S. Maskey new_aux_state != NWAM_AUX_STATE_INITIALIZED))) { 19076ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: " 19086ba597c5SAnurag S. Maskey "NCU %s cannot transition from state %s to state (%s, %s)", 19096ba597c5SAnurag S. Maskey object->nwamd_object_name, nwam_state_to_string(old_state), 19106ba597c5SAnurag S. Maskey nwam_state_to_string(new_state), 19116ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 19126ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 19136ba597c5SAnurag S. Maskey nwamd_object_release(object); 19146ba597c5SAnurag S. Maskey return; 19156ba597c5SAnurag S. Maskey } 19166ba597c5SAnurag S. Maskey 19176ba597c5SAnurag S. Maskey object->nwamd_object_state = new_state; 19186ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = new_aux_state; 19196ba597c5SAnurag S. Maskey 19206ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: changing state for NCU " 19216ba597c5SAnurag S. Maskey "%s to (%s, %s)", object->nwamd_object_name, 19226ba597c5SAnurag S. Maskey nwam_state_to_string(object->nwamd_object_state), 19236ba597c5SAnurag S. Maskey nwam_aux_state_to_string(object->nwamd_object_aux_state)); 19246ba597c5SAnurag S. Maskey 19256ba597c5SAnurag S. Maskey is_link = (ncu->ncu_type == NWAM_NCU_TYPE_LINK); 19266ba597c5SAnurag S. Maskey if (is_link) 19276ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname)); 19286ba597c5SAnurag S. Maskey prioritized = (ncu->ncu_type == NWAM_NCU_TYPE_LINK && 19296ba597c5SAnurag S. Maskey ncu->ncu_node.u_link.nwamd_link_activation_mode == 19306ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED); 19316ba597c5SAnurag S. Maskey enabled = ncu->ncu_enabled; 19326ba597c5SAnurag S. Maskey 19336ba597c5SAnurag S. Maskey nwamd_object_release(object); 19346ba597c5SAnurag S. Maskey 19356ba597c5SAnurag S. Maskey /* 19366ba597c5SAnurag S. Maskey * State machine for NCUs 19376ba597c5SAnurag S. Maskey */ 19386ba597c5SAnurag S. Maskey switch (new_state) { 19396ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE_TO_ONLINE: 19406ba597c5SAnurag S. Maskey if (enabled) { 19416ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(event->event_object); 19426ba597c5SAnurag S. Maskey } else { 19436ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: " 19446ba597c5SAnurag S. Maskey "cannot move disabled NCU %s online", 19456ba597c5SAnurag S. Maskey event->event_object); 19466ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 19476ba597c5SAnurag S. Maskey } 19486ba597c5SAnurag S. Maskey break; 19496ba597c5SAnurag S. Maskey 19506ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE_TO_OFFLINE: 19516ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(event->event_object); 19526ba597c5SAnurag S. Maskey break; 19536ba597c5SAnurag S. Maskey 19546ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE: 19556ba597c5SAnurag S. Maskey /* 19566ba597c5SAnurag S. Maskey * We usually don't need to do anything when we're in the 19576ba597c5SAnurag S. Maskey * ONLINE state. However, for WiFi we can be in INIT or 19586ba597c5SAnurag S. Maskey * SCAN aux states while being ONLINE. 19596ba597c5SAnurag S. Maskey */ 19606ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(event->event_object); 19616ba597c5SAnurag S. Maskey break; 19626ba597c5SAnurag S. Maskey 19636ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE: 19646ba597c5SAnurag S. Maskey /* Reassess priority group now member is offline */ 19656ba597c5SAnurag S. Maskey if (prioritized) { 19666ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(0); 19676ba597c5SAnurag S. Maskey } 19686ba597c5SAnurag S. Maskey break; 19696ba597c5SAnurag S. Maskey 19706ba597c5SAnurag S. Maskey case NWAM_STATE_DISABLED: 19716ba597c5SAnurag S. Maskey case NWAM_STATE_UNINITIALIZED: 19726ba597c5SAnurag S. Maskey case NWAM_STATE_MAINTENANCE: 19736ba597c5SAnurag S. Maskey case NWAM_STATE_DEGRADED: 19746ba597c5SAnurag S. Maskey default: 19756ba597c5SAnurag S. Maskey /* do nothing */ 19766ba597c5SAnurag S. Maskey break; 19776ba597c5SAnurag S. Maskey } 19786ba597c5SAnurag S. Maskey 19796ba597c5SAnurag S. Maskey if (is_link) { 19806ba597c5SAnurag S. Maskey if ((new_state == NWAM_STATE_ONLINE_TO_OFFLINE && 19816ba597c5SAnurag S. Maskey new_aux_state != NWAM_AUX_STATE_UNINITIALIZED && 19826ba597c5SAnurag S. Maskey new_aux_state != NWAM_AUX_STATE_NOT_FOUND) || 19836ba597c5SAnurag S. Maskey new_state == NWAM_STATE_DISABLED) { 19846ba597c5SAnurag S. Maskey /* 19856ba597c5SAnurag S. Maskey * Going offline, propogate down event to IP NCU. Do 19866ba597c5SAnurag S. Maskey * not propogate event if new aux state is uninitialized 19876ba597c5SAnurag S. Maskey * or not found as these auxiliary states signify 19886ba597c5SAnurag S. Maskey * that an NCP switch/device removal is in progress. 19896ba597c5SAnurag S. Maskey */ 19906ba597c5SAnurag S. Maskey nwamd_propogate_link_up_down_to_ip(linkname, B_FALSE); 19916ba597c5SAnurag S. Maskey } 19926ba597c5SAnurag S. Maskey if (new_state == NWAM_STATE_ONLINE) { 19936ba597c5SAnurag S. Maskey /* gone online, propogate up event to IP NCU */ 19946ba597c5SAnurag S. Maskey nwamd_propogate_link_up_down_to_ip(linkname, B_TRUE); 19956ba597c5SAnurag S. Maskey } 19966ba597c5SAnurag S. Maskey } else { 19976ba597c5SAnurag S. Maskey /* If IP NCU is online, reasses priority group */ 19986ba597c5SAnurag S. Maskey if (new_state == NWAM_STATE_ONLINE) 19996ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(0); 20006ba597c5SAnurag S. Maskey } 20016ba597c5SAnurag S. Maskey } 2002