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