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