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