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