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