13871Syz147064 /* 23871Syz147064 * CDDL HEADER START 33871Syz147064 * 43871Syz147064 * The contents of this file are subject to the terms of the 53871Syz147064 * Common Development and Distribution License (the "License"). 63871Syz147064 * You may not use this file except in compliance with the License. 73871Syz147064 * 83871Syz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93871Syz147064 * or http://www.opensolaris.org/os/licensing. 103871Syz147064 * See the License for the specific language governing permissions 113871Syz147064 * and limitations under the License. 123871Syz147064 * 133871Syz147064 * When distributing Covered Code, include this CDDL HEADER in each 143871Syz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153871Syz147064 * If applicable, add the following below this CDDL HEADER, with the 163871Syz147064 * fields enclosed by brackets "[]" replaced with your own identifying 173871Syz147064 * information: Portions Copyright [yyyy] [name of copyright owner] 183871Syz147064 * 193871Syz147064 * CDDL HEADER END 203871Syz147064 */ 213871Syz147064 /* 225895Syz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233871Syz147064 * Use is subject to license terms. 243871Syz147064 */ 253871Syz147064 263871Syz147064 #pragma ident "%Z%%M% %I% %E% SMI" 273871Syz147064 283871Syz147064 #include <libintl.h> 293871Syz147064 #include <stdio.h> 303871Syz147064 #include <stdlib.h> 313871Syz147064 #include <unistd.h> 323871Syz147064 #include <fcntl.h> 335895Syz147064 #include <stddef.h> 343871Syz147064 #include <string.h> 353871Syz147064 #include <stropts.h> 363871Syz147064 #include <libdevinfo.h> 373871Syz147064 #include <net/if.h> 383871Syz147064 #include <net/if_dl.h> 393871Syz147064 #include <net/if_types.h> 405895Syz147064 #include <libdlpi.h> 415895Syz147064 #include <libdllink.h> 424126Szf162725 #include <libscf.h> 433871Syz147064 #include <libdlwlan.h> 445895Syz147064 #include <libdladm_impl.h> 453871Syz147064 #include <libdlwlan_impl.h> 464126Szf162725 #include <net/wpa.h> 473871Syz147064 485895Syz147064 static dladm_status_t wpa_instance_create(datalink_id_t, void *); 495895Syz147064 static dladm_status_t wpa_instance_delete(datalink_id_t); 503871Syz147064 515895Syz147064 static dladm_status_t do_get_bsstype(datalink_id_t, wldp_t *); 525895Syz147064 static dladm_status_t do_get_essid(datalink_id_t, wldp_t *); 535895Syz147064 static dladm_status_t do_get_bssid(datalink_id_t, wldp_t *); 545895Syz147064 static dladm_status_t do_get_signal(datalink_id_t, wldp_t *); 555895Syz147064 static dladm_status_t do_get_encryption(datalink_id_t, wldp_t *); 565895Syz147064 static dladm_status_t do_get_authmode(datalink_id_t, wldp_t *); 575895Syz147064 static dladm_status_t do_get_linkstatus(datalink_id_t, wldp_t *); 585895Syz147064 static dladm_status_t do_get_esslist(datalink_id_t, wldp_t *); 595895Syz147064 static dladm_status_t do_get_rate(datalink_id_t, wldp_t *); 605895Syz147064 static dladm_status_t do_get_mode(datalink_id_t, wldp_t *); 615895Syz147064 static dladm_status_t do_get_capability(datalink_id_t, wldp_t *); 625895Syz147064 static dladm_status_t do_get_wpamode(datalink_id_t, wldp_t *); 634126Szf162725 645895Syz147064 static dladm_status_t do_set_bsstype(datalink_id_t, dladm_wlan_bsstype_t *); 655895Syz147064 static dladm_status_t do_set_authmode(datalink_id_t, dladm_wlan_auth_t *); 665895Syz147064 static dladm_status_t do_set_encryption(datalink_id_t, 675895Syz147064 dladm_wlan_secmode_t *); 685895Syz147064 static dladm_status_t do_set_essid(datalink_id_t, dladm_wlan_essid_t *); 695895Syz147064 static dladm_status_t do_set_createibss(datalink_id_t, boolean_t *); 705895Syz147064 static dladm_status_t do_set_key(datalink_id_t, dladm_wlan_key_t *, uint_t); 715895Syz147064 static dladm_status_t do_set_channel(datalink_id_t, dladm_wlan_channel_t *); 723871Syz147064 735895Syz147064 static dladm_status_t do_scan(datalink_id_t, wldp_t *); 745895Syz147064 static dladm_status_t do_connect(datalink_id_t, wldp_t *, dladm_wlan_attr_t *, 755895Syz147064 boolean_t, void *, uint_t, int); 765895Syz147064 static dladm_status_t do_disconnect(datalink_id_t, wldp_t *); 775895Syz147064 static boolean_t find_val_by_name(const char *, val_desc_t *, 785895Syz147064 uint_t, uint_t *); 795895Syz147064 static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **); 805895Syz147064 static void generate_essid(dladm_wlan_essid_t *); 813871Syz147064 823871Syz147064 static dladm_status_t dladm_wlan_wlresult2status(wldp_t *); 835895Syz147064 static dladm_status_t dladm_wlan_validate(datalink_id_t); 843871Syz147064 853871Syz147064 static val_desc_t linkstatus_vals[] = { 865903Ssowmini { "disconnected", DLADM_WLAN_LINK_DISCONNECTED }, 875903Ssowmini { "connected", DLADM_WLAN_LINK_CONNECTED } 883871Syz147064 }; 893871Syz147064 903871Syz147064 static val_desc_t secmode_vals[] = { 915903Ssowmini { "none", DLADM_WLAN_SECMODE_NONE }, 925903Ssowmini { "wep", DLADM_WLAN_SECMODE_WEP }, 935903Ssowmini { "wpa", DLADM_WLAN_SECMODE_WPA } 943871Syz147064 }; 953871Syz147064 963871Syz147064 static val_desc_t strength_vals[] = { 975903Ssowmini { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK }, 985895Syz147064 { "weak", DLADM_WLAN_STRENGTH_WEAK }, 995895Syz147064 { "good", DLADM_WLAN_STRENGTH_GOOD }, 1005903Ssowmini { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD }, 1015903Ssowmini { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT } 1023871Syz147064 }; 1033871Syz147064 1043871Syz147064 static val_desc_t mode_vals[] = { 1055903Ssowmini { "a", DLADM_WLAN_MODE_80211A }, 1065903Ssowmini { "b", DLADM_WLAN_MODE_80211B }, 1075903Ssowmini { "g", DLADM_WLAN_MODE_80211G }, 1083871Syz147064 }; 1093871Syz147064 1103871Syz147064 static val_desc_t auth_vals[] = { 1115895Syz147064 { "open", DLADM_WLAN_AUTH_OPEN }, 1125903Ssowmini { "shared", DLADM_WLAN_AUTH_SHARED } 1133871Syz147064 }; 1143871Syz147064 1153871Syz147064 static val_desc_t bsstype_vals[] = { 1165903Ssowmini { "bss", DLADM_WLAN_BSSTYPE_BSS }, 1175903Ssowmini { "ibss", DLADM_WLAN_BSSTYPE_IBSS }, 1185903Ssowmini { "any", DLADM_WLAN_BSSTYPE_ANY } 1193871Syz147064 }; 1203871Syz147064 1213871Syz147064 #define IS_CONNECTED(gbuf) \ 1223871Syz147064 ((*(wl_linkstatus_t *)((gbuf)->wldp_buf) == WL_CONNECTED)) 1233871Syz147064 1243871Syz147064 static dladm_status_t 1253871Syz147064 dladm_wlan_wlresult2status(wldp_t *gbuf) 1263871Syz147064 { 1273871Syz147064 switch (gbuf->wldp_result) { 1283871Syz147064 case WL_SUCCESS: 1293871Syz147064 return (DLADM_STATUS_OK); 1303871Syz147064 1313871Syz147064 case WL_NOTSUPPORTED: 1323871Syz147064 case WL_LACK_FEATURE: 1333871Syz147064 return (DLADM_STATUS_NOTSUP); 1343871Syz147064 1353871Syz147064 case WL_READONLY: 1363871Syz147064 return (DLADM_STATUS_PROPRDONLY); 1373871Syz147064 1383871Syz147064 default: 1393871Syz147064 break; 1403871Syz147064 } 1413871Syz147064 1423871Syz147064 return (DLADM_STATUS_FAILED); 1433871Syz147064 } 1443871Syz147064 1453871Syz147064 static dladm_wlan_mode_t 1463871Syz147064 do_convert_mode(wl_phy_conf_t *phyp) 1473871Syz147064 { 1483871Syz147064 switch (phyp->wl_phy_fhss_conf.wl_fhss_subtype) { 1493871Syz147064 case WL_ERP: 1503871Syz147064 return (DLADM_WLAN_MODE_80211G); 1513871Syz147064 case WL_OFDM: 1523871Syz147064 return (DLADM_WLAN_MODE_80211A); 1533871Syz147064 case WL_DSSS: 1543871Syz147064 case WL_FHSS: 1553871Syz147064 return (DLADM_WLAN_MODE_80211B); 1563871Syz147064 default: 1573871Syz147064 break; 1583871Syz147064 } 1593871Syz147064 1603871Syz147064 return (DLADM_WLAN_MODE_NONE); 1613871Syz147064 } 1623871Syz147064 1635895Syz147064 boolean_t 1645895Syz147064 i_dladm_wlan_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp) 1653871Syz147064 { 1663871Syz147064 wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf; 1673871Syz147064 wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf; 1683871Syz147064 1693871Syz147064 switch (wlfp->wl_fhss_subtype) { 1703871Syz147064 case WL_FHSS: 1713871Syz147064 case WL_DSSS: 1723871Syz147064 case WL_IRBASE: 1733871Syz147064 case WL_HRDS: 1743871Syz147064 case WL_ERP: 1753871Syz147064 *channelp = wlfp->wl_fhss_channel; 1763871Syz147064 break; 1773871Syz147064 case WL_OFDM: 1783871Syz147064 *channelp = DLADM_WLAN_OFDM2CHAN(wlop->wl_ofdm_frequency); 1793871Syz147064 break; 1803871Syz147064 default: 1813871Syz147064 return (B_FALSE); 1823871Syz147064 } 1833871Syz147064 return (B_TRUE); 1843871Syz147064 } 1853871Syz147064 1863871Syz147064 #define IEEE80211_RATE 0x7f 1873871Syz147064 static void 1883871Syz147064 fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp) 1893871Syz147064 { 1903871Syz147064 int i; 1913871Syz147064 1923871Syz147064 (void) memset(attrp, 0, sizeof (*attrp)); 1933871Syz147064 1943871Syz147064 (void) snprintf(attrp->wa_essid.we_bytes, DLADM_WLAN_MAX_ESSID_LEN, 1953871Syz147064 "%s", wlp->wl_ess_conf_essid.wl_essid_essid); 1963871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 1973871Syz147064 1983871Syz147064 (void) memcpy(attrp->wa_bssid.wb_bytes, wlp->wl_ess_conf_bssid, 1993871Syz147064 DLADM_WLAN_BSSID_LEN); 2003871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 2013871Syz147064 2023871Syz147064 attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled == 2033871Syz147064 WL_ENC_WEP ? DLADM_WLAN_SECMODE_WEP : DLADM_WLAN_SECMODE_NONE); 2044126Szf162725 if (wlp->wl_ess_conf_reserved[0] > 0) 2054126Szf162725 attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 2063871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 2073871Syz147064 2083871Syz147064 attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ? 2093871Syz147064 DLADM_WLAN_BSSTYPE_BSS : DLADM_WLAN_BSSTYPE_IBSS); 2103871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 2113871Syz147064 2123871Syz147064 attrp->wa_auth = (wlp->wl_ess_conf_authmode == 0 ? 2133871Syz147064 DLADM_WLAN_AUTH_OPEN : DLADM_WLAN_AUTH_SHARED); 2143871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 2153871Syz147064 2163871Syz147064 attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(wlp->wl_ess_conf_sl); 2173871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 2183871Syz147064 2193871Syz147064 attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)&wlp->wl_phy_conf); 2203871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 2213871Syz147064 2223871Syz147064 for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) { 2233871Syz147064 wlp->wl_supported_rates[i] &= IEEE80211_RATE; 2243871Syz147064 if (wlp->wl_supported_rates[i] > attrp->wa_speed) 2253871Syz147064 attrp->wa_speed = wlp->wl_supported_rates[i]; 2263871Syz147064 } 2273871Syz147064 if (attrp->wa_speed > 0) 2283871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 2293871Syz147064 2305895Syz147064 if (i_dladm_wlan_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf, 2313871Syz147064 &attrp->wa_channel)) 2323871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_CHANNEL; 2333871Syz147064 } 2343871Syz147064 2353871Syz147064 dladm_status_t 2365895Syz147064 dladm_wlan_scan(datalink_id_t linkid, void *arg, 2373871Syz147064 boolean_t (*func)(void *, dladm_wlan_attr_t *)) 2383871Syz147064 { 2395895Syz147064 int i; 2403871Syz147064 uint32_t count; 2413871Syz147064 wl_ess_conf_t *wlp; 2426131Syz147064 wldp_t *gbuf = NULL; 2433871Syz147064 dladm_wlan_attr_t wlattr; 2443871Syz147064 dladm_status_t status; 2453871Syz147064 boolean_t connected; 2463871Syz147064 2475895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 2485895Syz147064 goto done; 2493871Syz147064 2503871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 2513871Syz147064 status = DLADM_STATUS_NOMEM; 2523871Syz147064 goto done; 2533871Syz147064 } 2543871Syz147064 2555895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 2563871Syz147064 goto done; 2573871Syz147064 connected = IS_CONNECTED(gbuf); 2583871Syz147064 2595895Syz147064 if ((status = do_scan(linkid, gbuf)) != DLADM_STATUS_OK) 2603871Syz147064 goto done; 2613871Syz147064 2624126Szf162725 if (func == NULL) { 2634126Szf162725 status = DLADM_STATUS_OK; 2644126Szf162725 goto done; 2654126Szf162725 } 2664126Szf162725 2675895Syz147064 if ((status = do_get_esslist(linkid, gbuf)) != DLADM_STATUS_OK) 2683871Syz147064 goto done; 2693871Syz147064 2703871Syz147064 wlp = ((wl_ess_list_t *)gbuf->wldp_buf)->wl_ess_list_ess; 2713871Syz147064 count = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num; 2723871Syz147064 2733871Syz147064 for (i = 0; i < count; i++, wlp++) { 2743871Syz147064 fill_wlan_attr(wlp, &wlattr); 2753871Syz147064 if (!func(arg, &wlattr)) 2763871Syz147064 break; 2773871Syz147064 } 2783871Syz147064 2793871Syz147064 if (!connected) { 2805895Syz147064 status = do_get_linkstatus(linkid, gbuf); 2815895Syz147064 if (status != DLADM_STATUS_OK) 2823871Syz147064 goto done; 2833871Syz147064 if (IS_CONNECTED(gbuf)) 2845895Syz147064 (void) do_disconnect(linkid, gbuf); 2853871Syz147064 } 2863871Syz147064 2873871Syz147064 status = DLADM_STATUS_OK; 2883871Syz147064 done: 2893871Syz147064 free(gbuf); 2903871Syz147064 return (status); 2913871Syz147064 } 2923871Syz147064 2933871Syz147064 /* 2943871Syz147064 * Structures used in building the list of eligible WLANs to connect to. 2953871Syz147064 * Specifically, `connect_state' has the WLAN attributes that must be matched 2963871Syz147064 * (in `cs_attr') and a growing list of WLANs that matched those attributes 2973871Syz147064 * chained through `cs_list'. Each element in the list is of type `attr_node' 2983871Syz147064 * and has the matching WLAN's attributes and a pointer to the next element. 2993871Syz147064 * For convenience, `cs_count' tracks the number of elements in the list. 3003871Syz147064 */ 3013871Syz147064 typedef struct attr_node { 3023871Syz147064 dladm_wlan_attr_t an_attr; 3033871Syz147064 struct attr_node *an_next; 3043871Syz147064 } attr_node_t; 3053871Syz147064 3063871Syz147064 typedef struct connect_state { 3073871Syz147064 dladm_wlan_attr_t *cs_attr; 3083871Syz147064 uint_t cs_count; 3093871Syz147064 attr_node_t *cs_list; 3103871Syz147064 } connect_state_t; 3113871Syz147064 3123871Syz147064 /* 3133871Syz147064 * Compare two sets of WLAN attributes. For now, we only consider strength 3143871Syz147064 * and speed (in that order), which matches the documented default policy for 3153871Syz147064 * dladm_wlan_connect(). 3163871Syz147064 */ 3173871Syz147064 static int 3183871Syz147064 attr_compare(const void *p1, const void *p2) 3193871Syz147064 { 3203871Syz147064 dladm_wlan_attr_t *attrp1, *attrp2; 3213871Syz147064 3223871Syz147064 attrp1 = (*(dladm_wlan_attr_t **)p1); 3233871Syz147064 attrp2 = (*(dladm_wlan_attr_t **)p2); 3243871Syz147064 3253871Syz147064 if (attrp1->wa_strength < attrp2->wa_strength) 3263871Syz147064 return (1); 3273871Syz147064 3283871Syz147064 if (attrp1->wa_strength > attrp2->wa_strength) 3293871Syz147064 return (-1); 3303871Syz147064 3313871Syz147064 return (attrp2->wa_speed - attrp1->wa_speed); 3323871Syz147064 } 3333871Syz147064 3343871Syz147064 /* 3353871Syz147064 * Callback function used by dladm_wlan_connect() to filter out unwanted 3363871Syz147064 * WLANs when scanning for available WLANs. Always returns B_TRUE to 3373871Syz147064 * continue the scan. 3383871Syz147064 */ 3393871Syz147064 static boolean_t 3403871Syz147064 connect_cb(void *arg, dladm_wlan_attr_t *attrp) 3413871Syz147064 { 3423871Syz147064 attr_node_t *nodep; 3433871Syz147064 dladm_wlan_attr_t *fattrp; 3443871Syz147064 connect_state_t *statep = (connect_state_t *)arg; 3453871Syz147064 3463871Syz147064 fattrp = statep->cs_attr; 3473871Syz147064 if (fattrp == NULL) 3483871Syz147064 goto append; 3493871Syz147064 3503871Syz147064 if ((fattrp->wa_valid & attrp->wa_valid) != fattrp->wa_valid) 3513871Syz147064 return (B_TRUE); 3523871Syz147064 3533871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0 && 3543871Syz147064 strncmp(fattrp->wa_essid.we_bytes, attrp->wa_essid.we_bytes, 3553871Syz147064 DLADM_WLAN_MAX_ESSID_LEN) != 0) 3563871Syz147064 return (B_TRUE); 3573871Syz147064 3583871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 3593871Syz147064 fattrp->wa_secmode != attrp->wa_secmode) 3603871Syz147064 return (B_TRUE); 3613871Syz147064 3623871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0 && 3633871Syz147064 fattrp->wa_mode != attrp->wa_mode) 3643871Syz147064 return (B_TRUE); 3653871Syz147064 3663871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_STRENGTH) != 0 && 3673871Syz147064 fattrp->wa_strength != attrp->wa_strength) 3683871Syz147064 return (B_TRUE); 3693871Syz147064 3703871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SPEED) != 0 && 3713871Syz147064 fattrp->wa_speed != attrp->wa_speed) 3723871Syz147064 return (B_TRUE); 3733871Syz147064 3743871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) { 3753871Syz147064 attrp->wa_auth = fattrp->wa_auth; 3763871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 3773871Syz147064 } 3783871Syz147064 3793871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 3803871Syz147064 fattrp->wa_bsstype != attrp->wa_bsstype) 3813871Syz147064 return (B_TRUE); 3823871Syz147064 3833871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSID) != 0 && 3843871Syz147064 memcmp(fattrp->wa_bssid.wb_bytes, attrp->wa_bssid.wb_bytes, 3853871Syz147064 DLADM_WLAN_BSSID_LEN) != 0) 3863871Syz147064 return (B_TRUE); 3873871Syz147064 append: 3883871Syz147064 nodep = malloc(sizeof (attr_node_t)); 3893871Syz147064 if (nodep == NULL) 3903871Syz147064 return (B_TRUE); 3913871Syz147064 3923871Syz147064 (void) memcpy(&nodep->an_attr, attrp, sizeof (dladm_wlan_attr_t)); 3933871Syz147064 nodep->an_next = statep->cs_list; 3943871Syz147064 statep->cs_list = nodep; 3953871Syz147064 statep->cs_count++; 3963871Syz147064 3973871Syz147064 return (B_TRUE); 3983871Syz147064 } 3993871Syz147064 4004126Szf162725 #define IEEE80211_C_WPA 0x01800000 4014126Szf162725 4023871Syz147064 static dladm_status_t 4035895Syz147064 do_connect(datalink_id_t linkid, wldp_t *gbuf, dladm_wlan_attr_t *attrp, 4043871Syz147064 boolean_t create_ibss, void *keys, uint_t key_count, int timeout) 4053871Syz147064 { 4065895Syz147064 dladm_wlan_secmode_t secmode; 4075895Syz147064 dladm_wlan_auth_t authmode; 4085895Syz147064 dladm_wlan_bsstype_t bsstype; 4095895Syz147064 dladm_wlan_essid_t essid; 4105895Syz147064 boolean_t essid_valid = B_FALSE; 4115895Syz147064 dladm_status_t status; 4125895Syz147064 dladm_wlan_channel_t channel; 4135895Syz147064 hrtime_t start; 4145895Syz147064 wl_capability_t *caps; 4153871Syz147064 4163871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) { 4173871Syz147064 channel = attrp->wa_channel; 4185895Syz147064 status = do_set_channel(linkid, &channel); 4195895Syz147064 if (status != DLADM_STATUS_OK) 4203871Syz147064 goto fail; 4213871Syz147064 } 4223871Syz147064 4233871Syz147064 secmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) ? 4243871Syz147064 attrp->wa_secmode : DLADM_WLAN_SECMODE_NONE; 4253871Syz147064 4265895Syz147064 if ((status = do_set_encryption(linkid, &secmode)) != DLADM_STATUS_OK) 4273871Syz147064 goto fail; 4283871Syz147064 4293871Syz147064 authmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) ? 4303871Syz147064 attrp->wa_auth : DLADM_WLAN_AUTH_OPEN; 4313871Syz147064 4325895Syz147064 if ((status = do_set_authmode(linkid, &authmode)) != DLADM_STATUS_OK) 4333871Syz147064 goto fail; 4343871Syz147064 4353871Syz147064 bsstype = ((attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0) ? 4363871Syz147064 attrp->wa_bsstype : DLADM_WLAN_BSSTYPE_BSS; 4373871Syz147064 4385895Syz147064 if ((status = do_set_bsstype(linkid, &bsstype)) != DLADM_STATUS_OK) 4393871Syz147064 goto fail; 4403871Syz147064 4413871Syz147064 if (secmode == DLADM_WLAN_SECMODE_WEP) { 4425895Syz147064 if (keys == NULL || key_count == 0 || 4435895Syz147064 key_count > MAX_NWEPKEYS) { 4445895Syz147064 status = DLADM_STATUS_BADARG; 4455895Syz147064 goto fail; 4465895Syz147064 } 4475895Syz147064 status = do_set_key(linkid, keys, key_count); 4485895Syz147064 if (status != DLADM_STATUS_OK) 4493871Syz147064 goto fail; 4504126Szf162725 } else if (secmode == DLADM_WLAN_SECMODE_WPA) { 4515895Syz147064 if (keys == NULL || key_count == 0 || 4525895Syz147064 key_count > MAX_NWEPKEYS) { 4535895Syz147064 status = DLADM_STATUS_BADARG; 4545895Syz147064 goto fail; 4555895Syz147064 } 4565895Syz147064 status = do_get_capability(linkid, gbuf); 4575895Syz147064 if (status != DLADM_STATUS_OK) 4584126Szf162725 goto fail; 4594126Szf162725 caps = (wl_capability_t *)(gbuf->wldp_buf); 4604126Szf162725 if ((caps->caps & IEEE80211_C_WPA) == 0) 4614126Szf162725 return (DLADM_STATUS_NOTSUP); 4623871Syz147064 } 4633871Syz147064 4643871Syz147064 if (create_ibss) { 4655895Syz147064 status = do_set_channel(linkid, &channel); 4665895Syz147064 if (status != DLADM_STATUS_OK) 4673871Syz147064 goto fail; 4683871Syz147064 4695895Syz147064 status = do_set_createibss(linkid, &create_ibss); 4705895Syz147064 if (status != DLADM_STATUS_OK) 4713871Syz147064 goto fail; 4723871Syz147064 4733871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0) { 4743871Syz147064 generate_essid(&essid); 4753871Syz147064 essid_valid = B_TRUE; 4763871Syz147064 } 4773871Syz147064 } 4783871Syz147064 4793871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0) { 4803871Syz147064 essid = attrp->wa_essid; 4813871Syz147064 essid_valid = B_TRUE; 4823871Syz147064 } 4833871Syz147064 4845895Syz147064 if (!essid_valid) { 4855895Syz147064 status = DLADM_STATUS_FAILED; 4865895Syz147064 goto fail; 4875895Syz147064 } 4885895Syz147064 4895895Syz147064 if ((status = do_set_essid(linkid, &essid)) != DLADM_STATUS_OK) 4903871Syz147064 goto fail; 4913871Syz147064 4924126Szf162725 /* 4934126Szf162725 * Because wpa daemon needs getting essid from driver, 4944126Szf162725 * we need call do_set_essid() first, then call wpa_instance_create(). 4954126Szf162725 */ 4964126Szf162725 if (secmode == DLADM_WLAN_SECMODE_WPA && keys != NULL) 4975895Syz147064 (void) wpa_instance_create(linkid, keys); 4984126Szf162725 4993871Syz147064 start = gethrtime(); 5003871Syz147064 for (;;) { 5015895Syz147064 status = do_get_linkstatus(linkid, gbuf); 5025895Syz147064 if (status != DLADM_STATUS_OK) 5033871Syz147064 goto fail; 5043871Syz147064 5053871Syz147064 if (IS_CONNECTED(gbuf)) 5063871Syz147064 break; 5073871Syz147064 5083871Syz147064 (void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE); 5093871Syz147064 if ((timeout >= 0) && (gethrtime() - start) / 5105895Syz147064 NANOSEC >= timeout) { 5115895Syz147064 status = DLADM_STATUS_TIMEDOUT; 5125895Syz147064 goto fail; 5135895Syz147064 } 5143871Syz147064 } 5155895Syz147064 status = DLADM_STATUS_OK; 5163871Syz147064 fail: 5175895Syz147064 return (status); 5183871Syz147064 } 5193871Syz147064 5203871Syz147064 dladm_status_t 5215895Syz147064 dladm_wlan_connect(datalink_id_t linkid, dladm_wlan_attr_t *attrp, 5223871Syz147064 int timeout, void *keys, uint_t key_count, uint_t flags) 5233871Syz147064 { 5245895Syz147064 int i; 5253871Syz147064 wldp_t *gbuf = NULL; 5263871Syz147064 connect_state_t state = {0, NULL, NULL}; 5273871Syz147064 attr_node_t *nodep = NULL; 5283871Syz147064 boolean_t create_ibss, set_authmode; 5293871Syz147064 dladm_wlan_attr_t **wl_list = NULL; 5305895Syz147064 dladm_status_t status; 5313871Syz147064 5325895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 533*6233Syz147064 return (status); 5343871Syz147064 535*6233Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 536*6233Syz147064 return (DLADM_STATUS_NOMEM); 5373871Syz147064 5385895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 5393871Syz147064 goto done; 5403871Syz147064 5413871Syz147064 if (IS_CONNECTED(gbuf)) { 5423871Syz147064 status = DLADM_STATUS_ISCONN; 5433871Syz147064 goto done; 5443871Syz147064 } 5453871Syz147064 5463871Syz147064 set_authmode = ((attrp != NULL) && 5473871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0); 5483871Syz147064 create_ibss = ((flags & DLADM_WLAN_CONNECT_CREATEIBSS) != 0 && 5493871Syz147064 attrp != NULL && 5503871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 5513871Syz147064 attrp->wa_bsstype == DLADM_WLAN_BSSTYPE_IBSS); 5523871Syz147064 5533871Syz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 || 5543871Syz147064 (create_ibss && attrp != NULL && 5553871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) { 5565895Syz147064 status = do_connect(linkid, gbuf, attrp, create_ibss, keys, 5575895Syz147064 key_count, timeout); 5583871Syz147064 goto done; 5593871Syz147064 } 5603871Syz147064 5613871Syz147064 state.cs_attr = attrp; 5623871Syz147064 state.cs_list = NULL; 5633871Syz147064 state.cs_count = 0; 5643871Syz147064 5655895Syz147064 status = dladm_wlan_scan(linkid, &state, connect_cb); 5663871Syz147064 if (status != DLADM_STATUS_OK) 5673871Syz147064 goto done; 5683871Syz147064 5693871Syz147064 if (state.cs_count == 0) { 5703871Syz147064 if (!create_ibss) { 5713871Syz147064 status = DLADM_STATUS_NOTFOUND; 5723871Syz147064 goto done; 5733871Syz147064 } 5745895Syz147064 status = do_connect(linkid, gbuf, attrp, create_ibss, keys, 5755895Syz147064 key_count, timeout); 5763871Syz147064 goto done; 5773871Syz147064 } 5783871Syz147064 5793871Syz147064 wl_list = malloc(state.cs_count * sizeof (dladm_wlan_attr_t *)); 5803871Syz147064 if (wl_list == NULL) { 5813871Syz147064 status = DLADM_STATUS_NOMEM; 5823871Syz147064 goto done; 5833871Syz147064 } 5843871Syz147064 5853871Syz147064 nodep = state.cs_list; 5863871Syz147064 for (i = 0; i < state.cs_count; i++) { 5873871Syz147064 wl_list[i] = &nodep->an_attr; 5883871Syz147064 nodep = nodep->an_next; 5893871Syz147064 } 5903871Syz147064 qsort(wl_list, state.cs_count, sizeof (dladm_wlan_attr_t *), 5913871Syz147064 attr_compare); 5923871Syz147064 5933871Syz147064 for (i = 0; i < state.cs_count; i++) { 5943871Syz147064 dladm_wlan_attr_t *ap = wl_list[i]; 5953871Syz147064 5965895Syz147064 status = do_connect(linkid, gbuf, ap, create_ibss, keys, 5973871Syz147064 key_count, timeout); 5983871Syz147064 if (status == DLADM_STATUS_OK) 5993871Syz147064 break; 6003871Syz147064 6013871Syz147064 if (!set_authmode) { 6023871Syz147064 ap->wa_auth = DLADM_WLAN_AUTH_SHARED; 6033871Syz147064 ap->wa_valid |= DLADM_WLAN_ATTR_AUTH; 6045895Syz147064 status = do_connect(linkid, gbuf, ap, create_ibss, keys, 6055895Syz147064 key_count, timeout); 6063871Syz147064 if (status == DLADM_STATUS_OK) 6073871Syz147064 break; 6083871Syz147064 } 6093871Syz147064 } 6103871Syz147064 done: 6113871Syz147064 if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN)) 6125895Syz147064 (void) do_disconnect(linkid, gbuf); 6133871Syz147064 6143871Syz147064 while (state.cs_list != NULL) { 6153871Syz147064 nodep = state.cs_list; 6163871Syz147064 state.cs_list = nodep->an_next; 6173871Syz147064 free(nodep); 6183871Syz147064 } 6193871Syz147064 free(gbuf); 6203871Syz147064 free(wl_list); 6213871Syz147064 return (status); 6223871Syz147064 } 6233871Syz147064 6243871Syz147064 dladm_status_t 6255895Syz147064 dladm_wlan_disconnect(datalink_id_t linkid) 6263871Syz147064 { 6273871Syz147064 wldp_t *gbuf; 6283871Syz147064 dladm_status_t status; 6293871Syz147064 6305895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 6315895Syz147064 return (status); 6323871Syz147064 6333871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 6343871Syz147064 status = DLADM_STATUS_NOMEM; 6353871Syz147064 goto done; 6363871Syz147064 } 6373871Syz147064 6385895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 6393871Syz147064 goto done; 6403871Syz147064 6413871Syz147064 if (!IS_CONNECTED(gbuf)) { 6423871Syz147064 status = DLADM_STATUS_NOTCONN; 6433871Syz147064 goto done; 6443871Syz147064 } 6453871Syz147064 6465895Syz147064 if ((status = do_disconnect(linkid, gbuf)) != DLADM_STATUS_OK) 6473871Syz147064 goto done; 6483871Syz147064 6495895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 6503871Syz147064 goto done; 6513871Syz147064 6523871Syz147064 if (IS_CONNECTED(gbuf)) { 6533871Syz147064 status = DLADM_STATUS_FAILED; 6543871Syz147064 goto done; 6553871Syz147064 } 6563871Syz147064 6573871Syz147064 status = DLADM_STATUS_OK; 6583871Syz147064 done: 6593871Syz147064 free(gbuf); 6603871Syz147064 return (status); 6613871Syz147064 } 6623871Syz147064 6635895Syz147064 dladm_status_t 6645895Syz147064 dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) 6653871Syz147064 { 6666131Syz147064 wldp_t *gbuf = NULL; 6673871Syz147064 wl_rssi_t signal; 6683871Syz147064 wl_bss_type_t bsstype; 6693871Syz147064 wl_authmode_t authmode; 6703871Syz147064 wl_encryption_t encryption; 6713871Syz147064 wl_rates_t *ratesp; 6723871Syz147064 dladm_wlan_attr_t *wl_attrp; 6735895Syz147064 dladm_status_t status; 6743871Syz147064 6753871Syz147064 if (attrp == NULL) 6763871Syz147064 return (DLADM_STATUS_BADARG); 6773871Syz147064 6785895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 6795895Syz147064 goto done; 6803871Syz147064 6813871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 6823871Syz147064 status = DLADM_STATUS_NOMEM; 6833871Syz147064 goto done; 6843871Syz147064 } 6853871Syz147064 6863871Syz147064 (void) memset(attrp, 0, sizeof (*attrp)); 6873871Syz147064 wl_attrp = &attrp->la_wlan_attr; 6883871Syz147064 6895895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 6903871Syz147064 goto done; 6913871Syz147064 6923871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS; 6935895Syz147064 if (!IS_CONNECTED(gbuf)) 6945895Syz147064 attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED; 6955895Syz147064 else 6965895Syz147064 attrp->la_status = DLADM_WLAN_LINK_CONNECTED; 6973871Syz147064 6985895Syz147064 if ((status = do_get_essid(linkid, gbuf)) != DLADM_STATUS_OK) 6993871Syz147064 goto done; 7003871Syz147064 7013871Syz147064 (void) strlcpy(wl_attrp->wa_essid.we_bytes, 7023871Syz147064 ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid, 7033871Syz147064 DLADM_WLAN_MAX_ESSID_LEN); 7043871Syz147064 7053871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 7063871Syz147064 7075895Syz147064 if ((status = do_get_bssid(linkid, gbuf)) != DLADM_STATUS_OK) 7083871Syz147064 goto done; 7093871Syz147064 7103871Syz147064 (void) memcpy(wl_attrp->wa_bssid.wb_bytes, gbuf->wldp_buf, 7113871Syz147064 DLADM_WLAN_BSSID_LEN); 7123871Syz147064 7133871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 7143871Syz147064 7155895Syz147064 if (attrp->la_status == DLADM_WLAN_LINK_DISCONNECTED) { 7164126Szf162725 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 7174126Szf162725 status = DLADM_STATUS_OK; 7184126Szf162725 goto done; 7194126Szf162725 } 7204126Szf162725 7215895Syz147064 if ((status = do_get_encryption(linkid, gbuf)) != DLADM_STATUS_OK) 7223871Syz147064 goto done; 7233871Syz147064 7243871Syz147064 encryption = *(wl_encryption_t *)(gbuf->wldp_buf); 7253871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 7263871Syz147064 7273871Syz147064 switch (encryption) { 7283871Syz147064 case WL_NOENCRYPTION: 7293871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_NONE; 7303871Syz147064 break; 7313871Syz147064 case WL_ENC_WEP: 7323871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP; 7333871Syz147064 break; 7344126Szf162725 case WL_ENC_WPA: 7354126Szf162725 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 7364126Szf162725 break; 7373871Syz147064 default: 7383871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE; 7393871Syz147064 break; 7403871Syz147064 } 7413871Syz147064 7425895Syz147064 if ((status = do_get_signal(linkid, gbuf)) != DLADM_STATUS_OK) 7433871Syz147064 goto done; 7443871Syz147064 7453871Syz147064 signal = *(wl_rssi_t *)(gbuf->wldp_buf); 7463871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 7473871Syz147064 wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal); 7483871Syz147064 7495895Syz147064 if ((status = do_get_rate(linkid, gbuf)) != DLADM_STATUS_OK) 7503871Syz147064 goto done; 7513871Syz147064 7523871Syz147064 ratesp = (wl_rates_t *)(gbuf->wldp_buf); 7533871Syz147064 if (ratesp->wl_rates_num > 0) { 7543871Syz147064 uint_t i, r = 0; 7553871Syz147064 7563871Syz147064 for (i = 0; i < ratesp->wl_rates_num; i++) { 7573871Syz147064 if (ratesp->wl_rates_rates[i] > r) 7583871Syz147064 r = ratesp->wl_rates_rates[i]; 7593871Syz147064 } 7603871Syz147064 wl_attrp->wa_speed = r; 7613871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 7623871Syz147064 } 7633871Syz147064 7645895Syz147064 if ((status = do_get_authmode(linkid, gbuf)) != DLADM_STATUS_OK) 7653871Syz147064 goto done; 7663871Syz147064 7673871Syz147064 authmode = *(wl_authmode_t *)(gbuf->wldp_buf); 7683871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 7693871Syz147064 7703871Syz147064 switch (authmode) { 7713871Syz147064 case WL_OPENSYSTEM: 7723871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN; 7733871Syz147064 break; 7743871Syz147064 case WL_SHAREDKEY: 7753871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED; 7763871Syz147064 break; 7773871Syz147064 default: 7783871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH; 7793871Syz147064 break; 7803871Syz147064 } 7813871Syz147064 7825895Syz147064 if ((status = do_get_bsstype(linkid, gbuf)) != DLADM_STATUS_OK) 7833871Syz147064 goto done; 7843871Syz147064 7853871Syz147064 bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf); 7863871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 7873871Syz147064 7883871Syz147064 switch (bsstype) { 7893871Syz147064 case WL_BSS_BSS: 7903871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS; 7913871Syz147064 break; 7923871Syz147064 case WL_BSS_IBSS: 7933871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS; 7943871Syz147064 break; 7953871Syz147064 case WL_BSS_ANY: 7963871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY; 7973871Syz147064 break; 7983871Syz147064 default: 7993871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE; 8003871Syz147064 break; 8013871Syz147064 } 8023871Syz147064 8035895Syz147064 if ((status = do_get_mode(linkid, gbuf)) != DLADM_STATUS_OK) 8043871Syz147064 goto done; 8053871Syz147064 8063871Syz147064 wl_attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)(gbuf->wldp_buf)); 8073871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8083871Syz147064 if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE) 8093871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8103871Syz147064 8113871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 8123871Syz147064 status = DLADM_STATUS_OK; 8133871Syz147064 8143871Syz147064 done: 8153871Syz147064 free(gbuf); 8163871Syz147064 return (status); 8173871Syz147064 } 8183871Syz147064 8193871Syz147064 static dladm_status_t 8205895Syz147064 dladm_wlan_validate(datalink_id_t linkid) 8213871Syz147064 { 8225895Syz147064 wldp_t *gbuf; 8233871Syz147064 dladm_status_t status; 8243871Syz147064 8253871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 8263871Syz147064 status = DLADM_STATUS_NOMEM; 8273871Syz147064 goto done; 8283871Syz147064 } 8293871Syz147064 8305895Syz147064 /* 8315895Syz147064 * Check to see if the link is wireless. 8325895Syz147064 */ 8335895Syz147064 if ((status = do_get_bsstype(linkid, gbuf)) != DLADM_STATUS_OK) { 8345895Syz147064 status = DLADM_STATUS_LINKINVAL; 8355895Syz147064 goto done; 8365895Syz147064 } 8373871Syz147064 8383871Syz147064 done: 8393871Syz147064 free(gbuf); 8403871Syz147064 return (status); 8413871Syz147064 } 8423871Syz147064 8433871Syz147064 static boolean_t 8443871Syz147064 find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp) 8453871Syz147064 { 8463871Syz147064 int i; 8473871Syz147064 8483871Syz147064 for (i = 0; i < cnt; i++) { 8493871Syz147064 if (strcasecmp(str, vdp[i].vd_name) == 0) { 8503871Syz147064 *valp = vdp[i].vd_val; 8513871Syz147064 return (B_TRUE); 8523871Syz147064 } 8533871Syz147064 } 8543871Syz147064 return (B_FALSE); 8553871Syz147064 } 8563871Syz147064 8573871Syz147064 static boolean_t 8583871Syz147064 find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp) 8593871Syz147064 { 8603871Syz147064 int i; 8613871Syz147064 8623871Syz147064 for (i = 0; i < cnt; i++) { 8633871Syz147064 if (val == vdp[i].vd_val) { 8643871Syz147064 *strp = vdp[i].vd_name; 8653871Syz147064 return (B_TRUE); 8663871Syz147064 } 8673871Syz147064 } 8683871Syz147064 return (B_FALSE); 8693871Syz147064 } 8703871Syz147064 8713871Syz147064 const char * 8723871Syz147064 dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf) 8733871Syz147064 { 8743871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes); 8753871Syz147064 return (buf); 8763871Syz147064 } 8773871Syz147064 8783871Syz147064 const char * 8793871Syz147064 dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf) 8803871Syz147064 { 8813871Syz147064 return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN, 8823871Syz147064 IFT_OTHER)); 8833871Syz147064 } 8843871Syz147064 8853871Syz147064 static const char * 8863871Syz147064 dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf) 8873871Syz147064 { 8883871Syz147064 char *s; 8893871Syz147064 8903871Syz147064 if (!find_name_by_val(val, vdp, cnt, &s)) 8913871Syz147064 s = ""; 8923871Syz147064 8933871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 8943871Syz147064 return (buf); 8953871Syz147064 } 8963871Syz147064 8973871Syz147064 const char * 8983871Syz147064 dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf) 8993871Syz147064 { 9003871Syz147064 return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals, 9013871Syz147064 VALCNT(secmode_vals), buf)); 9023871Syz147064 } 9033871Syz147064 9043871Syz147064 const char * 9053871Syz147064 dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf) 9063871Syz147064 { 9073871Syz147064 return (dladm_wlan_val2str((uint_t)*strength, strength_vals, 9083871Syz147064 VALCNT(strength_vals), buf)); 9093871Syz147064 } 9103871Syz147064 9113871Syz147064 const char * 9123871Syz147064 dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf) 9133871Syz147064 { 9143871Syz147064 return (dladm_wlan_val2str((uint_t)*mode, mode_vals, 9153871Syz147064 VALCNT(mode_vals), buf)); 9163871Syz147064 } 9173871Syz147064 9183871Syz147064 const char * 9193871Syz147064 dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf) 9203871Syz147064 { 9213871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2, 9223871Syz147064 (float)(*speed) / 2); 9233871Syz147064 return (buf); 9243871Syz147064 } 9253871Syz147064 9263871Syz147064 const char * 9273871Syz147064 dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf) 9283871Syz147064 { 9293871Syz147064 return (dladm_wlan_val2str((uint_t)*auth, auth_vals, 9303871Syz147064 VALCNT(auth_vals), buf)); 9313871Syz147064 } 9323871Syz147064 9333871Syz147064 const char * 9343871Syz147064 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf) 9353871Syz147064 { 9363871Syz147064 return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals, 9373871Syz147064 VALCNT(bsstype_vals), buf)); 9383871Syz147064 } 9393871Syz147064 9403871Syz147064 const char * 9413871Syz147064 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf) 9423871Syz147064 { 9433871Syz147064 return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals, 9443871Syz147064 VALCNT(linkstatus_vals), buf)); 9453871Syz147064 } 9463871Syz147064 9473871Syz147064 dladm_status_t 9483871Syz147064 dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid) 9493871Syz147064 { 9503871Syz147064 if (str[0] == '\0') 9513871Syz147064 return (DLADM_STATUS_BADARG); 9523871Syz147064 9533871Syz147064 (void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN); 9543871Syz147064 return (DLADM_STATUS_OK); 9553871Syz147064 } 9563871Syz147064 9573871Syz147064 dladm_status_t 9583871Syz147064 dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid) 9593871Syz147064 { 9603871Syz147064 int len; 9613871Syz147064 uchar_t *buf; 9623871Syz147064 9633871Syz147064 buf = _link_aton(str, &len); 9643871Syz147064 if (buf == NULL) 9653871Syz147064 return (DLADM_STATUS_BADARG); 9663871Syz147064 9673871Syz147064 if (len != DLADM_WLAN_BSSID_LEN) { 9683871Syz147064 free(buf); 9693871Syz147064 return (DLADM_STATUS_BADARG); 9703871Syz147064 } 9713871Syz147064 9723871Syz147064 (void) memcpy(bssid->wb_bytes, buf, len); 9733871Syz147064 free(buf); 9743871Syz147064 return (DLADM_STATUS_OK); 9753871Syz147064 } 9763871Syz147064 9773871Syz147064 dladm_status_t 9783871Syz147064 dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode) 9793871Syz147064 { 9803871Syz147064 uint_t val; 9813871Syz147064 9823871Syz147064 if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val)) 9833871Syz147064 return (DLADM_STATUS_BADARG); 9843871Syz147064 9853871Syz147064 *secmode = (dladm_wlan_secmode_t)val; 9863871Syz147064 return (DLADM_STATUS_OK); 9873871Syz147064 } 9883871Syz147064 9893871Syz147064 dladm_status_t 9903871Syz147064 dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength) 9913871Syz147064 { 9923871Syz147064 uint_t val; 9933871Syz147064 9943871Syz147064 if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val)) 9953871Syz147064 return (DLADM_STATUS_BADARG); 9963871Syz147064 9973871Syz147064 *strength = (dladm_wlan_strength_t)val; 9983871Syz147064 return (DLADM_STATUS_OK); 9993871Syz147064 } 10003871Syz147064 10013871Syz147064 dladm_status_t 10023871Syz147064 dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode) 10033871Syz147064 { 10043871Syz147064 uint_t val; 10053871Syz147064 10063871Syz147064 if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val)) 10073871Syz147064 return (DLADM_STATUS_BADARG); 10083871Syz147064 10093871Syz147064 *mode = (dladm_wlan_mode_t)val; 10103871Syz147064 return (DLADM_STATUS_OK); 10113871Syz147064 } 10123871Syz147064 10133871Syz147064 dladm_status_t 10143871Syz147064 dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed) 10153871Syz147064 { 10163871Syz147064 *speed = (dladm_wlan_speed_t)(atof(str) * 2); 10173871Syz147064 return (DLADM_STATUS_OK); 10183871Syz147064 } 10193871Syz147064 10203871Syz147064 dladm_status_t 10213871Syz147064 dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth) 10223871Syz147064 { 10233871Syz147064 uint_t val; 10243871Syz147064 10253871Syz147064 if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val)) 10263871Syz147064 return (DLADM_STATUS_BADARG); 10273871Syz147064 10283871Syz147064 *auth = (dladm_wlan_auth_t)val; 10293871Syz147064 return (DLADM_STATUS_OK); 10303871Syz147064 } 10313871Syz147064 10323871Syz147064 dladm_status_t 10333871Syz147064 dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype) 10343871Syz147064 { 10353871Syz147064 uint_t val; 10363871Syz147064 10373871Syz147064 if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val)) 10383871Syz147064 return (DLADM_STATUS_BADARG); 10393871Syz147064 10403871Syz147064 *bsstype = (dladm_wlan_bsstype_t)val; 10413871Syz147064 return (DLADM_STATUS_OK); 10423871Syz147064 } 10433871Syz147064 10443871Syz147064 dladm_status_t 10453871Syz147064 dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus) 10463871Syz147064 { 10473871Syz147064 uint_t val; 10483871Syz147064 10495895Syz147064 if (!find_val_by_name(str, linkstatus_vals, 10505895Syz147064 VALCNT(linkstatus_vals), &val)) { 10513871Syz147064 return (DLADM_STATUS_BADARG); 10525895Syz147064 } 10533871Syz147064 10543871Syz147064 *linkstatus = (dladm_wlan_linkstatus_t)val; 10553871Syz147064 return (DLADM_STATUS_OK); 10563871Syz147064 } 10573871Syz147064 10585895Syz147064 dladm_status_t 10595895Syz147064 i_dladm_wlan_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id, size_t len, 10605895Syz147064 uint_t cmd, size_t cmdlen) 10613871Syz147064 { 10625895Syz147064 char linkname[MAXPATHLEN]; 10635895Syz147064 int fd, rc; 10643871Syz147064 struct strioctl stri; 10655895Syz147064 uint32_t flags; 10665895Syz147064 dladm_status_t status; 10675895Syz147064 uint32_t media; 10685895Syz147064 char link[MAXLINKNAMELEN]; 10695895Syz147064 10705895Syz147064 if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media, 10715895Syz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 10725895Syz147064 return (status); 10735895Syz147064 } 10745895Syz147064 10755895Syz147064 if (media != DL_WIFI) 10765895Syz147064 return (DLADM_STATUS_BADARG); 10775895Syz147064 10785895Syz147064 if (!(flags & DLADM_OPT_ACTIVE)) 10795895Syz147064 return (DLADM_STATUS_TEMPONLY); 10805895Syz147064 10815895Syz147064 /* 10825895Syz147064 * dlpi_open() is not used here because libdlpi depends on libdladm, 10835895Syz147064 * and we do not want to introduce recursive dependencies. 10845895Syz147064 */ 10855895Syz147064 (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link); 10865895Syz147064 if ((fd = open(linkname, O_RDWR)) < 0) 10875895Syz147064 return (DLADM_STATUS_LINKINVAL); 10883871Syz147064 10893871Syz147064 gbuf->wldp_type = NET_802_11; 10903871Syz147064 gbuf->wldp_id = id; 10913871Syz147064 gbuf->wldp_length = len; 10923871Syz147064 10933871Syz147064 stri.ic_timout = 0; 10943871Syz147064 stri.ic_dp = (char *)gbuf; 10953871Syz147064 stri.ic_cmd = cmd; 10963871Syz147064 stri.ic_len = cmdlen; 10973871Syz147064 10983871Syz147064 if ((rc = ioctl(fd, I_STR, &stri)) != 0) { 10995895Syz147064 if (rc > 0) { 11005895Syz147064 /* 11015895Syz147064 * Non-negative return value indicates the specific 11025895Syz147064 * operation failed and the reason for the failure 11035895Syz147064 * was stored in gbuf->wldp_result. 11045895Syz147064 */ 11055895Syz147064 status = dladm_wlan_wlresult2status(gbuf); 11065895Syz147064 } else { 11075895Syz147064 /* 11085895Syz147064 * Negative return value indicates the ioctl failed. 11095895Syz147064 */ 11105895Syz147064 status = dladm_errno2status(errno); 11115895Syz147064 } 11123871Syz147064 } 11135895Syz147064 (void) close(fd); 11145895Syz147064 return (status); 11153871Syz147064 } 11163871Syz147064 11175895Syz147064 dladm_status_t 11185895Syz147064 i_dladm_wlan_get_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id) 11193871Syz147064 { 11203871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11215895Syz147064 return (i_dladm_wlan_ioctl(linkid, gbuf, id, MAX_BUF_LEN, 11225895Syz147064 WLAN_GET_PARAM, MAX_BUF_LEN)); 11233871Syz147064 } 11243871Syz147064 11255895Syz147064 dladm_status_t 11265895Syz147064 i_dladm_wlan_set_ioctl(datalink_id_t linkid, uint_t id, void *buf, 11275895Syz147064 uint_t buflen) 11283871Syz147064 { 11295895Syz147064 wldp_t *gbuf; 11305895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 11315895Syz147064 11325895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 11335895Syz147064 return (DLADM_STATUS_NOMEM); 11345895Syz147064 11353871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11363871Syz147064 (void) memcpy(gbuf->wldp_buf, buf, buflen); 11373871Syz147064 buflen += WIFI_BUF_OFFSET; 11385895Syz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, id, buflen, 11395895Syz147064 WLAN_SET_PARAM, buflen); 11405895Syz147064 11415895Syz147064 free(gbuf); 11425895Syz147064 return (status); 11433871Syz147064 } 11443871Syz147064 11455895Syz147064 static dladm_status_t 11465895Syz147064 do_cmd_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t cmd) 11473871Syz147064 { 11483871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11495895Syz147064 return (i_dladm_wlan_ioctl(linkid, gbuf, cmd, sizeof (wldp_t), 11505895Syz147064 WLAN_COMMAND, sizeof (wldp_t))); 11513871Syz147064 } 11523871Syz147064 11535895Syz147064 static dladm_status_t 11545895Syz147064 do_scan(datalink_id_t linkid, wldp_t *gbuf) 11553871Syz147064 { 11565895Syz147064 return (do_cmd_ioctl(linkid, gbuf, WL_SCAN)); 11573871Syz147064 } 11583871Syz147064 11595895Syz147064 static dladm_status_t 11605895Syz147064 do_disconnect(datalink_id_t linkid, wldp_t *gbuf) 11613871Syz147064 { 11625895Syz147064 if (do_get_wpamode(linkid, gbuf) == 0 && 11635895Syz147064 ((wl_wpa_t *)(gbuf->wldp_buf))->wpa_flag > 0) 11645895Syz147064 (void) wpa_instance_delete(linkid); 11654126Szf162725 11665895Syz147064 return (do_cmd_ioctl(linkid, gbuf, WL_DISASSOCIATE)); 11673871Syz147064 } 11683871Syz147064 11695895Syz147064 static dladm_status_t 11705895Syz147064 do_get_esslist(datalink_id_t linkid, wldp_t *gbuf) 11713871Syz147064 { 11723871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11735895Syz147064 return (i_dladm_wlan_ioctl(linkid, gbuf, WL_ESS_LIST, MAX_BUF_LEN, 11743871Syz147064 WLAN_GET_PARAM, sizeof (wldp_t))); 11753871Syz147064 } 11763871Syz147064 11775895Syz147064 static dladm_status_t 11785895Syz147064 do_get_bssid(datalink_id_t linkid, wldp_t *gbuf) 11793871Syz147064 { 11805895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSSID)); 11813871Syz147064 } 11823871Syz147064 11835895Syz147064 static dladm_status_t 11845895Syz147064 do_get_essid(datalink_id_t linkid, wldp_t *gbuf) 11853871Syz147064 { 11865895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ESSID)); 11873871Syz147064 } 11883871Syz147064 11895895Syz147064 static dladm_status_t 11905895Syz147064 do_get_bsstype(datalink_id_t linkid, wldp_t *gbuf) 11913871Syz147064 { 11925895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSS_TYPE)); 11933871Syz147064 } 11943871Syz147064 11955895Syz147064 static dladm_status_t 11965895Syz147064 do_get_linkstatus(datalink_id_t linkid, wldp_t *gbuf) 11973871Syz147064 { 11985895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_LINKSTATUS)); 11993871Syz147064 } 12003871Syz147064 12013871Syz147064 static dladm_status_t 12025895Syz147064 do_get_rate(datalink_id_t linkid, wldp_t *gbuf) 12033871Syz147064 { 12045895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_DESIRED_RATES)); 12053871Syz147064 } 12063871Syz147064 12073871Syz147064 static dladm_status_t 12085895Syz147064 do_get_authmode(datalink_id_t linkid, wldp_t *gbuf) 12093871Syz147064 { 12105895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_AUTH_MODE)); 12113871Syz147064 } 12123871Syz147064 12133871Syz147064 static dladm_status_t 12145895Syz147064 do_get_encryption(datalink_id_t linkid, wldp_t *gbuf) 12153871Syz147064 { 12165895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ENCRYPTION)); 12173871Syz147064 } 12183871Syz147064 12193871Syz147064 static dladm_status_t 12205895Syz147064 do_get_signal(datalink_id_t linkid, wldp_t *gbuf) 12213871Syz147064 { 12225895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RSSI)); 12233871Syz147064 } 12243871Syz147064 12253871Syz147064 static dladm_status_t 12265895Syz147064 do_get_mode(datalink_id_t linkid, wldp_t *gbuf) 12273871Syz147064 { 12285895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 12293871Syz147064 } 12303871Syz147064 12315895Syz147064 static dladm_status_t 12325895Syz147064 do_set_bsstype(datalink_id_t linkid, dladm_wlan_bsstype_t *bsstype) 12333871Syz147064 { 12343871Syz147064 wl_bss_type_t ibsstype; 12353871Syz147064 12363871Syz147064 switch (*bsstype) { 12373871Syz147064 case DLADM_WLAN_BSSTYPE_BSS: 12383871Syz147064 ibsstype = WL_BSS_BSS; 12393871Syz147064 break; 12403871Syz147064 case DLADM_WLAN_BSSTYPE_IBSS: 12413871Syz147064 ibsstype = WL_BSS_IBSS; 12423871Syz147064 break; 12433871Syz147064 default: 12443871Syz147064 ibsstype = WL_BSS_ANY; 12453871Syz147064 break; 12463871Syz147064 } 12475895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_BSS_TYPE, &ibsstype, 12483871Syz147064 sizeof (ibsstype))); 12493871Syz147064 } 12503871Syz147064 12515895Syz147064 static dladm_status_t 12525895Syz147064 do_set_authmode(datalink_id_t linkid, dladm_wlan_auth_t *auth) 12533871Syz147064 { 12543871Syz147064 wl_authmode_t auth_mode; 12553871Syz147064 12563871Syz147064 switch (*auth) { 12573871Syz147064 case DLADM_WLAN_AUTH_OPEN: 12583871Syz147064 auth_mode = WL_OPENSYSTEM; 12593871Syz147064 break; 12603871Syz147064 case DLADM_WLAN_AUTH_SHARED: 12613871Syz147064 auth_mode = WL_SHAREDKEY; 12623871Syz147064 break; 12633871Syz147064 default: 12645895Syz147064 return (DLADM_STATUS_NOTSUP); 12653871Syz147064 } 12665895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_AUTH_MODE, &auth_mode, 12673871Syz147064 sizeof (auth_mode))); 12683871Syz147064 } 12693871Syz147064 12705895Syz147064 static dladm_status_t 12715895Syz147064 do_set_encryption(datalink_id_t linkid, dladm_wlan_secmode_t *secmode) 12723871Syz147064 { 12733871Syz147064 wl_encryption_t encryption; 12743871Syz147064 12753871Syz147064 switch (*secmode) { 12763871Syz147064 case DLADM_WLAN_SECMODE_NONE: 12773871Syz147064 encryption = WL_NOENCRYPTION; 12783871Syz147064 break; 12793871Syz147064 case DLADM_WLAN_SECMODE_WEP: 12803871Syz147064 encryption = WL_ENC_WEP; 12813871Syz147064 break; 12824126Szf162725 case DLADM_WLAN_SECMODE_WPA: 12834126Szf162725 return (0); 12843871Syz147064 default: 12855895Syz147064 return (DLADM_STATUS_NOTSUP); 12863871Syz147064 } 12875895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_ENCRYPTION, &encryption, 12883871Syz147064 sizeof (encryption))); 12893871Syz147064 } 12903871Syz147064 12915895Syz147064 static dladm_status_t 12925895Syz147064 do_set_key(datalink_id_t linkid, dladm_wlan_key_t *keys, 12933871Syz147064 uint_t key_count) 12943871Syz147064 { 12953871Syz147064 int i; 12963871Syz147064 wl_wep_key_t *wkp; 12973871Syz147064 wl_wep_key_tab_t wepkey_tab; 12984126Szf162725 dladm_wlan_key_t *kp; 12993871Syz147064 13003871Syz147064 if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL) 13015895Syz147064 return (DLADM_STATUS_BADARG); 13023871Syz147064 13033871Syz147064 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab)); 13043871Syz147064 for (i = 0; i < MAX_NWEPKEYS; i++) 13053871Syz147064 wepkey_tab[i].wl_wep_operation = WL_NUL; 13063871Syz147064 13073871Syz147064 for (i = 0; i < key_count; i++) { 13083871Syz147064 kp = &keys[i]; 13093871Syz147064 if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS) 13105895Syz147064 return (DLADM_STATUS_BADARG); 13113871Syz147064 if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN && 13123871Syz147064 kp->wk_len != DLADM_WLAN_WEPKEY128_LEN) 13135895Syz147064 return (DLADM_STATUS_BADARG); 13143871Syz147064 13153871Syz147064 wkp = &wepkey_tab[kp->wk_idx - 1]; 13163871Syz147064 wkp->wl_wep_operation = WL_ADD; 13173871Syz147064 wkp->wl_wep_length = kp->wk_len; 13183871Syz147064 (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len); 13193871Syz147064 } 13203871Syz147064 13215895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_WEP_KEY_TAB, &wepkey_tab, 13223871Syz147064 sizeof (wepkey_tab))); 13233871Syz147064 } 13243871Syz147064 13255895Syz147064 static dladm_status_t 13265895Syz147064 do_set_essid(datalink_id_t linkid, dladm_wlan_essid_t *essid) 13273871Syz147064 { 13283871Syz147064 wl_essid_t iessid; 13293871Syz147064 13303871Syz147064 (void) memset(&iessid, 0, sizeof (essid)); 13313871Syz147064 13323871Syz147064 if (essid != NULL && essid->we_bytes[0] != '\0') { 13333871Syz147064 iessid.wl_essid_length = strlen(essid->we_bytes); 13343871Syz147064 (void) strlcpy(iessid.wl_essid_essid, essid->we_bytes, 13353871Syz147064 sizeof (iessid.wl_essid_essid)); 13363871Syz147064 } else { 13375895Syz147064 return (DLADM_STATUS_BADARG); 13385102Syz147064 } 13395895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_ESSID, &iessid, 13405895Syz147064 sizeof (iessid))); 13413871Syz147064 } 13423871Syz147064 13433871Syz147064 static dladm_status_t 13445895Syz147064 do_set_channel(datalink_id_t linkid, dladm_wlan_channel_t *channel) 13453871Syz147064 { 13463871Syz147064 wl_phy_conf_t phy_conf; 13473871Syz147064 13483871Syz147064 if (*channel > MAX_CHANNEL_NUM) 13495895Syz147064 return (DLADM_STATUS_BADVAL); 13503871Syz147064 13513871Syz147064 (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); 13523871Syz147064 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel; 13533871Syz147064 13545895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_PHY_CONFIG, &phy_conf, 13553871Syz147064 sizeof (phy_conf))); 13563871Syz147064 } 13573871Syz147064 13585895Syz147064 static dladm_status_t 13595895Syz147064 do_set_createibss(datalink_id_t linkid, boolean_t *create_ibss) 13603871Syz147064 { 13613871Syz147064 wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss); 13623871Syz147064 13635895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_CREATE_IBSS, 13645895Syz147064 &cr, sizeof (cr))); 13653871Syz147064 } 13663871Syz147064 13673871Syz147064 static void 13683871Syz147064 generate_essid(dladm_wlan_essid_t *essid) 13693871Syz147064 { 13703871Syz147064 srandom(gethrtime()); 13713871Syz147064 (void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d", 13723871Syz147064 random()); 13733871Syz147064 } 13744126Szf162725 13755895Syz147064 static dladm_status_t 13765895Syz147064 do_get_capability(datalink_id_t linkid, wldp_t *gbuf) 13774126Szf162725 { 13785895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_CAPABILITY)); 13794126Szf162725 } 13804126Szf162725 13814126Szf162725 static dladm_status_t 13825895Syz147064 do_get_wpamode(datalink_id_t linkid, wldp_t *gbuf) 13834126Szf162725 { 13845895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_WPA)); 13854126Szf162725 } 13864126Szf162725 13874126Szf162725 dladm_status_t 13885895Syz147064 dladm_wlan_wpa_get_sr(datalink_id_t linkid, dladm_wlan_ess_t *sr, 13895895Syz147064 uint_t escnt, uint_t *estot) 13904126Szf162725 { 13914126Szf162725 int i, n; 13924126Szf162725 wldp_t *gbuf; 13934126Szf162725 wl_wpa_ess_t *es; 13944126Szf162725 dladm_status_t status; 13954126Szf162725 13964126Szf162725 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 13974126Szf162725 return (DLADM_STATUS_NOMEM); 13984126Szf162725 13995895Syz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, WL_SCANRESULTS); 14004126Szf162725 14014126Szf162725 if (status == DLADM_STATUS_OK) { 14024126Szf162725 es = (wl_wpa_ess_t *)(gbuf->wldp_buf); 14034126Szf162725 n = (es->count > escnt) ? escnt : es->count; 14044126Szf162725 for (i = 0; i < n; i ++) { 14054126Szf162725 (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid, 14064126Szf162725 DLADM_WLAN_BSSID_LEN); 14074126Szf162725 sr[i].we_ssid_len = es->ess[i].ssid_len; 14084126Szf162725 (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid, 14094126Szf162725 es->ess[i].ssid_len); 14104126Szf162725 sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len; 14114126Szf162725 (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie, 14124126Szf162725 es->ess[i].wpa_ie_len); 14134126Szf162725 sr[i].we_freq = es->ess[i].freq; 14144126Szf162725 } 14154126Szf162725 *estot = n; 14164126Szf162725 } 14174126Szf162725 14184126Szf162725 free(gbuf); 14194126Szf162725 return (status); 14204126Szf162725 } 14214126Szf162725 14224126Szf162725 dladm_status_t 14235895Syz147064 dladm_wlan_wpa_set_ie(datalink_id_t linkid, uint8_t *wpa_ie, uint_t wpa_ie_len) 14244126Szf162725 { 14254126Szf162725 wl_wpa_ie_t *ie; 14264126Szf162725 uint_t len; 14274126Szf162725 dladm_status_t status; 14284126Szf162725 14294126Szf162725 if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN) 14304126Szf162725 return (DLADM_STATUS_BADARG); 14314126Szf162725 len = sizeof (wl_wpa_ie_t) + wpa_ie_len; 14324126Szf162725 ie = malloc(len); 14334126Szf162725 if (ie == NULL) 14344126Szf162725 return (DLADM_STATUS_NOMEM); 14354126Szf162725 14364126Szf162725 (void) memset(ie, 0, len); 14374126Szf162725 ie->wpa_ie_len = wpa_ie_len; 14384126Szf162725 (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len); 14394126Szf162725 14405895Syz147064 status = i_dladm_wlan_set_ioctl(linkid, WL_SETOPTIE, ie, len); 14414126Szf162725 free(ie); 14424126Szf162725 14434126Szf162725 return (status); 14444126Szf162725 } 14454126Szf162725 14464126Szf162725 dladm_status_t 14475895Syz147064 dladm_wlan_wpa_set_wpa(datalink_id_t linkid, boolean_t flag) 14484126Szf162725 { 14495895Syz147064 wl_wpa_t wpa; 14504126Szf162725 14514126Szf162725 wpa.wpa_flag = flag; 14525895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_WPA, &wpa, 14535895Syz147064 sizeof (wl_wpa_t))); 14544126Szf162725 } 14554126Szf162725 14564126Szf162725 dladm_status_t 14575895Syz147064 dladm_wlan_wpa_del_key(datalink_id_t linkid, uint_t key_idx, 14584126Szf162725 const dladm_wlan_bssid_t *addr) 14594126Szf162725 { 14605895Syz147064 wl_del_key_t wk; 14614126Szf162725 14624126Szf162725 wk.idk_keyix = key_idx; 14634126Szf162725 if (addr != NULL) 14644126Szf162725 (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes, 14654126Szf162725 DLADM_WLAN_BSSID_LEN); 14664126Szf162725 14675895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_DELKEY, &wk, 14685895Syz147064 sizeof (wl_del_key_t))); 14694126Szf162725 } 14704126Szf162725 14714126Szf162725 dladm_status_t 14725895Syz147064 dladm_wlan_wpa_set_key(datalink_id_t linkid, dladm_wlan_cipher_t cipher, 14734126Szf162725 const dladm_wlan_bssid_t *addr, boolean_t set_tx, uint64_t seq, 14744126Szf162725 uint_t key_idx, uint8_t *key, uint_t key_len) 14754126Szf162725 { 14765895Syz147064 wl_key_t wk; 14774126Szf162725 14784126Szf162725 (void) memset(&wk, 0, sizeof (wl_key_t)); 14794126Szf162725 switch (cipher) { 14804126Szf162725 case DLADM_WLAN_CIPHER_WEP: 14814126Szf162725 wk.ik_type = IEEE80211_CIPHER_WEP; 14824126Szf162725 break; 14834126Szf162725 case DLADM_WLAN_CIPHER_TKIP: 14844126Szf162725 wk.ik_type = IEEE80211_CIPHER_TKIP; 14854126Szf162725 break; 14864126Szf162725 case DLADM_WLAN_CIPHER_AES_OCB: 14874126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_OCB; 14884126Szf162725 break; 14894126Szf162725 case DLADM_WLAN_CIPHER_AES_CCM: 14904126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_CCM; 14914126Szf162725 break; 14924126Szf162725 case DLADM_WLAN_CIPHER_CKIP: 14934126Szf162725 wk.ik_type = IEEE80211_CIPHER_CKIP; 14944126Szf162725 break; 14954126Szf162725 case DLADM_WLAN_CIPHER_NONE: 14964126Szf162725 wk.ik_type = IEEE80211_CIPHER_NONE; 14974126Szf162725 break; 14984126Szf162725 default: 14994126Szf162725 return (DLADM_STATUS_BADARG); 15004126Szf162725 } 15014126Szf162725 wk.ik_flags = IEEE80211_KEY_RECV; 15024126Szf162725 if (set_tx) { 15034126Szf162725 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; 15044126Szf162725 (void) memcpy(wk.ik_macaddr, addr->wb_bytes, 15054126Szf162725 DLADM_WLAN_BSSID_LEN); 15064126Szf162725 } else 15074126Szf162725 (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN); 15084126Szf162725 wk.ik_keyix = key_idx; 15094126Szf162725 wk.ik_keylen = key_len; 15104126Szf162725 (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */ 15114126Szf162725 (void) memcpy(wk.ik_keydata, key, key_len); 15124126Szf162725 15135895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_KEY, &wk, sizeof (wl_key_t))); 15144126Szf162725 } 15154126Szf162725 15164126Szf162725 dladm_status_t 15175895Syz147064 dladm_wlan_wpa_set_mlme(datalink_id_t linkid, dladm_wlan_mlme_op_t op, 15184126Szf162725 dladm_wlan_reason_t reason, dladm_wlan_bssid_t *bssid) 15194126Szf162725 { 15204126Szf162725 wl_mlme_t mlme; 15214126Szf162725 15224126Szf162725 (void) memset(&mlme, 0, sizeof (wl_mlme_t)); 15234126Szf162725 switch (op) { 15244126Szf162725 case DLADM_WLAN_MLME_ASSOC: 15254126Szf162725 mlme.im_op = IEEE80211_MLME_ASSOC; 15264126Szf162725 break; 15274126Szf162725 case DLADM_WLAN_MLME_DISASSOC: 15284126Szf162725 mlme.im_op = IEEE80211_MLME_DISASSOC; 15294126Szf162725 break; 15304126Szf162725 default: 15314126Szf162725 return (DLADM_STATUS_BADARG); 15324126Szf162725 } 15334126Szf162725 mlme.im_reason = reason; 15344126Szf162725 if (bssid != NULL) 15354126Szf162725 (void) memcpy(mlme.im_macaddr, bssid->wb_bytes, 15364126Szf162725 DLADM_WLAN_BSSID_LEN); 15374126Szf162725 15385895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_MLME, &mlme, 15395895Syz147064 sizeof (wl_mlme_t))); 15404126Szf162725 } 15414126Szf162725 15424126Szf162725 /* 15434126Szf162725 * routines of create instance 15444126Szf162725 */ 15454126Szf162725 static scf_propertygroup_t * 15464126Szf162725 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance, 15474126Szf162725 const char *pg_name, const char *pg_type) 15484126Szf162725 { 15494126Szf162725 scf_propertygroup_t *pg; 15504126Szf162725 15514126Szf162725 pg = scf_pg_create(handle); 15524126Szf162725 if (pg == NULL) 15534126Szf162725 return (NULL); 15544126Szf162725 15554126Szf162725 if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) { 15564126Szf162725 scf_pg_destroy(pg); 15574126Szf162725 return (NULL); 15584126Szf162725 } 15594126Szf162725 15604126Szf162725 return (pg); 15614126Szf162725 } 15624126Szf162725 15635895Syz147064 static dladm_status_t 15644126Szf162725 add_new_property(scf_handle_t *handle, const char *prop_name, 15654126Szf162725 scf_type_t type, const char *val, scf_transaction_t *tx) 15664126Szf162725 { 15674126Szf162725 scf_value_t *value = NULL; 15684126Szf162725 scf_transaction_entry_t *entry = NULL; 15694126Szf162725 15704126Szf162725 entry = scf_entry_create(handle); 15714126Szf162725 if (entry == NULL) 15724126Szf162725 goto out; 15734126Szf162725 15744126Szf162725 value = scf_value_create(handle); 15754126Szf162725 if (value == NULL) 15764126Szf162725 goto out; 15774126Szf162725 15784126Szf162725 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) 15794126Szf162725 goto out; 15804126Szf162725 15814126Szf162725 if (scf_value_set_from_string(value, type, val) != 0) 15824126Szf162725 goto out; 15834126Szf162725 15844126Szf162725 if (scf_entry_add_value(entry, value) != 0) 15854126Szf162725 goto out; 15864126Szf162725 15875895Syz147064 return (DLADM_STATUS_OK); 15884126Szf162725 15894126Szf162725 out: 15904126Szf162725 if (value != NULL) 15914126Szf162725 scf_value_destroy(value); 15924126Szf162725 if (entry != NULL) 15934126Szf162725 scf_entry_destroy(entry); 15944126Szf162725 15955895Syz147064 return (DLADM_STATUS_FAILED); 15964126Szf162725 } 15974126Szf162725 15985895Syz147064 static dladm_status_t 15994126Szf162725 add_pg_method(scf_handle_t *handle, scf_instance_t *instance, 16004126Szf162725 const char *pg_name, const char *flags) 16014126Szf162725 { 16024126Szf162725 int rv, size; 16035895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 16044126Szf162725 char *command = NULL; 16054126Szf162725 scf_transaction_t *tran = NULL; 16064126Szf162725 scf_propertygroup_t *pg; 16074126Szf162725 16084126Szf162725 pg = add_property_group_to_instance(handle, instance, 16094126Szf162725 pg_name, SCF_GROUP_METHOD); 16104126Szf162725 if (pg == NULL) 16114126Szf162725 goto out; 16124126Szf162725 16134126Szf162725 tran = scf_transaction_create(handle); 16144126Szf162725 if (tran == NULL) 16154126Szf162725 goto out; 16164126Szf162725 16174126Szf162725 size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1; 16184126Szf162725 command = malloc(size); 16194126Szf162725 if (command == NULL) { 16205895Syz147064 status = DLADM_STATUS_NOMEM; 16214126Szf162725 goto out; 16224126Szf162725 } 16234126Szf162725 (void) snprintf(command, size, "%s %s", SVC_METHOD, flags); 16244126Szf162725 16254126Szf162725 do { 16264126Szf162725 if (scf_transaction_start(tran, pg) != 0) 16274126Szf162725 goto out; 16284126Szf162725 16294126Szf162725 if (add_new_property(handle, SCF_PROPERTY_EXEC, 16305895Syz147064 SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) { 16314126Szf162725 goto out; 16324126Szf162725 } 16334126Szf162725 16344126Szf162725 rv = scf_transaction_commit(tran); 16354126Szf162725 switch (rv) { 16364126Szf162725 case 1: 16375895Syz147064 status = DLADM_STATUS_OK; 16384126Szf162725 goto out; 16394126Szf162725 case 0: 16404126Szf162725 scf_transaction_destroy_children(tran); 16414126Szf162725 if (scf_pg_update(pg) == -1) { 16424126Szf162725 goto out; 16434126Szf162725 } 16444126Szf162725 break; 16454126Szf162725 case -1: 16464126Szf162725 default: 16474126Szf162725 goto out; 16484126Szf162725 } 16494126Szf162725 } while (rv == 0); 16504126Szf162725 16514126Szf162725 out: 16524126Szf162725 if (tran != NULL) { 16534126Szf162725 scf_transaction_destroy_children(tran); 16544126Szf162725 scf_transaction_destroy(tran); 16554126Szf162725 } 16564126Szf162725 16574126Szf162725 if (pg != NULL) 16584126Szf162725 scf_pg_destroy(pg); 16594126Szf162725 16604126Szf162725 if (command != NULL) 16614126Szf162725 free(command); 16624126Szf162725 16634126Szf162725 return (status); 16644126Szf162725 } 16654126Szf162725 16665895Syz147064 static dladm_status_t 16674126Szf162725 do_create_instance(scf_handle_t *handle, scf_service_t *svc, 16684126Szf162725 const char *instance_name, const char *command) 16694126Szf162725 { 16705895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 16714126Szf162725 char *buf; 16724126Szf162725 ssize_t max_fmri_len; 16734126Szf162725 scf_instance_t *instance; 16744126Szf162725 16754126Szf162725 instance = scf_instance_create(handle); 16764126Szf162725 if (instance == NULL) 16774126Szf162725 goto out; 16784126Szf162725 16794126Szf162725 if (scf_service_add_instance(svc, instance_name, instance) != 0) { 16804126Szf162725 if (scf_error() == SCF_ERROR_EXISTS) 16814126Szf162725 /* Let the caller deal with the duplicate instance */ 16825895Syz147064 status = DLADM_STATUS_EXIST; 16834126Szf162725 goto out; 16844126Szf162725 } 16854126Szf162725 16864126Szf162725 if (add_pg_method(handle, instance, "start", 16875895Syz147064 command) != DLADM_STATUS_OK) { 16884126Szf162725 goto out; 16894126Szf162725 } 16904126Szf162725 16914126Szf162725 /* enabling the instance */ 16924126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 16934126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) 16944126Szf162725 goto out; 16954126Szf162725 16964126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 16974126Szf162725 if ((smf_disable_instance(buf, 0) != 0) || 16984126Szf162725 (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) { 16994126Szf162725 goto out; 17004126Szf162725 } 17015895Syz147064 status = DLADM_STATUS_OK; 17024126Szf162725 } 17034126Szf162725 17044126Szf162725 out: 17054126Szf162725 if (instance != NULL) 17064126Szf162725 scf_instance_destroy(instance); 17074126Szf162725 return (status); 17084126Szf162725 } 17094126Szf162725 17105895Syz147064 static dladm_status_t 17114126Szf162725 create_instance(const char *instance_name, const char *command) 17124126Szf162725 { 17135895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17144126Szf162725 scf_service_t *svc = NULL; 17154126Szf162725 scf_handle_t *handle = NULL; 17164126Szf162725 17174126Szf162725 handle = scf_handle_create(SCF_VERSION); 17184126Szf162725 if (handle == NULL) 17194126Szf162725 goto out; 17204126Szf162725 17214126Szf162725 if (scf_handle_bind(handle) == -1) 17224126Szf162725 goto out; 17234126Szf162725 17244126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 17254126Szf162725 goto out; 17264126Szf162725 17274126Szf162725 if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc, 17284126Szf162725 NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) 17294126Szf162725 goto out; 17304126Szf162725 17314126Szf162725 status = do_create_instance(handle, svc, instance_name, command); 17324126Szf162725 17334126Szf162725 out: 17344126Szf162725 if (svc != NULL) 17354126Szf162725 scf_service_destroy(svc); 17364126Szf162725 17374126Szf162725 if (handle != NULL) { 17384126Szf162725 (void) scf_handle_unbind(handle); 17394126Szf162725 scf_handle_destroy(handle); 17404126Szf162725 } 17414126Szf162725 17424126Szf162725 return (status); 17434126Szf162725 } 17444126Szf162725 17454126Szf162725 /* 17464126Szf162725 * routines of delete instance 17474126Szf162725 */ 17484126Szf162725 #define DEFAULT_TIMEOUT 60000000 17494126Szf162725 #define INIT_WAIT_USECS 50000 17504126Szf162725 17514126Szf162725 static void 17524126Szf162725 wait_until_disabled(scf_handle_t *handle, char *fmri) 17534126Szf162725 { 17544126Szf162725 char *state; 17554126Szf162725 useconds_t max; 17564126Szf162725 useconds_t usecs; 17574126Szf162725 uint64_t *cp = NULL; 17584126Szf162725 scf_simple_prop_t *sp = NULL; 17594126Szf162725 17604126Szf162725 max = DEFAULT_TIMEOUT; 17614126Szf162725 17624126Szf162725 if (((sp = scf_simple_prop_get(handle, fmri, "stop", 17634126Szf162725 SCF_PROPERTY_TIMEOUT)) != NULL) && 17644126Szf162725 ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0)) 17654126Szf162725 max = (*cp) * 1000000; /* convert to usecs */ 17664126Szf162725 17674126Szf162725 if (sp != NULL) 17684126Szf162725 scf_simple_prop_free(sp); 17694126Szf162725 17704126Szf162725 for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) { 17714126Szf162725 /* incremental wait */ 17724126Szf162725 usecs *= 2; 17734126Szf162725 usecs = (usecs > max) ? max : usecs; 17744126Szf162725 17754126Szf162725 (void) usleep(usecs); 17764126Szf162725 17774126Szf162725 /* Check state after the wait */ 17784126Szf162725 if ((state = smf_get_state(fmri)) != NULL) { 17794126Szf162725 if (strcmp(state, "disabled") == 0) 17804126Szf162725 return; 17814126Szf162725 } 17824126Szf162725 } 17834126Szf162725 } 17844126Szf162725 17855895Syz147064 static dladm_status_t 17864126Szf162725 delete_instance(const char *instance_name) 17874126Szf162725 { 17885895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17894126Szf162725 char *buf; 17904126Szf162725 ssize_t max_fmri_len; 17914126Szf162725 scf_scope_t *scope = NULL; 17924126Szf162725 scf_service_t *svc = NULL; 17934126Szf162725 scf_handle_t *handle = NULL; 17944126Szf162725 scf_instance_t *instance; 17954126Szf162725 17964126Szf162725 handle = scf_handle_create(SCF_VERSION); 17974126Szf162725 if (handle == NULL) 17984126Szf162725 goto out; 17994126Szf162725 18004126Szf162725 if (scf_handle_bind(handle) == -1) 18014126Szf162725 goto out; 18024126Szf162725 18034126Szf162725 if ((scope = scf_scope_create(handle)) == NULL) 18044126Szf162725 goto out; 18054126Szf162725 18064126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 18074126Szf162725 goto out; 18084126Szf162725 18094126Szf162725 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1) 18104126Szf162725 goto out; 18114126Szf162725 18124126Szf162725 if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0) 18134126Szf162725 goto out; 18144126Szf162725 18154126Szf162725 instance = scf_instance_create(handle); 18164126Szf162725 if (instance == NULL) 18174126Szf162725 goto out; 18184126Szf162725 18194126Szf162725 if (scf_service_get_instance(svc, instance_name, instance) != 0) { 18204126Szf162725 scf_error_t scf_errnum = scf_error(); 18214126Szf162725 18224126Szf162725 if (scf_errnum == SCF_ERROR_NOT_FOUND) 18235895Syz147064 status = DLADM_STATUS_OK; 18244126Szf162725 18254126Szf162725 scf_instance_destroy(instance); 18264126Szf162725 goto out; 18274126Szf162725 } 18284126Szf162725 18294126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 18304126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) { 18314126Szf162725 scf_instance_destroy(instance); 18324126Szf162725 goto out; 18334126Szf162725 } 18344126Szf162725 18354126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 18364126Szf162725 char *state; 18374126Szf162725 18384126Szf162725 state = smf_get_state(buf); 18394126Szf162725 if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 || 18404126Szf162725 strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) { 18414126Szf162725 if (smf_disable_instance(buf, 0) == 0) { 18424126Szf162725 /* 18434126Szf162725 * Wait for some time till timeout to avoid 18444126Szf162725 * a race with scf_instance_delete() below. 18454126Szf162725 */ 18464126Szf162725 wait_until_disabled(handle, buf); 18474126Szf162725 } 18484126Szf162725 } 18494126Szf162725 } 18504126Szf162725 18514126Szf162725 if (scf_instance_delete(instance) != 0) { 18524126Szf162725 scf_instance_destroy(instance); 18534126Szf162725 goto out; 18544126Szf162725 } 18554126Szf162725 18564126Szf162725 scf_instance_destroy(instance); 18574126Szf162725 18585895Syz147064 status = DLADM_STATUS_OK; 18594126Szf162725 18604126Szf162725 out: 18614126Szf162725 if (svc != NULL) 18624126Szf162725 scf_service_destroy(svc); 18634126Szf162725 18644126Szf162725 if (scope != NULL) 18654126Szf162725 scf_scope_destroy(scope); 18664126Szf162725 18674126Szf162725 if (handle != NULL) { 18684126Szf162725 (void) scf_handle_unbind(handle); 18694126Szf162725 scf_handle_destroy(handle); 18704126Szf162725 } 18714126Szf162725 18724126Szf162725 return (status); 18734126Szf162725 } 18744126Szf162725 18755895Syz147064 static dladm_status_t 18765895Syz147064 wpa_instance_create(datalink_id_t linkid, void *key) 18774126Szf162725 { 18785895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 18794126Szf162725 char *command = NULL; 18804126Szf162725 char *wk_name = ((dladm_wlan_key_t *)key)->wk_name; 18814126Szf162725 int size; 18825895Syz147064 char instance_name[MAXLINKNAMELEN]; 18835895Syz147064 18845895Syz147064 /* 18855895Syz147064 * Use the link name as the instance name of the network/wpad service. 18865895Syz147064 */ 18875895Syz147064 status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name, 18885895Syz147064 sizeof (instance_name)); 18895895Syz147064 if (status != DLADM_STATUS_OK) 18905895Syz147064 goto out; 18914126Szf162725 18924126Szf162725 size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1; 18934126Szf162725 command = malloc(size); 18944126Szf162725 if (command == NULL) { 18955895Syz147064 status = DLADM_STATUS_NOMEM; 18964126Szf162725 goto out; 18974126Szf162725 } 18984126Szf162725 (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name); 18994126Szf162725 19004126Szf162725 status = create_instance(instance_name, command); 19015895Syz147064 if (status == DLADM_STATUS_EXIST) { 19024126Szf162725 /* 19034126Szf162725 * Delete the existing instance and create a new instance 19044126Szf162725 * with the supplied arguments. 19054126Szf162725 */ 19064126Szf162725 if ((status = delete_instance(instance_name)) == 19075895Syz147064 DLADM_STATUS_OK) { 19084126Szf162725 status = create_instance(instance_name, command); 19094126Szf162725 } 19104126Szf162725 } 19114126Szf162725 19124126Szf162725 out: 19134126Szf162725 if (command != NULL) 19144126Szf162725 free(command); 19154126Szf162725 19164126Szf162725 return (status); 19174126Szf162725 } 19184126Szf162725 19195895Syz147064 static dladm_status_t 19205895Syz147064 wpa_instance_delete(datalink_id_t linkid) 19214126Szf162725 { 19225895Syz147064 char instance_name[MAXLINKNAMELEN]; 19234126Szf162725 19245895Syz147064 /* 19255895Syz147064 * Get the instance name of the network/wpad service (the same as 19265895Syz147064 * the link name). 19275895Syz147064 */ 19285895Syz147064 if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name, 19295895Syz147064 sizeof (instance_name)) != DLADM_STATUS_OK) 19305895Syz147064 return (DLADM_STATUS_FAILED); 19314126Szf162725 19325895Syz147064 return (delete_instance(instance_name)); 19334126Szf162725 } 1934