1f595a68aSyz147064 /* 2f595a68aSyz147064 * CDDL HEADER START 3f595a68aSyz147064 * 4f595a68aSyz147064 * The contents of this file are subject to the terms of the 5f595a68aSyz147064 * Common Development and Distribution License (the "License"). 6f595a68aSyz147064 * You may not use this file except in compliance with the License. 7f595a68aSyz147064 * 8f595a68aSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9f595a68aSyz147064 * or http://www.opensolaris.org/os/licensing. 10f595a68aSyz147064 * See the License for the specific language governing permissions 11f595a68aSyz147064 * and limitations under the License. 12f595a68aSyz147064 * 13f595a68aSyz147064 * When distributing Covered Code, include this CDDL HEADER in each 14f595a68aSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15f595a68aSyz147064 * If applicable, add the following below this CDDL HEADER, with the 16f595a68aSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying 17f595a68aSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner] 18f595a68aSyz147064 * 19f595a68aSyz147064 * CDDL HEADER END 20f595a68aSyz147064 */ 21f595a68aSyz147064 /* 22d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23f595a68aSyz147064 * Use is subject to license terms. 24f595a68aSyz147064 */ 25f595a68aSyz147064 26f595a68aSyz147064 #include <libintl.h> 27f595a68aSyz147064 #include <stdio.h> 28f595a68aSyz147064 #include <stdlib.h> 29f595a68aSyz147064 #include <unistd.h> 30f595a68aSyz147064 #include <fcntl.h> 31d62bc4baSyz147064 #include <stddef.h> 32f595a68aSyz147064 #include <string.h> 33f595a68aSyz147064 #include <stropts.h> 34f595a68aSyz147064 #include <libdevinfo.h> 35f595a68aSyz147064 #include <net/if.h> 36f595a68aSyz147064 #include <net/if_dl.h> 37f595a68aSyz147064 #include <net/if_types.h> 38d62bc4baSyz147064 #include <libdlpi.h> 39d62bc4baSyz147064 #include <libdllink.h> 40a399b765Szf162725 #include <libscf.h> 41f595a68aSyz147064 #include <libdlwlan.h> 42d62bc4baSyz147064 #include <libdladm_impl.h> 43f595a68aSyz147064 #include <libdlwlan_impl.h> 44a399b765Szf162725 #include <net/wpa.h> 45f595a68aSyz147064 46*4ac67f02SAnurag S. Maskey static dladm_status_t wpa_instance_create(dladm_handle_t, datalink_id_t, 47*4ac67f02SAnurag S. Maskey void *); 48*4ac67f02SAnurag S. Maskey static dladm_status_t wpa_instance_delete(dladm_handle_t, datalink_id_t); 49f595a68aSyz147064 50*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_bsstype(dladm_handle_t, datalink_id_t, void *, 51*4ac67f02SAnurag S. Maskey int); 52*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_essid(dladm_handle_t, datalink_id_t, void *, 53*4ac67f02SAnurag S. Maskey int); 54*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_bssid(dladm_handle_t, datalink_id_t, void *, 55*4ac67f02SAnurag S. Maskey int); 56*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_signal(dladm_handle_t, datalink_id_t, void *, 57*4ac67f02SAnurag S. Maskey int); 58*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_encryption(dladm_handle_t, datalink_id_t, void *, 59*4ac67f02SAnurag S. Maskey int); 60*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_authmode(dladm_handle_t, datalink_id_t, void *, 61*4ac67f02SAnurag S. Maskey int); 62*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_linkstatus(dladm_handle_t, datalink_id_t, void *, 63*4ac67f02SAnurag S. Maskey int); 64*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_esslist(dladm_handle_t, datalink_id_t, void *, 65*4ac67f02SAnurag S. Maskey int); 66*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_rate(dladm_handle_t, datalink_id_t, void *, int); 67*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_mode(dladm_handle_t, datalink_id_t, void *, int); 68*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_capability(dladm_handle_t, datalink_id_t, void *, 69*4ac67f02SAnurag S. Maskey int); 70*4ac67f02SAnurag S. Maskey static dladm_status_t do_get_wpamode(dladm_handle_t, datalink_id_t, void *, 71*4ac67f02SAnurag S. Maskey int); 72f595a68aSyz147064 73*4ac67f02SAnurag S. Maskey static dladm_status_t do_set_bsstype(dladm_handle_t, datalink_id_t, 74*4ac67f02SAnurag S. Maskey dladm_wlan_bsstype_t *); 75*4ac67f02SAnurag S. Maskey static dladm_status_t do_set_authmode(dladm_handle_t, datalink_id_t, 76*4ac67f02SAnurag S. Maskey dladm_wlan_auth_t *); 77*4ac67f02SAnurag S. Maskey static dladm_status_t do_set_encryption(dladm_handle_t, datalink_id_t, 78d62bc4baSyz147064 dladm_wlan_secmode_t *); 79*4ac67f02SAnurag S. Maskey static dladm_status_t do_set_essid(dladm_handle_t, datalink_id_t, 80*4ac67f02SAnurag S. Maskey dladm_wlan_essid_t *); 81*4ac67f02SAnurag S. Maskey static dladm_status_t do_set_createibss(dladm_handle_t, datalink_id_t, 82*4ac67f02SAnurag S. Maskey boolean_t *); 83*4ac67f02SAnurag S. Maskey static dladm_status_t do_set_key(dladm_handle_t, datalink_id_t, 84*4ac67f02SAnurag S. Maskey dladm_wlan_key_t *, uint_t); 85*4ac67f02SAnurag S. Maskey static dladm_status_t do_set_channel(dladm_handle_t, datalink_id_t, 86*4ac67f02SAnurag S. Maskey dladm_wlan_channel_t *); 87f595a68aSyz147064 88*4ac67f02SAnurag S. Maskey static dladm_status_t do_scan(dladm_handle_t, datalink_id_t, void *, int); 89*4ac67f02SAnurag S. Maskey static dladm_status_t do_connect(dladm_handle_t, datalink_id_t, void *, int, 90bcb5c89dSSowmini Varadhan dladm_wlan_attr_t *, boolean_t, void *, uint_t, 91bcb5c89dSSowmini Varadhan int); 92*4ac67f02SAnurag S. Maskey static dladm_status_t do_disconnect(dladm_handle_t, datalink_id_t, void *, 93*4ac67f02SAnurag S. Maskey int); 94d62bc4baSyz147064 static boolean_t find_val_by_name(const char *, val_desc_t *, 95d62bc4baSyz147064 uint_t, uint_t *); 96f595a68aSyz147064 static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **); 97f595a68aSyz147064 static void generate_essid(dladm_wlan_essid_t *); 98f595a68aSyz147064 99f595a68aSyz147064 static dladm_status_t dladm_wlan_wlresult2status(wldp_t *); 100*4ac67f02SAnurag S. Maskey static dladm_status_t dladm_wlan_validate(dladm_handle_t, datalink_id_t); 101f595a68aSyz147064 102f595a68aSyz147064 static val_desc_t linkstatus_vals[] = { 103d62bc4baSyz147064 { "disconnected", DLADM_WLAN_LINK_DISCONNECTED }, 104d62bc4baSyz147064 { "connected", DLADM_WLAN_LINK_CONNECTED } 105f595a68aSyz147064 }; 106f595a68aSyz147064 107f595a68aSyz147064 static val_desc_t secmode_vals[] = { 108f595a68aSyz147064 { "none", DLADM_WLAN_SECMODE_NONE }, 109a399b765Szf162725 { "wep", DLADM_WLAN_SECMODE_WEP }, 110a399b765Szf162725 { "wpa", DLADM_WLAN_SECMODE_WPA } 111f595a68aSyz147064 }; 112f595a68aSyz147064 113f595a68aSyz147064 static val_desc_t strength_vals[] = { 114f595a68aSyz147064 { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK }, 115f595a68aSyz147064 { "weak", DLADM_WLAN_STRENGTH_WEAK }, 116f595a68aSyz147064 { "good", DLADM_WLAN_STRENGTH_GOOD }, 117f595a68aSyz147064 { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD }, 118f595a68aSyz147064 { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT } 119f595a68aSyz147064 }; 120f595a68aSyz147064 121f595a68aSyz147064 static val_desc_t mode_vals[] = { 122f595a68aSyz147064 { "a", DLADM_WLAN_MODE_80211A }, 123f595a68aSyz147064 { "b", DLADM_WLAN_MODE_80211B }, 124f595a68aSyz147064 { "g", DLADM_WLAN_MODE_80211G }, 125f595a68aSyz147064 }; 126f595a68aSyz147064 127f595a68aSyz147064 static val_desc_t auth_vals[] = { 128f595a68aSyz147064 { "open", DLADM_WLAN_AUTH_OPEN }, 129f595a68aSyz147064 { "shared", DLADM_WLAN_AUTH_SHARED } 130f595a68aSyz147064 }; 131f595a68aSyz147064 132f595a68aSyz147064 static val_desc_t bsstype_vals[] = { 133f595a68aSyz147064 { "bss", DLADM_WLAN_BSSTYPE_BSS }, 134f595a68aSyz147064 { "ibss", DLADM_WLAN_BSSTYPE_IBSS }, 135f595a68aSyz147064 { "any", DLADM_WLAN_BSSTYPE_ANY } 136f595a68aSyz147064 }; 137f595a68aSyz147064 138bcb5c89dSSowmini Varadhan #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET) 139f595a68aSyz147064 140f595a68aSyz147064 static dladm_status_t 141f595a68aSyz147064 dladm_wlan_wlresult2status(wldp_t *gbuf) 142f595a68aSyz147064 { 143f595a68aSyz147064 switch (gbuf->wldp_result) { 144f595a68aSyz147064 case WL_SUCCESS: 145f595a68aSyz147064 return (DLADM_STATUS_OK); 146f595a68aSyz147064 147f595a68aSyz147064 case WL_NOTSUPPORTED: 148f595a68aSyz147064 case WL_LACK_FEATURE: 149f595a68aSyz147064 return (DLADM_STATUS_NOTSUP); 150f595a68aSyz147064 151f595a68aSyz147064 case WL_READONLY: 152f595a68aSyz147064 return (DLADM_STATUS_PROPRDONLY); 153f595a68aSyz147064 154f595a68aSyz147064 default: 155f595a68aSyz147064 break; 156f595a68aSyz147064 } 157f595a68aSyz147064 158f595a68aSyz147064 return (DLADM_STATUS_FAILED); 159f595a68aSyz147064 } 160f595a68aSyz147064 161f595a68aSyz147064 static dladm_wlan_mode_t 162f595a68aSyz147064 do_convert_mode(wl_phy_conf_t *phyp) 163f595a68aSyz147064 { 164f595a68aSyz147064 switch (phyp->wl_phy_fhss_conf.wl_fhss_subtype) { 165f595a68aSyz147064 case WL_ERP: 166f595a68aSyz147064 return (DLADM_WLAN_MODE_80211G); 167f595a68aSyz147064 case WL_OFDM: 168f595a68aSyz147064 return (DLADM_WLAN_MODE_80211A); 169f595a68aSyz147064 case WL_DSSS: 170f595a68aSyz147064 case WL_FHSS: 171f595a68aSyz147064 return (DLADM_WLAN_MODE_80211B); 172f595a68aSyz147064 default: 173f595a68aSyz147064 break; 174f595a68aSyz147064 } 175f595a68aSyz147064 176f595a68aSyz147064 return (DLADM_WLAN_MODE_NONE); 177f595a68aSyz147064 } 178f595a68aSyz147064 179d62bc4baSyz147064 boolean_t 180d62bc4baSyz147064 i_dladm_wlan_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp) 181f595a68aSyz147064 { 182f595a68aSyz147064 wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf; 183f595a68aSyz147064 wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf; 184f595a68aSyz147064 185f595a68aSyz147064 switch (wlfp->wl_fhss_subtype) { 186f595a68aSyz147064 case WL_FHSS: 187f595a68aSyz147064 case WL_DSSS: 188f595a68aSyz147064 case WL_IRBASE: 189f595a68aSyz147064 case WL_HRDS: 190f595a68aSyz147064 case WL_ERP: 191f595a68aSyz147064 *channelp = wlfp->wl_fhss_channel; 192f595a68aSyz147064 break; 193f595a68aSyz147064 case WL_OFDM: 194f595a68aSyz147064 *channelp = DLADM_WLAN_OFDM2CHAN(wlop->wl_ofdm_frequency); 195f595a68aSyz147064 break; 196f595a68aSyz147064 default: 197f595a68aSyz147064 return (B_FALSE); 198f595a68aSyz147064 } 199f595a68aSyz147064 return (B_TRUE); 200f595a68aSyz147064 } 201f595a68aSyz147064 202f595a68aSyz147064 #define IEEE80211_RATE 0x7f 203f595a68aSyz147064 static void 204f595a68aSyz147064 fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp) 205f595a68aSyz147064 { 206f595a68aSyz147064 int i; 207f595a68aSyz147064 208f595a68aSyz147064 (void) memset(attrp, 0, sizeof (*attrp)); 209f595a68aSyz147064 210f595a68aSyz147064 (void) snprintf(attrp->wa_essid.we_bytes, DLADM_WLAN_MAX_ESSID_LEN, 211f595a68aSyz147064 "%s", wlp->wl_ess_conf_essid.wl_essid_essid); 212f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 213f595a68aSyz147064 214f595a68aSyz147064 (void) memcpy(attrp->wa_bssid.wb_bytes, wlp->wl_ess_conf_bssid, 215f595a68aSyz147064 DLADM_WLAN_BSSID_LEN); 216f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 217f595a68aSyz147064 218f595a68aSyz147064 attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled == 219f595a68aSyz147064 WL_ENC_WEP ? DLADM_WLAN_SECMODE_WEP : DLADM_WLAN_SECMODE_NONE); 220a399b765Szf162725 if (wlp->wl_ess_conf_reserved[0] > 0) 221a399b765Szf162725 attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 222f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 223f595a68aSyz147064 224f595a68aSyz147064 attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ? 225f595a68aSyz147064 DLADM_WLAN_BSSTYPE_BSS : DLADM_WLAN_BSSTYPE_IBSS); 226f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 227f595a68aSyz147064 228f595a68aSyz147064 attrp->wa_auth = (wlp->wl_ess_conf_authmode == 0 ? 229f595a68aSyz147064 DLADM_WLAN_AUTH_OPEN : DLADM_WLAN_AUTH_SHARED); 230f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 231f595a68aSyz147064 232f595a68aSyz147064 attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(wlp->wl_ess_conf_sl); 233f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 234f595a68aSyz147064 235f595a68aSyz147064 attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)&wlp->wl_phy_conf); 236f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 237f595a68aSyz147064 238f595a68aSyz147064 for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) { 239f595a68aSyz147064 wlp->wl_supported_rates[i] &= IEEE80211_RATE; 240f595a68aSyz147064 if (wlp->wl_supported_rates[i] > attrp->wa_speed) 241f595a68aSyz147064 attrp->wa_speed = wlp->wl_supported_rates[i]; 242f595a68aSyz147064 } 243f595a68aSyz147064 if (attrp->wa_speed > 0) 244f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 245f595a68aSyz147064 246d62bc4baSyz147064 if (i_dladm_wlan_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf, 247f595a68aSyz147064 &attrp->wa_channel)) 248f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_CHANNEL; 249f595a68aSyz147064 } 250f595a68aSyz147064 251f595a68aSyz147064 dladm_status_t 252*4ac67f02SAnurag S. Maskey dladm_wlan_scan(dladm_handle_t handle, datalink_id_t linkid, void *arg, 253f595a68aSyz147064 boolean_t (*func)(void *, dladm_wlan_attr_t *)) 254f595a68aSyz147064 { 255d62bc4baSyz147064 int i; 256f595a68aSyz147064 uint32_t count; 257f595a68aSyz147064 wl_ess_conf_t *wlp; 258bcb5c89dSSowmini Varadhan wl_ess_list_t *wls = NULL; 259bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE]; 260bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status; 261f595a68aSyz147064 dladm_wlan_attr_t wlattr; 262f595a68aSyz147064 dladm_status_t status; 263f595a68aSyz147064 264*4ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 265d62bc4baSyz147064 goto done; 266f595a68aSyz147064 267*4ac67f02SAnurag S. Maskey status = do_get_linkstatus(handle, linkid, &wl_status, 268*4ac67f02SAnurag S. Maskey sizeof (wl_status)); 269bcb5c89dSSowmini Varadhan if (status != DLADM_STATUS_OK) 270f595a68aSyz147064 goto done; 271f595a68aSyz147064 272*4ac67f02SAnurag S. Maskey if ((status = do_scan(handle, linkid, buf, sizeof (buf))) != 273*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 274f595a68aSyz147064 goto done; 275f595a68aSyz147064 276a399b765Szf162725 if (func == NULL) { 277a399b765Szf162725 status = DLADM_STATUS_OK; 278a399b765Szf162725 goto done; 279a399b765Szf162725 } 280a399b765Szf162725 281bcb5c89dSSowmini Varadhan wls = malloc(WLDP_BUFSIZE); 282bcb5c89dSSowmini Varadhan if (wls == NULL) { 283bcb5c89dSSowmini Varadhan status = DLADM_STATUS_NOMEM; 284bcb5c89dSSowmini Varadhan goto done; 285bcb5c89dSSowmini Varadhan } 286bcb5c89dSSowmini Varadhan 287*4ac67f02SAnurag S. Maskey if ((status = do_get_esslist(handle, linkid, wls, WLDP_BUFSIZE)) 288bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK) 289f595a68aSyz147064 goto done; 290f595a68aSyz147064 291bcb5c89dSSowmini Varadhan wlp = wls->wl_ess_list_ess; 292bcb5c89dSSowmini Varadhan count = wls->wl_ess_list_num; 293f595a68aSyz147064 294f595a68aSyz147064 for (i = 0; i < count; i++, wlp++) { 295f595a68aSyz147064 fill_wlan_attr(wlp, &wlattr); 296f595a68aSyz147064 if (!func(arg, &wlattr)) 297f595a68aSyz147064 break; 298f595a68aSyz147064 } 299f595a68aSyz147064 300bcb5c89dSSowmini Varadhan if (wl_status != WL_CONNECTED) { 301*4ac67f02SAnurag S. Maskey status = do_get_linkstatus(handle, linkid, &wl_status, 302bcb5c89dSSowmini Varadhan sizeof (&wl_status)); 303d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 304f595a68aSyz147064 goto done; 305bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED) 306*4ac67f02SAnurag S. Maskey (void) do_disconnect(handle, linkid, buf, sizeof (buf)); 307f595a68aSyz147064 } 308f595a68aSyz147064 309f595a68aSyz147064 status = DLADM_STATUS_OK; 310f595a68aSyz147064 done: 311bcb5c89dSSowmini Varadhan free(wls); 312f595a68aSyz147064 return (status); 313f595a68aSyz147064 } 314f595a68aSyz147064 315f595a68aSyz147064 /* 316f595a68aSyz147064 * Structures used in building the list of eligible WLANs to connect to. 317f595a68aSyz147064 * Specifically, `connect_state' has the WLAN attributes that must be matched 318f595a68aSyz147064 * (in `cs_attr') and a growing list of WLANs that matched those attributes 319f595a68aSyz147064 * chained through `cs_list'. Each element in the list is of type `attr_node' 320f595a68aSyz147064 * and has the matching WLAN's attributes and a pointer to the next element. 321f595a68aSyz147064 * For convenience, `cs_count' tracks the number of elements in the list. 322f595a68aSyz147064 */ 323f595a68aSyz147064 typedef struct attr_node { 324f595a68aSyz147064 dladm_wlan_attr_t an_attr; 325f595a68aSyz147064 struct attr_node *an_next; 326f595a68aSyz147064 } attr_node_t; 327f595a68aSyz147064 328f595a68aSyz147064 typedef struct connect_state { 329f595a68aSyz147064 dladm_wlan_attr_t *cs_attr; 330f595a68aSyz147064 uint_t cs_count; 331f595a68aSyz147064 attr_node_t *cs_list; 332f595a68aSyz147064 } connect_state_t; 333f595a68aSyz147064 334f595a68aSyz147064 /* 335f595a68aSyz147064 * Compare two sets of WLAN attributes. For now, we only consider strength 336f595a68aSyz147064 * and speed (in that order), which matches the documented default policy for 337f595a68aSyz147064 * dladm_wlan_connect(). 338f595a68aSyz147064 */ 339f595a68aSyz147064 static int 340f595a68aSyz147064 attr_compare(const void *p1, const void *p2) 341f595a68aSyz147064 { 342f595a68aSyz147064 dladm_wlan_attr_t *attrp1, *attrp2; 343f595a68aSyz147064 344f595a68aSyz147064 attrp1 = (*(dladm_wlan_attr_t **)p1); 345f595a68aSyz147064 attrp2 = (*(dladm_wlan_attr_t **)p2); 346f595a68aSyz147064 347f595a68aSyz147064 if (attrp1->wa_strength < attrp2->wa_strength) 348f595a68aSyz147064 return (1); 349f595a68aSyz147064 350f595a68aSyz147064 if (attrp1->wa_strength > attrp2->wa_strength) 351f595a68aSyz147064 return (-1); 352f595a68aSyz147064 353f595a68aSyz147064 return (attrp2->wa_speed - attrp1->wa_speed); 354f595a68aSyz147064 } 355f595a68aSyz147064 356f595a68aSyz147064 /* 357f595a68aSyz147064 * Callback function used by dladm_wlan_connect() to filter out unwanted 358f595a68aSyz147064 * WLANs when scanning for available WLANs. Always returns B_TRUE to 359f595a68aSyz147064 * continue the scan. 360f595a68aSyz147064 */ 361f595a68aSyz147064 static boolean_t 362f595a68aSyz147064 connect_cb(void *arg, dladm_wlan_attr_t *attrp) 363f595a68aSyz147064 { 364f595a68aSyz147064 attr_node_t *nodep; 365f595a68aSyz147064 dladm_wlan_attr_t *fattrp; 366f595a68aSyz147064 connect_state_t *statep = (connect_state_t *)arg; 367f595a68aSyz147064 368f595a68aSyz147064 fattrp = statep->cs_attr; 369f595a68aSyz147064 if (fattrp == NULL) 370f595a68aSyz147064 goto append; 371f595a68aSyz147064 372f595a68aSyz147064 if ((fattrp->wa_valid & attrp->wa_valid) != fattrp->wa_valid) 373f595a68aSyz147064 return (B_TRUE); 374f595a68aSyz147064 375f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0 && 376f595a68aSyz147064 strncmp(fattrp->wa_essid.we_bytes, attrp->wa_essid.we_bytes, 377f595a68aSyz147064 DLADM_WLAN_MAX_ESSID_LEN) != 0) 378f595a68aSyz147064 return (B_TRUE); 379f595a68aSyz147064 380f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 381f595a68aSyz147064 fattrp->wa_secmode != attrp->wa_secmode) 382f595a68aSyz147064 return (B_TRUE); 383f595a68aSyz147064 384f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0 && 385f595a68aSyz147064 fattrp->wa_mode != attrp->wa_mode) 386f595a68aSyz147064 return (B_TRUE); 387f595a68aSyz147064 388f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_STRENGTH) != 0 && 389f595a68aSyz147064 fattrp->wa_strength != attrp->wa_strength) 390f595a68aSyz147064 return (B_TRUE); 391f595a68aSyz147064 392f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SPEED) != 0 && 393f595a68aSyz147064 fattrp->wa_speed != attrp->wa_speed) 394f595a68aSyz147064 return (B_TRUE); 395f595a68aSyz147064 396f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) { 397f595a68aSyz147064 attrp->wa_auth = fattrp->wa_auth; 398f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 399f595a68aSyz147064 } 400f595a68aSyz147064 401f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 402f595a68aSyz147064 fattrp->wa_bsstype != attrp->wa_bsstype) 403f595a68aSyz147064 return (B_TRUE); 404f595a68aSyz147064 405f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSID) != 0 && 406f595a68aSyz147064 memcmp(fattrp->wa_bssid.wb_bytes, attrp->wa_bssid.wb_bytes, 407f595a68aSyz147064 DLADM_WLAN_BSSID_LEN) != 0) 408f595a68aSyz147064 return (B_TRUE); 409f595a68aSyz147064 append: 410f595a68aSyz147064 nodep = malloc(sizeof (attr_node_t)); 411f595a68aSyz147064 if (nodep == NULL) 412f595a68aSyz147064 return (B_TRUE); 413f595a68aSyz147064 414f595a68aSyz147064 (void) memcpy(&nodep->an_attr, attrp, sizeof (dladm_wlan_attr_t)); 415f595a68aSyz147064 nodep->an_next = statep->cs_list; 416f595a68aSyz147064 statep->cs_list = nodep; 417f595a68aSyz147064 statep->cs_count++; 418f595a68aSyz147064 419f595a68aSyz147064 return (B_TRUE); 420f595a68aSyz147064 } 421f595a68aSyz147064 422a399b765Szf162725 #define IEEE80211_C_WPA 0x01800000 423a399b765Szf162725 424f595a68aSyz147064 static dladm_status_t 425*4ac67f02SAnurag S. Maskey do_connect(dladm_handle_t handle, datalink_id_t linkid, void *buf, int bufsize, 426bcb5c89dSSowmini Varadhan dladm_wlan_attr_t *attrp, boolean_t create_ibss, void *keys, 427bcb5c89dSSowmini Varadhan uint_t key_count, int timeout) 428f595a68aSyz147064 { 429f595a68aSyz147064 dladm_wlan_secmode_t secmode; 430f595a68aSyz147064 dladm_wlan_auth_t authmode; 431f595a68aSyz147064 dladm_wlan_bsstype_t bsstype; 432f595a68aSyz147064 dladm_wlan_essid_t essid; 433f595a68aSyz147064 boolean_t essid_valid = B_FALSE; 434d62bc4baSyz147064 dladm_status_t status; 435f595a68aSyz147064 dladm_wlan_channel_t channel; 436f595a68aSyz147064 hrtime_t start; 437a399b765Szf162725 wl_capability_t *caps; 438bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status; 439f595a68aSyz147064 440f595a68aSyz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) { 441f595a68aSyz147064 channel = attrp->wa_channel; 442*4ac67f02SAnurag S. Maskey status = do_set_channel(handle, linkid, &channel); 443d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 444f595a68aSyz147064 goto fail; 445f595a68aSyz147064 } 446f595a68aSyz147064 447f595a68aSyz147064 secmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) ? 448f595a68aSyz147064 attrp->wa_secmode : DLADM_WLAN_SECMODE_NONE; 449f595a68aSyz147064 450*4ac67f02SAnurag S. Maskey if ((status = do_set_encryption(handle, linkid, &secmode)) != 451*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 452f595a68aSyz147064 goto fail; 453f595a68aSyz147064 454f595a68aSyz147064 authmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) ? 455f595a68aSyz147064 attrp->wa_auth : DLADM_WLAN_AUTH_OPEN; 456f595a68aSyz147064 457*4ac67f02SAnurag S. Maskey if ((status = do_set_authmode(handle, linkid, &authmode)) != 458*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 459f595a68aSyz147064 goto fail; 460f595a68aSyz147064 461f595a68aSyz147064 bsstype = ((attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0) ? 462f595a68aSyz147064 attrp->wa_bsstype : DLADM_WLAN_BSSTYPE_BSS; 463f595a68aSyz147064 464*4ac67f02SAnurag S. Maskey if ((status = do_set_bsstype(handle, linkid, &bsstype)) != 465*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 466f595a68aSyz147064 goto fail; 467f595a68aSyz147064 468f595a68aSyz147064 if (secmode == DLADM_WLAN_SECMODE_WEP) { 469d62bc4baSyz147064 if (keys == NULL || key_count == 0 || 470d62bc4baSyz147064 key_count > MAX_NWEPKEYS) { 471d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 472d62bc4baSyz147064 goto fail; 473d62bc4baSyz147064 } 474*4ac67f02SAnurag S. Maskey status = do_set_key(handle, linkid, keys, key_count); 475d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 476f595a68aSyz147064 goto fail; 477a399b765Szf162725 } else if (secmode == DLADM_WLAN_SECMODE_WPA) { 478d62bc4baSyz147064 if (keys == NULL || key_count == 0 || 479d62bc4baSyz147064 key_count > MAX_NWEPKEYS) { 480d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 481d62bc4baSyz147064 goto fail; 482d62bc4baSyz147064 } 483*4ac67f02SAnurag S. Maskey status = do_get_capability(handle, linkid, buf, bufsize); 484d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 485a399b765Szf162725 goto fail; 486bcb5c89dSSowmini Varadhan caps = (wl_capability_t *)buf; 487a399b765Szf162725 if ((caps->caps & IEEE80211_C_WPA) == 0) 488a399b765Szf162725 return (DLADM_STATUS_NOTSUP); 489f595a68aSyz147064 } 490f595a68aSyz147064 491f595a68aSyz147064 if (create_ibss) { 492*4ac67f02SAnurag S. Maskey status = do_set_channel(handle, linkid, &channel); 493d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 494f595a68aSyz147064 goto fail; 495f595a68aSyz147064 496*4ac67f02SAnurag S. Maskey status = do_set_createibss(handle, linkid, &create_ibss); 497d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 498f595a68aSyz147064 goto fail; 499f595a68aSyz147064 500f595a68aSyz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0) { 501f595a68aSyz147064 generate_essid(&essid); 502f595a68aSyz147064 essid_valid = B_TRUE; 503f595a68aSyz147064 } 504f595a68aSyz147064 } 505f595a68aSyz147064 506f595a68aSyz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0) { 507f595a68aSyz147064 essid = attrp->wa_essid; 508f595a68aSyz147064 essid_valid = B_TRUE; 509f595a68aSyz147064 } 510f595a68aSyz147064 511d62bc4baSyz147064 if (!essid_valid) { 512d62bc4baSyz147064 status = DLADM_STATUS_FAILED; 513d62bc4baSyz147064 goto fail; 514d62bc4baSyz147064 } 515d62bc4baSyz147064 516*4ac67f02SAnurag S. Maskey if ((status = do_set_essid(handle, linkid, &essid)) != DLADM_STATUS_OK) 517f595a68aSyz147064 goto fail; 518f595a68aSyz147064 519a399b765Szf162725 /* 520a399b765Szf162725 * Because wpa daemon needs getting essid from driver, 521a399b765Szf162725 * we need call do_set_essid() first, then call wpa_instance_create(). 522a399b765Szf162725 */ 523a399b765Szf162725 if (secmode == DLADM_WLAN_SECMODE_WPA && keys != NULL) 524*4ac67f02SAnurag S. Maskey (void) wpa_instance_create(handle, linkid, keys); 525a399b765Szf162725 526f595a68aSyz147064 start = gethrtime(); 527f595a68aSyz147064 for (;;) { 528*4ac67f02SAnurag S. Maskey status = do_get_linkstatus(handle, linkid, &wl_status, 529bcb5c89dSSowmini Varadhan sizeof (wl_status)); 530d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 531f595a68aSyz147064 goto fail; 532f595a68aSyz147064 533bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED) 534f595a68aSyz147064 break; 535f595a68aSyz147064 536f595a68aSyz147064 (void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE); 537f595a68aSyz147064 if ((timeout >= 0) && (gethrtime() - start) / 538d62bc4baSyz147064 NANOSEC >= timeout) { 539d62bc4baSyz147064 status = DLADM_STATUS_TIMEDOUT; 540d62bc4baSyz147064 goto fail; 541f595a68aSyz147064 } 542d62bc4baSyz147064 } 543d62bc4baSyz147064 status = DLADM_STATUS_OK; 544f595a68aSyz147064 fail: 545d62bc4baSyz147064 return (status); 546f595a68aSyz147064 } 547f595a68aSyz147064 548f595a68aSyz147064 dladm_status_t 549*4ac67f02SAnurag S. Maskey dladm_wlan_connect(dladm_handle_t handle, datalink_id_t linkid, 550*4ac67f02SAnurag S. Maskey dladm_wlan_attr_t *attrp, int timeout, void *keys, uint_t key_count, 551*4ac67f02SAnurag S. Maskey uint_t flags) 552f595a68aSyz147064 { 553d62bc4baSyz147064 int i; 554bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE]; 555f595a68aSyz147064 connect_state_t state = {0, NULL, NULL}; 556f595a68aSyz147064 attr_node_t *nodep = NULL; 557f595a68aSyz147064 boolean_t create_ibss, set_authmode; 558f595a68aSyz147064 dladm_wlan_attr_t **wl_list = NULL; 559d62bc4baSyz147064 dladm_status_t status; 560bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status; 561f595a68aSyz147064 562*4ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 563811fc8e1Syz147064 return (status); 564f595a68aSyz147064 565*4ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status, 566*4ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK) 567f595a68aSyz147064 goto done; 568f595a68aSyz147064 569bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED) { 570f595a68aSyz147064 status = DLADM_STATUS_ISCONN; 571f595a68aSyz147064 goto done; 572f595a68aSyz147064 } 573f595a68aSyz147064 574f595a68aSyz147064 set_authmode = ((attrp != NULL) && 575f595a68aSyz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0); 576f595a68aSyz147064 create_ibss = ((flags & DLADM_WLAN_CONNECT_CREATEIBSS) != 0 && 577f595a68aSyz147064 attrp != NULL && 578f595a68aSyz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 579f595a68aSyz147064 attrp->wa_bsstype == DLADM_WLAN_BSSTYPE_IBSS); 580f595a68aSyz147064 581f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 || 582f595a68aSyz147064 (create_ibss && attrp != NULL && 583f595a68aSyz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) { 584*4ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf), attrp, 585bcb5c89dSSowmini Varadhan create_ibss, keys, key_count, timeout); 586f595a68aSyz147064 goto done; 587f595a68aSyz147064 } 588f595a68aSyz147064 589f595a68aSyz147064 state.cs_attr = attrp; 590f595a68aSyz147064 state.cs_list = NULL; 591f595a68aSyz147064 state.cs_count = 0; 592f595a68aSyz147064 593*4ac67f02SAnurag S. Maskey status = dladm_wlan_scan(handle, linkid, &state, connect_cb); 594f595a68aSyz147064 if (status != DLADM_STATUS_OK) 595f595a68aSyz147064 goto done; 596f595a68aSyz147064 597f595a68aSyz147064 if (state.cs_count == 0) { 598f595a68aSyz147064 if (!create_ibss) { 599f595a68aSyz147064 status = DLADM_STATUS_NOTFOUND; 600f595a68aSyz147064 goto done; 601f595a68aSyz147064 } 602*4ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf), 603bcb5c89dSSowmini Varadhan attrp, create_ibss, keys, key_count, timeout); 604f595a68aSyz147064 goto done; 605f595a68aSyz147064 } 606f595a68aSyz147064 607f595a68aSyz147064 wl_list = malloc(state.cs_count * sizeof (dladm_wlan_attr_t *)); 608f595a68aSyz147064 if (wl_list == NULL) { 609f595a68aSyz147064 status = DLADM_STATUS_NOMEM; 610f595a68aSyz147064 goto done; 611f595a68aSyz147064 } 612f595a68aSyz147064 613f595a68aSyz147064 nodep = state.cs_list; 614f595a68aSyz147064 for (i = 0; i < state.cs_count; i++) { 615f595a68aSyz147064 wl_list[i] = &nodep->an_attr; 616f595a68aSyz147064 nodep = nodep->an_next; 617f595a68aSyz147064 } 618f595a68aSyz147064 qsort(wl_list, state.cs_count, sizeof (dladm_wlan_attr_t *), 619f595a68aSyz147064 attr_compare); 620f595a68aSyz147064 621f595a68aSyz147064 for (i = 0; i < state.cs_count; i++) { 622f595a68aSyz147064 dladm_wlan_attr_t *ap = wl_list[i]; 623f595a68aSyz147064 624*4ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf), 625bcb5c89dSSowmini Varadhan ap, create_ibss, keys, key_count, timeout); 626f595a68aSyz147064 if (status == DLADM_STATUS_OK) 627f595a68aSyz147064 break; 628f595a68aSyz147064 629f595a68aSyz147064 if (!set_authmode) { 630f595a68aSyz147064 ap->wa_auth = DLADM_WLAN_AUTH_SHARED; 631f595a68aSyz147064 ap->wa_valid |= DLADM_WLAN_ATTR_AUTH; 632*4ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf), 633bcb5c89dSSowmini Varadhan ap, create_ibss, keys, key_count, timeout); 634f595a68aSyz147064 if (status == DLADM_STATUS_OK) 635f595a68aSyz147064 break; 636f595a68aSyz147064 } 637f595a68aSyz147064 } 638f595a68aSyz147064 done: 639f595a68aSyz147064 if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN)) 640*4ac67f02SAnurag S. Maskey (void) do_disconnect(handle, linkid, buf, sizeof (buf)); 641f595a68aSyz147064 642f595a68aSyz147064 while (state.cs_list != NULL) { 643f595a68aSyz147064 nodep = state.cs_list; 644f595a68aSyz147064 state.cs_list = nodep->an_next; 645f595a68aSyz147064 free(nodep); 646f595a68aSyz147064 } 647f595a68aSyz147064 free(wl_list); 648f595a68aSyz147064 return (status); 649f595a68aSyz147064 } 650f595a68aSyz147064 651f595a68aSyz147064 dladm_status_t 652*4ac67f02SAnurag S. Maskey dladm_wlan_disconnect(dladm_handle_t handle, datalink_id_t linkid) 653f595a68aSyz147064 { 654bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE]; 655f595a68aSyz147064 dladm_status_t status; 656bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status; 657f595a68aSyz147064 658*4ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 659d62bc4baSyz147064 return (status); 660f595a68aSyz147064 661*4ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status, 662*4ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK) 663f595a68aSyz147064 goto done; 664f595a68aSyz147064 665bcb5c89dSSowmini Varadhan if (wl_status != WL_CONNECTED) { 666f595a68aSyz147064 status = DLADM_STATUS_NOTCONN; 667f595a68aSyz147064 goto done; 668f595a68aSyz147064 } 669f595a68aSyz147064 670*4ac67f02SAnurag S. Maskey if ((status = do_disconnect(handle, linkid, buf, sizeof (buf))) 671bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK) 672f595a68aSyz147064 goto done; 673f595a68aSyz147064 674*4ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status, 675*4ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK) 676f595a68aSyz147064 goto done; 677f595a68aSyz147064 678bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED) { 679f595a68aSyz147064 status = DLADM_STATUS_FAILED; 680f595a68aSyz147064 goto done; 681f595a68aSyz147064 } 682f595a68aSyz147064 683f595a68aSyz147064 status = DLADM_STATUS_OK; 684f595a68aSyz147064 done: 685f595a68aSyz147064 return (status); 686f595a68aSyz147064 } 687f595a68aSyz147064 688f595a68aSyz147064 dladm_status_t 689*4ac67f02SAnurag S. Maskey dladm_wlan_get_linkattr(dladm_handle_t handle, datalink_id_t linkid, 690*4ac67f02SAnurag S. Maskey dladm_wlan_linkattr_t *attrp) 691f595a68aSyz147064 { 692f595a68aSyz147064 wl_rssi_t signal; 693f595a68aSyz147064 wl_bss_type_t bsstype; 694f595a68aSyz147064 wl_authmode_t authmode; 695f595a68aSyz147064 wl_encryption_t encryption; 696bcb5c89dSSowmini Varadhan wl_rates_t *ratesp = NULL; 697f595a68aSyz147064 dladm_wlan_attr_t *wl_attrp; 698d62bc4baSyz147064 dladm_status_t status; 699bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE]; 700bcb5c89dSSowmini Varadhan wl_essid_t wls; 701bcb5c89dSSowmini Varadhan wl_phy_conf_t wl_phy_conf; 702bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status; 703f595a68aSyz147064 704f595a68aSyz147064 if (attrp == NULL) 705f595a68aSyz147064 return (DLADM_STATUS_BADARG); 706f595a68aSyz147064 707*4ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 708d62bc4baSyz147064 goto done; 709f595a68aSyz147064 710f595a68aSyz147064 (void) memset(attrp, 0, sizeof (*attrp)); 711f595a68aSyz147064 wl_attrp = &attrp->la_wlan_attr; 712f595a68aSyz147064 713*4ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status, 714*4ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK) 715f595a68aSyz147064 goto done; 716f595a68aSyz147064 717f595a68aSyz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS; 718bcb5c89dSSowmini Varadhan if (wl_status != WL_CONNECTED) 719d62bc4baSyz147064 attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED; 720d62bc4baSyz147064 else 721d62bc4baSyz147064 attrp->la_status = DLADM_WLAN_LINK_CONNECTED; 722f595a68aSyz147064 723*4ac67f02SAnurag S. Maskey if ((status = do_get_essid(handle, linkid, &wls, sizeof (wls))) 724bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK) 725f595a68aSyz147064 goto done; 726f595a68aSyz147064 727bcb5c89dSSowmini Varadhan (void) strlcpy(wl_attrp->wa_essid.we_bytes, wls.wl_essid_essid, 728f595a68aSyz147064 DLADM_WLAN_MAX_ESSID_LEN); 729f595a68aSyz147064 730f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 731f595a68aSyz147064 732*4ac67f02SAnurag S. Maskey if ((status = do_get_bssid(handle, linkid, buf, sizeof (buf))) 733bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK) 734f595a68aSyz147064 goto done; 735f595a68aSyz147064 736bcb5c89dSSowmini Varadhan (void) memcpy(wl_attrp->wa_bssid.wb_bytes, buf, DLADM_WLAN_BSSID_LEN); 737f595a68aSyz147064 738f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 739f595a68aSyz147064 740d62bc4baSyz147064 if (attrp->la_status == DLADM_WLAN_LINK_DISCONNECTED) { 741a399b765Szf162725 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 742a399b765Szf162725 status = DLADM_STATUS_OK; 743a399b765Szf162725 goto done; 744a399b765Szf162725 } 745a399b765Szf162725 746*4ac67f02SAnurag S. Maskey if ((status = do_get_encryption(handle, linkid, &encryption, 747bcb5c89dSSowmini Varadhan sizeof (encryption))) != DLADM_STATUS_OK) 748f595a68aSyz147064 goto done; 749f595a68aSyz147064 750f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 751f595a68aSyz147064 752f595a68aSyz147064 switch (encryption) { 753f595a68aSyz147064 case WL_NOENCRYPTION: 754f595a68aSyz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_NONE; 755f595a68aSyz147064 break; 756f595a68aSyz147064 case WL_ENC_WEP: 757f595a68aSyz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP; 758f595a68aSyz147064 break; 759a399b765Szf162725 case WL_ENC_WPA: 760a399b765Szf162725 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 761a399b765Szf162725 break; 762f595a68aSyz147064 default: 763f595a68aSyz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE; 764f595a68aSyz147064 break; 765f595a68aSyz147064 } 766f595a68aSyz147064 767*4ac67f02SAnurag S. Maskey if ((status = do_get_signal(handle, linkid, &signal, sizeof (signal))) 768bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK) 769f595a68aSyz147064 goto done; 770f595a68aSyz147064 771f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 772f595a68aSyz147064 wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal); 773f595a68aSyz147064 774bcb5c89dSSowmini Varadhan ratesp = malloc(WLDP_BUFSIZE); 775bcb5c89dSSowmini Varadhan if (ratesp == NULL) { 776bcb5c89dSSowmini Varadhan status = DLADM_STATUS_NOMEM; 777bcb5c89dSSowmini Varadhan goto done; 778bcb5c89dSSowmini Varadhan } 779bcb5c89dSSowmini Varadhan 780*4ac67f02SAnurag S. Maskey if ((status = do_get_rate(handle, linkid, ratesp, WLDP_BUFSIZE)) 781bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK) 782f595a68aSyz147064 goto done; 783f595a68aSyz147064 784f595a68aSyz147064 if (ratesp->wl_rates_num > 0) { 785f595a68aSyz147064 uint_t i, r = 0; 786f595a68aSyz147064 787f595a68aSyz147064 for (i = 0; i < ratesp->wl_rates_num; i++) { 788f595a68aSyz147064 if (ratesp->wl_rates_rates[i] > r) 789f595a68aSyz147064 r = ratesp->wl_rates_rates[i]; 790f595a68aSyz147064 } 791f595a68aSyz147064 wl_attrp->wa_speed = r; 792f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 793f595a68aSyz147064 } 794f595a68aSyz147064 795*4ac67f02SAnurag S. Maskey if ((status = do_get_authmode(handle, linkid, &authmode, 796bcb5c89dSSowmini Varadhan sizeof (authmode))) != DLADM_STATUS_OK) 797f595a68aSyz147064 goto done; 798f595a68aSyz147064 799f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 800f595a68aSyz147064 801f595a68aSyz147064 switch (authmode) { 802f595a68aSyz147064 case WL_OPENSYSTEM: 803f595a68aSyz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN; 804f595a68aSyz147064 break; 805f595a68aSyz147064 case WL_SHAREDKEY: 806f595a68aSyz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED; 807f595a68aSyz147064 break; 808f595a68aSyz147064 default: 809f595a68aSyz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH; 810f595a68aSyz147064 break; 811f595a68aSyz147064 } 812f595a68aSyz147064 813*4ac67f02SAnurag S. Maskey if ((status = do_get_bsstype(handle, linkid, &bsstype, 814bcb5c89dSSowmini Varadhan sizeof (bsstype))) != DLADM_STATUS_OK) 815f595a68aSyz147064 goto done; 816f595a68aSyz147064 817f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 818f595a68aSyz147064 819f595a68aSyz147064 switch (bsstype) { 820f595a68aSyz147064 case WL_BSS_BSS: 821f595a68aSyz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS; 822f595a68aSyz147064 break; 823f595a68aSyz147064 case WL_BSS_IBSS: 824f595a68aSyz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS; 825f595a68aSyz147064 break; 826f595a68aSyz147064 case WL_BSS_ANY: 827f595a68aSyz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY; 828f595a68aSyz147064 break; 829f595a68aSyz147064 default: 830f595a68aSyz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE; 831f595a68aSyz147064 break; 832f595a68aSyz147064 } 833f595a68aSyz147064 834*4ac67f02SAnurag S. Maskey if ((status = do_get_mode(handle, linkid, &wl_phy_conf, 835bcb5c89dSSowmini Varadhan sizeof (wl_phy_conf))) != DLADM_STATUS_OK) 836f595a68aSyz147064 goto done; 837f595a68aSyz147064 838bcb5c89dSSowmini Varadhan wl_attrp->wa_mode = do_convert_mode(&wl_phy_conf); 839f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 840f595a68aSyz147064 if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE) 841f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 842f595a68aSyz147064 843f595a68aSyz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 844f595a68aSyz147064 status = DLADM_STATUS_OK; 845f595a68aSyz147064 846f595a68aSyz147064 done: 847bcb5c89dSSowmini Varadhan free(ratesp); 848f595a68aSyz147064 return (status); 849f595a68aSyz147064 } 850f595a68aSyz147064 851d62bc4baSyz147064 /* 852d62bc4baSyz147064 * Check to see if the link is wireless. 853d62bc4baSyz147064 */ 854eae72b5bSSebastien Roy static dladm_status_t 855*4ac67f02SAnurag S. Maskey dladm_wlan_validate(dladm_handle_t handle, datalink_id_t linkid) 856eae72b5bSSebastien Roy { 857eae72b5bSSebastien Roy uint32_t media; 858eae72b5bSSebastien Roy dladm_status_t status; 859f595a68aSyz147064 860*4ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, 861*4ac67f02SAnurag S. Maskey NULL, 0); 862eae72b5bSSebastien Roy if (status == DLADM_STATUS_OK) { 863eae72b5bSSebastien Roy if (media != DL_WIFI) 864eae72b5bSSebastien Roy status = DLADM_STATUS_LINKINVAL; 865eae72b5bSSebastien Roy } 866f595a68aSyz147064 return (status); 867f595a68aSyz147064 } 868f595a68aSyz147064 869f595a68aSyz147064 static boolean_t 870f595a68aSyz147064 find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp) 871f595a68aSyz147064 { 872f595a68aSyz147064 int i; 873f595a68aSyz147064 874f595a68aSyz147064 for (i = 0; i < cnt; i++) { 875f595a68aSyz147064 if (strcasecmp(str, vdp[i].vd_name) == 0) { 876f595a68aSyz147064 *valp = vdp[i].vd_val; 877f595a68aSyz147064 return (B_TRUE); 878f595a68aSyz147064 } 879f595a68aSyz147064 } 880f595a68aSyz147064 return (B_FALSE); 881f595a68aSyz147064 } 882f595a68aSyz147064 883f595a68aSyz147064 static boolean_t 884f595a68aSyz147064 find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp) 885f595a68aSyz147064 { 886f595a68aSyz147064 int i; 887f595a68aSyz147064 888f595a68aSyz147064 for (i = 0; i < cnt; i++) { 889f595a68aSyz147064 if (val == vdp[i].vd_val) { 890f595a68aSyz147064 *strp = vdp[i].vd_name; 891f595a68aSyz147064 return (B_TRUE); 892f595a68aSyz147064 } 893f595a68aSyz147064 } 894f595a68aSyz147064 return (B_FALSE); 895f595a68aSyz147064 } 896f595a68aSyz147064 897f595a68aSyz147064 const char * 898f595a68aSyz147064 dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf) 899f595a68aSyz147064 { 900f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes); 901f595a68aSyz147064 return (buf); 902f595a68aSyz147064 } 903f595a68aSyz147064 904f595a68aSyz147064 const char * 905f595a68aSyz147064 dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf) 906f595a68aSyz147064 { 907f595a68aSyz147064 return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN, 908f595a68aSyz147064 IFT_OTHER)); 909f595a68aSyz147064 } 910f595a68aSyz147064 911f595a68aSyz147064 static const char * 912f595a68aSyz147064 dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf) 913f595a68aSyz147064 { 914f595a68aSyz147064 char *s; 915f595a68aSyz147064 916f595a68aSyz147064 if (!find_name_by_val(val, vdp, cnt, &s)) 917f595a68aSyz147064 s = ""; 918f595a68aSyz147064 919f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 920f595a68aSyz147064 return (buf); 921f595a68aSyz147064 } 922f595a68aSyz147064 923f595a68aSyz147064 const char * 924f595a68aSyz147064 dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf) 925f595a68aSyz147064 { 926f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals, 927f595a68aSyz147064 VALCNT(secmode_vals), buf)); 928f595a68aSyz147064 } 929f595a68aSyz147064 930f595a68aSyz147064 const char * 931f595a68aSyz147064 dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf) 932f595a68aSyz147064 { 933f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*strength, strength_vals, 934f595a68aSyz147064 VALCNT(strength_vals), buf)); 935f595a68aSyz147064 } 936f595a68aSyz147064 937f595a68aSyz147064 const char * 938f595a68aSyz147064 dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf) 939f595a68aSyz147064 { 940f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*mode, mode_vals, 941f595a68aSyz147064 VALCNT(mode_vals), buf)); 942f595a68aSyz147064 } 943f595a68aSyz147064 944f595a68aSyz147064 const char * 945f595a68aSyz147064 dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf) 946f595a68aSyz147064 { 947f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2, 948f595a68aSyz147064 (float)(*speed) / 2); 949f595a68aSyz147064 return (buf); 950f595a68aSyz147064 } 951f595a68aSyz147064 952f595a68aSyz147064 const char * 953f595a68aSyz147064 dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf) 954f595a68aSyz147064 { 955f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*auth, auth_vals, 956f595a68aSyz147064 VALCNT(auth_vals), buf)); 957f595a68aSyz147064 } 958f595a68aSyz147064 959f595a68aSyz147064 const char * 960f595a68aSyz147064 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf) 961f595a68aSyz147064 { 962f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals, 963f595a68aSyz147064 VALCNT(bsstype_vals), buf)); 964f595a68aSyz147064 } 965f595a68aSyz147064 966f595a68aSyz147064 const char * 967f595a68aSyz147064 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf) 968f595a68aSyz147064 { 969f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals, 970f595a68aSyz147064 VALCNT(linkstatus_vals), buf)); 971f595a68aSyz147064 } 972f595a68aSyz147064 973f595a68aSyz147064 dladm_status_t 974f595a68aSyz147064 dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid) 975f595a68aSyz147064 { 9760d2f4bc9Sff224033 if (str[0] == '\0' || strlen(str) > DLADM_WLAN_MAX_ESSID_LEN - 1) 977f595a68aSyz147064 return (DLADM_STATUS_BADARG); 978f595a68aSyz147064 979f595a68aSyz147064 (void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN); 980f595a68aSyz147064 return (DLADM_STATUS_OK); 981f595a68aSyz147064 } 982f595a68aSyz147064 983f595a68aSyz147064 dladm_status_t 984f595a68aSyz147064 dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid) 985f595a68aSyz147064 { 986f595a68aSyz147064 int len; 987f595a68aSyz147064 uchar_t *buf; 988f595a68aSyz147064 989f595a68aSyz147064 buf = _link_aton(str, &len); 990f595a68aSyz147064 if (buf == NULL) 991f595a68aSyz147064 return (DLADM_STATUS_BADARG); 992f595a68aSyz147064 993f595a68aSyz147064 if (len != DLADM_WLAN_BSSID_LEN) { 994f595a68aSyz147064 free(buf); 995f595a68aSyz147064 return (DLADM_STATUS_BADARG); 996f595a68aSyz147064 } 997f595a68aSyz147064 998f595a68aSyz147064 (void) memcpy(bssid->wb_bytes, buf, len); 999f595a68aSyz147064 free(buf); 1000f595a68aSyz147064 return (DLADM_STATUS_OK); 1001f595a68aSyz147064 } 1002f595a68aSyz147064 1003f595a68aSyz147064 dladm_status_t 1004f595a68aSyz147064 dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode) 1005f595a68aSyz147064 { 1006f595a68aSyz147064 uint_t val; 1007f595a68aSyz147064 1008f595a68aSyz147064 if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val)) 1009f595a68aSyz147064 return (DLADM_STATUS_BADARG); 1010f595a68aSyz147064 1011f595a68aSyz147064 *secmode = (dladm_wlan_secmode_t)val; 1012f595a68aSyz147064 return (DLADM_STATUS_OK); 1013f595a68aSyz147064 } 1014f595a68aSyz147064 1015f595a68aSyz147064 dladm_status_t 1016f595a68aSyz147064 dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength) 1017f595a68aSyz147064 { 1018f595a68aSyz147064 uint_t val; 1019f595a68aSyz147064 1020f595a68aSyz147064 if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val)) 1021f595a68aSyz147064 return (DLADM_STATUS_BADARG); 1022f595a68aSyz147064 1023f595a68aSyz147064 *strength = (dladm_wlan_strength_t)val; 1024f595a68aSyz147064 return (DLADM_STATUS_OK); 1025f595a68aSyz147064 } 1026f595a68aSyz147064 1027f595a68aSyz147064 dladm_status_t 1028f595a68aSyz147064 dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode) 1029f595a68aSyz147064 { 1030f595a68aSyz147064 uint_t val; 1031f595a68aSyz147064 1032f595a68aSyz147064 if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val)) 1033f595a68aSyz147064 return (DLADM_STATUS_BADARG); 1034f595a68aSyz147064 1035f595a68aSyz147064 *mode = (dladm_wlan_mode_t)val; 1036f595a68aSyz147064 return (DLADM_STATUS_OK); 1037f595a68aSyz147064 } 1038f595a68aSyz147064 1039f595a68aSyz147064 dladm_status_t 1040f595a68aSyz147064 dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed) 1041f595a68aSyz147064 { 1042f595a68aSyz147064 *speed = (dladm_wlan_speed_t)(atof(str) * 2); 1043f595a68aSyz147064 return (DLADM_STATUS_OK); 1044f595a68aSyz147064 } 1045f595a68aSyz147064 1046f595a68aSyz147064 dladm_status_t 1047f595a68aSyz147064 dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth) 1048f595a68aSyz147064 { 1049f595a68aSyz147064 uint_t val; 1050f595a68aSyz147064 1051f595a68aSyz147064 if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val)) 1052f595a68aSyz147064 return (DLADM_STATUS_BADARG); 1053f595a68aSyz147064 1054f595a68aSyz147064 *auth = (dladm_wlan_auth_t)val; 1055f595a68aSyz147064 return (DLADM_STATUS_OK); 1056f595a68aSyz147064 } 1057f595a68aSyz147064 1058f595a68aSyz147064 dladm_status_t 1059f595a68aSyz147064 dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype) 1060f595a68aSyz147064 { 1061f595a68aSyz147064 uint_t val; 1062f595a68aSyz147064 1063f595a68aSyz147064 if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val)) 1064f595a68aSyz147064 return (DLADM_STATUS_BADARG); 1065f595a68aSyz147064 1066f595a68aSyz147064 *bsstype = (dladm_wlan_bsstype_t)val; 1067f595a68aSyz147064 return (DLADM_STATUS_OK); 1068f595a68aSyz147064 } 1069f595a68aSyz147064 1070f595a68aSyz147064 dladm_status_t 1071f595a68aSyz147064 dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus) 1072f595a68aSyz147064 { 1073f595a68aSyz147064 uint_t val; 1074f595a68aSyz147064 1075d62bc4baSyz147064 if (!find_val_by_name(str, linkstatus_vals, 1076d62bc4baSyz147064 VALCNT(linkstatus_vals), &val)) { 1077f595a68aSyz147064 return (DLADM_STATUS_BADARG); 1078d62bc4baSyz147064 } 1079f595a68aSyz147064 1080f595a68aSyz147064 *linkstatus = (dladm_wlan_linkstatus_t)val; 1081f595a68aSyz147064 return (DLADM_STATUS_OK); 1082f595a68aSyz147064 } 1083f595a68aSyz147064 1084d62bc4baSyz147064 dladm_status_t 1085*4ac67f02SAnurag S. Maskey i_dladm_wlan_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid, 1086*4ac67f02SAnurag S. Maskey wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen) 1087f595a68aSyz147064 { 1088d62bc4baSyz147064 char linkname[MAXPATHLEN]; 1089d62bc4baSyz147064 int fd, rc; 1090f595a68aSyz147064 struct strioctl stri; 1091d62bc4baSyz147064 uint32_t flags; 1092d62bc4baSyz147064 dladm_status_t status; 1093d62bc4baSyz147064 uint32_t media; 1094d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 1095d62bc4baSyz147064 1096*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 1097*4ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 1098d62bc4baSyz147064 return (status); 1099d62bc4baSyz147064 } 1100d62bc4baSyz147064 1101d62bc4baSyz147064 if (media != DL_WIFI) 1102d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 1103d62bc4baSyz147064 1104d62bc4baSyz147064 if (!(flags & DLADM_OPT_ACTIVE)) 1105d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY); 1106d62bc4baSyz147064 1107d62bc4baSyz147064 /* 1108d62bc4baSyz147064 * dlpi_open() is not used here because libdlpi depends on libdladm, 1109d62bc4baSyz147064 * and we do not want to introduce recursive dependencies. 1110d62bc4baSyz147064 */ 1111d62bc4baSyz147064 (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link); 1112d62bc4baSyz147064 if ((fd = open(linkname, O_RDWR)) < 0) 1113eae72b5bSSebastien Roy return (dladm_errno2status(errno)); 1114f595a68aSyz147064 1115f595a68aSyz147064 gbuf->wldp_type = NET_802_11; 1116f595a68aSyz147064 gbuf->wldp_id = id; 1117f595a68aSyz147064 gbuf->wldp_length = len; 1118f595a68aSyz147064 1119f595a68aSyz147064 stri.ic_timout = 0; 1120f595a68aSyz147064 stri.ic_dp = (char *)gbuf; 1121f595a68aSyz147064 stri.ic_cmd = cmd; 1122f595a68aSyz147064 stri.ic_len = cmdlen; 1123f595a68aSyz147064 1124f595a68aSyz147064 if ((rc = ioctl(fd, I_STR, &stri)) != 0) { 1125d62bc4baSyz147064 if (rc > 0) { 1126d62bc4baSyz147064 /* 1127d62bc4baSyz147064 * Non-negative return value indicates the specific 1128d62bc4baSyz147064 * operation failed and the reason for the failure 1129d62bc4baSyz147064 * was stored in gbuf->wldp_result. 1130d62bc4baSyz147064 */ 1131d62bc4baSyz147064 status = dladm_wlan_wlresult2status(gbuf); 1132d62bc4baSyz147064 } else { 1133d62bc4baSyz147064 /* 1134d62bc4baSyz147064 * Negative return value indicates the ioctl failed. 1135d62bc4baSyz147064 */ 1136d62bc4baSyz147064 status = dladm_errno2status(errno); 1137f595a68aSyz147064 } 1138d62bc4baSyz147064 } 1139d62bc4baSyz147064 (void) close(fd); 1140d62bc4baSyz147064 return (status); 1141f595a68aSyz147064 } 1142f595a68aSyz147064 1143bcb5c89dSSowmini Varadhan static dladm_status_t 1144*4ac67f02SAnurag S. Maskey do_cmd_ioctl(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1145*4ac67f02SAnurag S. Maskey int buflen, uint_t cmd) 1146f595a68aSyz147064 { 1147d62bc4baSyz147064 wldp_t *gbuf; 1148d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 1149d62bc4baSyz147064 1150d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1151d62bc4baSyz147064 return (DLADM_STATUS_NOMEM); 1152d62bc4baSyz147064 1153f595a68aSyz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 1154*4ac67f02SAnurag S. Maskey status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, cmd, 1155*4ac67f02SAnurag S. Maskey WLDP_BUFSIZE, WLAN_COMMAND, sizeof (wldp_t)); 1156bcb5c89dSSowmini Varadhan (void) memcpy(buf, gbuf->wldp_buf, buflen); 1157d62bc4baSyz147064 free(gbuf); 1158d62bc4baSyz147064 return (status); 1159f595a68aSyz147064 } 1160f595a68aSyz147064 1161d62bc4baSyz147064 static dladm_status_t 1162*4ac67f02SAnurag S. Maskey do_scan(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1163f595a68aSyz147064 { 1164*4ac67f02SAnurag S. Maskey return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_SCAN)); 1165f595a68aSyz147064 } 1166f595a68aSyz147064 1167d62bc4baSyz147064 static dladm_status_t 1168*4ac67f02SAnurag S. Maskey do_disconnect(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1169*4ac67f02SAnurag S. Maskey int buflen) 1170f595a68aSyz147064 { 1171*4ac67f02SAnurag S. Maskey if (do_get_wpamode(handle, linkid, buf, buflen) == 0 && 1172bcb5c89dSSowmini Varadhan ((wl_wpa_t *)(buf))->wpa_flag > 0) 1173*4ac67f02SAnurag S. Maskey (void) wpa_instance_delete(handle, linkid); 1174a399b765Szf162725 1175*4ac67f02SAnurag S. Maskey return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_DISASSOCIATE)); 1176f595a68aSyz147064 } 1177f595a68aSyz147064 1178d62bc4baSyz147064 static dladm_status_t 1179*4ac67f02SAnurag S. Maskey do_get_esslist(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1180*4ac67f02SAnurag S. Maskey int buflen) 1181f595a68aSyz147064 { 1182*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESS_LIST, 1183bcb5c89dSSowmini Varadhan buflen, B_FALSE)); 1184f595a68aSyz147064 } 1185f595a68aSyz147064 1186f595a68aSyz147064 static dladm_status_t 1187*4ac67f02SAnurag S. Maskey do_get_bssid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1188f595a68aSyz147064 { 1189*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_BSSID, 1190bcb5c89dSSowmini Varadhan buflen, B_FALSE)); 1191d62bc4baSyz147064 } 1192d62bc4baSyz147064 1193d62bc4baSyz147064 static dladm_status_t 1194*4ac67f02SAnurag S. Maskey do_get_essid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1195*4ac67f02SAnurag S. Maskey { 1196*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESSID, 1197*4ac67f02SAnurag S. Maskey buflen, B_FALSE)); 1198*4ac67f02SAnurag S. Maskey } 1199*4ac67f02SAnurag S. Maskey 1200*4ac67f02SAnurag S. Maskey static dladm_status_t 1201*4ac67f02SAnurag S. Maskey do_get_bsstype(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1202*4ac67f02SAnurag S. Maskey int buflen) 1203*4ac67f02SAnurag S. Maskey { 1204*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_BSSTYPE, 1205*4ac67f02SAnurag S. Maskey buflen, B_FALSE)); 1206*4ac67f02SAnurag S. Maskey } 1207*4ac67f02SAnurag S. Maskey 1208*4ac67f02SAnurag S. Maskey static dladm_status_t 1209*4ac67f02SAnurag S. Maskey do_get_linkstatus(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1210*4ac67f02SAnurag S. Maskey int buflen) 1211*4ac67f02SAnurag S. Maskey { 1212*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_LINKSTATUS, 1213*4ac67f02SAnurag S. Maskey buflen, B_FALSE)); 1214*4ac67f02SAnurag S. Maskey } 1215*4ac67f02SAnurag S. Maskey 1216*4ac67f02SAnurag S. Maskey static dladm_status_t 1217*4ac67f02SAnurag S. Maskey do_get_rate(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1218*4ac67f02SAnurag S. Maskey { 1219*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, 1220*4ac67f02SAnurag S. Maskey MAC_PROP_WL_DESIRED_RATES, buflen, B_FALSE)); 1221*4ac67f02SAnurag S. Maskey } 1222*4ac67f02SAnurag S. Maskey 1223*4ac67f02SAnurag S. Maskey static dladm_status_t 1224*4ac67f02SAnurag S. Maskey do_get_authmode(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1225*4ac67f02SAnurag S. Maskey int buflen) 1226*4ac67f02SAnurag S. Maskey { 1227*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, 1228*4ac67f02SAnurag S. Maskey MAC_PROP_WL_AUTH_MODE, buflen, B_FALSE)); 1229*4ac67f02SAnurag S. Maskey } 1230*4ac67f02SAnurag S. Maskey 1231*4ac67f02SAnurag S. Maskey static dladm_status_t 1232*4ac67f02SAnurag S. Maskey do_get_encryption(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1233*4ac67f02SAnurag S. Maskey int buflen) 1234*4ac67f02SAnurag S. Maskey { 1235*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, 1236*4ac67f02SAnurag S. Maskey MAC_PROP_WL_ENCRYPTION, buflen, B_FALSE)); 1237*4ac67f02SAnurag S. Maskey } 1238*4ac67f02SAnurag S. Maskey 1239*4ac67f02SAnurag S. Maskey static dladm_status_t 1240*4ac67f02SAnurag S. Maskey do_get_signal(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1241*4ac67f02SAnurag S. Maskey int buflen) 1242*4ac67f02SAnurag S. Maskey { 1243*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RSSI, 1244*4ac67f02SAnurag S. Maskey buflen, B_FALSE)); 1245*4ac67f02SAnurag S. Maskey } 1246*4ac67f02SAnurag S. Maskey 1247*4ac67f02SAnurag S. Maskey static dladm_status_t 1248*4ac67f02SAnurag S. Maskey do_get_mode(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1249*4ac67f02SAnurag S. Maskey { 1250*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG, 1251*4ac67f02SAnurag S. Maskey buflen, B_FALSE)); 1252*4ac67f02SAnurag S. Maskey } 1253*4ac67f02SAnurag S. Maskey 1254*4ac67f02SAnurag S. Maskey static dladm_status_t 1255*4ac67f02SAnurag S. Maskey do_set_bsstype(dladm_handle_t handle, datalink_id_t linkid, 1256*4ac67f02SAnurag S. Maskey dladm_wlan_bsstype_t *bsstype) 1257f595a68aSyz147064 { 1258f595a68aSyz147064 wl_bss_type_t ibsstype; 1259f595a68aSyz147064 1260f595a68aSyz147064 switch (*bsstype) { 1261f595a68aSyz147064 case DLADM_WLAN_BSSTYPE_BSS: 1262f595a68aSyz147064 ibsstype = WL_BSS_BSS; 1263f595a68aSyz147064 break; 1264f595a68aSyz147064 case DLADM_WLAN_BSSTYPE_IBSS: 1265f595a68aSyz147064 ibsstype = WL_BSS_IBSS; 1266f595a68aSyz147064 break; 1267f595a68aSyz147064 default: 1268f595a68aSyz147064 ibsstype = WL_BSS_ANY; 1269f595a68aSyz147064 break; 1270f595a68aSyz147064 } 1271*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &ibsstype, 1272*4ac67f02SAnurag S. Maskey MAC_PROP_WL_BSSTYPE, sizeof (ibsstype), B_TRUE)); 1273f595a68aSyz147064 } 1274f595a68aSyz147064 1275d62bc4baSyz147064 static dladm_status_t 1276*4ac67f02SAnurag S. Maskey do_set_authmode(dladm_handle_t handle, datalink_id_t linkid, 1277*4ac67f02SAnurag S. Maskey dladm_wlan_auth_t *auth) 1278f595a68aSyz147064 { 1279f595a68aSyz147064 wl_authmode_t auth_mode; 1280f595a68aSyz147064 1281f595a68aSyz147064 switch (*auth) { 1282f595a68aSyz147064 case DLADM_WLAN_AUTH_OPEN: 1283f595a68aSyz147064 auth_mode = WL_OPENSYSTEM; 1284f595a68aSyz147064 break; 1285f595a68aSyz147064 case DLADM_WLAN_AUTH_SHARED: 1286f595a68aSyz147064 auth_mode = WL_SHAREDKEY; 1287f595a68aSyz147064 break; 1288f595a68aSyz147064 default: 1289d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1290f595a68aSyz147064 } 1291*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &auth_mode, 1292*4ac67f02SAnurag S. Maskey MAC_PROP_WL_AUTH_MODE, sizeof (auth_mode), B_TRUE)); 1293f595a68aSyz147064 } 1294f595a68aSyz147064 1295d62bc4baSyz147064 static dladm_status_t 1296*4ac67f02SAnurag S. Maskey do_set_encryption(dladm_handle_t handle, datalink_id_t linkid, 1297*4ac67f02SAnurag S. Maskey dladm_wlan_secmode_t *secmode) 1298f595a68aSyz147064 { 1299f595a68aSyz147064 wl_encryption_t encryption; 1300f595a68aSyz147064 1301f595a68aSyz147064 switch (*secmode) { 1302f595a68aSyz147064 case DLADM_WLAN_SECMODE_NONE: 1303f595a68aSyz147064 encryption = WL_NOENCRYPTION; 1304f595a68aSyz147064 break; 1305f595a68aSyz147064 case DLADM_WLAN_SECMODE_WEP: 1306f595a68aSyz147064 encryption = WL_ENC_WEP; 1307f595a68aSyz147064 break; 1308a399b765Szf162725 case DLADM_WLAN_SECMODE_WPA: 1309a399b765Szf162725 return (0); 1310f595a68aSyz147064 default: 1311d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP); 1312f595a68aSyz147064 } 1313*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &encryption, 1314*4ac67f02SAnurag S. Maskey MAC_PROP_WL_ENCRYPTION, sizeof (encryption), B_TRUE)); 1315f595a68aSyz147064 } 1316f595a68aSyz147064 1317d62bc4baSyz147064 static dladm_status_t 1318*4ac67f02SAnurag S. Maskey do_set_key(dladm_handle_t handle, datalink_id_t linkid, dladm_wlan_key_t *keys, 1319f595a68aSyz147064 uint_t key_count) 1320f595a68aSyz147064 { 1321f595a68aSyz147064 int i; 1322f595a68aSyz147064 wl_wep_key_t *wkp; 1323f595a68aSyz147064 wl_wep_key_tab_t wepkey_tab; 1324a399b765Szf162725 dladm_wlan_key_t *kp; 1325f595a68aSyz147064 1326f595a68aSyz147064 if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL) 1327d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 1328f595a68aSyz147064 1329f595a68aSyz147064 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab)); 1330f595a68aSyz147064 for (i = 0; i < MAX_NWEPKEYS; i++) 1331f595a68aSyz147064 wepkey_tab[i].wl_wep_operation = WL_NUL; 1332f595a68aSyz147064 1333f595a68aSyz147064 for (i = 0; i < key_count; i++) { 1334f595a68aSyz147064 kp = &keys[i]; 1335f595a68aSyz147064 if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS) 1336d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 1337f595a68aSyz147064 if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN && 1338f595a68aSyz147064 kp->wk_len != DLADM_WLAN_WEPKEY128_LEN) 1339d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 1340f595a68aSyz147064 1341f595a68aSyz147064 wkp = &wepkey_tab[kp->wk_idx - 1]; 1342f595a68aSyz147064 wkp->wl_wep_operation = WL_ADD; 1343f595a68aSyz147064 wkp->wl_wep_length = kp->wk_len; 1344f595a68aSyz147064 (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len); 1345f595a68aSyz147064 } 1346f595a68aSyz147064 1347*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wepkey_tab, 1348*4ac67f02SAnurag S. Maskey MAC_PROP_WL_KEY_TAB, sizeof (wepkey_tab), B_TRUE)); 1349f595a68aSyz147064 } 1350f595a68aSyz147064 1351d62bc4baSyz147064 static dladm_status_t 1352*4ac67f02SAnurag S. Maskey do_set_essid(dladm_handle_t handle, datalink_id_t linkid, 1353*4ac67f02SAnurag S. Maskey dladm_wlan_essid_t *essid) 1354f595a68aSyz147064 { 1355f595a68aSyz147064 wl_essid_t iessid; 1356f595a68aSyz147064 1357f595a68aSyz147064 (void) memset(&iessid, 0, sizeof (essid)); 1358f595a68aSyz147064 1359f595a68aSyz147064 if (essid != NULL && essid->we_bytes[0] != '\0') { 1360f595a68aSyz147064 iessid.wl_essid_length = strlen(essid->we_bytes); 1361f595a68aSyz147064 (void) strlcpy(iessid.wl_essid_essid, essid->we_bytes, 1362f595a68aSyz147064 sizeof (iessid.wl_essid_essid)); 1363f595a68aSyz147064 } else { 1364d62bc4baSyz147064 return (DLADM_STATUS_BADARG); 1365f595a68aSyz147064 } 1366*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &iessid, MAC_PROP_WL_ESSID, 1367bcb5c89dSSowmini Varadhan sizeof (iessid), B_TRUE)); 1368f595a68aSyz147064 } 1369f595a68aSyz147064 1370f595a68aSyz147064 static dladm_status_t 1371*4ac67f02SAnurag S. Maskey do_set_channel(dladm_handle_t handle, datalink_id_t linkid, 1372*4ac67f02SAnurag S. Maskey dladm_wlan_channel_t *channel) 1373f595a68aSyz147064 { 1374f595a68aSyz147064 wl_phy_conf_t phy_conf; 1375f595a68aSyz147064 1376f595a68aSyz147064 if (*channel > MAX_CHANNEL_NUM) 1377d62bc4baSyz147064 return (DLADM_STATUS_BADVAL); 1378f595a68aSyz147064 1379f595a68aSyz147064 (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); 1380f595a68aSyz147064 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel; 1381f595a68aSyz147064 1382*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &phy_conf, 1383*4ac67f02SAnurag S. Maskey MAC_PROP_WL_PHY_CONFIG, sizeof (phy_conf), B_TRUE)); 1384f595a68aSyz147064 } 1385f595a68aSyz147064 1386d62bc4baSyz147064 static dladm_status_t 1387*4ac67f02SAnurag S. Maskey do_set_createibss(dladm_handle_t handle, datalink_id_t linkid, 1388*4ac67f02SAnurag S. Maskey boolean_t *create_ibss) 1389f595a68aSyz147064 { 1390f595a68aSyz147064 wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss); 1391f595a68aSyz147064 1392*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &cr, MAC_PROP_WL_CREATE_IBSS, 1393bcb5c89dSSowmini Varadhan sizeof (cr), B_TRUE)); 1394f595a68aSyz147064 } 1395f595a68aSyz147064 1396f595a68aSyz147064 static void 1397f595a68aSyz147064 generate_essid(dladm_wlan_essid_t *essid) 1398f595a68aSyz147064 { 1399f595a68aSyz147064 srandom(gethrtime()); 1400f595a68aSyz147064 (void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d", 1401f595a68aSyz147064 random()); 1402f595a68aSyz147064 } 1403a399b765Szf162725 1404d62bc4baSyz147064 static dladm_status_t 1405*4ac67f02SAnurag S. Maskey do_get_capability(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1406*4ac67f02SAnurag S. Maskey int buflen) 1407a399b765Szf162725 { 1408*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_CAPABILITY, 1409bcb5c89dSSowmini Varadhan buflen, B_FALSE)); 1410a399b765Szf162725 } 1411a399b765Szf162725 1412a399b765Szf162725 static dladm_status_t 1413*4ac67f02SAnurag S. Maskey do_get_wpamode(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1414*4ac67f02SAnurag S. Maskey int buflen) 1415a399b765Szf162725 { 1416*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_WPA, buflen, 1417bcb5c89dSSowmini Varadhan B_FALSE)); 1418a399b765Szf162725 } 1419a399b765Szf162725 1420a399b765Szf162725 dladm_status_t 1421*4ac67f02SAnurag S. Maskey dladm_wlan_wpa_get_sr(dladm_handle_t handle, datalink_id_t linkid, 1422*4ac67f02SAnurag S. Maskey dladm_wlan_ess_t *sr, uint_t escnt, uint_t *estot) 1423a399b765Szf162725 { 1424a399b765Szf162725 int i, n; 1425a399b765Szf162725 wl_wpa_ess_t *es; 1426a399b765Szf162725 dladm_status_t status; 1427a399b765Szf162725 1428bcb5c89dSSowmini Varadhan es = malloc(WLDP_BUFSIZE); 1429bcb5c89dSSowmini Varadhan if (es == NULL) 1430a399b765Szf162725 return (DLADM_STATUS_NOMEM); 1431a399b765Szf162725 1432*4ac67f02SAnurag S. Maskey status = i_dladm_wlan_param(handle, linkid, es, MAC_PROP_WL_SCANRESULTS, 1433bcb5c89dSSowmini Varadhan WLDP_BUFSIZE, B_FALSE); 1434a399b765Szf162725 1435a399b765Szf162725 if (status == DLADM_STATUS_OK) { 1436a399b765Szf162725 n = (es->count > escnt) ? escnt : es->count; 1437a399b765Szf162725 for (i = 0; i < n; i ++) { 1438a399b765Szf162725 (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid, 1439a399b765Szf162725 DLADM_WLAN_BSSID_LEN); 1440a399b765Szf162725 sr[i].we_ssid_len = es->ess[i].ssid_len; 1441a399b765Szf162725 (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid, 1442a399b765Szf162725 es->ess[i].ssid_len); 1443a399b765Szf162725 sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len; 1444a399b765Szf162725 (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie, 1445a399b765Szf162725 es->ess[i].wpa_ie_len); 1446a399b765Szf162725 sr[i].we_freq = es->ess[i].freq; 1447a399b765Szf162725 } 1448a399b765Szf162725 *estot = n; 1449a399b765Szf162725 } 1450a399b765Szf162725 1451bcb5c89dSSowmini Varadhan free(es); 1452a399b765Szf162725 return (status); 1453a399b765Szf162725 } 1454a399b765Szf162725 1455a399b765Szf162725 dladm_status_t 1456*4ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_ie(dladm_handle_t handle, datalink_id_t linkid, 1457*4ac67f02SAnurag S. Maskey uint8_t *wpa_ie, uint_t wpa_ie_len) 1458a399b765Szf162725 { 1459a399b765Szf162725 wl_wpa_ie_t *ie; 1460a399b765Szf162725 uint_t len; 1461a399b765Szf162725 dladm_status_t status; 1462a399b765Szf162725 1463a399b765Szf162725 if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN) 1464a399b765Szf162725 return (DLADM_STATUS_BADARG); 1465a399b765Szf162725 len = sizeof (wl_wpa_ie_t) + wpa_ie_len; 1466a399b765Szf162725 ie = malloc(len); 1467a399b765Szf162725 if (ie == NULL) 1468a399b765Szf162725 return (DLADM_STATUS_NOMEM); 1469a399b765Szf162725 1470a399b765Szf162725 (void) memset(ie, 0, len); 1471a399b765Szf162725 ie->wpa_ie_len = wpa_ie_len; 1472a399b765Szf162725 (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len); 1473a399b765Szf162725 1474*4ac67f02SAnurag S. Maskey status = i_dladm_wlan_param(handle, linkid, ie, MAC_PROP_WL_SETOPTIE, 1475*4ac67f02SAnurag S. Maskey len, B_TRUE); 1476a399b765Szf162725 free(ie); 1477a399b765Szf162725 1478a399b765Szf162725 return (status); 1479a399b765Szf162725 } 1480a399b765Szf162725 1481a399b765Szf162725 dladm_status_t 1482*4ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_wpa(dladm_handle_t handle, datalink_id_t linkid, 1483*4ac67f02SAnurag S. Maskey boolean_t flag) 1484a399b765Szf162725 { 1485a399b765Szf162725 wl_wpa_t wpa; 1486a399b765Szf162725 1487a399b765Szf162725 wpa.wpa_flag = flag; 1488*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wpa, MAC_PROP_WL_WPA, 1489bcb5c89dSSowmini Varadhan sizeof (wpa), B_TRUE)); 1490a399b765Szf162725 } 1491a399b765Szf162725 1492a399b765Szf162725 dladm_status_t 1493*4ac67f02SAnurag S. Maskey dladm_wlan_wpa_del_key(dladm_handle_t handle, datalink_id_t linkid, 1494*4ac67f02SAnurag S. Maskey uint_t key_idx, const dladm_wlan_bssid_t *addr) 1495a399b765Szf162725 { 1496a399b765Szf162725 wl_del_key_t wk; 1497a399b765Szf162725 1498a399b765Szf162725 wk.idk_keyix = key_idx; 1499a399b765Szf162725 if (addr != NULL) 1500a399b765Szf162725 (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes, 1501a399b765Szf162725 DLADM_WLAN_BSSID_LEN); 1502a399b765Szf162725 1503*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_DELKEY, 1504bcb5c89dSSowmini Varadhan sizeof (wk), B_TRUE)); 1505a399b765Szf162725 } 1506a399b765Szf162725 1507a399b765Szf162725 dladm_status_t 1508*4ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_key(dladm_handle_t handle, datalink_id_t linkid, 1509*4ac67f02SAnurag S. Maskey dladm_wlan_cipher_t cipher, const dladm_wlan_bssid_t *addr, 1510*4ac67f02SAnurag S. Maskey boolean_t set_tx, uint64_t seq, uint_t key_idx, uint8_t *key, 1511*4ac67f02SAnurag S. Maskey uint_t key_len) 1512a399b765Szf162725 { 1513a399b765Szf162725 wl_key_t wk; 1514a399b765Szf162725 1515a399b765Szf162725 (void) memset(&wk, 0, sizeof (wl_key_t)); 1516a399b765Szf162725 switch (cipher) { 1517a399b765Szf162725 case DLADM_WLAN_CIPHER_WEP: 1518a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_WEP; 1519a399b765Szf162725 break; 1520a399b765Szf162725 case DLADM_WLAN_CIPHER_TKIP: 1521a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_TKIP; 1522a399b765Szf162725 break; 1523a399b765Szf162725 case DLADM_WLAN_CIPHER_AES_OCB: 1524a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_OCB; 1525a399b765Szf162725 break; 1526a399b765Szf162725 case DLADM_WLAN_CIPHER_AES_CCM: 1527a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_CCM; 1528a399b765Szf162725 break; 1529a399b765Szf162725 case DLADM_WLAN_CIPHER_CKIP: 1530a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_CKIP; 1531a399b765Szf162725 break; 1532a399b765Szf162725 case DLADM_WLAN_CIPHER_NONE: 1533a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_NONE; 1534a399b765Szf162725 break; 1535a399b765Szf162725 default: 1536a399b765Szf162725 return (DLADM_STATUS_BADARG); 1537a399b765Szf162725 } 1538a399b765Szf162725 wk.ik_flags = IEEE80211_KEY_RECV; 1539a399b765Szf162725 if (set_tx) { 1540a399b765Szf162725 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; 1541a399b765Szf162725 (void) memcpy(wk.ik_macaddr, addr->wb_bytes, 1542a399b765Szf162725 DLADM_WLAN_BSSID_LEN); 1543a399b765Szf162725 } else 1544a399b765Szf162725 (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN); 1545a399b765Szf162725 wk.ik_keyix = key_idx; 1546a399b765Szf162725 wk.ik_keylen = key_len; 1547a399b765Szf162725 (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */ 1548a399b765Szf162725 (void) memcpy(wk.ik_keydata, key, key_len); 1549a399b765Szf162725 1550*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_KEY, 1551bcb5c89dSSowmini Varadhan sizeof (wk), B_TRUE)); 1552a399b765Szf162725 } 1553a399b765Szf162725 1554a399b765Szf162725 dladm_status_t 1555*4ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_mlme(dladm_handle_t handle, datalink_id_t linkid, 1556*4ac67f02SAnurag S. Maskey dladm_wlan_mlme_op_t op, dladm_wlan_reason_t reason, 1557*4ac67f02SAnurag S. Maskey dladm_wlan_bssid_t *bssid) 1558a399b765Szf162725 { 1559a399b765Szf162725 wl_mlme_t mlme; 1560a399b765Szf162725 1561a399b765Szf162725 (void) memset(&mlme, 0, sizeof (wl_mlme_t)); 1562a399b765Szf162725 switch (op) { 1563a399b765Szf162725 case DLADM_WLAN_MLME_ASSOC: 1564a399b765Szf162725 mlme.im_op = IEEE80211_MLME_ASSOC; 1565a399b765Szf162725 break; 1566a399b765Szf162725 case DLADM_WLAN_MLME_DISASSOC: 1567a399b765Szf162725 mlme.im_op = IEEE80211_MLME_DISASSOC; 1568a399b765Szf162725 break; 1569a399b765Szf162725 default: 1570a399b765Szf162725 return (DLADM_STATUS_BADARG); 1571a399b765Szf162725 } 1572a399b765Szf162725 mlme.im_reason = reason; 1573a399b765Szf162725 if (bssid != NULL) 1574a399b765Szf162725 (void) memcpy(mlme.im_macaddr, bssid->wb_bytes, 1575a399b765Szf162725 DLADM_WLAN_BSSID_LEN); 1576a399b765Szf162725 1577*4ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &mlme, MAC_PROP_WL_MLME, 1578bcb5c89dSSowmini Varadhan sizeof (mlme), B_TRUE)); 1579a399b765Szf162725 } 1580a399b765Szf162725 1581a399b765Szf162725 /* 1582a399b765Szf162725 * routines of create instance 1583a399b765Szf162725 */ 1584a399b765Szf162725 static scf_propertygroup_t * 1585a399b765Szf162725 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance, 1586a399b765Szf162725 const char *pg_name, const char *pg_type) 1587a399b765Szf162725 { 1588a399b765Szf162725 scf_propertygroup_t *pg; 1589a399b765Szf162725 1590a399b765Szf162725 pg = scf_pg_create(handle); 1591a399b765Szf162725 if (pg == NULL) 1592a399b765Szf162725 return (NULL); 1593a399b765Szf162725 1594a399b765Szf162725 if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) { 1595a399b765Szf162725 scf_pg_destroy(pg); 1596a399b765Szf162725 return (NULL); 1597a399b765Szf162725 } 1598a399b765Szf162725 1599a399b765Szf162725 return (pg); 1600a399b765Szf162725 } 1601a399b765Szf162725 1602d62bc4baSyz147064 static dladm_status_t 1603a399b765Szf162725 add_new_property(scf_handle_t *handle, const char *prop_name, 1604a399b765Szf162725 scf_type_t type, const char *val, scf_transaction_t *tx) 1605a399b765Szf162725 { 1606a399b765Szf162725 scf_value_t *value = NULL; 1607a399b765Szf162725 scf_transaction_entry_t *entry = NULL; 1608a399b765Szf162725 1609a399b765Szf162725 entry = scf_entry_create(handle); 1610a399b765Szf162725 if (entry == NULL) 1611a399b765Szf162725 goto out; 1612a399b765Szf162725 1613a399b765Szf162725 value = scf_value_create(handle); 1614a399b765Szf162725 if (value == NULL) 1615a399b765Szf162725 goto out; 1616a399b765Szf162725 1617a399b765Szf162725 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) 1618a399b765Szf162725 goto out; 1619a399b765Szf162725 1620a399b765Szf162725 if (scf_value_set_from_string(value, type, val) != 0) 1621a399b765Szf162725 goto out; 1622a399b765Szf162725 1623a399b765Szf162725 if (scf_entry_add_value(entry, value) != 0) 1624a399b765Szf162725 goto out; 1625a399b765Szf162725 1626d62bc4baSyz147064 return (DLADM_STATUS_OK); 1627a399b765Szf162725 1628a399b765Szf162725 out: 1629a399b765Szf162725 if (value != NULL) 1630a399b765Szf162725 scf_value_destroy(value); 1631a399b765Szf162725 if (entry != NULL) 1632a399b765Szf162725 scf_entry_destroy(entry); 1633a399b765Szf162725 1634d62bc4baSyz147064 return (DLADM_STATUS_FAILED); 1635a399b765Szf162725 } 1636a399b765Szf162725 1637d62bc4baSyz147064 static dladm_status_t 1638a399b765Szf162725 add_pg_method(scf_handle_t *handle, scf_instance_t *instance, 1639a399b765Szf162725 const char *pg_name, const char *flags) 1640a399b765Szf162725 { 1641a399b765Szf162725 int rv, size; 1642d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED; 1643a399b765Szf162725 char *command = NULL; 1644a399b765Szf162725 scf_transaction_t *tran = NULL; 1645a399b765Szf162725 scf_propertygroup_t *pg; 1646a399b765Szf162725 1647a399b765Szf162725 pg = add_property_group_to_instance(handle, instance, 1648a399b765Szf162725 pg_name, SCF_GROUP_METHOD); 1649a399b765Szf162725 if (pg == NULL) 1650a399b765Szf162725 goto out; 1651a399b765Szf162725 1652a399b765Szf162725 tran = scf_transaction_create(handle); 1653a399b765Szf162725 if (tran == NULL) 1654a399b765Szf162725 goto out; 1655a399b765Szf162725 1656a399b765Szf162725 size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1; 1657a399b765Szf162725 command = malloc(size); 1658a399b765Szf162725 if (command == NULL) { 1659d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 1660a399b765Szf162725 goto out; 1661a399b765Szf162725 } 1662a399b765Szf162725 (void) snprintf(command, size, "%s %s", SVC_METHOD, flags); 1663a399b765Szf162725 1664a399b765Szf162725 do { 1665a399b765Szf162725 if (scf_transaction_start(tran, pg) != 0) 1666a399b765Szf162725 goto out; 1667a399b765Szf162725 1668a399b765Szf162725 if (add_new_property(handle, SCF_PROPERTY_EXEC, 1669d62bc4baSyz147064 SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) { 1670a399b765Szf162725 goto out; 1671a399b765Szf162725 } 1672a399b765Szf162725 1673a399b765Szf162725 rv = scf_transaction_commit(tran); 1674a399b765Szf162725 switch (rv) { 1675a399b765Szf162725 case 1: 1676d62bc4baSyz147064 status = DLADM_STATUS_OK; 1677a399b765Szf162725 goto out; 1678a399b765Szf162725 case 0: 1679a399b765Szf162725 scf_transaction_destroy_children(tran); 1680a399b765Szf162725 if (scf_pg_update(pg) == -1) { 1681a399b765Szf162725 goto out; 1682a399b765Szf162725 } 1683a399b765Szf162725 break; 1684a399b765Szf162725 case -1: 1685a399b765Szf162725 default: 1686a399b765Szf162725 goto out; 1687a399b765Szf162725 } 1688a399b765Szf162725 } while (rv == 0); 1689a399b765Szf162725 1690a399b765Szf162725 out: 1691a399b765Szf162725 if (tran != NULL) { 1692a399b765Szf162725 scf_transaction_destroy_children(tran); 1693a399b765Szf162725 scf_transaction_destroy(tran); 1694a399b765Szf162725 } 1695a399b765Szf162725 1696a399b765Szf162725 if (pg != NULL) 1697a399b765Szf162725 scf_pg_destroy(pg); 1698a399b765Szf162725 1699a399b765Szf162725 if (command != NULL) 1700a399b765Szf162725 free(command); 1701a399b765Szf162725 1702a399b765Szf162725 return (status); 1703a399b765Szf162725 } 1704a399b765Szf162725 1705d62bc4baSyz147064 static dladm_status_t 1706a399b765Szf162725 do_create_instance(scf_handle_t *handle, scf_service_t *svc, 1707a399b765Szf162725 const char *instance_name, const char *command) 1708a399b765Szf162725 { 1709d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED; 1710a399b765Szf162725 char *buf; 1711a399b765Szf162725 ssize_t max_fmri_len; 1712a399b765Szf162725 scf_instance_t *instance; 1713a399b765Szf162725 1714a399b765Szf162725 instance = scf_instance_create(handle); 1715a399b765Szf162725 if (instance == NULL) 1716a399b765Szf162725 goto out; 1717a399b765Szf162725 1718a399b765Szf162725 if (scf_service_add_instance(svc, instance_name, instance) != 0) { 1719a399b765Szf162725 if (scf_error() == SCF_ERROR_EXISTS) 1720a399b765Szf162725 /* Let the caller deal with the duplicate instance */ 1721d62bc4baSyz147064 status = DLADM_STATUS_EXIST; 1722a399b765Szf162725 goto out; 1723a399b765Szf162725 } 1724a399b765Szf162725 1725a399b765Szf162725 if (add_pg_method(handle, instance, "start", 1726d62bc4baSyz147064 command) != DLADM_STATUS_OK) { 1727a399b765Szf162725 goto out; 1728a399b765Szf162725 } 1729a399b765Szf162725 1730a399b765Szf162725 /* enabling the instance */ 1731a399b765Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 1732a399b765Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) 1733a399b765Szf162725 goto out; 1734a399b765Szf162725 1735a399b765Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 1736a399b765Szf162725 if ((smf_disable_instance(buf, 0) != 0) || 1737a399b765Szf162725 (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) { 1738a399b765Szf162725 goto out; 1739a399b765Szf162725 } 1740d62bc4baSyz147064 status = DLADM_STATUS_OK; 1741a399b765Szf162725 } 1742a399b765Szf162725 1743a399b765Szf162725 out: 1744a399b765Szf162725 if (instance != NULL) 1745a399b765Szf162725 scf_instance_destroy(instance); 1746a399b765Szf162725 return (status); 1747a399b765Szf162725 } 1748a399b765Szf162725 1749d62bc4baSyz147064 static dladm_status_t 1750a399b765Szf162725 create_instance(const char *instance_name, const char *command) 1751a399b765Szf162725 { 1752d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED; 1753a399b765Szf162725 scf_service_t *svc = NULL; 1754a399b765Szf162725 scf_handle_t *handle = NULL; 1755a399b765Szf162725 1756a399b765Szf162725 handle = scf_handle_create(SCF_VERSION); 1757a399b765Szf162725 if (handle == NULL) 1758a399b765Szf162725 goto out; 1759a399b765Szf162725 1760a399b765Szf162725 if (scf_handle_bind(handle) == -1) 1761a399b765Szf162725 goto out; 1762a399b765Szf162725 1763a399b765Szf162725 if ((svc = scf_service_create(handle)) == NULL) 1764a399b765Szf162725 goto out; 1765a399b765Szf162725 1766a399b765Szf162725 if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc, 1767a399b765Szf162725 NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) 1768a399b765Szf162725 goto out; 1769a399b765Szf162725 1770a399b765Szf162725 status = do_create_instance(handle, svc, instance_name, command); 1771a399b765Szf162725 1772a399b765Szf162725 out: 1773a399b765Szf162725 if (svc != NULL) 1774a399b765Szf162725 scf_service_destroy(svc); 1775a399b765Szf162725 1776a399b765Szf162725 if (handle != NULL) { 1777a399b765Szf162725 (void) scf_handle_unbind(handle); 1778a399b765Szf162725 scf_handle_destroy(handle); 1779a399b765Szf162725 } 1780a399b765Szf162725 1781a399b765Szf162725 return (status); 1782a399b765Szf162725 } 1783a399b765Szf162725 1784a399b765Szf162725 /* 1785a399b765Szf162725 * routines of delete instance 1786a399b765Szf162725 */ 1787a399b765Szf162725 #define DEFAULT_TIMEOUT 60000000 1788a399b765Szf162725 #define INIT_WAIT_USECS 50000 1789a399b765Szf162725 1790a399b765Szf162725 static void 1791a399b765Szf162725 wait_until_disabled(scf_handle_t *handle, char *fmri) 1792a399b765Szf162725 { 1793a399b765Szf162725 char *state; 1794a399b765Szf162725 useconds_t max; 1795a399b765Szf162725 useconds_t usecs; 1796a399b765Szf162725 uint64_t *cp = NULL; 1797a399b765Szf162725 scf_simple_prop_t *sp = NULL; 1798a399b765Szf162725 1799a399b765Szf162725 max = DEFAULT_TIMEOUT; 1800a399b765Szf162725 1801a399b765Szf162725 if (((sp = scf_simple_prop_get(handle, fmri, "stop", 1802a399b765Szf162725 SCF_PROPERTY_TIMEOUT)) != NULL) && 1803a399b765Szf162725 ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0)) 1804a399b765Szf162725 max = (*cp) * 1000000; /* convert to usecs */ 1805a399b765Szf162725 1806a399b765Szf162725 if (sp != NULL) 1807a399b765Szf162725 scf_simple_prop_free(sp); 1808a399b765Szf162725 1809a399b765Szf162725 for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) { 1810a399b765Szf162725 /* incremental wait */ 1811a399b765Szf162725 usecs *= 2; 1812a399b765Szf162725 usecs = (usecs > max) ? max : usecs; 1813a399b765Szf162725 1814a399b765Szf162725 (void) usleep(usecs); 1815a399b765Szf162725 1816a399b765Szf162725 /* Check state after the wait */ 1817a399b765Szf162725 if ((state = smf_get_state(fmri)) != NULL) { 1818a399b765Szf162725 if (strcmp(state, "disabled") == 0) 1819a399b765Szf162725 return; 1820a399b765Szf162725 } 1821a399b765Szf162725 } 1822a399b765Szf162725 } 1823a399b765Szf162725 1824d62bc4baSyz147064 static dladm_status_t 1825a399b765Szf162725 delete_instance(const char *instance_name) 1826a399b765Szf162725 { 1827d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED; 1828a399b765Szf162725 char *buf; 1829a399b765Szf162725 ssize_t max_fmri_len; 1830a399b765Szf162725 scf_scope_t *scope = NULL; 1831a399b765Szf162725 scf_service_t *svc = NULL; 1832a399b765Szf162725 scf_handle_t *handle = NULL; 1833a399b765Szf162725 scf_instance_t *instance; 1834a399b765Szf162725 1835a399b765Szf162725 handle = scf_handle_create(SCF_VERSION); 1836a399b765Szf162725 if (handle == NULL) 1837a399b765Szf162725 goto out; 1838a399b765Szf162725 1839a399b765Szf162725 if (scf_handle_bind(handle) == -1) 1840a399b765Szf162725 goto out; 1841a399b765Szf162725 1842a399b765Szf162725 if ((scope = scf_scope_create(handle)) == NULL) 1843a399b765Szf162725 goto out; 1844a399b765Szf162725 1845a399b765Szf162725 if ((svc = scf_service_create(handle)) == NULL) 1846a399b765Szf162725 goto out; 1847a399b765Szf162725 1848a399b765Szf162725 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1) 1849a399b765Szf162725 goto out; 1850a399b765Szf162725 1851a399b765Szf162725 if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0) 1852a399b765Szf162725 goto out; 1853a399b765Szf162725 1854a399b765Szf162725 instance = scf_instance_create(handle); 1855a399b765Szf162725 if (instance == NULL) 1856a399b765Szf162725 goto out; 1857a399b765Szf162725 1858a399b765Szf162725 if (scf_service_get_instance(svc, instance_name, instance) != 0) { 1859a399b765Szf162725 scf_error_t scf_errnum = scf_error(); 1860a399b765Szf162725 1861a399b765Szf162725 if (scf_errnum == SCF_ERROR_NOT_FOUND) 1862d62bc4baSyz147064 status = DLADM_STATUS_OK; 1863a399b765Szf162725 1864a399b765Szf162725 scf_instance_destroy(instance); 1865a399b765Szf162725 goto out; 1866a399b765Szf162725 } 1867a399b765Szf162725 1868a399b765Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 1869a399b765Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) { 1870a399b765Szf162725 scf_instance_destroy(instance); 1871a399b765Szf162725 goto out; 1872a399b765Szf162725 } 1873a399b765Szf162725 1874a399b765Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 1875a399b765Szf162725 char *state; 1876a399b765Szf162725 1877a399b765Szf162725 state = smf_get_state(buf); 1878a399b765Szf162725 if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 || 1879a399b765Szf162725 strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) { 1880a399b765Szf162725 if (smf_disable_instance(buf, 0) == 0) { 1881a399b765Szf162725 /* 1882a399b765Szf162725 * Wait for some time till timeout to avoid 1883a399b765Szf162725 * a race with scf_instance_delete() below. 1884a399b765Szf162725 */ 1885a399b765Szf162725 wait_until_disabled(handle, buf); 1886a399b765Szf162725 } 1887a399b765Szf162725 } 1888a399b765Szf162725 } 1889a399b765Szf162725 1890a399b765Szf162725 if (scf_instance_delete(instance) != 0) { 1891a399b765Szf162725 scf_instance_destroy(instance); 1892a399b765Szf162725 goto out; 1893a399b765Szf162725 } 1894a399b765Szf162725 1895a399b765Szf162725 scf_instance_destroy(instance); 1896a399b765Szf162725 1897d62bc4baSyz147064 status = DLADM_STATUS_OK; 1898a399b765Szf162725 1899a399b765Szf162725 out: 1900a399b765Szf162725 if (svc != NULL) 1901a399b765Szf162725 scf_service_destroy(svc); 1902a399b765Szf162725 1903a399b765Szf162725 if (scope != NULL) 1904a399b765Szf162725 scf_scope_destroy(scope); 1905a399b765Szf162725 1906a399b765Szf162725 if (handle != NULL) { 1907a399b765Szf162725 (void) scf_handle_unbind(handle); 1908a399b765Szf162725 scf_handle_destroy(handle); 1909a399b765Szf162725 } 1910a399b765Szf162725 1911a399b765Szf162725 return (status); 1912a399b765Szf162725 } 1913a399b765Szf162725 1914d62bc4baSyz147064 static dladm_status_t 1915*4ac67f02SAnurag S. Maskey wpa_instance_create(dladm_handle_t handle, datalink_id_t linkid, void *key) 1916a399b765Szf162725 { 1917d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED; 1918a399b765Szf162725 char *command = NULL; 1919a399b765Szf162725 char *wk_name = ((dladm_wlan_key_t *)key)->wk_name; 1920a399b765Szf162725 int size; 1921d62bc4baSyz147064 char instance_name[MAXLINKNAMELEN]; 1922d62bc4baSyz147064 1923d62bc4baSyz147064 /* 1924d62bc4baSyz147064 * Use the link name as the instance name of the network/wpad service. 1925d62bc4baSyz147064 */ 1926*4ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, 1927*4ac67f02SAnurag S. Maskey instance_name, sizeof (instance_name)); 1928d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1929d62bc4baSyz147064 goto out; 1930a399b765Szf162725 1931a399b765Szf162725 size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1; 1932a399b765Szf162725 command = malloc(size); 1933a399b765Szf162725 if (command == NULL) { 1934d62bc4baSyz147064 status = DLADM_STATUS_NOMEM; 1935a399b765Szf162725 goto out; 1936a399b765Szf162725 } 1937a399b765Szf162725 (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name); 1938a399b765Szf162725 1939a399b765Szf162725 status = create_instance(instance_name, command); 1940d62bc4baSyz147064 if (status == DLADM_STATUS_EXIST) { 1941a399b765Szf162725 /* 1942a399b765Szf162725 * Delete the existing instance and create a new instance 1943a399b765Szf162725 * with the supplied arguments. 1944a399b765Szf162725 */ 1945a399b765Szf162725 if ((status = delete_instance(instance_name)) == 1946d62bc4baSyz147064 DLADM_STATUS_OK) { 1947a399b765Szf162725 status = create_instance(instance_name, command); 1948a399b765Szf162725 } 1949a399b765Szf162725 } 1950a399b765Szf162725 1951a399b765Szf162725 out: 1952a399b765Szf162725 if (command != NULL) 1953a399b765Szf162725 free(command); 1954a399b765Szf162725 1955a399b765Szf162725 return (status); 1956a399b765Szf162725 } 1957a399b765Szf162725 1958d62bc4baSyz147064 static dladm_status_t 1959*4ac67f02SAnurag S. Maskey wpa_instance_delete(dladm_handle_t handle, datalink_id_t linkid) 1960a399b765Szf162725 { 1961d62bc4baSyz147064 char instance_name[MAXLINKNAMELEN]; 1962a399b765Szf162725 1963d62bc4baSyz147064 /* 1964d62bc4baSyz147064 * Get the instance name of the network/wpad service (the same as 1965d62bc4baSyz147064 * the link name). 1966d62bc4baSyz147064 */ 1967*4ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, 1968*4ac67f02SAnurag S. Maskey instance_name, sizeof (instance_name)) != DLADM_STATUS_OK) 1969d62bc4baSyz147064 return (DLADM_STATUS_FAILED); 1970a399b765Szf162725 1971d62bc4baSyz147064 return (delete_instance(instance_name)); 1972a399b765Szf162725 } 1973