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