1*6ba597c5SAnurag S. Maskey /* 2*6ba597c5SAnurag S. Maskey * CDDL HEADER START 3*6ba597c5SAnurag S. Maskey * 4*6ba597c5SAnurag S. Maskey * The contents of this file are subject to the terms of the 5*6ba597c5SAnurag S. Maskey * Common Development and Distribution License (the "License"). 6*6ba597c5SAnurag S. Maskey * You may not use this file except in compliance with the License. 7*6ba597c5SAnurag S. Maskey * 8*6ba597c5SAnurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6ba597c5SAnurag S. Maskey * or http://www.opensolaris.org/os/licensing. 10*6ba597c5SAnurag S. Maskey * See the License for the specific language governing permissions 11*6ba597c5SAnurag S. Maskey * and limitations under the License. 12*6ba597c5SAnurag S. Maskey * 13*6ba597c5SAnurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each 14*6ba597c5SAnurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6ba597c5SAnurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the 16*6ba597c5SAnurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying 17*6ba597c5SAnurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner] 18*6ba597c5SAnurag S. Maskey * 19*6ba597c5SAnurag S. Maskey * CDDL HEADER END 20*6ba597c5SAnurag S. Maskey */ 21*6ba597c5SAnurag S. Maskey 22*6ba597c5SAnurag S. Maskey /* 23*6ba597c5SAnurag S. Maskey * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24*6ba597c5SAnurag S. Maskey * Use is subject to license terms. 25*6ba597c5SAnurag S. Maskey */ 26*6ba597c5SAnurag S. Maskey 27*6ba597c5SAnurag S. Maskey #include <arpa/inet.h> 28*6ba597c5SAnurag S. Maskey #include <assert.h> 29*6ba597c5SAnurag S. Maskey #include <libdlaggr.h> 30*6ba597c5SAnurag S. Maskey #include <libdllink.h> 31*6ba597c5SAnurag S. Maskey #include <libdlstat.h> 32*6ba597c5SAnurag S. Maskey #include <libnwam.h> 33*6ba597c5SAnurag S. Maskey #include <libscf.h> 34*6ba597c5SAnurag S. Maskey #include <netinet/in.h> 35*6ba597c5SAnurag S. Maskey #include <stdlib.h> 36*6ba597c5SAnurag S. Maskey #include <strings.h> 37*6ba597c5SAnurag S. Maskey #include <sys/socket.h> 38*6ba597c5SAnurag S. Maskey #include <sys/time.h> 39*6ba597c5SAnurag S. Maskey #include <sys/types.h> 40*6ba597c5SAnurag S. Maskey #include <values.h> 41*6ba597c5SAnurag S. Maskey 42*6ba597c5SAnurag S. Maskey #include "conditions.h" 43*6ba597c5SAnurag S. Maskey #include "events.h" 44*6ba597c5SAnurag S. Maskey #include "objects.h" 45*6ba597c5SAnurag S. Maskey #include "ncp.h" 46*6ba597c5SAnurag S. Maskey #include "util.h" 47*6ba597c5SAnurag S. Maskey 48*6ba597c5SAnurag S. Maskey /* 49*6ba597c5SAnurag S. Maskey * ncu.c - handles various NCU tasks - intialization/refresh, state machine 50*6ba597c5SAnurag S. Maskey * for NCUs etc. 51*6ba597c5SAnurag S. Maskey */ 52*6ba597c5SAnurag S. Maskey 53*6ba597c5SAnurag S. Maskey #define VBOX_IFACE_PREFIX "vboxnet" 54*6ba597c5SAnurag S. Maskey 55*6ba597c5SAnurag S. Maskey /* 56*6ba597c5SAnurag S. Maskey * Find ncu of specified type for link/interface name. 57*6ba597c5SAnurag S. Maskey */ 58*6ba597c5SAnurag S. Maskey nwamd_object_t 59*6ba597c5SAnurag S. Maskey nwamd_ncu_object_find(nwam_ncu_type_t type, const char *name) 60*6ba597c5SAnurag S. Maskey { 61*6ba597c5SAnurag S. Maskey nwam_error_t err; 62*6ba597c5SAnurag S. Maskey char *object_name; 63*6ba597c5SAnurag S. Maskey nwamd_object_t ncu_obj = NULL; 64*6ba597c5SAnurag S. Maskey 65*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_name_to_typed_name(name, type, &object_name)) 66*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 67*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_find: nwam_ncu_name_to_typed_name " 68*6ba597c5SAnurag S. Maskey "returned %s", nwam_strerror(err)); 69*6ba597c5SAnurag S. Maskey return (NULL); 70*6ba597c5SAnurag S. Maskey } 71*6ba597c5SAnurag S. Maskey ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name); 72*6ba597c5SAnurag S. Maskey 73*6ba597c5SAnurag S. Maskey free(object_name); 74*6ba597c5SAnurag S. Maskey return (ncu_obj); 75*6ba597c5SAnurag S. Maskey } 76*6ba597c5SAnurag S. Maskey 77*6ba597c5SAnurag S. Maskey nwam_error_t 78*6ba597c5SAnurag S. Maskey nwamd_set_ncu_string(nwam_ncu_handle_t ncuh, char **strval, uint_t cnt, 79*6ba597c5SAnurag S. Maskey const char *prop) 80*6ba597c5SAnurag S. Maskey { 81*6ba597c5SAnurag S. Maskey nwam_error_t err; 82*6ba597c5SAnurag S. Maskey nwam_value_t val; 83*6ba597c5SAnurag S. Maskey 84*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string_array(strval, cnt, &val)) 85*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 86*6ba597c5SAnurag S. Maskey return (err); 87*6ba597c5SAnurag S. Maskey err = nwam_ncu_set_prop_value(ncuh, prop, val); 88*6ba597c5SAnurag S. Maskey nwam_value_free(val); 89*6ba597c5SAnurag S. Maskey return (err); 90*6ba597c5SAnurag S. Maskey } 91*6ba597c5SAnurag S. Maskey 92*6ba597c5SAnurag S. Maskey nwam_error_t 93*6ba597c5SAnurag S. Maskey nwamd_set_ncu_uint(nwam_ncu_handle_t ncuh, uint64_t *uintval, uint_t cnt, 94*6ba597c5SAnurag S. Maskey const char *prop) 95*6ba597c5SAnurag S. Maskey { 96*6ba597c5SAnurag S. Maskey nwam_error_t err; 97*6ba597c5SAnurag S. Maskey nwam_value_t val; 98*6ba597c5SAnurag S. Maskey 99*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64_array(uintval, cnt, &val)) 100*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 101*6ba597c5SAnurag S. Maskey return (err); 102*6ba597c5SAnurag S. Maskey err = nwam_ncu_set_prop_value(ncuh, prop, val); 103*6ba597c5SAnurag S. Maskey nwam_value_free(val); 104*6ba597c5SAnurag S. Maskey return (err); 105*6ba597c5SAnurag S. Maskey } 106*6ba597c5SAnurag S. Maskey 107*6ba597c5SAnurag S. Maskey nwam_error_t 108*6ba597c5SAnurag S. Maskey nwamd_get_ncu_string(nwam_ncu_handle_t ncuh, nwam_value_t *val, char ***strval, 109*6ba597c5SAnurag S. Maskey uint_t *cnt, const char *prop) 110*6ba597c5SAnurag S. Maskey { 111*6ba597c5SAnurag S. Maskey nwam_error_t err; 112*6ba597c5SAnurag S. Maskey 113*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS) 114*6ba597c5SAnurag S. Maskey return (err); 115*6ba597c5SAnurag S. Maskey return (nwam_value_get_string_array(*val, strval, cnt)); 116*6ba597c5SAnurag S. Maskey } 117*6ba597c5SAnurag S. Maskey 118*6ba597c5SAnurag S. Maskey nwam_error_t 119*6ba597c5SAnurag S. Maskey nwamd_get_ncu_uint(nwam_ncu_handle_t ncuh, nwam_value_t *val, 120*6ba597c5SAnurag S. Maskey uint64_t **uintval, uint_t *cnt, const char *prop) 121*6ba597c5SAnurag S. Maskey { 122*6ba597c5SAnurag S. Maskey nwam_error_t err; 123*6ba597c5SAnurag S. Maskey 124*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS) 125*6ba597c5SAnurag S. Maskey return (err); 126*6ba597c5SAnurag S. Maskey return (nwam_value_get_uint64_array(*val, uintval, cnt)); 127*6ba597c5SAnurag S. Maskey } 128*6ba597c5SAnurag S. Maskey 129*6ba597c5SAnurag S. Maskey /* 130*6ba597c5SAnurag S. Maskey * Run link/interface state machine in response to a state change 131*6ba597c5SAnurag S. Maskey * or enable/disable action event. 132*6ba597c5SAnurag S. Maskey */ 133*6ba597c5SAnurag S. Maskey static void 134*6ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(const char *object_name) 135*6ba597c5SAnurag S. Maskey { 136*6ba597c5SAnurag S. Maskey nwamd_object_t object; 137*6ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu; 138*6ba597c5SAnurag S. Maskey link_state_t link_state; 139*6ba597c5SAnurag S. Maskey nwamd_event_t event; 140*6ba597c5SAnurag S. Maskey nwam_wlan_t key_wlan, connected_wlan; 141*6ba597c5SAnurag S. Maskey nwamd_link_t *link; 142*6ba597c5SAnurag S. Maskey char linkname[NWAM_MAX_NAME_LEN]; 143*6ba597c5SAnurag S. Maskey boolean_t up; 144*6ba597c5SAnurag S. Maskey 145*6ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name)) 146*6ba597c5SAnurag S. Maskey == NULL) { 147*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_state_machine: " 148*6ba597c5SAnurag S. Maskey "request for nonexistent NCU %s", object_name); 149*6ba597c5SAnurag S. Maskey return; 150*6ba597c5SAnurag S. Maskey } 151*6ba597c5SAnurag S. Maskey 152*6ba597c5SAnurag S. Maskey ncu = object->nwamd_object_data; 153*6ba597c5SAnurag S. Maskey link = &ncu->ncu_node.u_link; 154*6ba597c5SAnurag S. Maskey 155*6ba597c5SAnurag S. Maskey switch (object->nwamd_object_aux_state) { 156*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_INITIALIZED: 157*6ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 158*6ba597c5SAnurag S. Maskey /* 159*6ba597c5SAnurag S. Maskey * For wired/wireless links, need to get link 160*6ba597c5SAnurag S. Maskey * up/down events and even if these are not supported, 161*6ba597c5SAnurag S. Maskey * dlpi_open()ing the link prevents the driver from 162*6ba597c5SAnurag S. Maskey * being unloaded. 163*6ba597c5SAnurag S. Maskey */ 164*6ba597c5SAnurag S. Maskey nwamd_dlpi_add_link(object); 165*6ba597c5SAnurag S. Maskey 166*6ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 167*6ba597c5SAnurag S. Maskey /* 168*6ba597c5SAnurag S. Maskey * First, if we're unexpectedly connected, 169*6ba597c5SAnurag S. Maskey * disconnect. 170*6ba597c5SAnurag S. Maskey */ 171*6ba597c5SAnurag S. Maskey if (!link->nwamd_link_wifi_connected && 172*6ba597c5SAnurag S. Maskey nwamd_wlan_connected(object)) { 173*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 174*6ba597c5SAnurag S. Maskey "nwamd_ncu_state_machine: " 175*6ba597c5SAnurag S. Maskey "WiFi unexpectedly connected, " 176*6ba597c5SAnurag S. Maskey "disconnecting..."); 177*6ba597c5SAnurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, 178*6ba597c5SAnurag S. Maskey link->nwamd_link_id); 179*6ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, 180*6ba597c5SAnurag S. Maskey B_FALSE, B_FALSE); 181*6ba597c5SAnurag S. Maskey } 182*6ba597c5SAnurag S. Maskey /* move to scanning aux state */ 183*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 184*6ba597c5SAnurag S. Maskey object_name, object->nwamd_object_state, 185*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_LINK_WIFI_SCANNING); 186*6ba597c5SAnurag S. Maskey } else { 187*6ba597c5SAnurag S. Maskey /* 188*6ba597c5SAnurag S. Maskey * If initial wired link state is unknown, we 189*6ba597c5SAnurag S. Maskey * will need to assume the link is up, since 190*6ba597c5SAnurag S. Maskey * we won´t get DL_NOTE_LINK_UP/DOWN events. 191*6ba597c5SAnurag S. Maskey */ 192*6ba597c5SAnurag S. Maskey link_state = nwamd_get_link_state 193*6ba597c5SAnurag S. Maskey (ncu->ncu_name); 194*6ba597c5SAnurag S. Maskey if (link_state == LINK_STATE_UP || 195*6ba597c5SAnurag S. Maskey link_state == LINK_STATE_UNKNOWN) { 196*6ba597c5SAnurag S. Maskey nwamd_object_set_state 197*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 198*6ba597c5SAnurag S. Maskey object_name, NWAM_STATE_ONLINE, 199*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_UP); 200*6ba597c5SAnurag S. Maskey } else { 201*6ba597c5SAnurag S. Maskey nwamd_object_set_state 202*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 203*6ba597c5SAnurag S. Maskey object_name, 204*6ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 205*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_DOWN); 206*6ba597c5SAnurag S. Maskey } 207*6ba597c5SAnurag S. Maskey } 208*6ba597c5SAnurag S. Maskey } else { 209*6ba597c5SAnurag S. Maskey /* 210*6ba597c5SAnurag S. Maskey * In the current implementation, initialization has to 211*6ba597c5SAnurag S. Maskey * start from scratch since the complexity of minimizing 212*6ba597c5SAnurag S. Maskey * configuration change is considerable (e.g. if we 213*6ba597c5SAnurag S. Maskey * refresh and had DHCP running on the physical 214*6ba597c5SAnurag S. Maskey * interface, and now have changed to static assignment, 215*6ba597c5SAnurag S. Maskey * we need to remove DHCP etc). To avoid all this, 216*6ba597c5SAnurag S. Maskey * unplumb before re-plumbing the protocols and 217*6ba597c5SAnurag S. Maskey * addresses we wish to configure. In the future, it 218*6ba597c5SAnurag S. Maskey * would be good to try and minimize configuration 219*6ba597c5SAnurag S. Maskey * changes. 220*6ba597c5SAnurag S. Maskey */ 221*6ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET); 222*6ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET6); 223*6ba597c5SAnurag S. Maskey 224*6ba597c5SAnurag S. Maskey /* 225*6ba597c5SAnurag S. Maskey * Enqueue a WAITING_FOR_ADDR aux state change so that 226*6ba597c5SAnurag S. Maskey * we are eligible to receive the IF_STATE events 227*6ba597c5SAnurag S. Maskey * associated with static, DHCP, DHCPv6 and autoconf 228*6ba597c5SAnurag S. Maskey * address assignment. The latter two can happen 229*6ba597c5SAnurag S. Maskey * quite quickly after plumbing so we need to be ready. 230*6ba597c5SAnurag S. Maskey */ 231*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 232*6ba597c5SAnurag S. Maskey object_name, NWAM_STATE_OFFLINE_TO_ONLINE, 233*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_IF_WAITING_FOR_ADDR); 234*6ba597c5SAnurag S. Maskey 235*6ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv4) 236*6ba597c5SAnurag S. Maskey nwamd_plumb_interface(ncu, 0, AF_INET); 237*6ba597c5SAnurag S. Maskey 238*6ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv6) 239*6ba597c5SAnurag S. Maskey nwamd_plumb_interface(ncu, 0, AF_INET6); 240*6ba597c5SAnurag S. Maskey 241*6ba597c5SAnurag S. Maskey /* 242*6ba597c5SAnurag S. Maskey * Configure addresses. Configure any static addresses 243*6ba597c5SAnurag S. Maskey * and start DHCP if required. If DHCP is not required, 244*6ba597c5SAnurag S. Maskey * do a DHCPINFORM to get other networking config 245*6ba597c5SAnurag S. Maskey * parameters. RTM_NEWADDRs - translated into IF_STATE 246*6ba597c5SAnurag S. Maskey * events - will then finish the job of bringing us 247*6ba597c5SAnurag S. Maskey * online. 248*6ba597c5SAnurag S. Maskey */ 249*6ba597c5SAnurag S. Maskey nwamd_configure_interface_addresses(ncu); 250*6ba597c5SAnurag S. Maskey 251*6ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_dhcp_requested) 252*6ba597c5SAnurag S. Maskey nwamd_start_dhcp(ncu); 253*6ba597c5SAnurag S. Maskey else 254*6ba597c5SAnurag S. Maskey nwamd_dhcp_inform(ncu); 255*6ba597c5SAnurag S. Maskey } 256*6ba597c5SAnurag S. Maskey break; 257*6ba597c5SAnurag S. Maskey 258*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_IF_DHCP_TIMED_OUT: 259*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_IF_WAITING_FOR_ADDR: 260*6ba597c5SAnurag S. Maskey /* 261*6ba597c5SAnurag S. Maskey * nothing to do here - RTM_NEWADDRs will trigger IF_STATE 262*6ba597c5SAnurag S. Maskey * events to move us online. 263*6ba597c5SAnurag S. Maskey */ 264*6ba597c5SAnurag S. Maskey break; 265*6ba597c5SAnurag S. Maskey 266*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_SCANNING: 267*6ba597c5SAnurag S. Maskey /* launch scan thread */ 268*6ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname)); 269*6ba597c5SAnurag S. Maskey (void) nwamd_wlan_scan(linkname); 270*6ba597c5SAnurag S. Maskey /* Create periodic scan event */ 271*6ba597c5SAnurag S. Maskey nwamd_ncu_create_periodic_scan_event(object); 272*6ba597c5SAnurag S. Maskey break; 273*6ba597c5SAnurag S. Maskey 274*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION: 275*6ba597c5SAnurag S. Maskey /* send "need choice" event */ 276*6ba597c5SAnurag S. Maskey event = nwamd_event_init_wlan 277*6ba597c5SAnurag S. Maskey (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_CHOICE, B_FALSE, 278*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr, 279*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num); 280*6ba597c5SAnurag S. Maskey if (event == NULL) 281*6ba597c5SAnurag S. Maskey break; 282*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 283*6ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_FALSE, B_FALSE); 284*6ba597c5SAnurag S. Maskey break; 285*6ba597c5SAnurag S. Maskey 286*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_NEED_KEY: 287*6ba597c5SAnurag S. Maskey /* 288*6ba597c5SAnurag S. Maskey * Send "need key" event. Set selected to true, connected 289*6ba597c5SAnurag S. Maskey * and have_key to false. Do not fill in WLAN details as 290*6ba597c5SAnurag S. Maskey * multiple WLANs may match the ESSID name, and each may 291*6ba597c5SAnurag S. Maskey * have a different speed and channel. 292*6ba597c5SAnurag S. Maskey */ 293*6ba597c5SAnurag S. Maskey bzero(&key_wlan, sizeof (key_wlan)); 294*6ba597c5SAnurag S. Maskey (void) strlcpy(key_wlan.nww_essid, link->nwamd_link_wifi_essid, 295*6ba597c5SAnurag S. Maskey sizeof (key_wlan.nww_essid)); 296*6ba597c5SAnurag S. Maskey (void) strlcpy(key_wlan.nww_bssid, link->nwamd_link_wifi_bssid, 297*6ba597c5SAnurag S. Maskey sizeof (key_wlan.nww_bssid)); 298*6ba597c5SAnurag S. Maskey key_wlan.nww_security_mode = 299*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_security_mode; 300*6ba597c5SAnurag S. Maskey key_wlan.nww_selected = B_TRUE; 301*6ba597c5SAnurag S. Maskey key_wlan.nww_connected = B_FALSE; 302*6ba597c5SAnurag S. Maskey key_wlan.nww_have_key = B_FALSE; 303*6ba597c5SAnurag S. Maskey event = nwamd_event_init_wlan 304*6ba597c5SAnurag S. Maskey (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_KEY, B_FALSE, 305*6ba597c5SAnurag S. Maskey &key_wlan, 1); 306*6ba597c5SAnurag S. Maskey if (event == NULL) 307*6ba597c5SAnurag S. Maskey break; 308*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 309*6ba597c5SAnurag S. Maskey break; 310*6ba597c5SAnurag S. Maskey 311*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_LINK_WIFI_CONNECTING: 312*6ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname)); 313*6ba597c5SAnurag S. Maskey nwamd_wlan_connect(linkname); 314*6ba597c5SAnurag S. Maskey break; 315*6ba597c5SAnurag S. Maskey 316*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_UP: 317*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_DOWN: 318*6ba597c5SAnurag S. Maskey up = (object->nwamd_object_aux_state == NWAM_AUX_STATE_UP); 319*6ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 320*6ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 321*6ba597c5SAnurag S. Maskey /* 322*6ba597c5SAnurag S. Maskey * Connected/disconnected - send WLAN 323*6ba597c5SAnurag S. Maskey * connection report. 324*6ba597c5SAnurag S. Maskey */ 325*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = up; 326*6ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_TRUE, up); 327*6ba597c5SAnurag S. Maskey 328*6ba597c5SAnurag S. Maskey (void) strlcpy(connected_wlan.nww_essid, 329*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_essid, 330*6ba597c5SAnurag S. Maskey sizeof (connected_wlan.nww_essid)); 331*6ba597c5SAnurag S. Maskey (void) strlcpy(connected_wlan.nww_bssid, 332*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_bssid, 333*6ba597c5SAnurag S. Maskey sizeof (connected_wlan.nww_bssid)); 334*6ba597c5SAnurag S. Maskey connected_wlan.nww_security_mode = 335*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_security_mode; 336*6ba597c5SAnurag S. Maskey event = nwamd_event_init_wlan 337*6ba597c5SAnurag S. Maskey (ncu->ncu_name, 338*6ba597c5SAnurag S. Maskey NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT, up, 339*6ba597c5SAnurag S. Maskey &connected_wlan, 1); 340*6ba597c5SAnurag S. Maskey if (event == NULL) 341*6ba597c5SAnurag S. Maskey break; 342*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(event); 343*6ba597c5SAnurag S. Maskey 344*6ba597c5SAnurag S. Maskey /* 345*6ba597c5SAnurag S. Maskey * If disconnected, restart the state machine 346*6ba597c5SAnurag S. Maskey * for the WiFi link (WiFi is always trying 347*6ba597c5SAnurag S. Maskey * to connect). 348*6ba597c5SAnurag S. Maskey * 349*6ba597c5SAnurag S. Maskey * If connected, start signal strength 350*6ba597c5SAnurag S. Maskey * monitoring thread. 351*6ba597c5SAnurag S. Maskey */ 352*6ba597c5SAnurag S. Maskey if (!up && ncu->ncu_enabled) { 353*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 354*6ba597c5SAnurag S. Maskey "nwamd_ncu_state_machine: " 355*6ba597c5SAnurag S. Maskey "wifi disconnect - start over " 356*6ba597c5SAnurag S. Maskey "after %dsec interval", 357*6ba597c5SAnurag S. Maskey WIRELESS_RETRY_INTERVAL); 358*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = 359*6ba597c5SAnurag S. Maskey B_FALSE; 360*6ba597c5SAnurag S. Maskey /* propogate down event to IP NCU */ 361*6ba597c5SAnurag S. Maskey nwamd_propogate_link_up_down_to_ip 362*6ba597c5SAnurag S. Maskey (ncu->ncu_name, B_FALSE); 363*6ba597c5SAnurag S. Maskey nwamd_object_set_state_timed 364*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, object_name, 365*6ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 366*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED, 367*6ba597c5SAnurag S. Maskey WIRELESS_RETRY_INTERVAL); 368*6ba597c5SAnurag S. Maskey } else { 369*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 370*6ba597c5SAnurag S. Maskey "nwamd_ncu_state_machine: " 371*6ba597c5SAnurag S. Maskey "wifi connected, start monitoring"); 372*6ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, 373*6ba597c5SAnurag S. Maskey sizeof (linkname)); 374*6ba597c5SAnurag S. Maskey nwamd_wlan_monitor_signal(linkname); 375*6ba597c5SAnurag S. Maskey } 376*6ba597c5SAnurag S. Maskey } 377*6ba597c5SAnurag S. Maskey } 378*6ba597c5SAnurag S. Maskey 379*6ba597c5SAnurag S. Maskey /* If not in ONLINE/OFFLINE state yet, change state */ 380*6ba597c5SAnurag S. Maskey if ((up && object->nwamd_object_state != NWAM_STATE_ONLINE) || 381*6ba597c5SAnurag S. Maskey (!up && object->nwamd_object_state != NWAM_STATE_OFFLINE)) { 382*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_state_machine: " 383*6ba597c5SAnurag S. Maskey "%s is moving %s", object_name, 384*6ba597c5SAnurag S. Maskey up ? "online" : "offline"); 385*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 386*6ba597c5SAnurag S. Maskey object_name, 387*6ba597c5SAnurag S. Maskey up ? NWAM_STATE_ONLINE : NWAM_STATE_OFFLINE, 388*6ba597c5SAnurag S. Maskey up ? NWAM_AUX_STATE_UP : NWAM_AUX_STATE_DOWN); 389*6ba597c5SAnurag S. Maskey 390*6ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) { 391*6ba597c5SAnurag S. Maskey if (up) { 392*6ba597c5SAnurag S. Maskey /* 393*6ba597c5SAnurag S. Maskey * Moving online, add v4/v6 default 394*6ba597c5SAnurag S. Maskey * routes (if any). 395*6ba597c5SAnurag S. Maskey */ 396*6ba597c5SAnurag S. Maskey nwamd_add_default_routes(ncu); 397*6ba597c5SAnurag S. Maskey } else { 398*6ba597c5SAnurag S. Maskey /* 399*6ba597c5SAnurag S. Maskey * If this is an interface NCU and we 400*6ba597c5SAnurag S. Maskey * got a down event, it is a consequence 401*6ba597c5SAnurag S. Maskey * of NCU refresh, so reapply addresses 402*6ba597c5SAnurag S. Maskey * by reinitializing. 403*6ba597c5SAnurag S. Maskey */ 404*6ba597c5SAnurag S. Maskey nwamd_object_set_state 405*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, object_name, 406*6ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 407*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 408*6ba597c5SAnurag S. Maskey } 409*6ba597c5SAnurag S. Maskey } 410*6ba597c5SAnurag S. Maskey } else { 411*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_state_machine: " 412*6ba597c5SAnurag S. Maskey "%s is %s", object_name, 413*6ba597c5SAnurag S. Maskey up ? "online" : "offline"); 414*6ba597c5SAnurag S. Maskey } 415*6ba597c5SAnurag S. Maskey /* 416*6ba597c5SAnurag S. Maskey * NCU is UP or DOWN, trigger all condition checking, even if 417*6ba597c5SAnurag S. Maskey * the NCU is already in the ONLINE state - an ENM may depend 418*6ba597c5SAnurag S. Maskey * on NCU activity. 419*6ba597c5SAnurag S. Maskey */ 420*6ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(NEXT_FEW_SECONDS); 421*6ba597c5SAnurag S. Maskey break; 422*6ba597c5SAnurag S. Maskey 423*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_CONDITIONS_NOT_MET: 424*6ba597c5SAnurag S. Maskey /* 425*6ba597c5SAnurag S. Maskey * Link/interface is moving offline. Nothing to do except 426*6ba597c5SAnurag S. Maskey * for WiFi, where we disconnect. Don't unplumb IP on 427*6ba597c5SAnurag S. Maskey * a link since it may be a transient change. 428*6ba597c5SAnurag S. Maskey */ 429*6ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 430*6ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 431*6ba597c5SAnurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, 432*6ba597c5SAnurag S. Maskey link->nwamd_link_id); 433*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = B_FALSE; 434*6ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_FALSE, 435*6ba597c5SAnurag S. Maskey B_FALSE); 436*6ba597c5SAnurag S. Maskey } 437*6ba597c5SAnurag S. Maskey } else { 438*6ba597c5SAnurag S. Maskey /* 439*6ba597c5SAnurag S. Maskey * Unplumb here. In the future we may elaborate on 440*6ba597c5SAnurag S. Maskey * the approach used and not unplumb for WiFi 441*6ba597c5SAnurag S. Maskey * until we reconnect to a different WLAN (i.e. with 442*6ba597c5SAnurag S. Maskey * a different ESSID). 443*6ba597c5SAnurag S. Maskey */ 444*6ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET); 445*6ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET6); 446*6ba597c5SAnurag S. Maskey } 447*6ba597c5SAnurag S. Maskey if (object->nwamd_object_state != NWAM_STATE_OFFLINE) { 448*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 449*6ba597c5SAnurag S. Maskey object_name, NWAM_STATE_OFFLINE, 450*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET); 451*6ba597c5SAnurag S. Maskey } 452*6ba597c5SAnurag S. Maskey break; 453*6ba597c5SAnurag S. Maskey 454*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_MANUAL_DISABLE: 455*6ba597c5SAnurag S. Maskey /* Manual disable, set enabled state appropriately. */ 456*6ba597c5SAnurag S. Maskey ncu->ncu_enabled = B_FALSE; 457*6ba597c5SAnurag S. Maskey /* FALLTHROUGH */ 458*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_UNINITIALIZED: 459*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_NOT_FOUND: 460*6ba597c5SAnurag S. Maskey /* 461*6ba597c5SAnurag S. Maskey * Link/interface NCU has been disabled/deactivated/removed. 462*6ba597c5SAnurag S. Maskey * For WiFi links disconnect, and for IP interfaces we unplumb. 463*6ba597c5SAnurag S. Maskey */ 464*6ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 465*6ba597c5SAnurag S. Maskey if (link->nwamd_link_media == DL_WIFI) { 466*6ba597c5SAnurag S. Maskey (void) dladm_wlan_disconnect(dld_handle, 467*6ba597c5SAnurag S. Maskey link->nwamd_link_id); 468*6ba597c5SAnurag S. Maskey link->nwamd_link_wifi_connected = B_FALSE; 469*6ba597c5SAnurag S. Maskey nwamd_set_selected_connected(ncu, B_FALSE, 470*6ba597c5SAnurag S. Maskey B_FALSE); 471*6ba597c5SAnurag S. Maskey } 472*6ba597c5SAnurag S. Maskey nwamd_dlpi_delete_link(object); 473*6ba597c5SAnurag S. Maskey } else { 474*6ba597c5SAnurag S. Maskey /* Unplumb here. */ 475*6ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv4) { 476*6ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET); 477*6ba597c5SAnurag S. Maskey } 478*6ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_if.nwamd_if_ipv6) { 479*6ba597c5SAnurag S. Maskey nwamd_unplumb_interface(ncu, 0, AF_INET6); 480*6ba597c5SAnurag S. Maskey } 481*6ba597c5SAnurag S. Maskey /* trigger location condition checking */ 482*6ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(0); 483*6ba597c5SAnurag S. Maskey } 484*6ba597c5SAnurag S. Maskey 485*6ba597c5SAnurag S. Maskey switch (object->nwamd_object_aux_state) { 486*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_MANUAL_DISABLE: 487*6ba597c5SAnurag S. Maskey /* Change state to DISABLED if manually disabled */ 488*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 489*6ba597c5SAnurag S. Maskey object_name, NWAM_STATE_DISABLED, 490*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 491*6ba597c5SAnurag S. Maskey /* Note that NCU has been disabled */ 492*6ba597c5SAnurag S. Maskey ncu->ncu_enabled = B_FALSE; 493*6ba597c5SAnurag S. Maskey break; 494*6ba597c5SAnurag S. Maskey case NWAM_AUX_STATE_NOT_FOUND: 495*6ba597c5SAnurag S. Maskey /* Change state to UNINITIALIZED for device removal */ 496*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 497*6ba597c5SAnurag S. Maskey object_name, NWAM_STATE_UNINITIALIZED, 498*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 499*6ba597c5SAnurag S. Maskey break; 500*6ba597c5SAnurag S. Maskey default: 501*6ba597c5SAnurag S. Maskey break; 502*6ba597c5SAnurag S. Maskey } 503*6ba597c5SAnurag S. Maskey break; 504*6ba597c5SAnurag S. Maskey default: 505*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_state_machine: unexpected state"); 506*6ba597c5SAnurag S. Maskey break; 507*6ba597c5SAnurag S. Maskey } 508*6ba597c5SAnurag S. Maskey 509*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 510*6ba597c5SAnurag S. Maskey } 511*6ba597c5SAnurag S. Maskey 512*6ba597c5SAnurag S. Maskey static int 513*6ba597c5SAnurag S. Maskey ncu_create_init_fini_event(nwam_ncu_handle_t ncuh, void *data) 514*6ba597c5SAnurag S. Maskey { 515*6ba597c5SAnurag S. Maskey boolean_t *init = data; 516*6ba597c5SAnurag S. Maskey char *name, *typedname; 517*6ba597c5SAnurag S. Maskey nwam_error_t err; 518*6ba597c5SAnurag S. Maskey nwam_value_t typeval = NULL; 519*6ba597c5SAnurag S. Maskey uint64_t *type; 520*6ba597c5SAnurag S. Maskey uint_t numvalues; 521*6ba597c5SAnurag S. Maskey nwamd_event_t ncu_event; 522*6ba597c5SAnurag S. Maskey 523*6ba597c5SAnurag S. Maskey if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) { 524*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, 525*6ba597c5SAnurag S. Maskey "ncu_create_init_fini_event: could not get NCU name"); 526*6ba597c5SAnurag S. Maskey return (0); 527*6ba597c5SAnurag S. Maskey } 528*6ba597c5SAnurag S. Maskey 529*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "ncu_create_init_fini_event(%s, %p)", name, data); 530*6ba597c5SAnurag S. Maskey 531*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &typeval, &type, &numvalues, 532*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_TYPE)) != NWAM_SUCCESS) { 533*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "ncu_create_init_fini_event: " 534*6ba597c5SAnurag S. Maskey "could not get NCU type: %s", nwam_strerror(err)); 535*6ba597c5SAnurag S. Maskey free(name); 536*6ba597c5SAnurag S. Maskey nwam_value_free(typeval); 537*6ba597c5SAnurag S. Maskey return (0); 538*6ba597c5SAnurag S. Maskey } 539*6ba597c5SAnurag S. Maskey 540*6ba597c5SAnurag S. Maskey /* convert name to typedname for event */ 541*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_name_to_typed_name(name, *type, &typedname)) 542*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 543*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "ncu_create_init_fini_event: " 544*6ba597c5SAnurag S. Maskey "NCU name translation failed: %s", nwam_strerror(err)); 545*6ba597c5SAnurag S. Maskey free(name); 546*6ba597c5SAnurag S. Maskey return (0); 547*6ba597c5SAnurag S. Maskey } 548*6ba597c5SAnurag S. Maskey free(name); 549*6ba597c5SAnurag S. Maskey nwam_value_free(typeval); 550*6ba597c5SAnurag S. Maskey 551*6ba597c5SAnurag S. Maskey ncu_event = nwamd_event_init(*init ? 552*6ba597c5SAnurag S. Maskey NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI, 553*6ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_NCU, 0, typedname); 554*6ba597c5SAnurag S. Maskey if (ncu_event != NULL) 555*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(ncu_event); 556*6ba597c5SAnurag S. Maskey free(typedname); 557*6ba597c5SAnurag S. Maskey 558*6ba597c5SAnurag S. Maskey return (0); 559*6ba597c5SAnurag S. Maskey } 560*6ba597c5SAnurag S. Maskey 561*6ba597c5SAnurag S. Maskey /* 562*6ba597c5SAnurag S. Maskey * Initialization - walk the NCUs, creating initialization events for each 563*6ba597c5SAnurag S. Maskey * NCU. nwamd_ncu_handle_init_event() will check if the associated 564*6ba597c5SAnurag S. Maskey * physical link exists or not. 565*6ba597c5SAnurag S. Maskey */ 566*6ba597c5SAnurag S. Maskey void 567*6ba597c5SAnurag S. Maskey nwamd_init_ncus(void) 568*6ba597c5SAnurag S. Maskey { 569*6ba597c5SAnurag S. Maskey boolean_t init = B_TRUE; 570*6ba597c5SAnurag S. Maskey 571*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 572*6ba597c5SAnurag S. Maskey if (active_ncph != NULL) { 573*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_init_ncus: " 574*6ba597c5SAnurag S. Maskey "(re)intializing NCUs for NCP %s", active_ncp); 575*6ba597c5SAnurag S. Maskey (void) nwam_ncp_walk_ncus(active_ncph, 576*6ba597c5SAnurag S. Maskey ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL, 577*6ba597c5SAnurag S. Maskey NULL); 578*6ba597c5SAnurag S. Maskey } 579*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 580*6ba597c5SAnurag S. Maskey } 581*6ba597c5SAnurag S. Maskey 582*6ba597c5SAnurag S. Maskey void 583*6ba597c5SAnurag S. Maskey nwamd_fini_ncus(void) 584*6ba597c5SAnurag S. Maskey { 585*6ba597c5SAnurag S. Maskey boolean_t init = B_FALSE; 586*6ba597c5SAnurag S. Maskey 587*6ba597c5SAnurag S. Maskey /* We may not have an active NCP on initialization, so skip fini */ 588*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 589*6ba597c5SAnurag S. Maskey if (active_ncph != NULL) { 590*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_fini_ncus: deinitializing NCUs for %s", 591*6ba597c5SAnurag S. Maskey active_ncp); 592*6ba597c5SAnurag S. Maskey (void) nwam_ncp_walk_ncus(active_ncph, 593*6ba597c5SAnurag S. Maskey ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL, 594*6ba597c5SAnurag S. Maskey NULL); 595*6ba597c5SAnurag S. Maskey } 596*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 597*6ba597c5SAnurag S. Maskey } 598*6ba597c5SAnurag S. Maskey 599*6ba597c5SAnurag S. Maskey /* 600*6ba597c5SAnurag S. Maskey * Most properties of this type don't need to be cached locally. Only those 601*6ba597c5SAnurag S. Maskey * interesting to the daemon are stored in an nwamd_ncu_t. 602*6ba597c5SAnurag S. Maskey */ 603*6ba597c5SAnurag S. Maskey static void 604*6ba597c5SAnurag S. Maskey populate_common_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) 605*6ba597c5SAnurag S. Maskey { 606*6ba597c5SAnurag S. Maskey nwam_value_t ncu_prop; 607*6ba597c5SAnurag S. Maskey nwam_error_t err; 608*6ba597c5SAnurag S. Maskey boolean_t enablevalue; 609*6ba597c5SAnurag S. Maskey uint_t numvalues; 610*6ba597c5SAnurag S. Maskey char **parent; 611*6ba597c5SAnurag S. Maskey 612*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED, 613*6ba597c5SAnurag S. Maskey &ncu_prop)) != NWAM_SUCCESS) { 614*6ba597c5SAnurag S. Maskey char *name; 615*6ba597c5SAnurag S. Maskey (void) nwam_ncu_name_to_typed_name(ncu_data->ncu_name, 616*6ba597c5SAnurag S. Maskey ncu_data->ncu_type, &name); 617*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwam_ncu_get_prop_value %s ENABLED failed: %s", 618*6ba597c5SAnurag S. Maskey name, nwam_strerror(err)); 619*6ba597c5SAnurag S. Maskey free(name); 620*6ba597c5SAnurag S. Maskey ncu_data->ncu_enabled = B_TRUE; 621*6ba597c5SAnurag S. Maskey } else { 622*6ba597c5SAnurag S. Maskey if ((err = nwam_value_get_boolean(ncu_prop, &enablevalue)) != 623*6ba597c5SAnurag S. Maskey NWAM_SUCCESS) { 624*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwam_value_get_boolean ENABLED failed: " 625*6ba597c5SAnurag S. Maskey "%s", nwam_strerror(err)); 626*6ba597c5SAnurag S. Maskey } else { 627*6ba597c5SAnurag S. Maskey ncu_data->ncu_enabled = enablevalue; 628*6ba597c5SAnurag S. Maskey } 629*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 630*6ba597c5SAnurag S. Maskey } 631*6ba597c5SAnurag S. Maskey 632*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &parent, 633*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_PARENT_NCP)) != NWAM_SUCCESS) { 634*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwam_ncu_get_prop_value %s PARENT failed: %s", 635*6ba597c5SAnurag S. Maskey ncu_data->ncu_name, nwam_strerror(err)); 636*6ba597c5SAnurag S. Maskey } else { 637*6ba597c5SAnurag S. Maskey (void) strlcpy(ncu_data->ncu_parent, parent[0], 638*6ba597c5SAnurag S. Maskey sizeof (ncu_data->ncu_parent)); 639*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 640*6ba597c5SAnurag S. Maskey } 641*6ba597c5SAnurag S. Maskey } 642*6ba597c5SAnurag S. Maskey 643*6ba597c5SAnurag S. Maskey /* 644*6ba597c5SAnurag S. Maskey * Read in link properties. 645*6ba597c5SAnurag S. Maskey */ 646*6ba597c5SAnurag S. Maskey static void 647*6ba597c5SAnurag S. Maskey populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) 648*6ba597c5SAnurag S. Maskey { 649*6ba597c5SAnurag S. Maskey nwam_value_t ncu_prop; 650*6ba597c5SAnurag S. Maskey nwam_error_t err; 651*6ba597c5SAnurag S. Maskey char **mac_addr; 652*6ba597c5SAnurag S. Maskey uint64_t *uintval; 653*6ba597c5SAnurag S. Maskey uint_t numvalues; 654*6ba597c5SAnurag S. Maskey 655*6ba597c5SAnurag S. Maskey /* activation-mode */ 656*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues, 657*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) { 658*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, 659*6ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 660*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_ACTIVATION_MODE, nwam_strerror(err)); 661*6ba597c5SAnurag S. Maskey } else { 662*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_activation_mode = 663*6ba597c5SAnurag S. Maskey uintval[0]; 664*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 665*6ba597c5SAnurag S. Maskey } 666*6ba597c5SAnurag S. Maskey 667*6ba597c5SAnurag S. Maskey /* priority-group and priority-mode for prioritized activation */ 668*6ba597c5SAnurag S. Maskey if (ncu_data->ncu_node.u_link.nwamd_link_activation_mode == 669*6ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED) { 670*6ba597c5SAnurag S. Maskey /* ncus with prioritized activation are always enabled */ 671*6ba597c5SAnurag S. Maskey ncu_data->ncu_enabled = B_TRUE; 672*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, 673*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_PRIORITY_MODE)) 674*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 675*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_link_ncu_properties: " 676*6ba597c5SAnurag S. Maskey "could not get %s value: %s", 677*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_MODE, nwam_strerror(err)); 678*6ba597c5SAnurag S. Maskey } else { 679*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_priority_mode = 680*6ba597c5SAnurag S. Maskey uintval[0]; 681*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 682*6ba597c5SAnurag S. Maskey } 683*6ba597c5SAnurag S. Maskey 684*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, 685*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_PRIORITY_GROUP)) 686*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 687*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_link_ncu_properties: " 688*6ba597c5SAnurag S. Maskey "could not get %s value: %s", 689*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_GROUP, nwam_strerror(err)); 690*6ba597c5SAnurag S. Maskey } else { 691*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_priority_group = 692*6ba597c5SAnurag S. Maskey uintval[0]; 693*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 694*6ba597c5SAnurag S. Maskey } 695*6ba597c5SAnurag S. Maskey } 696*6ba597c5SAnurag S. Maskey 697*6ba597c5SAnurag S. Maskey /* link-mac-addr */ 698*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &mac_addr, &numvalues, 699*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MAC_ADDR)) != NWAM_SUCCESS) { 700*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 701*6ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 702*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MAC_ADDR, nwam_strerror(err)); 703*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mac_addr = NULL; 704*6ba597c5SAnurag S. Maskey } else { 705*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mac_addr = 706*6ba597c5SAnurag S. Maskey strdup(*mac_addr); 707*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mac_addr_len = 708*6ba597c5SAnurag S. Maskey strlen(*mac_addr); 709*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 710*6ba597c5SAnurag S. Maskey } 711*6ba597c5SAnurag S. Maskey 712*6ba597c5SAnurag S. Maskey /* link-mtu */ 713*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues, 714*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MTU)) != NWAM_SUCCESS) { 715*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 716*6ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 717*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_MTU, nwam_strerror(err)); 718*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mtu = 0; 719*6ba597c5SAnurag S. Maskey } else { 720*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_mtu = uintval[0]; 721*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 722*6ba597c5SAnurag S. Maskey } 723*6ba597c5SAnurag S. Maskey 724*6ba597c5SAnurag S. Maskey /* link-autopush */ 725*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, 726*6ba597c5SAnurag S. Maskey &ncu_data->ncu_node.u_link.nwamd_link_autopush, 727*6ba597c5SAnurag S. Maskey &ncu_data->ncu_node.u_link.nwamd_link_num_autopush, 728*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_AUTOPUSH)) != NWAM_SUCCESS) { 729*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 730*6ba597c5SAnurag S. Maskey "populate_link_ncu_properties: could not get %s value: %s", 731*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_LINK_AUTOPUSH, nwam_strerror(err)); 732*6ba597c5SAnurag S. Maskey ncu_data->ncu_node.u_link.nwamd_link_num_autopush = 0; 733*6ba597c5SAnurag S. Maskey } 734*6ba597c5SAnurag S. Maskey } 735*6ba597c5SAnurag S. Maskey 736*6ba597c5SAnurag S. Maskey static void 737*6ba597c5SAnurag S. Maskey populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) 738*6ba597c5SAnurag S. Maskey { 739*6ba597c5SAnurag S. Maskey nwamd_if_t *nif = &ncu_data->ncu_node.u_if; 740*6ba597c5SAnurag S. Maskey struct nwamd_if_address **nifa, *nifai, *nifait; 741*6ba597c5SAnurag S. Maskey char *prefix; 742*6ba597c5SAnurag S. Maskey boolean_t static_addr = B_FALSE; 743*6ba597c5SAnurag S. Maskey uint64_t *addrsrcvalue; 744*6ba597c5SAnurag S. Maskey nwam_value_t ncu_prop; 745*6ba597c5SAnurag S. Maskey nwam_error_t err; 746*6ba597c5SAnurag S. Maskey char **addrvalue; 747*6ba597c5SAnurag S. Maskey uint_t numvalues; 748*6ba597c5SAnurag S. Maskey uint64_t *ipversion; 749*6ba597c5SAnurag S. Maskey int i; 750*6ba597c5SAnurag S. Maskey 751*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4 = B_FALSE; 752*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6 = B_FALSE; 753*6ba597c5SAnurag S. Maskey nif->nwamd_if_dhcp_requested = B_FALSE; 754*6ba597c5SAnurag S. Maskey nif->nwamd_if_stateful_requested = B_FALSE; 755*6ba597c5SAnurag S. Maskey nif->nwamd_if_stateless_requested = B_FALSE; 756*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4_default_route_set = B_FALSE; 757*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6_default_route_set = B_FALSE; 758*6ba597c5SAnurag S. Maskey 759*6ba597c5SAnurag S. Maskey /* ip-version */ 760*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &ipversion, &numvalues, 761*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IP_VERSION)) != NWAM_SUCCESS) { 762*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, 763*6ba597c5SAnurag S. Maskey "populate_ip_ncu_properties: could not get %s value: %s", 764*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IP_VERSION, nwam_strerror(err)); 765*6ba597c5SAnurag S. Maskey } else { 766*6ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 767*6ba597c5SAnurag S. Maskey switch (ipversion[i]) { 768*6ba597c5SAnurag S. Maskey case IPV4_VERSION: 769*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4 = B_TRUE; 770*6ba597c5SAnurag S. Maskey break; 771*6ba597c5SAnurag S. Maskey case IPV6_VERSION: 772*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6 = B_TRUE; 773*6ba597c5SAnurag S. Maskey break; 774*6ba597c5SAnurag S. Maskey default: 775*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "bogus ip version %lld", 776*6ba597c5SAnurag S. Maskey ipversion[i]); 777*6ba597c5SAnurag S. Maskey break; 778*6ba597c5SAnurag S. Maskey } 779*6ba597c5SAnurag S. Maskey } 780*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 781*6ba597c5SAnurag S. Maskey } 782*6ba597c5SAnurag S. Maskey 783*6ba597c5SAnurag S. Maskey /* Free the old list. */ 784*6ba597c5SAnurag S. Maskey for (nifai = nif->nwamd_if_list; nifai != NULL; nifai = nifait) { 785*6ba597c5SAnurag S. Maskey nifait = nifai->next; 786*6ba597c5SAnurag S. Maskey nifai->next = NULL; 787*6ba597c5SAnurag S. Maskey free(nifai); 788*6ba597c5SAnurag S. Maskey } 789*6ba597c5SAnurag S. Maskey nif->nwamd_if_list = NULL; 790*6ba597c5SAnurag S. Maskey nifa = &(nif->nwamd_if_list); 791*6ba597c5SAnurag S. Maskey 792*6ba597c5SAnurag S. Maskey if (!nif->nwamd_if_ipv4) 793*6ba597c5SAnurag S. Maskey goto skip_ipv4; 794*6ba597c5SAnurag S. Maskey 795*6ba597c5SAnurag S. Maskey /* ipv4-addrsrc */ 796*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue, 797*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV4_ADDRSRC)) != NWAM_SUCCESS) { 798*6ba597c5SAnurag S. Maskey nlog(nif->nwamd_if_ipv4 ? LOG_ERR : LOG_DEBUG, 799*6ba597c5SAnurag S. Maskey "populate_ip_ncu_properties: could not get %s value: %s", 800*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV4_ADDRSRC, nwam_strerror(err)); 801*6ba597c5SAnurag S. Maskey } else { 802*6ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 803*6ba597c5SAnurag S. Maskey switch (addrsrcvalue[i]) { 804*6ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_DHCP: 805*6ba597c5SAnurag S. Maskey nif->nwamd_if_dhcp_requested = B_TRUE; 806*6ba597c5SAnurag S. Maskey break; 807*6ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_STATIC: 808*6ba597c5SAnurag S. Maskey static_addr = B_TRUE; 809*6ba597c5SAnurag S. Maskey break; 810*6ba597c5SAnurag S. Maskey default: 811*6ba597c5SAnurag S. Maskey break; 812*6ba597c5SAnurag S. Maskey } 813*6ba597c5SAnurag S. Maskey } 814*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 815*6ba597c5SAnurag S. Maskey } 816*6ba597c5SAnurag S. Maskey if (nif->nwamd_if_dhcp_requested) { 817*6ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { 818*6ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET; 819*6ba597c5SAnurag S. Maskey (*nifa)->dhcp_if = B_TRUE; 820*6ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 821*6ba597c5SAnurag S. Maskey *nifa = NULL; 822*6ba597c5SAnurag S. Maskey } 823*6ba597c5SAnurag S. Maskey } 824*6ba597c5SAnurag S. Maskey 825*6ba597c5SAnurag S. Maskey /* ipv4-addr */ 826*6ba597c5SAnurag S. Maskey if (static_addr) { 827*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 828*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV4_ADDR)) != NWAM_SUCCESS) { 829*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_ip_ncu_properties: " 830*6ba597c5SAnurag S. Maskey "could not get %s value; %s", 831*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV4_ADDR, nwam_strerror(err)); 832*6ba597c5SAnurag S. Maskey } else { 833*6ba597c5SAnurag S. Maskey struct sockaddr_in *s; 834*6ba597c5SAnurag S. Maskey 835*6ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 836*6ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) 837*6ba597c5SAnurag S. Maskey == NULL) { 838*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "couldn't allocate nwamd" 839*6ba597c5SAnurag S. Maskey "address"); 840*6ba597c5SAnurag S. Maskey continue; 841*6ba597c5SAnurag S. Maskey } 842*6ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET; 843*6ba597c5SAnurag S. Maskey /*LINTED*/ 844*6ba597c5SAnurag S. Maskey s = (struct sockaddr_in *)&(*nifa)->address; 845*6ba597c5SAnurag S. Maskey s->sin_family = AF_INET; 846*6ba597c5SAnurag S. Maskey s->sin_port = 0; 847*6ba597c5SAnurag S. Maskey prefix = strchr(addrvalue[i], '/'); 848*6ba597c5SAnurag S. Maskey if (prefix != NULL) { 849*6ba597c5SAnurag S. Maskey *prefix++ = 0; 850*6ba597c5SAnurag S. Maskey (*nifa)->prefix = atoi(prefix); 851*6ba597c5SAnurag S. Maskey } 852*6ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET, addrvalue[i], 853*6ba597c5SAnurag S. Maskey &(s->sin_addr)); 854*6ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 855*6ba597c5SAnurag S. Maskey } 856*6ba597c5SAnurag S. Maskey *nifa = NULL; 857*6ba597c5SAnurag S. Maskey 858*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 859*6ba597c5SAnurag S. Maskey } 860*6ba597c5SAnurag S. Maskey } 861*6ba597c5SAnurag S. Maskey 862*6ba597c5SAnurag S. Maskey /* get default route, if any */ 863*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 864*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE)) == NWAM_SUCCESS) { 865*6ba597c5SAnurag S. Maskey /* Only one default route is allowed. */ 866*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4_default_route.sin_family = AF_INET; 867*6ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET, addrvalue[0], 868*6ba597c5SAnurag S. Maskey &(nif->nwamd_if_ipv4_default_route.sin_addr)); 869*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv4_default_route_set = B_TRUE; 870*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 871*6ba597c5SAnurag S. Maskey } 872*6ba597c5SAnurag S. Maskey 873*6ba597c5SAnurag S. Maskey skip_ipv4: 874*6ba597c5SAnurag S. Maskey 875*6ba597c5SAnurag S. Maskey if (!nif->nwamd_if_ipv6) 876*6ba597c5SAnurag S. Maskey goto skip_ipv6; 877*6ba597c5SAnurag S. Maskey 878*6ba597c5SAnurag S. Maskey /* ipv6-addrsrc */ 879*6ba597c5SAnurag S. Maskey static_addr = B_FALSE; 880*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue, 881*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV6_ADDRSRC)) != NWAM_SUCCESS) { 882*6ba597c5SAnurag S. Maskey nlog(nif->nwamd_if_ipv6 ? LOG_ERR : LOG_DEBUG, 883*6ba597c5SAnurag S. Maskey "populate_ip_ncu_properties: could not get %s value: %s", 884*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV6_ADDRSRC, nwam_strerror(err)); 885*6ba597c5SAnurag S. Maskey } else { 886*6ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 887*6ba597c5SAnurag S. Maskey switch (addrsrcvalue[i]) { 888*6ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_DHCP: 889*6ba597c5SAnurag S. Maskey nif->nwamd_if_stateful_requested = B_TRUE; 890*6ba597c5SAnurag S. Maskey break; 891*6ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_AUTOCONF: 892*6ba597c5SAnurag S. Maskey nif->nwamd_if_stateless_requested = B_TRUE; 893*6ba597c5SAnurag S. Maskey break; 894*6ba597c5SAnurag S. Maskey case NWAM_ADDRSRC_STATIC: 895*6ba597c5SAnurag S. Maskey static_addr = B_TRUE; 896*6ba597c5SAnurag S. Maskey break; 897*6ba597c5SAnurag S. Maskey default: 898*6ba597c5SAnurag S. Maskey break; 899*6ba597c5SAnurag S. Maskey } 900*6ba597c5SAnurag S. Maskey } 901*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 902*6ba597c5SAnurag S. Maskey } 903*6ba597c5SAnurag S. Maskey if (nif->nwamd_if_stateful_requested) { 904*6ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { 905*6ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET6; 906*6ba597c5SAnurag S. Maskey (*nifa)->dhcp_if = B_TRUE; 907*6ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 908*6ba597c5SAnurag S. Maskey *nifa = NULL; 909*6ba597c5SAnurag S. Maskey } 910*6ba597c5SAnurag S. Maskey } 911*6ba597c5SAnurag S. Maskey if (nif->nwamd_if_stateless_requested) { 912*6ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { 913*6ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET6; 914*6ba597c5SAnurag S. Maskey (*nifa)->stateless_if = B_TRUE; 915*6ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 916*6ba597c5SAnurag S. Maskey *nifa = NULL; 917*6ba597c5SAnurag S. Maskey } 918*6ba597c5SAnurag S. Maskey } 919*6ba597c5SAnurag S. Maskey 920*6ba597c5SAnurag S. Maskey /* ipv6-addr */ 921*6ba597c5SAnurag S. Maskey if (static_addr) { 922*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 923*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV6_ADDR)) != NWAM_SUCCESS) { 924*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "populate_ip_ncu_properties: " 925*6ba597c5SAnurag S. Maskey "could not get %s value; %s", 926*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_IPV6_ADDR, nwam_strerror(err)); 927*6ba597c5SAnurag S. Maskey } else { 928*6ba597c5SAnurag S. Maskey struct sockaddr_in6 *s; 929*6ba597c5SAnurag S. Maskey 930*6ba597c5SAnurag S. Maskey for (i = 0; i < numvalues; i++) { 931*6ba597c5SAnurag S. Maskey if ((*nifa = calloc(sizeof (**nifa), 1)) 932*6ba597c5SAnurag S. Maskey == NULL) { 933*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "couldn't allocate nwamd" 934*6ba597c5SAnurag S. Maskey "address"); 935*6ba597c5SAnurag S. Maskey continue; 936*6ba597c5SAnurag S. Maskey } 937*6ba597c5SAnurag S. Maskey (*nifa)->address.sa_family = AF_INET6; 938*6ba597c5SAnurag S. Maskey /*LINTED*/ 939*6ba597c5SAnurag S. Maskey s = (struct sockaddr_in6 *)&(*nifa)->address; 940*6ba597c5SAnurag S. Maskey s->sin6_family = AF_INET6; 941*6ba597c5SAnurag S. Maskey s->sin6_port = 0; 942*6ba597c5SAnurag S. Maskey prefix = strchr(addrvalue[i], '/'); 943*6ba597c5SAnurag S. Maskey if (prefix != NULL) { 944*6ba597c5SAnurag S. Maskey *prefix++ = 0; 945*6ba597c5SAnurag S. Maskey (*nifa)->prefix = atoi(prefix); 946*6ba597c5SAnurag S. Maskey } 947*6ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET6, addrvalue[i], 948*6ba597c5SAnurag S. Maskey &(s->sin6_addr)); 949*6ba597c5SAnurag S. Maskey nifa = &((*nifa)->next); 950*6ba597c5SAnurag S. Maskey } 951*6ba597c5SAnurag S. Maskey *nifa = NULL; 952*6ba597c5SAnurag S. Maskey 953*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 954*6ba597c5SAnurag S. Maskey } 955*6ba597c5SAnurag S. Maskey } 956*6ba597c5SAnurag S. Maskey 957*6ba597c5SAnurag S. Maskey /* get default route, if any */ 958*6ba597c5SAnurag S. Maskey if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, 959*6ba597c5SAnurag S. Maskey &numvalues, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE)) == NWAM_SUCCESS) { 960*6ba597c5SAnurag S. Maskey /* Only one default route is allowed. */ 961*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6_default_route.sin6_family = AF_INET6; 962*6ba597c5SAnurag S. Maskey (void) inet_pton(AF_INET6, addrvalue[0], 963*6ba597c5SAnurag S. Maskey &(nif->nwamd_if_ipv6_default_route.sin6_addr)); 964*6ba597c5SAnurag S. Maskey nif->nwamd_if_ipv6_default_route_set = B_TRUE; 965*6ba597c5SAnurag S. Maskey nwam_value_free(ncu_prop); 966*6ba597c5SAnurag S. Maskey } 967*6ba597c5SAnurag S. Maskey 968*6ba597c5SAnurag S. Maskey skip_ipv6: 969*6ba597c5SAnurag S. Maskey ; 970*6ba597c5SAnurag S. Maskey } 971*6ba597c5SAnurag S. Maskey 972*6ba597c5SAnurag S. Maskey static nwamd_ncu_t * 973*6ba597c5SAnurag S. Maskey nwamd_ncu_init(nwam_ncu_type_t ncu_type, const char *name) 974*6ba597c5SAnurag S. Maskey { 975*6ba597c5SAnurag S. Maskey nwamd_ncu_t *rv; 976*6ba597c5SAnurag S. Maskey 977*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_init(%d, %s)", ncu_type, name); 978*6ba597c5SAnurag S. Maskey 979*6ba597c5SAnurag S. Maskey if ((rv = calloc(1, sizeof (*rv))) == NULL) 980*6ba597c5SAnurag S. Maskey return (NULL); 981*6ba597c5SAnurag S. Maskey 982*6ba597c5SAnurag S. Maskey rv->ncu_type = ncu_type; 983*6ba597c5SAnurag S. Maskey rv->ncu_name = strdup(name); 984*6ba597c5SAnurag S. Maskey rv->ncu_enabled = B_FALSE; 985*6ba597c5SAnurag S. Maskey 986*6ba597c5SAnurag S. Maskey /* Initialize link/interface-specific data */ 987*6ba597c5SAnurag S. Maskey if (rv->ncu_type == NWAM_NCU_TYPE_LINK) { 988*6ba597c5SAnurag S. Maskey (void) bzero(&rv->ncu_node.u_link, sizeof (nwamd_link_t)); 989*6ba597c5SAnurag S. Maskey (void) dladm_name2info(dld_handle, name, 990*6ba597c5SAnurag S. Maskey &rv->ncu_node.u_link.nwamd_link_id, NULL, NULL, 991*6ba597c5SAnurag S. Maskey &rv->ncu_node.u_link.nwamd_link_media); 992*6ba597c5SAnurag S. Maskey (void) pthread_mutex_init( 993*6ba597c5SAnurag S. Maskey &rv->ncu_node.u_link.nwamd_link_wifi_mutex, NULL); 994*6ba597c5SAnurag S. Maskey rv->ncu_node.u_link.nwamd_link_wifi_priority = MAXINT; 995*6ba597c5SAnurag S. Maskey } else { 996*6ba597c5SAnurag S. Maskey (void) bzero(&rv->ncu_node.u_if, sizeof (nwamd_if_t)); 997*6ba597c5SAnurag S. Maskey } 998*6ba597c5SAnurag S. Maskey 999*6ba597c5SAnurag S. Maskey return (rv); 1000*6ba597c5SAnurag S. Maskey } 1001*6ba597c5SAnurag S. Maskey 1002*6ba597c5SAnurag S. Maskey void 1003*6ba597c5SAnurag S. Maskey nwamd_ncu_free(nwamd_ncu_t *ncu) 1004*6ba597c5SAnurag S. Maskey { 1005*6ba597c5SAnurag S. Maskey if (ncu != NULL) { 1006*6ba597c5SAnurag S. Maskey assert(ncu->ncu_type == NWAM_NCU_TYPE_LINK || 1007*6ba597c5SAnurag S. Maskey ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE); 1008*6ba597c5SAnurag S. Maskey if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { 1009*6ba597c5SAnurag S. Maskey struct nwamd_link *l = &ncu->ncu_node.u_link; 1010*6ba597c5SAnurag S. Maskey int i; 1011*6ba597c5SAnurag S. Maskey 1012*6ba597c5SAnurag S. Maskey free(l->nwamd_link_wifi_key); 1013*6ba597c5SAnurag S. Maskey free(l->nwamd_link_mac_addr); 1014*6ba597c5SAnurag S. Maskey for (i = 0; i < l->nwamd_link_num_autopush; i++) 1015*6ba597c5SAnurag S. Maskey free(l->nwamd_link_autopush[i]); 1016*6ba597c5SAnurag S. Maskey } else if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) { 1017*6ba597c5SAnurag S. Maskey struct nwamd_if_address *nifa; 1018*6ba597c5SAnurag S. Maskey 1019*6ba597c5SAnurag S. Maskey nifa = ncu->ncu_node.u_if.nwamd_if_list; 1020*6ba597c5SAnurag S. Maskey while (nifa != NULL) { 1021*6ba597c5SAnurag S. Maskey struct nwamd_if_address *n; 1022*6ba597c5SAnurag S. Maskey 1023*6ba597c5SAnurag S. Maskey n = nifa; 1024*6ba597c5SAnurag S. Maskey nifa = nifa->next; 1025*6ba597c5SAnurag S. Maskey free(n); 1026*6ba597c5SAnurag S. Maskey } 1027*6ba597c5SAnurag S. Maskey } 1028*6ba597c5SAnurag S. Maskey free(ncu->ncu_name); 1029*6ba597c5SAnurag S. Maskey free(ncu); 1030*6ba597c5SAnurag S. Maskey } 1031*6ba597c5SAnurag S. Maskey } 1032*6ba597c5SAnurag S. Maskey 1033*6ba597c5SAnurag S. Maskey static int 1034*6ba597c5SAnurag S. Maskey nwamd_ncu_display(nwamd_object_t ncu_obj, void *data) 1035*6ba597c5SAnurag S. Maskey { 1036*6ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu = (nwamd_ncu_t *)ncu_obj->nwamd_object_data; 1037*6ba597c5SAnurag S. Maskey data = data; 1038*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "NCU (%p) %s state %s, %s", 1039*6ba597c5SAnurag S. Maskey (void *)ncu, ncu_obj->nwamd_object_name, 1040*6ba597c5SAnurag S. Maskey nwam_state_to_string(ncu_obj->nwamd_object_state), 1041*6ba597c5SAnurag S. Maskey nwam_aux_state_to_string(ncu_obj->nwamd_object_aux_state)); 1042*6ba597c5SAnurag S. Maskey return (0); 1043*6ba597c5SAnurag S. Maskey } 1044*6ba597c5SAnurag S. Maskey 1045*6ba597c5SAnurag S. Maskey void 1046*6ba597c5SAnurag S. Maskey nwamd_log_ncus(void) 1047*6ba597c5SAnurag S. Maskey { 1048*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "NCP %s", active_ncp); 1049*6ba597c5SAnurag S. Maskey (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, nwamd_ncu_display, 1050*6ba597c5SAnurag S. Maskey NULL); 1051*6ba597c5SAnurag S. Maskey } 1052*6ba597c5SAnurag S. Maskey 1053*6ba597c5SAnurag S. Maskey int 1054*6ba597c5SAnurag S. Maskey nwamd_ncu_action(const char *ncu, const char *parent, nwam_action_t action) 1055*6ba597c5SAnurag S. Maskey { 1056*6ba597c5SAnurag S. Maskey nwamd_event_t ncu_event = nwamd_event_init_object_action 1057*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, ncu, parent, action); 1058*6ba597c5SAnurag S. Maskey if (ncu_event == NULL) 1059*6ba597c5SAnurag S. Maskey return (1); 1060*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(ncu_event); 1061*6ba597c5SAnurag S. Maskey return (0); 1062*6ba597c5SAnurag S. Maskey } 1063*6ba597c5SAnurag S. Maskey 1064*6ba597c5SAnurag S. Maskey static void 1065*6ba597c5SAnurag S. Maskey add_phys_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name) 1066*6ba597c5SAnurag S. Maskey { 1067*6ba597c5SAnurag S. Maskey dladm_status_t dlrtn; 1068*6ba597c5SAnurag S. Maskey uint32_t media; 1069*6ba597c5SAnurag S. Maskey boolean_t is_wireless; 1070*6ba597c5SAnurag S. Maskey nwam_error_t err; 1071*6ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 1072*6ba597c5SAnurag S. Maskey uint64_t uintval; 1073*6ba597c5SAnurag S. Maskey 1074*6ba597c5SAnurag S. Maskey if ((dlrtn = dladm_name2info(dld_handle, name, NULL, NULL, NULL, 1075*6ba597c5SAnurag S. Maskey &media)) != DLADM_STATUS_OK) { 1076*6ba597c5SAnurag S. Maskey char errmsg[DLADM_STRSIZE]; 1077*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to get media type for %s: %s", name, 1078*6ba597c5SAnurag S. Maskey dladm_status2str(dlrtn, errmsg)); 1079*6ba597c5SAnurag S. Maskey return; 1080*6ba597c5SAnurag S. Maskey } 1081*6ba597c5SAnurag S. Maskey is_wireless = (media == DL_WIFI); 1082*6ba597c5SAnurag S. Maskey 1083*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_LINK, 1084*6ba597c5SAnurag S. Maskey NWAM_NCU_CLASS_PHYS, &ncuh)) != NWAM_SUCCESS) { 1085*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to create link ncu for %s: %s", name, 1086*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1087*6ba597c5SAnurag S. Maskey if (err == NWAM_ENTITY_READ_ONLY) { 1088*6ba597c5SAnurag S. Maskey nwamd_event_t retry_event; 1089*6ba597c5SAnurag S. Maskey 1090*6ba597c5SAnurag S. Maskey /* 1091*6ba597c5SAnurag S. Maskey * Root filesystem may be read-only, retry in 1092*6ba597c5SAnurag S. Maskey * a few seconds. 1093*6ba597c5SAnurag S. Maskey */ 1094*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "Retrying addition of phys ncu for %s", 1095*6ba597c5SAnurag S. Maskey name); 1096*6ba597c5SAnurag S. Maskey retry_event = nwamd_event_init_link_action(name, 1097*6ba597c5SAnurag S. Maskey NWAM_ACTION_ADD); 1098*6ba597c5SAnurag S. Maskey if (retry_event != NULL) { 1099*6ba597c5SAnurag S. Maskey nwamd_event_enqueue_timed(retry_event, 1100*6ba597c5SAnurag S. Maskey NWAMD_READONLY_RETRY_INTERVAL); 1101*6ba597c5SAnurag S. Maskey } 1102*6ba597c5SAnurag S. Maskey } 1103*6ba597c5SAnurag S. Maskey return; 1104*6ba597c5SAnurag S. Maskey } 1105*6ba597c5SAnurag S. Maskey 1106*6ba597c5SAnurag S. Maskey uintval = NWAM_ACTIVATION_MODE_PRIORITIZED; 1107*6ba597c5SAnurag S. Maskey if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1, 1108*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) { 1109*6ba597c5SAnurag S. Maskey goto finish; 1110*6ba597c5SAnurag S. Maskey } 1111*6ba597c5SAnurag S. Maskey 1112*6ba597c5SAnurag S. Maskey uintval = is_wireless ? 1 : 0; 1113*6ba597c5SAnurag S. Maskey if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1, 1114*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_GROUP)) != NWAM_SUCCESS) { 1115*6ba597c5SAnurag S. Maskey goto finish; 1116*6ba597c5SAnurag S. Maskey } 1117*6ba597c5SAnurag S. Maskey 1118*6ba597c5SAnurag S. Maskey uintval = is_wireless ? NWAM_PRIORITY_MODE_EXCLUSIVE : 1119*6ba597c5SAnurag S. Maskey NWAM_PRIORITY_MODE_SHARED; 1120*6ba597c5SAnurag S. Maskey if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1, 1121*6ba597c5SAnurag S. Maskey NWAM_NCU_PROP_PRIORITY_MODE)) != NWAM_SUCCESS) { 1122*6ba597c5SAnurag S. Maskey goto finish; 1123*6ba597c5SAnurag S. Maskey } 1124*6ba597c5SAnurag S. Maskey 1125*6ba597c5SAnurag S. Maskey err = nwam_ncu_commit(ncuh, 0); 1126*6ba597c5SAnurag S. Maskey 1127*6ba597c5SAnurag S. Maskey finish: 1128*6ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 1129*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 1130*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, 1131*6ba597c5SAnurag S. Maskey "failed to create automatic link ncu for %s: %s", 1132*6ba597c5SAnurag S. Maskey name, nwam_strerror(err)); 1133*6ba597c5SAnurag S. Maskey } 1134*6ba597c5SAnurag S. Maskey } 1135*6ba597c5SAnurag S. Maskey 1136*6ba597c5SAnurag S. Maskey static void 1137*6ba597c5SAnurag S. Maskey add_ip_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name) 1138*6ba597c5SAnurag S. Maskey { 1139*6ba597c5SAnurag S. Maskey nwam_error_t err; 1140*6ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 1141*6ba597c5SAnurag S. Maskey 1142*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_INTERFACE, 1143*6ba597c5SAnurag S. Maskey NWAM_NCU_CLASS_IP, &ncuh)) != NWAM_SUCCESS) { 1144*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to create ip ncu for %s: %s", name, 1145*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1146*6ba597c5SAnurag S. Maskey /* 1147*6ba597c5SAnurag S. Maskey * Root filesystem may be read-only, but no need to 1148*6ba597c5SAnurag S. Maskey * retry here since add_phys_ncu_to_ncp() enqueues 1149*6ba597c5SAnurag S. Maskey * a retry event which will lead to add_ip_ncu_to_ncp() 1150*6ba597c5SAnurag S. Maskey * being called. 1151*6ba597c5SAnurag S. Maskey */ 1152*6ba597c5SAnurag S. Maskey return; 1153*6ba597c5SAnurag S. Maskey } 1154*6ba597c5SAnurag S. Maskey 1155*6ba597c5SAnurag S. Maskey /* IP NCU has the default values, so nothing else to do */ 1156*6ba597c5SAnurag S. Maskey err = nwam_ncu_commit(ncuh, 0); 1157*6ba597c5SAnurag S. Maskey 1158*6ba597c5SAnurag S. Maskey finish: 1159*6ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 1160*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 1161*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, 1162*6ba597c5SAnurag S. Maskey "failed to create ip ncu for %s: %s", name, 1163*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1164*6ba597c5SAnurag S. Maskey } 1165*6ba597c5SAnurag S. Maskey } 1166*6ba597c5SAnurag S. Maskey 1167*6ba597c5SAnurag S. Maskey static void 1168*6ba597c5SAnurag S. Maskey remove_ncu_from_ncp(nwam_ncp_handle_t ncph, const char *name, 1169*6ba597c5SAnurag S. Maskey nwam_ncu_type_t type) 1170*6ba597c5SAnurag S. Maskey { 1171*6ba597c5SAnurag S. Maskey nwam_error_t err; 1172*6ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 1173*6ba597c5SAnurag S. Maskey 1174*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_read(ncph, name, type, 0, &ncuh)) != NWAM_SUCCESS) { 1175*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to read automatic ncu %s: %s", name, 1176*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1177*6ba597c5SAnurag S. Maskey return; 1178*6ba597c5SAnurag S. Maskey } 1179*6ba597c5SAnurag S. Maskey 1180*6ba597c5SAnurag S. Maskey err = nwam_ncu_destroy(ncuh, 0); 1181*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 1182*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "failed to delete automatic ncu %s: %s", name, 1183*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1184*6ba597c5SAnurag S. Maskey } 1185*6ba597c5SAnurag S. Maskey } 1186*6ba597c5SAnurag S. Maskey 1187*6ba597c5SAnurag S. Maskey /* 1188*6ba597c5SAnurag S. Maskey * Device represented by NCU has been added or removed for the active 1189*6ba597c5SAnurag S. Maskey * User NCP. If an associated NCU of the given type is found, transition it 1190*6ba597c5SAnurag S. Maskey * to the appropriate state. 1191*6ba597c5SAnurag S. Maskey */ 1192*6ba597c5SAnurag S. Maskey void 1193*6ba597c5SAnurag S. Maskey ncu_action_change_state(nwam_action_t action, nwam_ncu_type_t type, 1194*6ba597c5SAnurag S. Maskey const char *name) 1195*6ba597c5SAnurag S. Maskey { 1196*6ba597c5SAnurag S. Maskey nwamd_object_t ncu_obj = NULL; 1197*6ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu; 1198*6ba597c5SAnurag S. Maskey 1199*6ba597c5SAnurag S. Maskey if ((ncu_obj = nwamd_ncu_object_find(type, name)) == NULL) 1200*6ba597c5SAnurag S. Maskey return; 1201*6ba597c5SAnurag S. Maskey 1202*6ba597c5SAnurag S. Maskey ncu = ncu_obj->nwamd_object_data; 1203*6ba597c5SAnurag S. Maskey 1204*6ba597c5SAnurag S. Maskey /* 1205*6ba597c5SAnurag S. Maskey * If device has been added, transition from uninitialized to offline. 1206*6ba597c5SAnurag S. Maskey * If device has been removed, transition to uninitialized (via online* 1207*6ba597c5SAnurag S. Maskey * if the NCU is currently enabled in order to tear down config). 1208*6ba597c5SAnurag S. Maskey */ 1209*6ba597c5SAnurag S. Maskey if (action == NWAM_ACTION_ADD) { 1210*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1211*6ba597c5SAnurag S. Maskey ncu_obj->nwamd_object_name, 1212*6ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE, NWAM_AUX_STATE_CONDITIONS_NOT_MET); 1213*6ba597c5SAnurag S. Maskey } else { 1214*6ba597c5SAnurag S. Maskey if (ncu->ncu_enabled) { 1215*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1216*6ba597c5SAnurag S. Maskey ncu_obj->nwamd_object_name, 1217*6ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 1218*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 1219*6ba597c5SAnurag S. Maskey } else { 1220*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1221*6ba597c5SAnurag S. Maskey ncu_obj->nwamd_object_name, 1222*6ba597c5SAnurag S. Maskey NWAM_STATE_UNINITIALIZED, 1223*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 1224*6ba597c5SAnurag S. Maskey } 1225*6ba597c5SAnurag S. Maskey } 1226*6ba597c5SAnurag S. Maskey nwamd_object_release(ncu_obj); 1227*6ba597c5SAnurag S. Maskey } 1228*6ba597c5SAnurag S. Maskey 1229*6ba597c5SAnurag S. Maskey /* 1230*6ba597c5SAnurag S. Maskey * Called with hotplug sysevent or when nwam is started and walking the 1231*6ba597c5SAnurag S. Maskey * physical interfaces. Add/remove both link and interface NCUs from the 1232*6ba597c5SAnurag S. Maskey * Automatic NCP. Assumes that both link and interface NCUs don't exist. 1233*6ba597c5SAnurag S. Maskey */ 1234*6ba597c5SAnurag S. Maskey void 1235*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_link_action_event(nwamd_event_t event) 1236*6ba597c5SAnurag S. Maskey { 1237*6ba597c5SAnurag S. Maskey nwam_ncp_handle_t ncph; 1238*6ba597c5SAnurag S. Maskey nwam_ncu_type_t type; 1239*6ba597c5SAnurag S. Maskey nwam_action_t action = 1240*6ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_link_action.nwe_action; 1241*6ba597c5SAnurag S. Maskey nwam_error_t err; 1242*6ba597c5SAnurag S. Maskey char *name; 1243*6ba597c5SAnurag S. Maskey boolean_t automatic_ncp_active = B_FALSE; 1244*6ba597c5SAnurag S. Maskey 1245*6ba597c5SAnurag S. Maskey if (action != NWAM_ACTION_ADD && action != NWAM_ACTION_REMOVE) { 1246*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: " 1247*6ba597c5SAnurag S. Maskey "invalid link action %s", nwam_action_to_string(action)); 1248*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1249*6ba597c5SAnurag S. Maskey return; 1250*6ba597c5SAnurag S. Maskey } 1251*6ba597c5SAnurag S. Maskey 1252*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_link_action_event: " 1253*6ba597c5SAnurag S. Maskey "link action '%s' event on %s", nwam_action_to_string(action), 1254*6ba597c5SAnurag S. Maskey event->event_object[0] == 0 ? "n/a" : event->event_object); 1255*6ba597c5SAnurag S. Maskey 1256*6ba597c5SAnurag S. Maskey if ((err = nwam_ncu_typed_name_to_name(event->event_object, &type, 1257*6ba597c5SAnurag S. Maskey &name)) != NWAM_SUCCESS) { 1258*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: " 1259*6ba597c5SAnurag S. Maskey "translation from typedname error: %s", nwam_strerror(err)); 1260*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1261*6ba597c5SAnurag S. Maskey return; 1262*6ba597c5SAnurag S. Maskey } 1263*6ba597c5SAnurag S. Maskey 1264*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 1265*6ba597c5SAnurag S. Maskey if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 && 1266*6ba597c5SAnurag S. Maskey active_ncph != NULL) { 1267*6ba597c5SAnurag S. Maskey automatic_ncp_active = B_TRUE; 1268*6ba597c5SAnurag S. Maskey } 1269*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 1270*6ba597c5SAnurag S. Maskey 1271*6ba597c5SAnurag S. Maskey /* 1272*6ba597c5SAnurag S. Maskey * We could use active_ncph for cases where the Automatic NCP is active, 1273*6ba597c5SAnurag S. Maskey * but that would involve holding the active_ncp_mutex for too long. 1274*6ba597c5SAnurag S. Maskey */ 1275*6ba597c5SAnurag S. Maskey if ((err = nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph)) 1276*6ba597c5SAnurag S. Maskey == NWAM_ENTITY_NOT_FOUND) { 1277*6ba597c5SAnurag S. Maskey /* Automatic NCP doesn't exist, create it */ 1278*6ba597c5SAnurag S. Maskey if ((err = nwam_ncp_create(NWAM_NCP_NAME_AUTOMATIC, 0, 1279*6ba597c5SAnurag S. Maskey &ncph)) != NWAM_SUCCESS) { 1280*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, 1281*6ba597c5SAnurag S. Maskey "nwamd_ncu_handle_link_action_event: " 1282*6ba597c5SAnurag S. Maskey "could not create %s NCP: %s", 1283*6ba597c5SAnurag S. Maskey NWAM_NCP_NAME_AUTOMATIC, 1284*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1285*6ba597c5SAnurag S. Maskey goto cleanup_exit; 1286*6ba597c5SAnurag S. Maskey } 1287*6ba597c5SAnurag S. Maskey } else if (err != NWAM_SUCCESS) { 1288*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: " 1289*6ba597c5SAnurag S. Maskey "failed to read Automatic NCP: %s", 1290*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1291*6ba597c5SAnurag S. Maskey goto cleanup_exit; 1292*6ba597c5SAnurag S. Maskey } 1293*6ba597c5SAnurag S. Maskey 1294*6ba597c5SAnurag S. Maskey /* add or remove NCUs from Automatic NCP */ 1295*6ba597c5SAnurag S. Maskey if (action == NWAM_ACTION_ADD) { 1296*6ba597c5SAnurag S. Maskey add_phys_ncu_to_ncp(ncph, name); 1297*6ba597c5SAnurag S. Maskey add_ip_ncu_to_ncp(ncph, name); 1298*6ba597c5SAnurag S. Maskey } else { 1299*6ba597c5SAnurag S. Maskey /* 1300*6ba597c5SAnurag S. Maskey * Order is important here, remove IP NCU first to prevent 1301*6ba597c5SAnurag S. Maskey * propogation of down event from link to IP. No need to 1302*6ba597c5SAnurag S. Maskey * create REFRESH or DESTROY events. They are generated by 1303*6ba597c5SAnurag S. Maskey * nwam_ncu_commit() and nwam_ncu_destroy(). 1304*6ba597c5SAnurag S. Maskey */ 1305*6ba597c5SAnurag S. Maskey remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_INTERFACE); 1306*6ba597c5SAnurag S. Maskey remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_LINK); 1307*6ba597c5SAnurag S. Maskey } 1308*6ba597c5SAnurag S. Maskey nwam_ncp_free(ncph); 1309*6ba597c5SAnurag S. Maskey 1310*6ba597c5SAnurag S. Maskey /* 1311*6ba597c5SAnurag S. Maskey * If the Automatic NCP is not active, and the associated NCUs 1312*6ba597c5SAnurag S. Maskey * exist, they must be moved into the appropriate states given the 1313*6ba597c5SAnurag S. Maskey * action that has occurred. 1314*6ba597c5SAnurag S. Maskey */ 1315*6ba597c5SAnurag S. Maskey if (!automatic_ncp_active) { 1316*6ba597c5SAnurag S. Maskey ncu_action_change_state(action, NWAM_NCU_TYPE_INTERFACE, name); 1317*6ba597c5SAnurag S. Maskey ncu_action_change_state(action, NWAM_NCU_TYPE_LINK, name); 1318*6ba597c5SAnurag S. Maskey } 1319*6ba597c5SAnurag S. Maskey 1320*6ba597c5SAnurag S. Maskey /* Need NCU check to evaluate state in light of added/removed NCUs */ 1321*6ba597c5SAnurag S. Maskey if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK, 1322*6ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_NCP, NULL)) { 1323*6ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(NEXT_FEW_SECONDS); 1324*6ba597c5SAnurag S. Maskey } 1325*6ba597c5SAnurag S. Maskey 1326*6ba597c5SAnurag S. Maskey cleanup_exit: 1327*6ba597c5SAnurag S. Maskey free(name); 1328*6ba597c5SAnurag S. Maskey } 1329*6ba597c5SAnurag S. Maskey 1330*6ba597c5SAnurag S. Maskey /* 1331*6ba597c5SAnurag S. Maskey * Figure out if this link is part of an aggregation. This is fairly 1332*6ba597c5SAnurag S. Maskey * inefficient since we generate this list for every query and search 1333*6ba597c5SAnurag S. Maskey * linearly. A better way would be to generate the list of links in an 1334*6ba597c5SAnurag S. Maskey * aggregation once and then check each link against it. 1335*6ba597c5SAnurag S. Maskey */ 1336*6ba597c5SAnurag S. Maskey struct link_aggr_search_data { 1337*6ba597c5SAnurag S. Maskey datalink_id_t linkid; 1338*6ba597c5SAnurag S. Maskey boolean_t under; 1339*6ba597c5SAnurag S. Maskey }; 1340*6ba597c5SAnurag S. Maskey 1341*6ba597c5SAnurag S. Maskey static int 1342*6ba597c5SAnurag S. Maskey ncu_aggr_search(const char *name, void *data) 1343*6ba597c5SAnurag S. Maskey { 1344*6ba597c5SAnurag S. Maskey struct link_aggr_search_data *lasd = data; 1345*6ba597c5SAnurag S. Maskey dladm_aggr_grp_attr_t ginfo; 1346*6ba597c5SAnurag S. Maskey datalink_id_t linkid; 1347*6ba597c5SAnurag S. Maskey int i; 1348*6ba597c5SAnurag S. Maskey 1349*6ba597c5SAnurag S. Maskey if (dladm_name2info(dld_handle, name, &linkid, NULL, NULL, NULL) != 1350*6ba597c5SAnurag S. Maskey DLADM_STATUS_OK) 1351*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1352*6ba597c5SAnurag S. Maskey if (dladm_aggr_info(dld_handle, linkid, &ginfo, DLADM_OPT_ACTIVE) 1353*6ba597c5SAnurag S. Maskey != DLADM_STATUS_OK || ginfo.lg_nports == 0) 1354*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1355*6ba597c5SAnurag S. Maskey 1356*6ba597c5SAnurag S. Maskey for (i = 0; i < ginfo.lg_nports; i++) { 1357*6ba597c5SAnurag S. Maskey if (lasd->linkid == ginfo.lg_ports[i].lp_linkid) { 1358*6ba597c5SAnurag S. Maskey lasd->under = B_TRUE; 1359*6ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 1360*6ba597c5SAnurag S. Maskey } 1361*6ba597c5SAnurag S. Maskey } 1362*6ba597c5SAnurag S. Maskey free(ginfo.lg_ports); 1363*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1364*6ba597c5SAnurag S. Maskey } 1365*6ba597c5SAnurag S. Maskey 1366*6ba597c5SAnurag S. Maskey static boolean_t 1367*6ba597c5SAnurag S. Maskey nwamd_link_belongs_to_an_aggr(const char *name) 1368*6ba597c5SAnurag S. Maskey { 1369*6ba597c5SAnurag S. Maskey struct link_aggr_search_data lasd; 1370*6ba597c5SAnurag S. Maskey 1371*6ba597c5SAnurag S. Maskey if (dladm_name2info(dld_handle, name, &lasd.linkid, NULL, NULL, NULL) 1372*6ba597c5SAnurag S. Maskey != DLADM_STATUS_OK) 1373*6ba597c5SAnurag S. Maskey return (B_FALSE); 1374*6ba597c5SAnurag S. Maskey lasd.under = B_FALSE; 1375*6ba597c5SAnurag S. Maskey (void) dladm_walk(ncu_aggr_search, dld_handle, &lasd, 1376*6ba597c5SAnurag S. Maskey DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 1377*6ba597c5SAnurag S. Maskey return (lasd.under); 1378*6ba597c5SAnurag S. Maskey } 1379*6ba597c5SAnurag S. Maskey 1380*6ba597c5SAnurag S. Maskey /* 1381*6ba597c5SAnurag S. Maskey * If NCU doesn't exist for interface with given name, enqueue a ADD 1382*6ba597c5SAnurag S. Maskey * LINK_ACTION event. 1383*6ba597c5SAnurag S. Maskey */ 1384*6ba597c5SAnurag S. Maskey static int 1385*6ba597c5SAnurag S. Maskey ncu_create_link_action_event(const char *name, void *data) 1386*6ba597c5SAnurag S. Maskey { 1387*6ba597c5SAnurag S. Maskey nwam_ncp_handle_t ncph = data; 1388*6ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 1389*6ba597c5SAnurag S. Maskey nwamd_event_t link_event; 1390*6ba597c5SAnurag S. Maskey 1391*6ba597c5SAnurag S. Maskey /* Do not generate an event if this is a VirtualBox interface. */ 1392*6ba597c5SAnurag S. Maskey if (strncmp(name, VBOX_IFACE_PREFIX, strlen(VBOX_IFACE_PREFIX)) == 0) 1393*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1394*6ba597c5SAnurag S. Maskey 1395*6ba597c5SAnurag S. Maskey /* Do not generate an event if this link belongs to another zone. */ 1396*6ba597c5SAnurag S. Maskey if (!nwamd_link_belongs_to_this_zone(name)) 1397*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1398*6ba597c5SAnurag S. Maskey 1399*6ba597c5SAnurag S. Maskey /* Do not generate an event if this link belongs to an aggregation. */ 1400*6ba597c5SAnurag S. Maskey if (nwamd_link_belongs_to_an_aggr(name)) { 1401*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1402*6ba597c5SAnurag S. Maskey } 1403*6ba597c5SAnurag S. Maskey 1404*6ba597c5SAnurag S. Maskey /* Don't create an event if the NCU already exists. */ 1405*6ba597c5SAnurag S. Maskey if (ncph != NULL && nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK, 0, 1406*6ba597c5SAnurag S. Maskey &ncuh) == NWAM_SUCCESS) { 1407*6ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 1408*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1409*6ba597c5SAnurag S. Maskey } 1410*6ba597c5SAnurag S. Maskey 1411*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "ncu_create_link_action_event: adding ncus for %s", 1412*6ba597c5SAnurag S. Maskey name); 1413*6ba597c5SAnurag S. Maskey 1414*6ba597c5SAnurag S. Maskey link_event = nwamd_event_init_link_action(name, NWAM_ACTION_ADD); 1415*6ba597c5SAnurag S. Maskey if (link_event != NULL) 1416*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(link_event); 1417*6ba597c5SAnurag S. Maskey 1418*6ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 1419*6ba597c5SAnurag S. Maskey } 1420*6ba597c5SAnurag S. Maskey 1421*6ba597c5SAnurag S. Maskey /* 1422*6ba597c5SAnurag S. Maskey * Check if interface exists for this NCU. If not, enqueue a REMOVE 1423*6ba597c5SAnurag S. Maskey * LINK_ACTION event. 1424*6ba597c5SAnurag S. Maskey */ 1425*6ba597c5SAnurag S. Maskey /* ARGSUSED */ 1426*6ba597c5SAnurag S. Maskey static int 1427*6ba597c5SAnurag S. Maskey nwamd_destroy_ncu(nwam_ncu_handle_t ncuh, void *data) 1428*6ba597c5SAnurag S. Maskey { 1429*6ba597c5SAnurag S. Maskey char *name; 1430*6ba597c5SAnurag S. Maskey uint32_t flags; 1431*6ba597c5SAnurag S. Maskey nwamd_event_t link_event; 1432*6ba597c5SAnurag S. Maskey 1433*6ba597c5SAnurag S. Maskey if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) { 1434*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_destroy_ncu: could not get NCU name"); 1435*6ba597c5SAnurag S. Maskey return (0); 1436*6ba597c5SAnurag S. Maskey } 1437*6ba597c5SAnurag S. Maskey 1438*6ba597c5SAnurag S. Maskey /* Interfaces that exist return DLADM_OPT_ACTIVE flag */ 1439*6ba597c5SAnurag S. Maskey if ((dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL) 1440*6ba597c5SAnurag S. Maskey == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) && 1441*6ba597c5SAnurag S. Maskey !nwamd_link_belongs_to_an_aggr(name)) { 1442*6ba597c5SAnurag S. Maskey free(name); 1443*6ba597c5SAnurag S. Maskey return (0); 1444*6ba597c5SAnurag S. Maskey } 1445*6ba597c5SAnurag S. Maskey 1446*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_destroy_ncu: destroying ncus for %s", name); 1447*6ba597c5SAnurag S. Maskey 1448*6ba597c5SAnurag S. Maskey link_event = nwamd_event_init_link_action(name, NWAM_ACTION_REMOVE); 1449*6ba597c5SAnurag S. Maskey if (link_event != NULL) 1450*6ba597c5SAnurag S. Maskey nwamd_event_enqueue(link_event); 1451*6ba597c5SAnurag S. Maskey free(name); 1452*6ba597c5SAnurag S. Maskey return (0); 1453*6ba597c5SAnurag S. Maskey } 1454*6ba597c5SAnurag S. Maskey 1455*6ba597c5SAnurag S. Maskey /* 1456*6ba597c5SAnurag S. Maskey * Called when nwamd is starting up. 1457*6ba597c5SAnurag S. Maskey * 1458*6ba597c5SAnurag S. Maskey * Walk all NCUs and destroy any NCU from the Automatic NCP without an 1459*6ba597c5SAnurag S. Maskey * underlying interface (assumption here is that the interface was removed 1460*6ba597c5SAnurag S. Maskey * when nwam was disabled). 1461*6ba597c5SAnurag S. Maskey * 1462*6ba597c5SAnurag S. Maskey * Walk the physical interfaces and create ADD LINK_ACTION event, which 1463*6ba597c5SAnurag S. Maskey * will create appropriate interface and link NCUs in the Automatic NCP. 1464*6ba597c5SAnurag S. Maskey */ 1465*6ba597c5SAnurag S. Maskey void 1466*6ba597c5SAnurag S. Maskey nwamd_walk_physical_configuration(void) 1467*6ba597c5SAnurag S. Maskey { 1468*6ba597c5SAnurag S. Maskey nwam_ncp_handle_t ncph; 1469*6ba597c5SAnurag S. Maskey 1470*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 1471*6ba597c5SAnurag S. Maskey if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 && 1472*6ba597c5SAnurag S. Maskey active_ncph != NULL) { 1473*6ba597c5SAnurag S. Maskey ncph = active_ncph; 1474*6ba597c5SAnurag S. Maskey } else { 1475*6ba597c5SAnurag S. Maskey if (nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph) 1476*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 1477*6ba597c5SAnurag S. Maskey ncph = NULL; 1478*6ba597c5SAnurag S. Maskey } 1479*6ba597c5SAnurag S. Maskey } 1480*6ba597c5SAnurag S. Maskey 1481*6ba597c5SAnurag S. Maskey /* destroy NCUs for interfaces that don't exist */ 1482*6ba597c5SAnurag S. Maskey if (ncph != NULL) { 1483*6ba597c5SAnurag S. Maskey (void) nwam_ncp_walk_ncus(ncph, nwamd_destroy_ncu, NULL, 1484*6ba597c5SAnurag S. Maskey NWAM_FLAG_NCU_TYPE_LINK, NULL); 1485*6ba597c5SAnurag S. Maskey } 1486*6ba597c5SAnurag S. Maskey 1487*6ba597c5SAnurag S. Maskey /* create NCUs for interfaces without NCUs */ 1488*6ba597c5SAnurag S. Maskey (void) dladm_walk(ncu_create_link_action_event, dld_handle, ncph, 1489*6ba597c5SAnurag S. Maskey DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 1490*6ba597c5SAnurag S. Maskey 1491*6ba597c5SAnurag S. Maskey if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) != 0 || 1492*6ba597c5SAnurag S. Maskey active_ncph == NULL) { 1493*6ba597c5SAnurag S. Maskey nwam_ncp_free(ncph); 1494*6ba597c5SAnurag S. Maskey } 1495*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 1496*6ba597c5SAnurag S. Maskey } 1497*6ba597c5SAnurag S. Maskey 1498*6ba597c5SAnurag S. Maskey /* 1499*6ba597c5SAnurag S. Maskey * Handle NCU initialization/refresh event. 1500*6ba597c5SAnurag S. Maskey */ 1501*6ba597c5SAnurag S. Maskey void 1502*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_init_event(nwamd_event_t event) 1503*6ba597c5SAnurag S. Maskey { 1504*6ba597c5SAnurag S. Maskey nwamd_object_t object = NULL; 1505*6ba597c5SAnurag S. Maskey nwam_ncu_handle_t ncuh; 1506*6ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu = NULL; 1507*6ba597c5SAnurag S. Maskey nwam_error_t err; 1508*6ba597c5SAnurag S. Maskey nwam_ncu_type_t type; 1509*6ba597c5SAnurag S. Maskey char *name; 1510*6ba597c5SAnurag S. Maskey uint32_t flags; 1511*6ba597c5SAnurag S. Maskey boolean_t new = B_TRUE; 1512*6ba597c5SAnurag S. Maskey 1513*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event(%s)", 1514*6ba597c5SAnurag S. Maskey event->event_object); 1515*6ba597c5SAnurag S. Maskey 1516*6ba597c5SAnurag S. Maskey /* Get base linkname rather than interface:linkname or link:linkname */ 1517*6ba597c5SAnurag S. Maskey err = nwam_ncu_typed_name_to_name(event->event_object, 1518*6ba597c5SAnurag S. Maskey &type, &name); 1519*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 1520*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_init_event: " 1521*6ba597c5SAnurag S. Maskey "nwam_ncu_typed_name_to_name returned %s", 1522*6ba597c5SAnurag S. Maskey nwam_strerror(err)); 1523*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1524*6ba597c5SAnurag S. Maskey return; 1525*6ba597c5SAnurag S. Maskey } 1526*6ba597c5SAnurag S. Maskey 1527*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 1528*6ba597c5SAnurag S. Maskey if (active_ncph == NULL) { 1529*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, 1530*6ba597c5SAnurag S. Maskey "nwamd_ncu_handle_init_event: active NCP handle NULL"); 1531*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1532*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 1533*6ba597c5SAnurag S. Maskey return; 1534*6ba597c5SAnurag S. Maskey } 1535*6ba597c5SAnurag S. Maskey err = nwam_ncu_read(active_ncph, event->event_object, 1536*6ba597c5SAnurag S. Maskey type, 0, &ncuh); 1537*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 1538*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 1539*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_init_event: " 1540*6ba597c5SAnurag S. Maskey "could not read object '%s': %s", 1541*6ba597c5SAnurag S. Maskey event->event_object, nwam_strerror(err)); 1542*6ba597c5SAnurag S. Maskey free(name); 1543*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1544*6ba597c5SAnurag S. Maskey return; 1545*6ba597c5SAnurag S. Maskey } 1546*6ba597c5SAnurag S. Maskey 1547*6ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 1548*6ba597c5SAnurag S. Maskey event->event_object)) != NULL) 1549*6ba597c5SAnurag S. Maskey new = B_FALSE; 1550*6ba597c5SAnurag S. Maskey 1551*6ba597c5SAnurag S. Maskey /* 1552*6ba597c5SAnurag S. Maskey * For new NCUs, or interface NCUs, we (re)initialize data from scratch. 1553*6ba597c5SAnurag S. Maskey * For link NCUs, we want to retain object data. 1554*6ba597c5SAnurag S. Maskey */ 1555*6ba597c5SAnurag S. Maskey switch (type) { 1556*6ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_LINK: 1557*6ba597c5SAnurag S. Maskey if (new) { 1558*6ba597c5SAnurag S. Maskey ncu = nwamd_ncu_init(type, name); 1559*6ba597c5SAnurag S. Maskey } else { 1560*6ba597c5SAnurag S. Maskey ncu = object->nwamd_object_data; 1561*6ba597c5SAnurag S. Maskey nwam_ncu_free(object->nwamd_object_handle); 1562*6ba597c5SAnurag S. Maskey } 1563*6ba597c5SAnurag S. Maskey populate_common_ncu_properties(ncuh, ncu); 1564*6ba597c5SAnurag S. Maskey populate_link_ncu_properties(ncuh, ncu); 1565*6ba597c5SAnurag S. Maskey break; 1566*6ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_INTERFACE: 1567*6ba597c5SAnurag S. Maskey if (!new) { 1568*6ba597c5SAnurag S. Maskey nwam_ncu_free(object->nwamd_object_handle); 1569*6ba597c5SAnurag S. Maskey nwamd_ncu_free(object->nwamd_object_data); 1570*6ba597c5SAnurag S. Maskey } 1571*6ba597c5SAnurag S. Maskey ncu = nwamd_ncu_init(type, name); 1572*6ba597c5SAnurag S. Maskey populate_common_ncu_properties(ncuh, ncu); 1573*6ba597c5SAnurag S. Maskey populate_ip_ncu_properties(ncuh, ncu); 1574*6ba597c5SAnurag S. Maskey break; 1575*6ba597c5SAnurag S. Maskey default: 1576*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "unknown ncu type %d", type); 1577*6ba597c5SAnurag S. Maskey free(name); 1578*6ba597c5SAnurag S. Maskey nwam_ncu_free(ncuh); 1579*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1580*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1581*6ba597c5SAnurag S. Maskey return; 1582*6ba597c5SAnurag S. Maskey } 1583*6ba597c5SAnurag S. Maskey 1584*6ba597c5SAnurag S. Maskey if (new) { 1585*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: didn't find " 1586*6ba597c5SAnurag S. Maskey "ncu so create it %s", name); 1587*6ba597c5SAnurag S. Maskey object = nwamd_object_init(NWAM_OBJECT_TYPE_NCU, 1588*6ba597c5SAnurag S. Maskey event->event_object, ncuh, ncu); 1589*6ba597c5SAnurag S. Maskey } else { 1590*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: refreshing " 1591*6ba597c5SAnurag S. Maskey "ncu %s", name); 1592*6ba597c5SAnurag S. Maskey object->nwamd_object_data = ncu; 1593*6ba597c5SAnurag S. Maskey object->nwamd_object_handle = ncuh; 1594*6ba597c5SAnurag S. Maskey } 1595*6ba597c5SAnurag S. Maskey 1596*6ba597c5SAnurag S. Maskey /* 1597*6ba597c5SAnurag S. Maskey * If the physical link for this NCU doesn't exist in the system, 1598*6ba597c5SAnurag S. Maskey * the state should be UNINITIALIZED/NOT_FOUND. Interfaces that 1599*6ba597c5SAnurag S. Maskey * exist return DLADM_OPT_ACTIVE flag. 1600*6ba597c5SAnurag S. Maskey */ 1601*6ba597c5SAnurag S. Maskey if (dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL) 1602*6ba597c5SAnurag S. Maskey != DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) { 1603*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwam_ncu_handle_init_event: " 1604*6ba597c5SAnurag S. Maskey "interface for NCU %s doesn't exist", 1605*6ba597c5SAnurag S. Maskey event->event_object); 1606*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1607*6ba597c5SAnurag S. Maskey object->nwamd_object_name, NWAM_STATE_UNINITIALIZED, 1608*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_NOT_FOUND); 1609*6ba597c5SAnurag S. Maskey free(name); 1610*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1611*6ba597c5SAnurag S. Maskey return; 1612*6ba597c5SAnurag S. Maskey } 1613*6ba597c5SAnurag S. Maskey 1614*6ba597c5SAnurag S. Maskey /* 1615*6ba597c5SAnurag S. Maskey * If NCU is being initialized (rather than refreshed), the 1616*6ba597c5SAnurag S. Maskey * object_state is INITIALIZED (from nwamd_object_init()). 1617*6ba597c5SAnurag S. Maskey */ 1618*6ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_INITIALIZED) { 1619*6ba597c5SAnurag S. Maskey /* 1620*6ba597c5SAnurag S. Maskey * If the NCU is disabled, initial state should be DISABLED. 1621*6ba597c5SAnurag S. Maskey * 1622*6ba597c5SAnurag S. Maskey * Otherwise, the initial state will be 1623*6ba597c5SAnurag S. Maskey * OFFLINE/CONDITIONS_NOT_MET, and the link selection 1624*6ba597c5SAnurag S. Maskey * algorithm will do the rest. 1625*6ba597c5SAnurag S. Maskey */ 1626*6ba597c5SAnurag S. Maskey if (!ncu->ncu_enabled) { 1627*6ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_DISABLED; 1628*6ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 1629*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE; 1630*6ba597c5SAnurag S. Maskey } else { 1631*6ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_OFFLINE; 1632*6ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 1633*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET; 1634*6ba597c5SAnurag S. Maskey } 1635*6ba597c5SAnurag S. Maskey } else { 1636*6ba597c5SAnurag S. Maskey nwamd_link_t *link = &ncu->ncu_node.u_link; 1637*6ba597c5SAnurag S. Maskey 1638*6ba597c5SAnurag S. Maskey /* 1639*6ba597c5SAnurag S. Maskey * Refresh NCU. Deal with disabled cases first, moving NCUs 1640*6ba597c5SAnurag S. Maskey * that are not disabled - but have the enabled value set - to 1641*6ba597c5SAnurag S. Maskey * the disabled state. Then handle cases where the NCU was 1642*6ba597c5SAnurag S. Maskey * disabled but is no longer. Finally, deal with refresh of 1643*6ba597c5SAnurag S. Maskey * link and interface NCUs, as these are handled differently. 1644*6ba597c5SAnurag S. Maskey */ 1645*6ba597c5SAnurag S. Maskey if (!ncu->ncu_enabled) { 1646*6ba597c5SAnurag S. Maskey if (object->nwamd_object_state != NWAM_STATE_DISABLED) { 1647*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1648*6ba597c5SAnurag S. Maskey object->nwamd_object_name, 1649*6ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 1650*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 1651*6ba597c5SAnurag S. Maskey } 1652*6ba597c5SAnurag S. Maskey goto done; 1653*6ba597c5SAnurag S. Maskey } else { 1654*6ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_DISABLED) { 1655*6ba597c5SAnurag S. Maskey int64_t c; 1656*6ba597c5SAnurag S. Maskey 1657*6ba597c5SAnurag S. Maskey /* 1658*6ba597c5SAnurag S. Maskey * Try to activate the NCU if manual or 1659*6ba597c5SAnurag S. Maskey * prioritized (when priority <= current). 1660*6ba597c5SAnurag S. Maskey */ 1661*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 1662*6ba597c5SAnurag S. Maskey c = current_ncu_priority_group; 1663*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 1664*6ba597c5SAnurag S. Maskey if (link->nwamd_link_activation_mode == 1665*6ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_MANUAL || 1666*6ba597c5SAnurag S. Maskey (link->nwamd_link_activation_mode == 1667*6ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED && 1668*6ba597c5SAnurag S. Maskey link->nwamd_link_priority_mode <= c)) { 1669*6ba597c5SAnurag S. Maskey nwamd_object_set_state 1670*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 1671*6ba597c5SAnurag S. Maskey object->nwamd_object_name, 1672*6ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 1673*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 1674*6ba597c5SAnurag S. Maskey } else { 1675*6ba597c5SAnurag S. Maskey nwamd_object_set_state 1676*6ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_NCU, 1677*6ba597c5SAnurag S. Maskey object->nwamd_object_name, 1678*6ba597c5SAnurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, 1679*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 1680*6ba597c5SAnurag S. Maskey } 1681*6ba597c5SAnurag S. Maskey goto done; 1682*6ba597c5SAnurag S. Maskey } 1683*6ba597c5SAnurag S. Maskey } 1684*6ba597c5SAnurag S. Maskey 1685*6ba597c5SAnurag S. Maskey switch (type) { 1686*6ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_LINK: 1687*6ba597c5SAnurag S. Maskey if (ncu->ncu_node.u_link.nwamd_link_media == DL_WIFI) { 1688*6ba597c5SAnurag S. Maskey /* 1689*6ba597c5SAnurag S. Maskey * Do rescan. If the current state and the 1690*6ba597c5SAnurag S. Maskey * active priority-group do not allow wireless 1691*6ba597c5SAnurag S. Maskey * network selection, then it won't happen. 1692*6ba597c5SAnurag S. Maskey */ 1693*6ba597c5SAnurag S. Maskey (void) nwamd_wlan_scan(ncu->ncu_name); 1694*6ba597c5SAnurag S. Maskey } 1695*6ba597c5SAnurag S. Maskey break; 1696*6ba597c5SAnurag S. Maskey case NWAM_NCU_TYPE_INTERFACE: 1697*6ba597c5SAnurag S. Maskey /* 1698*6ba597c5SAnurag S. Maskey * If interface NCU is offline*, online or in 1699*6ba597c5SAnurag S. Maskey * maintenance, mark it down (from there, it will be 1700*6ba597c5SAnurag S. Maskey * reinitialized to reapply addresses). 1701*6ba597c5SAnurag S. Maskey */ 1702*6ba597c5SAnurag S. Maskey if (object->nwamd_object_state != NWAM_STATE_OFFLINE) { 1703*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1704*6ba597c5SAnurag S. Maskey object->nwamd_object_name, 1705*6ba597c5SAnurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE, 1706*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_DOWN); 1707*6ba597c5SAnurag S. Maskey } else { 1708*6ba597c5SAnurag S. Maskey object->nwamd_object_state = NWAM_STATE_OFFLINE; 1709*6ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = 1710*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET; 1711*6ba597c5SAnurag S. Maskey } 1712*6ba597c5SAnurag S. Maskey break; 1713*6ba597c5SAnurag S. Maskey } 1714*6ba597c5SAnurag S. Maskey } 1715*6ba597c5SAnurag S. Maskey 1716*6ba597c5SAnurag S. Maskey done: 1717*6ba597c5SAnurag S. Maskey if (type == NWAM_NCU_TYPE_LINK && 1718*6ba597c5SAnurag S. Maskey !nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK, 1719*6ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_NCP, NULL)) { 1720*6ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(NEXT_FEW_SECONDS); 1721*6ba597c5SAnurag S. Maskey } 1722*6ba597c5SAnurag S. Maskey free(name); 1723*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1724*6ba597c5SAnurag S. Maskey } 1725*6ba597c5SAnurag S. Maskey 1726*6ba597c5SAnurag S. Maskey void 1727*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_fini_event(nwamd_event_t event) 1728*6ba597c5SAnurag S. Maskey { 1729*6ba597c5SAnurag S. Maskey nwamd_object_t object; 1730*6ba597c5SAnurag S. Maskey nwamd_event_t state_event; 1731*6ba597c5SAnurag S. Maskey 1732*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_fini_event(%s)", 1733*6ba597c5SAnurag S. Maskey event->event_object); 1734*6ba597c5SAnurag S. Maskey 1735*6ba597c5SAnurag S. Maskey /* 1736*6ba597c5SAnurag S. Maskey * Simulate a state event so that the state machine can correctly 1737*6ba597c5SAnurag S. Maskey * disable the NCU. Then free up allocated objects. 1738*6ba597c5SAnurag S. Maskey */ 1739*6ba597c5SAnurag S. Maskey state_event = nwamd_event_init_object_state(NWAM_OBJECT_TYPE_NCU, 1740*6ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE, 1741*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_UNINITIALIZED); 1742*6ba597c5SAnurag S. Maskey if (state_event == NULL) { 1743*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1744*6ba597c5SAnurag S. Maskey return; 1745*6ba597c5SAnurag S. Maskey } 1746*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_state_event(state_event); 1747*6ba597c5SAnurag S. Maskey nwamd_event_fini(state_event); 1748*6ba597c5SAnurag S. Maskey 1749*6ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 1750*6ba597c5SAnurag S. Maskey event->event_object)) == NULL) { 1751*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_fini_event: " 1752*6ba597c5SAnurag S. Maskey "ncu %s not found", event->event_object); 1753*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1754*6ba597c5SAnurag S. Maskey return; 1755*6ba597c5SAnurag S. Maskey } 1756*6ba597c5SAnurag S. Maskey nwamd_object_release_and_destroy(object); 1757*6ba597c5SAnurag S. Maskey } 1758*6ba597c5SAnurag S. Maskey 1759*6ba597c5SAnurag S. Maskey void 1760*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_action_event(nwamd_event_t event) 1761*6ba597c5SAnurag S. Maskey { 1762*6ba597c5SAnurag S. Maskey nwamd_object_t object; 1763*6ba597c5SAnurag S. Maskey 1764*6ba597c5SAnurag S. Maskey (void) pthread_mutex_lock(&active_ncp_mutex); 1765*6ba597c5SAnurag S. Maskey if (strcmp(event->event_msg->nwe_data.nwe_object_action.nwe_parent, 1766*6ba597c5SAnurag S. Maskey active_ncp) != 0) { 1767*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: action for " 1768*6ba597c5SAnurag S. Maskey "inactive NCP %s, nothing to do", 1769*6ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_object_action.nwe_parent); 1770*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 1771*6ba597c5SAnurag S. Maskey return; 1772*6ba597c5SAnurag S. Maskey } 1773*6ba597c5SAnurag S. Maskey (void) pthread_mutex_unlock(&active_ncp_mutex); 1774*6ba597c5SAnurag S. Maskey 1775*6ba597c5SAnurag S. Maskey switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) { 1776*6ba597c5SAnurag S. Maskey case NWAM_ACTION_ENABLE: 1777*6ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 1778*6ba597c5SAnurag S. Maskey event->event_object); 1779*6ba597c5SAnurag S. Maskey if (object == NULL) { 1780*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_action_event: " 1781*6ba597c5SAnurag S. Maskey "could not find ncu %s", event->event_object); 1782*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1783*6ba597c5SAnurag S. Maskey return; 1784*6ba597c5SAnurag S. Maskey } 1785*6ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_ONLINE) { 1786*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: " 1787*6ba597c5SAnurag S. Maskey "ncu %s already online, nothing to do", 1788*6ba597c5SAnurag S. Maskey event->event_object); 1789*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1790*6ba597c5SAnurag S. Maskey return; 1791*6ba597c5SAnurag S. Maskey } 1792*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1793*6ba597c5SAnurag S. Maskey 1794*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1795*6ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE, 1796*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_INITIALIZED); 1797*6ba597c5SAnurag S. Maskey break; 1798*6ba597c5SAnurag S. Maskey case NWAM_ACTION_DISABLE: 1799*6ba597c5SAnurag S. Maskey object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 1800*6ba597c5SAnurag S. Maskey event->event_object); 1801*6ba597c5SAnurag S. Maskey if (object == NULL) { 1802*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_action_event: " 1803*6ba597c5SAnurag S. Maskey "could not find ncu %s", event->event_object); 1804*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1805*6ba597c5SAnurag S. Maskey return; 1806*6ba597c5SAnurag S. Maskey } 1807*6ba597c5SAnurag S. Maskey if (object->nwamd_object_state == NWAM_STATE_DISABLED) { 1808*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: " 1809*6ba597c5SAnurag S. Maskey "ncu %s already disabled, nothing to do", 1810*6ba597c5SAnurag S. Maskey event->event_object); 1811*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1812*6ba597c5SAnurag S. Maskey return; 1813*6ba597c5SAnurag S. Maskey } 1814*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1815*6ba597c5SAnurag S. Maskey 1816*6ba597c5SAnurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, 1817*6ba597c5SAnurag S. Maskey event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE, 1818*6ba597c5SAnurag S. Maskey NWAM_AUX_STATE_MANUAL_DISABLE); 1819*6ba597c5SAnurag S. Maskey break; 1820*6ba597c5SAnurag S. Maskey case NWAM_ACTION_ADD: 1821*6ba597c5SAnurag S. Maskey case NWAM_ACTION_REFRESH: 1822*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_init_event(event); 1823*6ba597c5SAnurag S. Maskey break; 1824*6ba597c5SAnurag S. Maskey case NWAM_ACTION_DESTROY: 1825*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_fini_event(event); 1826*6ba597c5SAnurag S. Maskey break; 1827*6ba597c5SAnurag S. Maskey default: 1828*6ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwam_ncu_handle_action_event: " 1829*6ba597c5SAnurag S. Maskey "unexpected action"); 1830*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1831*6ba597c5SAnurag S. Maskey break; 1832*6ba597c5SAnurag S. Maskey } 1833*6ba597c5SAnurag S. Maskey } 1834*6ba597c5SAnurag S. Maskey 1835*6ba597c5SAnurag S. Maskey void 1836*6ba597c5SAnurag S. Maskey nwamd_ncu_handle_state_event(nwamd_event_t event) 1837*6ba597c5SAnurag S. Maskey { 1838*6ba597c5SAnurag S. Maskey nwamd_object_t object; 1839*6ba597c5SAnurag S. Maskey nwam_state_t old_state, new_state; 1840*6ba597c5SAnurag S. Maskey nwam_aux_state_t new_aux_state; 1841*6ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu; 1842*6ba597c5SAnurag S. Maskey boolean_t is_link, enabled, prioritized = B_FALSE; 1843*6ba597c5SAnurag S. Maskey char linkname[NWAM_MAX_NAME_LEN]; 1844*6ba597c5SAnurag S. Maskey nwam_event_t m = event->event_msg; 1845*6ba597c5SAnurag S. Maskey 1846*6ba597c5SAnurag S. Maskey if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, 1847*6ba597c5SAnurag S. Maskey event->event_object)) == NULL) { 1848*6ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_state_event %lld: " 1849*6ba597c5SAnurag S. Maskey "state event for nonexistent NCU %s", event->event_id, 1850*6ba597c5SAnurag S. Maskey event->event_object); 1851*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1852*6ba597c5SAnurag S. Maskey return; 1853*6ba597c5SAnurag S. Maskey } 1854*6ba597c5SAnurag S. Maskey ncu = object->nwamd_object_data; 1855*6ba597c5SAnurag S. Maskey old_state = object->nwamd_object_state; 1856*6ba597c5SAnurag S. Maskey new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state; 1857*6ba597c5SAnurag S. Maskey new_aux_state = 1858*6ba597c5SAnurag S. Maskey event->event_msg->nwe_data.nwe_object_state.nwe_aux_state; 1859*6ba597c5SAnurag S. Maskey 1860*6ba597c5SAnurag S. Maskey /* 1861*6ba597c5SAnurag S. Maskey * For NCU state changes, we need to supply the parent NCP name also, 1862*6ba597c5SAnurag S. Maskey * regardless of whether the event is handled or not. It is best to 1863*6ba597c5SAnurag S. Maskey * fill this in here as we have the object lock - when we create 1864*6ba597c5SAnurag S. Maskey * object state events we sometimes do not have the object lock, but 1865*6ba597c5SAnurag S. Maskey * at this point in consuming the events (and prior to the associated 1866*6ba597c5SAnurag S. Maskey * event message being sent out) we do. 1867*6ba597c5SAnurag S. Maskey */ 1868*6ba597c5SAnurag S. Maskey (void) strlcpy(m->nwe_data.nwe_object_state.nwe_parent, ncu->ncu_parent, 1869*6ba597c5SAnurag S. Maskey sizeof (m->nwe_data.nwe_object_state.nwe_parent)); 1870*6ba597c5SAnurag S. Maskey 1871*6ba597c5SAnurag S. Maskey /* 1872*6ba597c5SAnurag S. Maskey * If we receive a state change event moving this NCU to 1873*6ba597c5SAnurag S. Maskey * DHCP_TIMED_OUT or UP state but this NCU is already ONLINE, then 1874*6ba597c5SAnurag S. Maskey * ignore this state change event. 1875*6ba597c5SAnurag S. Maskey */ 1876*6ba597c5SAnurag S. Maskey if ((new_aux_state == NWAM_AUX_STATE_IF_DHCP_TIMED_OUT || 1877*6ba597c5SAnurag S. Maskey new_aux_state == NWAM_AUX_STATE_UP) && 1878*6ba597c5SAnurag S. Maskey object->nwamd_object_state == NWAM_STATE_ONLINE) { 1879*6ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwamd_ncu_handle_state_event: " 1880*6ba597c5SAnurag S. Maskey "NCU %s already online, not going to '%s' state", 1881*6ba597c5SAnurag S. Maskey object->nwamd_object_name, 1882*6ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 1883*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1884*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1885*6ba597c5SAnurag S. Maskey return; 1886*6ba597c5SAnurag S. Maskey } 1887*6ba597c5SAnurag S. Maskey 1888*6ba597c5SAnurag S. Maskey if (new_state == object->nwamd_object_state && 1889*6ba597c5SAnurag S. Maskey new_aux_state == object->nwamd_object_aux_state) { 1890*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: " 1891*6ba597c5SAnurag S. Maskey "NCU %s already in state (%s, %s)", 1892*6ba597c5SAnurag S. Maskey object->nwamd_object_name, nwam_state_to_string(new_state), 1893*6ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 1894*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1895*6ba597c5SAnurag S. Maskey return; 1896*6ba597c5SAnurag S. Maskey } 1897*6ba597c5SAnurag S. Maskey 1898*6ba597c5SAnurag S. Maskey if (old_state == NWAM_STATE_MAINTENANCE && 1899*6ba597c5SAnurag S. Maskey (new_state == NWAM_STATE_ONLINE || 1900*6ba597c5SAnurag S. Maskey (new_state == NWAM_STATE_OFFLINE_TO_ONLINE && 1901*6ba597c5SAnurag S. Maskey new_aux_state != NWAM_AUX_STATE_INITIALIZED))) { 1902*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: " 1903*6ba597c5SAnurag S. Maskey "NCU %s cannot transition from state %s to state (%s, %s)", 1904*6ba597c5SAnurag S. Maskey object->nwamd_object_name, nwam_state_to_string(old_state), 1905*6ba597c5SAnurag S. Maskey nwam_state_to_string(new_state), 1906*6ba597c5SAnurag S. Maskey nwam_aux_state_to_string(new_aux_state)); 1907*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1908*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1909*6ba597c5SAnurag S. Maskey return; 1910*6ba597c5SAnurag S. Maskey } 1911*6ba597c5SAnurag S. Maskey 1912*6ba597c5SAnurag S. Maskey object->nwamd_object_state = new_state; 1913*6ba597c5SAnurag S. Maskey object->nwamd_object_aux_state = new_aux_state; 1914*6ba597c5SAnurag S. Maskey 1915*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: changing state for NCU " 1916*6ba597c5SAnurag S. Maskey "%s to (%s, %s)", object->nwamd_object_name, 1917*6ba597c5SAnurag S. Maskey nwam_state_to_string(object->nwamd_object_state), 1918*6ba597c5SAnurag S. Maskey nwam_aux_state_to_string(object->nwamd_object_aux_state)); 1919*6ba597c5SAnurag S. Maskey 1920*6ba597c5SAnurag S. Maskey is_link = (ncu->ncu_type == NWAM_NCU_TYPE_LINK); 1921*6ba597c5SAnurag S. Maskey if (is_link) 1922*6ba597c5SAnurag S. Maskey (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname)); 1923*6ba597c5SAnurag S. Maskey prioritized = (ncu->ncu_type == NWAM_NCU_TYPE_LINK && 1924*6ba597c5SAnurag S. Maskey ncu->ncu_node.u_link.nwamd_link_activation_mode == 1925*6ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_PRIORITIZED); 1926*6ba597c5SAnurag S. Maskey enabled = ncu->ncu_enabled; 1927*6ba597c5SAnurag S. Maskey 1928*6ba597c5SAnurag S. Maskey nwamd_object_release(object); 1929*6ba597c5SAnurag S. Maskey 1930*6ba597c5SAnurag S. Maskey /* 1931*6ba597c5SAnurag S. Maskey * State machine for NCUs 1932*6ba597c5SAnurag S. Maskey */ 1933*6ba597c5SAnurag S. Maskey switch (new_state) { 1934*6ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE_TO_ONLINE: 1935*6ba597c5SAnurag S. Maskey if (enabled) { 1936*6ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(event->event_object); 1937*6ba597c5SAnurag S. Maskey } else { 1938*6ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: " 1939*6ba597c5SAnurag S. Maskey "cannot move disabled NCU %s online", 1940*6ba597c5SAnurag S. Maskey event->event_object); 1941*6ba597c5SAnurag S. Maskey nwamd_event_do_not_send(event); 1942*6ba597c5SAnurag S. Maskey } 1943*6ba597c5SAnurag S. Maskey break; 1944*6ba597c5SAnurag S. Maskey 1945*6ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE_TO_OFFLINE: 1946*6ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(event->event_object); 1947*6ba597c5SAnurag S. Maskey break; 1948*6ba597c5SAnurag S. Maskey 1949*6ba597c5SAnurag S. Maskey case NWAM_STATE_ONLINE: 1950*6ba597c5SAnurag S. Maskey /* 1951*6ba597c5SAnurag S. Maskey * We usually don't need to do anything when we're in the 1952*6ba597c5SAnurag S. Maskey * ONLINE state. However, for WiFi we can be in INIT or 1953*6ba597c5SAnurag S. Maskey * SCAN aux states while being ONLINE. 1954*6ba597c5SAnurag S. Maskey */ 1955*6ba597c5SAnurag S. Maskey nwamd_ncu_state_machine(event->event_object); 1956*6ba597c5SAnurag S. Maskey break; 1957*6ba597c5SAnurag S. Maskey 1958*6ba597c5SAnurag S. Maskey case NWAM_STATE_OFFLINE: 1959*6ba597c5SAnurag S. Maskey /* Reassess priority group now member is offline */ 1960*6ba597c5SAnurag S. Maskey if (prioritized) { 1961*6ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(0); 1962*6ba597c5SAnurag S. Maskey } 1963*6ba597c5SAnurag S. Maskey break; 1964*6ba597c5SAnurag S. Maskey 1965*6ba597c5SAnurag S. Maskey case NWAM_STATE_DISABLED: 1966*6ba597c5SAnurag S. Maskey case NWAM_STATE_UNINITIALIZED: 1967*6ba597c5SAnurag S. Maskey case NWAM_STATE_MAINTENANCE: 1968*6ba597c5SAnurag S. Maskey case NWAM_STATE_DEGRADED: 1969*6ba597c5SAnurag S. Maskey default: 1970*6ba597c5SAnurag S. Maskey /* do nothing */ 1971*6ba597c5SAnurag S. Maskey break; 1972*6ba597c5SAnurag S. Maskey } 1973*6ba597c5SAnurag S. Maskey 1974*6ba597c5SAnurag S. Maskey if (is_link) { 1975*6ba597c5SAnurag S. Maskey if ((new_state == NWAM_STATE_ONLINE_TO_OFFLINE && 1976*6ba597c5SAnurag S. Maskey new_aux_state != NWAM_AUX_STATE_UNINITIALIZED && 1977*6ba597c5SAnurag S. Maskey new_aux_state != NWAM_AUX_STATE_NOT_FOUND) || 1978*6ba597c5SAnurag S. Maskey new_state == NWAM_STATE_DISABLED) { 1979*6ba597c5SAnurag S. Maskey /* 1980*6ba597c5SAnurag S. Maskey * Going offline, propogate down event to IP NCU. Do 1981*6ba597c5SAnurag S. Maskey * not propogate event if new aux state is uninitialized 1982*6ba597c5SAnurag S. Maskey * or not found as these auxiliary states signify 1983*6ba597c5SAnurag S. Maskey * that an NCP switch/device removal is in progress. 1984*6ba597c5SAnurag S. Maskey */ 1985*6ba597c5SAnurag S. Maskey nwamd_propogate_link_up_down_to_ip(linkname, B_FALSE); 1986*6ba597c5SAnurag S. Maskey } 1987*6ba597c5SAnurag S. Maskey if (new_state == NWAM_STATE_ONLINE) { 1988*6ba597c5SAnurag S. Maskey /* gone online, propogate up event to IP NCU */ 1989*6ba597c5SAnurag S. Maskey nwamd_propogate_link_up_down_to_ip(linkname, B_TRUE); 1990*6ba597c5SAnurag S. Maskey } 1991*6ba597c5SAnurag S. Maskey } else { 1992*6ba597c5SAnurag S. Maskey /* If IP NCU is online, reasses priority group */ 1993*6ba597c5SAnurag S. Maskey if (new_state == NWAM_STATE_ONLINE) 1994*6ba597c5SAnurag S. Maskey nwamd_create_ncu_check_event(0); 1995*6ba597c5SAnurag S. Maskey } 1996*6ba597c5SAnurag S. Maskey } 1997