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