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 ((uint_t)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 uint_t 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 uint_t i; 561 char buf[WLDP_BUFSIZE]; 562 connect_state_t state = {0, 0, 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; 793 int r = 0; 794 795 for (i = 0; i < ratesp->wl_rates_num; i++) { 796 if (ratesp->wl_rates_rates[i] > r) 797 r = ratesp->wl_rates_rates[i]; 798 } 799 wl_attrp->wa_speed = r; 800 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 801 } 802 803 if ((status = do_get_authmode(handle, linkid, &authmode, 804 sizeof (authmode))) != DLADM_STATUS_OK) 805 goto done; 806 807 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 808 809 switch (authmode) { 810 case WL_OPENSYSTEM: 811 wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN; 812 break; 813 case WL_SHAREDKEY: 814 wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED; 815 break; 816 default: 817 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH; 818 break; 819 } 820 821 if ((status = do_get_bsstype(handle, linkid, &bsstype, 822 sizeof (bsstype))) != DLADM_STATUS_OK) 823 goto done; 824 825 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 826 827 switch (bsstype) { 828 case WL_BSS_BSS: 829 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS; 830 break; 831 case WL_BSS_IBSS: 832 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS; 833 break; 834 case WL_BSS_ANY: 835 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY; 836 break; 837 default: 838 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE; 839 break; 840 } 841 842 if ((status = do_get_mode(handle, linkid, &wl_phy_conf, 843 sizeof (wl_phy_conf))) != DLADM_STATUS_OK) 844 goto done; 845 846 wl_attrp->wa_mode = do_convert_mode(&wl_phy_conf); 847 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 848 if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE) 849 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 850 851 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 852 status = DLADM_STATUS_OK; 853 854 done: 855 free(ratesp); 856 return (status); 857 } 858 859 /* 860 * Check to see if the link is wireless. 861 */ 862 static dladm_status_t 863 dladm_wlan_validate(dladm_handle_t handle, datalink_id_t linkid) 864 { 865 uint32_t media; 866 dladm_status_t status; 867 868 status = dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, 869 NULL, 0); 870 if (status == DLADM_STATUS_OK) { 871 if (media != DL_WIFI) 872 status = DLADM_STATUS_LINKINVAL; 873 } 874 return (status); 875 } 876 877 static boolean_t 878 find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp) 879 { 880 uint_t i; 881 882 for (i = 0; i < cnt; i++) { 883 if (strcasecmp(str, vdp[i].vd_name) == 0) { 884 *valp = vdp[i].vd_val; 885 return (B_TRUE); 886 } 887 } 888 return (B_FALSE); 889 } 890 891 static boolean_t 892 find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp) 893 { 894 uint_t i; 895 896 for (i = 0; i < cnt; i++) { 897 if (val == vdp[i].vd_val) { 898 *strp = vdp[i].vd_name; 899 return (B_TRUE); 900 } 901 } 902 return (B_FALSE); 903 } 904 905 const char * 906 dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf) 907 { 908 (void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes); 909 return (buf); 910 } 911 912 const char * 913 dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf) 914 { 915 return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN, 916 IFT_OTHER)); 917 } 918 919 static const char * 920 dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf) 921 { 922 char *s; 923 924 if (!find_name_by_val(val, vdp, cnt, &s)) 925 s = ""; 926 927 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 928 return (buf); 929 } 930 931 const char * 932 dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf) 933 { 934 return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals, 935 VALCNT(secmode_vals), buf)); 936 } 937 938 const char * 939 dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf) 940 { 941 return (dladm_wlan_val2str((uint_t)*strength, strength_vals, 942 VALCNT(strength_vals), buf)); 943 } 944 945 const char * 946 dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf) 947 { 948 return (dladm_wlan_val2str((uint_t)*mode, mode_vals, 949 VALCNT(mode_vals), buf)); 950 } 951 952 const char * 953 dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf) 954 { 955 (void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2, 956 (float)(*speed) / 2); 957 return (buf); 958 } 959 960 const char * 961 dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf) 962 { 963 return (dladm_wlan_val2str((uint_t)*auth, auth_vals, 964 VALCNT(auth_vals), buf)); 965 } 966 967 const char * 968 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf) 969 { 970 return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals, 971 VALCNT(bsstype_vals), buf)); 972 } 973 974 const char * 975 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf) 976 { 977 return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals, 978 VALCNT(linkstatus_vals), buf)); 979 } 980 981 dladm_status_t 982 dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid) 983 { 984 if (str[0] == '\0' || strlen(str) > DLADM_WLAN_MAX_ESSID_LEN - 1) 985 return (DLADM_STATUS_BADARG); 986 987 (void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN); 988 return (DLADM_STATUS_OK); 989 } 990 991 dladm_status_t 992 dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid) 993 { 994 int len; 995 uchar_t *buf; 996 997 buf = _link_aton(str, &len); 998 if (buf == NULL) 999 return (DLADM_STATUS_BADARG); 1000 1001 if (len != DLADM_WLAN_BSSID_LEN) { 1002 free(buf); 1003 return (DLADM_STATUS_BADARG); 1004 } 1005 1006 (void) memcpy(bssid->wb_bytes, buf, len); 1007 free(buf); 1008 return (DLADM_STATUS_OK); 1009 } 1010 1011 dladm_status_t 1012 dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode) 1013 { 1014 uint_t val; 1015 1016 if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val)) 1017 return (DLADM_STATUS_BADARG); 1018 1019 *secmode = (dladm_wlan_secmode_t)val; 1020 return (DLADM_STATUS_OK); 1021 } 1022 1023 dladm_status_t 1024 dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength) 1025 { 1026 uint_t val; 1027 1028 if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val)) 1029 return (DLADM_STATUS_BADARG); 1030 1031 *strength = (dladm_wlan_strength_t)val; 1032 return (DLADM_STATUS_OK); 1033 } 1034 1035 dladm_status_t 1036 dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode) 1037 { 1038 uint_t val; 1039 1040 if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val)) 1041 return (DLADM_STATUS_BADARG); 1042 1043 *mode = (dladm_wlan_mode_t)val; 1044 return (DLADM_STATUS_OK); 1045 } 1046 1047 dladm_status_t 1048 dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed) 1049 { 1050 *speed = (dladm_wlan_speed_t)(atof(str) * 2); 1051 return (DLADM_STATUS_OK); 1052 } 1053 1054 dladm_status_t 1055 dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth) 1056 { 1057 uint_t val; 1058 1059 if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val)) 1060 return (DLADM_STATUS_BADARG); 1061 1062 *auth = (dladm_wlan_auth_t)val; 1063 return (DLADM_STATUS_OK); 1064 } 1065 1066 dladm_status_t 1067 dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype) 1068 { 1069 uint_t val; 1070 1071 if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val)) 1072 return (DLADM_STATUS_BADARG); 1073 1074 *bsstype = (dladm_wlan_bsstype_t)val; 1075 return (DLADM_STATUS_OK); 1076 } 1077 1078 dladm_status_t 1079 dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus) 1080 { 1081 uint_t val; 1082 1083 if (!find_val_by_name(str, linkstatus_vals, 1084 VALCNT(linkstatus_vals), &val)) { 1085 return (DLADM_STATUS_BADARG); 1086 } 1087 1088 *linkstatus = (dladm_wlan_linkstatus_t)val; 1089 return (DLADM_STATUS_OK); 1090 } 1091 1092 dladm_status_t 1093 i_dladm_wlan_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid, 1094 wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen) 1095 { 1096 char linkname[MAXPATHLEN]; 1097 int fd, rc; 1098 struct strioctl stri; 1099 uint32_t flags; 1100 dladm_status_t status; 1101 uint32_t media; 1102 char link[MAXLINKNAMELEN]; 1103 1104 if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 1105 &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 1106 return (status); 1107 } 1108 1109 if (media != DL_WIFI) 1110 return (DLADM_STATUS_BADARG); 1111 1112 if (!(flags & DLADM_OPT_ACTIVE)) 1113 return (DLADM_STATUS_TEMPONLY); 1114 1115 /* 1116 * dlpi_open() is not used here because libdlpi depends on libdladm, 1117 * and we do not want to introduce recursive dependencies. 1118 */ 1119 (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link); 1120 if ((fd = open(linkname, O_RDWR)) < 0) 1121 return (dladm_errno2status(errno)); 1122 1123 gbuf->wldp_type = NET_802_11; 1124 gbuf->wldp_id = id; 1125 gbuf->wldp_length = len; 1126 1127 stri.ic_timout = 0; 1128 stri.ic_dp = (char *)gbuf; 1129 stri.ic_cmd = cmd; 1130 stri.ic_len = cmdlen; 1131 1132 if ((rc = ioctl(fd, I_STR, &stri)) != 0) { 1133 if (rc > 0) { 1134 /* 1135 * Non-negative return value indicates the specific 1136 * operation failed and the reason for the failure 1137 * was stored in gbuf->wldp_result. 1138 */ 1139 status = dladm_wlan_wlresult2status(gbuf); 1140 } else { 1141 /* 1142 * Negative return value indicates the ioctl failed. 1143 */ 1144 status = dladm_errno2status(errno); 1145 } 1146 } 1147 (void) close(fd); 1148 return (status); 1149 } 1150 1151 static dladm_status_t 1152 do_cmd_ioctl(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1153 int buflen, uint_t cmd) 1154 { 1155 wldp_t *gbuf; 1156 dladm_status_t status = DLADM_STATUS_OK; 1157 1158 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 1159 return (DLADM_STATUS_NOMEM); 1160 1161 (void) memset(gbuf, 0, MAX_BUF_LEN); 1162 status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, cmd, 1163 WLDP_BUFSIZE, WLAN_COMMAND, sizeof (wldp_t)); 1164 (void) memcpy(buf, gbuf->wldp_buf, buflen); 1165 free(gbuf); 1166 return (status); 1167 } 1168 1169 static dladm_status_t 1170 do_scan(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1171 { 1172 return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_SCAN)); 1173 } 1174 1175 static dladm_status_t 1176 do_disconnect(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1177 int buflen) 1178 { 1179 if (do_get_wpamode(handle, linkid, buf, buflen) == 0 && 1180 ((wl_wpa_t *)(buf))->wpa_flag > 0) 1181 (void) wpa_instance_delete(handle, linkid); 1182 1183 return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_DISASSOCIATE)); 1184 } 1185 1186 static dladm_status_t 1187 do_get_esslist(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1188 int buflen) 1189 { 1190 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESS_LIST, 1191 buflen, B_FALSE)); 1192 } 1193 1194 static dladm_status_t 1195 do_get_bssid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1196 { 1197 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_BSSID, 1198 buflen, B_FALSE)); 1199 } 1200 1201 static dladm_status_t 1202 do_get_essid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1203 { 1204 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESSID, 1205 buflen, B_FALSE)); 1206 } 1207 1208 static dladm_status_t 1209 do_get_bsstype(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_BSSTYPE, 1213 buflen, B_FALSE)); 1214 } 1215 1216 static dladm_status_t 1217 do_get_linkstatus(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1218 int buflen) 1219 { 1220 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_LINKSTATUS, 1221 buflen, B_FALSE)); 1222 } 1223 1224 static dladm_status_t 1225 do_get_rate(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1226 { 1227 return (i_dladm_wlan_param(handle, linkid, buf, 1228 MAC_PROP_WL_DESIRED_RATES, buflen, B_FALSE)); 1229 } 1230 1231 static dladm_status_t 1232 do_get_authmode(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_AUTH_MODE, buflen, B_FALSE)); 1237 } 1238 1239 static dladm_status_t 1240 do_get_encryption(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1241 int buflen) 1242 { 1243 return (i_dladm_wlan_param(handle, linkid, buf, 1244 MAC_PROP_WL_ENCRYPTION, buflen, B_FALSE)); 1245 } 1246 1247 static dladm_status_t 1248 do_get_signal(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1249 int buflen) 1250 { 1251 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RSSI, 1252 buflen, B_FALSE)); 1253 } 1254 1255 static dladm_status_t 1256 do_get_mode(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 1257 { 1258 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG, 1259 buflen, B_FALSE)); 1260 } 1261 1262 static dladm_status_t 1263 do_set_bsstype(dladm_handle_t handle, datalink_id_t linkid, 1264 dladm_wlan_bsstype_t *bsstype) 1265 { 1266 wl_bss_type_t ibsstype; 1267 1268 switch (*bsstype) { 1269 case DLADM_WLAN_BSSTYPE_BSS: 1270 ibsstype = WL_BSS_BSS; 1271 break; 1272 case DLADM_WLAN_BSSTYPE_IBSS: 1273 ibsstype = WL_BSS_IBSS; 1274 break; 1275 default: 1276 ibsstype = WL_BSS_ANY; 1277 break; 1278 } 1279 return (i_dladm_wlan_param(handle, linkid, &ibsstype, 1280 MAC_PROP_WL_BSSTYPE, sizeof (ibsstype), B_TRUE)); 1281 } 1282 1283 static dladm_status_t 1284 do_set_authmode(dladm_handle_t handle, datalink_id_t linkid, 1285 dladm_wlan_auth_t *auth) 1286 { 1287 wl_authmode_t auth_mode; 1288 1289 switch (*auth) { 1290 case DLADM_WLAN_AUTH_OPEN: 1291 auth_mode = WL_OPENSYSTEM; 1292 break; 1293 case DLADM_WLAN_AUTH_SHARED: 1294 auth_mode = WL_SHAREDKEY; 1295 break; 1296 default: 1297 return (DLADM_STATUS_NOTSUP); 1298 } 1299 return (i_dladm_wlan_param(handle, linkid, &auth_mode, 1300 MAC_PROP_WL_AUTH_MODE, sizeof (auth_mode), B_TRUE)); 1301 } 1302 1303 static dladm_status_t 1304 do_set_encryption(dladm_handle_t handle, datalink_id_t linkid, 1305 dladm_wlan_secmode_t *secmode) 1306 { 1307 wl_encryption_t encryption; 1308 1309 switch (*secmode) { 1310 case DLADM_WLAN_SECMODE_NONE: 1311 encryption = WL_NOENCRYPTION; 1312 break; 1313 case DLADM_WLAN_SECMODE_WEP: 1314 encryption = WL_ENC_WEP; 1315 break; 1316 case DLADM_WLAN_SECMODE_WPA: 1317 return (0); 1318 default: 1319 return (DLADM_STATUS_NOTSUP); 1320 } 1321 return (i_dladm_wlan_param(handle, linkid, &encryption, 1322 MAC_PROP_WL_ENCRYPTION, sizeof (encryption), B_TRUE)); 1323 } 1324 1325 static dladm_status_t 1326 do_set_key(dladm_handle_t handle, datalink_id_t linkid, dladm_wlan_key_t *keys, 1327 uint_t key_count) 1328 { 1329 uint_t i; 1330 wl_wep_key_t *wkp; 1331 wl_wep_key_tab_t wepkey_tab; 1332 dladm_wlan_key_t *kp; 1333 1334 if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL) 1335 return (DLADM_STATUS_BADARG); 1336 1337 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab)); 1338 for (i = 0; i < MAX_NWEPKEYS; i++) 1339 wepkey_tab[i].wl_wep_operation = WL_NUL; 1340 1341 for (i = 0; i < key_count; i++) { 1342 kp = &keys[i]; 1343 if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS) 1344 return (DLADM_STATUS_BADARG); 1345 if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN && 1346 kp->wk_len != DLADM_WLAN_WEPKEY128_LEN) 1347 return (DLADM_STATUS_BADARG); 1348 1349 wkp = &wepkey_tab[kp->wk_idx - 1]; 1350 wkp->wl_wep_operation = WL_ADD; 1351 wkp->wl_wep_length = kp->wk_len; 1352 (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len); 1353 } 1354 1355 return (i_dladm_wlan_param(handle, linkid, &wepkey_tab, 1356 MAC_PROP_WL_KEY_TAB, sizeof (wepkey_tab), B_TRUE)); 1357 } 1358 1359 static dladm_status_t 1360 do_set_essid(dladm_handle_t handle, datalink_id_t linkid, 1361 dladm_wlan_essid_t *essid) 1362 { 1363 wl_essid_t iessid; 1364 1365 (void) memset(&iessid, 0, sizeof (essid)); 1366 1367 if (essid != NULL && essid->we_bytes[0] != '\0') { 1368 iessid.wl_essid_length = strlen(essid->we_bytes); 1369 (void) strlcpy(iessid.wl_essid_essid, essid->we_bytes, 1370 sizeof (iessid.wl_essid_essid)); 1371 } else { 1372 return (DLADM_STATUS_BADARG); 1373 } 1374 return (i_dladm_wlan_param(handle, linkid, &iessid, MAC_PROP_WL_ESSID, 1375 sizeof (iessid), B_TRUE)); 1376 } 1377 1378 static dladm_status_t 1379 do_set_channel(dladm_handle_t handle, datalink_id_t linkid, 1380 dladm_wlan_channel_t *channel) 1381 { 1382 wl_phy_conf_t phy_conf; 1383 1384 if (*channel > MAX_CHANNEL_NUM) 1385 return (DLADM_STATUS_BADVAL); 1386 1387 (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); 1388 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel; 1389 1390 return (i_dladm_wlan_param(handle, linkid, &phy_conf, 1391 MAC_PROP_WL_PHY_CONFIG, sizeof (phy_conf), B_TRUE)); 1392 } 1393 1394 static dladm_status_t 1395 do_set_createibss(dladm_handle_t handle, datalink_id_t linkid, 1396 boolean_t *create_ibss) 1397 { 1398 wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss); 1399 1400 return (i_dladm_wlan_param(handle, linkid, &cr, MAC_PROP_WL_CREATE_IBSS, 1401 sizeof (cr), B_TRUE)); 1402 } 1403 1404 static void 1405 generate_essid(dladm_wlan_essid_t *essid) 1406 { 1407 srandom(gethrtime()); 1408 (void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d", 1409 random()); 1410 } 1411 1412 static dladm_status_t 1413 do_get_capability(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_CAPABILITY, 1417 buflen, B_FALSE)); 1418 } 1419 1420 static dladm_status_t 1421 do_get_wpamode(dladm_handle_t handle, datalink_id_t linkid, void *buf, 1422 int buflen) 1423 { 1424 return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_WPA, buflen, 1425 B_FALSE)); 1426 } 1427 1428 dladm_status_t 1429 dladm_wlan_wpa_get_sr(dladm_handle_t handle, datalink_id_t linkid, 1430 dladm_wlan_ess_t *sr, uint_t escnt, uint_t *estot) 1431 { 1432 int i, n; 1433 wl_wpa_ess_t *es; 1434 dladm_status_t status; 1435 1436 es = malloc(WLDP_BUFSIZE); 1437 if (es == NULL) 1438 return (DLADM_STATUS_NOMEM); 1439 1440 status = i_dladm_wlan_param(handle, linkid, es, MAC_PROP_WL_SCANRESULTS, 1441 WLDP_BUFSIZE, B_FALSE); 1442 1443 if (status == DLADM_STATUS_OK) { 1444 n = (es->count > escnt) ? escnt : es->count; 1445 for (i = 0; i < n; i ++) { 1446 (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid, 1447 DLADM_WLAN_BSSID_LEN); 1448 sr[i].we_ssid_len = es->ess[i].ssid_len; 1449 (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid, 1450 es->ess[i].ssid_len); 1451 sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len; 1452 (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie, 1453 es->ess[i].wpa_ie_len); 1454 sr[i].we_freq = es->ess[i].freq; 1455 } 1456 *estot = n; 1457 } 1458 1459 free(es); 1460 return (status); 1461 } 1462 1463 dladm_status_t 1464 dladm_wlan_wpa_set_ie(dladm_handle_t handle, datalink_id_t linkid, 1465 uint8_t *wpa_ie, uint_t wpa_ie_len) 1466 { 1467 wl_wpa_ie_t *ie; 1468 uint_t len; 1469 dladm_status_t status; 1470 1471 if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN) 1472 return (DLADM_STATUS_BADARG); 1473 len = sizeof (wl_wpa_ie_t) + wpa_ie_len; 1474 ie = malloc(len); 1475 if (ie == NULL) 1476 return (DLADM_STATUS_NOMEM); 1477 1478 (void) memset(ie, 0, len); 1479 ie->wpa_ie_len = wpa_ie_len; 1480 (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len); 1481 1482 status = i_dladm_wlan_param(handle, linkid, ie, MAC_PROP_WL_SETOPTIE, 1483 len, B_TRUE); 1484 free(ie); 1485 1486 return (status); 1487 } 1488 1489 dladm_status_t 1490 dladm_wlan_wpa_set_wpa(dladm_handle_t handle, datalink_id_t linkid, 1491 boolean_t flag) 1492 { 1493 wl_wpa_t wpa; 1494 1495 wpa.wpa_flag = flag; 1496 return (i_dladm_wlan_param(handle, linkid, &wpa, MAC_PROP_WL_WPA, 1497 sizeof (wpa), B_TRUE)); 1498 } 1499 1500 dladm_status_t 1501 dladm_wlan_wpa_del_key(dladm_handle_t handle, datalink_id_t linkid, 1502 uint_t key_idx, const dladm_wlan_bssid_t *addr) 1503 { 1504 wl_del_key_t wk; 1505 1506 wk.idk_keyix = key_idx; 1507 if (addr != NULL) 1508 (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes, 1509 DLADM_WLAN_BSSID_LEN); 1510 1511 return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_DELKEY, 1512 sizeof (wk), B_TRUE)); 1513 } 1514 1515 dladm_status_t 1516 dladm_wlan_wpa_set_key(dladm_handle_t handle, datalink_id_t linkid, 1517 dladm_wlan_cipher_t cipher, const dladm_wlan_bssid_t *addr, 1518 boolean_t set_tx, uint64_t seq, uint_t key_idx, uint8_t *key, 1519 uint_t key_len) 1520 { 1521 wl_key_t wk; 1522 1523 (void) memset(&wk, 0, sizeof (wl_key_t)); 1524 switch (cipher) { 1525 case DLADM_WLAN_CIPHER_WEP: 1526 wk.ik_type = IEEE80211_CIPHER_WEP; 1527 break; 1528 case DLADM_WLAN_CIPHER_TKIP: 1529 wk.ik_type = IEEE80211_CIPHER_TKIP; 1530 break; 1531 case DLADM_WLAN_CIPHER_AES_OCB: 1532 wk.ik_type = IEEE80211_CIPHER_AES_OCB; 1533 break; 1534 case DLADM_WLAN_CIPHER_AES_CCM: 1535 wk.ik_type = IEEE80211_CIPHER_AES_CCM; 1536 break; 1537 case DLADM_WLAN_CIPHER_CKIP: 1538 wk.ik_type = IEEE80211_CIPHER_CKIP; 1539 break; 1540 case DLADM_WLAN_CIPHER_NONE: 1541 wk.ik_type = IEEE80211_CIPHER_NONE; 1542 break; 1543 default: 1544 return (DLADM_STATUS_BADARG); 1545 } 1546 wk.ik_flags = IEEE80211_KEY_RECV; 1547 if (set_tx) { 1548 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; 1549 (void) memcpy(wk.ik_macaddr, addr->wb_bytes, 1550 DLADM_WLAN_BSSID_LEN); 1551 } else 1552 (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN); 1553 wk.ik_keyix = key_idx; 1554 wk.ik_keylen = key_len; 1555 (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */ 1556 (void) memcpy(wk.ik_keydata, key, key_len); 1557 1558 return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_KEY, 1559 sizeof (wk), B_TRUE)); 1560 } 1561 1562 dladm_status_t 1563 dladm_wlan_wpa_set_mlme(dladm_handle_t handle, datalink_id_t linkid, 1564 dladm_wlan_mlme_op_t op, dladm_wlan_reason_t reason, 1565 dladm_wlan_bssid_t *bssid) 1566 { 1567 wl_mlme_t mlme; 1568 1569 (void) memset(&mlme, 0, sizeof (wl_mlme_t)); 1570 switch (op) { 1571 case DLADM_WLAN_MLME_ASSOC: 1572 mlme.im_op = IEEE80211_MLME_ASSOC; 1573 break; 1574 case DLADM_WLAN_MLME_DISASSOC: 1575 mlme.im_op = IEEE80211_MLME_DISASSOC; 1576 break; 1577 default: 1578 return (DLADM_STATUS_BADARG); 1579 } 1580 mlme.im_reason = reason; 1581 if (bssid != NULL) 1582 (void) memcpy(mlme.im_macaddr, bssid->wb_bytes, 1583 DLADM_WLAN_BSSID_LEN); 1584 1585 return (i_dladm_wlan_param(handle, linkid, &mlme, MAC_PROP_WL_MLME, 1586 sizeof (mlme), B_TRUE)); 1587 } 1588 1589 /* 1590 * routines of create instance 1591 */ 1592 static scf_propertygroup_t * 1593 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance, 1594 const char *pg_name, const char *pg_type) 1595 { 1596 scf_propertygroup_t *pg; 1597 1598 pg = scf_pg_create(handle); 1599 if (pg == NULL) 1600 return (NULL); 1601 1602 if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) { 1603 scf_pg_destroy(pg); 1604 return (NULL); 1605 } 1606 1607 return (pg); 1608 } 1609 1610 static dladm_status_t 1611 add_new_property(scf_handle_t *handle, const char *prop_name, 1612 scf_type_t type, const char *val, scf_transaction_t *tx) 1613 { 1614 scf_value_t *value = NULL; 1615 scf_transaction_entry_t *entry = NULL; 1616 1617 entry = scf_entry_create(handle); 1618 if (entry == NULL) 1619 goto out; 1620 1621 value = scf_value_create(handle); 1622 if (value == NULL) 1623 goto out; 1624 1625 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) 1626 goto out; 1627 1628 if (scf_value_set_from_string(value, type, val) != 0) 1629 goto out; 1630 1631 if (scf_entry_add_value(entry, value) != 0) 1632 goto out; 1633 1634 return (DLADM_STATUS_OK); 1635 1636 out: 1637 if (value != NULL) 1638 scf_value_destroy(value); 1639 if (entry != NULL) 1640 scf_entry_destroy(entry); 1641 1642 return (DLADM_STATUS_FAILED); 1643 } 1644 1645 static dladm_status_t 1646 add_pg_method(scf_handle_t *handle, scf_instance_t *instance, 1647 const char *pg_name, const char *flags) 1648 { 1649 int rv, size; 1650 dladm_status_t status = DLADM_STATUS_FAILED; 1651 char *command = NULL; 1652 scf_transaction_t *tran = NULL; 1653 scf_propertygroup_t *pg; 1654 1655 pg = add_property_group_to_instance(handle, instance, 1656 pg_name, SCF_GROUP_METHOD); 1657 if (pg == NULL) 1658 goto out; 1659 1660 tran = scf_transaction_create(handle); 1661 if (tran == NULL) 1662 goto out; 1663 1664 size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1; 1665 command = malloc(size); 1666 if (command == NULL) { 1667 status = DLADM_STATUS_NOMEM; 1668 goto out; 1669 } 1670 (void) snprintf(command, size, "%s %s", SVC_METHOD, flags); 1671 1672 do { 1673 if (scf_transaction_start(tran, pg) != 0) 1674 goto out; 1675 1676 if (add_new_property(handle, SCF_PROPERTY_EXEC, 1677 SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) { 1678 goto out; 1679 } 1680 1681 rv = scf_transaction_commit(tran); 1682 switch (rv) { 1683 case 1: 1684 status = DLADM_STATUS_OK; 1685 goto out; 1686 case 0: 1687 scf_transaction_destroy_children(tran); 1688 if (scf_pg_update(pg) == -1) { 1689 goto out; 1690 } 1691 break; 1692 case -1: 1693 default: 1694 goto out; 1695 } 1696 } while (rv == 0); 1697 1698 out: 1699 if (tran != NULL) { 1700 scf_transaction_destroy_children(tran); 1701 scf_transaction_destroy(tran); 1702 } 1703 1704 if (pg != NULL) 1705 scf_pg_destroy(pg); 1706 1707 if (command != NULL) 1708 free(command); 1709 1710 return (status); 1711 } 1712 1713 static dladm_status_t 1714 do_create_instance(scf_handle_t *handle, scf_service_t *svc, 1715 const char *instance_name, const char *command) 1716 { 1717 dladm_status_t status = DLADM_STATUS_FAILED; 1718 char *buf; 1719 ssize_t max_fmri_len; 1720 scf_instance_t *instance; 1721 1722 instance = scf_instance_create(handle); 1723 if (instance == NULL) 1724 goto out; 1725 1726 if (scf_service_add_instance(svc, instance_name, instance) != 0) { 1727 if (scf_error() == SCF_ERROR_EXISTS) 1728 /* Let the caller deal with the duplicate instance */ 1729 status = DLADM_STATUS_EXIST; 1730 goto out; 1731 } 1732 1733 if (add_pg_method(handle, instance, "start", 1734 command) != DLADM_STATUS_OK) { 1735 goto out; 1736 } 1737 1738 /* enabling the instance */ 1739 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 1740 if ((buf = malloc(max_fmri_len + 1)) == NULL) 1741 goto out; 1742 1743 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 1744 if ((smf_disable_instance(buf, 0) != 0) || 1745 (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) { 1746 goto out; 1747 } 1748 status = DLADM_STATUS_OK; 1749 } 1750 1751 out: 1752 if (instance != NULL) 1753 scf_instance_destroy(instance); 1754 return (status); 1755 } 1756 1757 static dladm_status_t 1758 create_instance(const char *instance_name, const char *command) 1759 { 1760 dladm_status_t status = DLADM_STATUS_FAILED; 1761 scf_service_t *svc = NULL; 1762 scf_handle_t *handle = NULL; 1763 1764 handle = scf_handle_create(SCF_VERSION); 1765 if (handle == NULL) 1766 goto out; 1767 1768 if (scf_handle_bind(handle) == -1) 1769 goto out; 1770 1771 if ((svc = scf_service_create(handle)) == NULL) 1772 goto out; 1773 1774 if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc, 1775 NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) 1776 goto out; 1777 1778 status = do_create_instance(handle, svc, instance_name, command); 1779 1780 out: 1781 if (svc != NULL) 1782 scf_service_destroy(svc); 1783 1784 if (handle != NULL) { 1785 (void) scf_handle_unbind(handle); 1786 scf_handle_destroy(handle); 1787 } 1788 1789 return (status); 1790 } 1791 1792 /* 1793 * routines of delete instance 1794 */ 1795 #define DEFAULT_TIMEOUT 60000000 1796 #define INIT_WAIT_USECS 50000 1797 1798 static void 1799 wait_until_disabled(scf_handle_t *handle, char *fmri) 1800 { 1801 char *state; 1802 useconds_t max; 1803 useconds_t usecs; 1804 uint64_t *cp = NULL; 1805 scf_simple_prop_t *sp = NULL; 1806 1807 max = DEFAULT_TIMEOUT; 1808 1809 if (((sp = scf_simple_prop_get(handle, fmri, "stop", 1810 SCF_PROPERTY_TIMEOUT)) != NULL) && 1811 ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0)) 1812 max = (*cp) * 1000000; /* convert to usecs */ 1813 1814 if (sp != NULL) 1815 scf_simple_prop_free(sp); 1816 1817 for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) { 1818 /* incremental wait */ 1819 usecs *= 2; 1820 usecs = (usecs > max) ? max : usecs; 1821 1822 (void) usleep(usecs); 1823 1824 /* Check state after the wait */ 1825 if ((state = smf_get_state(fmri)) != NULL) { 1826 if (strcmp(state, "disabled") == 0) 1827 return; 1828 } 1829 } 1830 } 1831 1832 static dladm_status_t 1833 delete_instance(const char *instance_name) 1834 { 1835 dladm_status_t status = DLADM_STATUS_FAILED; 1836 char *buf; 1837 ssize_t max_fmri_len; 1838 scf_scope_t *scope = NULL; 1839 scf_service_t *svc = NULL; 1840 scf_handle_t *handle = NULL; 1841 scf_instance_t *instance; 1842 1843 handle = scf_handle_create(SCF_VERSION); 1844 if (handle == NULL) 1845 goto out; 1846 1847 if (scf_handle_bind(handle) == -1) 1848 goto out; 1849 1850 if ((scope = scf_scope_create(handle)) == NULL) 1851 goto out; 1852 1853 if ((svc = scf_service_create(handle)) == NULL) 1854 goto out; 1855 1856 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1) 1857 goto out; 1858 1859 if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0) 1860 goto out; 1861 1862 instance = scf_instance_create(handle); 1863 if (instance == NULL) 1864 goto out; 1865 1866 if (scf_service_get_instance(svc, instance_name, instance) != 0) { 1867 scf_error_t scf_errnum = scf_error(); 1868 1869 if (scf_errnum == SCF_ERROR_NOT_FOUND) 1870 status = DLADM_STATUS_OK; 1871 1872 scf_instance_destroy(instance); 1873 goto out; 1874 } 1875 1876 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 1877 if ((buf = malloc(max_fmri_len + 1)) == NULL) { 1878 scf_instance_destroy(instance); 1879 goto out; 1880 } 1881 1882 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 1883 char *state; 1884 1885 state = smf_get_state(buf); 1886 if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 || 1887 strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) { 1888 if (smf_disable_instance(buf, 0) == 0) { 1889 /* 1890 * Wait for some time till timeout to avoid 1891 * a race with scf_instance_delete() below. 1892 */ 1893 wait_until_disabled(handle, buf); 1894 } 1895 } 1896 } 1897 1898 if (scf_instance_delete(instance) != 0) { 1899 scf_instance_destroy(instance); 1900 goto out; 1901 } 1902 1903 scf_instance_destroy(instance); 1904 1905 status = DLADM_STATUS_OK; 1906 1907 out: 1908 if (svc != NULL) 1909 scf_service_destroy(svc); 1910 1911 if (scope != NULL) 1912 scf_scope_destroy(scope); 1913 1914 if (handle != NULL) { 1915 (void) scf_handle_unbind(handle); 1916 scf_handle_destroy(handle); 1917 } 1918 1919 return (status); 1920 } 1921 1922 static dladm_status_t 1923 wpa_instance_create(dladm_handle_t handle, datalink_id_t linkid, void *key) 1924 { 1925 dladm_status_t status = DLADM_STATUS_FAILED; 1926 char *command = NULL; 1927 char *wk_name = ((dladm_wlan_key_t *)key)->wk_name; 1928 int size; 1929 char instance_name[MAXLINKNAMELEN]; 1930 1931 /* 1932 * Use the link name as the instance name of the network/wpad service. 1933 */ 1934 status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, 1935 instance_name, sizeof (instance_name)); 1936 if (status != DLADM_STATUS_OK) 1937 goto out; 1938 1939 size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1; 1940 command = malloc(size); 1941 if (command == NULL) { 1942 status = DLADM_STATUS_NOMEM; 1943 goto out; 1944 } 1945 (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name); 1946 1947 status = create_instance(instance_name, command); 1948 if (status == DLADM_STATUS_EXIST) { 1949 /* 1950 * Delete the existing instance and create a new instance 1951 * with the supplied arguments. 1952 */ 1953 if ((status = delete_instance(instance_name)) == 1954 DLADM_STATUS_OK) { 1955 status = create_instance(instance_name, command); 1956 } 1957 } 1958 1959 out: 1960 if (command != NULL) 1961 free(command); 1962 1963 return (status); 1964 } 1965 1966 static dladm_status_t 1967 wpa_instance_delete(dladm_handle_t handle, datalink_id_t linkid) 1968 { 1969 char instance_name[MAXLINKNAMELEN]; 1970 1971 /* 1972 * Get the instance name of the network/wpad service (the same as 1973 * the link name). 1974 */ 1975 if (dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, 1976 instance_name, sizeof (instance_name)) != DLADM_STATUS_OK) 1977 return (DLADM_STATUS_FAILED); 1978 1979 return (delete_instance(instance_name)); 1980 } 1981