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