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[] = { 86*5903Ssowmini { "disconnected", DLADM_WLAN_LINK_DISCONNECTED }, 87*5903Ssowmini { "connected", DLADM_WLAN_LINK_CONNECTED } 883871Syz147064 }; 893871Syz147064 903871Syz147064 static val_desc_t secmode_vals[] = { 91*5903Ssowmini { "none", DLADM_WLAN_SECMODE_NONE }, 92*5903Ssowmini { "wep", DLADM_WLAN_SECMODE_WEP }, 93*5903Ssowmini { "wpa", DLADM_WLAN_SECMODE_WPA } 943871Syz147064 }; 953871Syz147064 963871Syz147064 static val_desc_t strength_vals[] = { 97*5903Ssowmini { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK }, 985895Syz147064 { "weak", DLADM_WLAN_STRENGTH_WEAK }, 995895Syz147064 { "good", DLADM_WLAN_STRENGTH_GOOD }, 100*5903Ssowmini { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD }, 101*5903Ssowmini { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT } 1023871Syz147064 }; 1033871Syz147064 1043871Syz147064 static val_desc_t mode_vals[] = { 105*5903Ssowmini { "a", DLADM_WLAN_MODE_80211A }, 106*5903Ssowmini { "b", DLADM_WLAN_MODE_80211B }, 107*5903Ssowmini { "g", DLADM_WLAN_MODE_80211G }, 1083871Syz147064 }; 1093871Syz147064 1103871Syz147064 static val_desc_t auth_vals[] = { 1115895Syz147064 { "open", DLADM_WLAN_AUTH_OPEN }, 112*5903Ssowmini { "shared", DLADM_WLAN_AUTH_SHARED } 1133871Syz147064 }; 1143871Syz147064 1153871Syz147064 static val_desc_t bsstype_vals[] = { 116*5903Ssowmini { "bss", DLADM_WLAN_BSSTYPE_BSS }, 117*5903Ssowmini { "ibss", DLADM_WLAN_BSSTYPE_IBSS }, 118*5903Ssowmini { "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; 2423871Syz147064 wldp_t *gbuf; 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) 5335895Syz147064 goto done; 5343871Syz147064 5353871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 5363871Syz147064 status = DLADM_STATUS_NOMEM; 5373871Syz147064 goto done; 5383871Syz147064 } 5393871Syz147064 5405895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 5413871Syz147064 goto done; 5423871Syz147064 5433871Syz147064 if (IS_CONNECTED(gbuf)) { 5443871Syz147064 status = DLADM_STATUS_ISCONN; 5453871Syz147064 goto done; 5463871Syz147064 } 5473871Syz147064 5483871Syz147064 set_authmode = ((attrp != NULL) && 5493871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0); 5503871Syz147064 create_ibss = ((flags & DLADM_WLAN_CONNECT_CREATEIBSS) != 0 && 5513871Syz147064 attrp != NULL && 5523871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 5533871Syz147064 attrp->wa_bsstype == DLADM_WLAN_BSSTYPE_IBSS); 5543871Syz147064 5553871Syz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 || 5563871Syz147064 (create_ibss && attrp != NULL && 5573871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) { 5585895Syz147064 status = do_connect(linkid, gbuf, attrp, create_ibss, keys, 5595895Syz147064 key_count, timeout); 5603871Syz147064 goto done; 5613871Syz147064 } 5623871Syz147064 5633871Syz147064 state.cs_attr = attrp; 5643871Syz147064 state.cs_list = NULL; 5653871Syz147064 state.cs_count = 0; 5663871Syz147064 5675895Syz147064 status = dladm_wlan_scan(linkid, &state, connect_cb); 5683871Syz147064 if (status != DLADM_STATUS_OK) 5693871Syz147064 goto done; 5703871Syz147064 5713871Syz147064 if (state.cs_count == 0) { 5723871Syz147064 if (!create_ibss) { 5733871Syz147064 status = DLADM_STATUS_NOTFOUND; 5743871Syz147064 goto done; 5753871Syz147064 } 5765895Syz147064 status = do_connect(linkid, gbuf, attrp, create_ibss, keys, 5775895Syz147064 key_count, timeout); 5783871Syz147064 goto done; 5793871Syz147064 } 5803871Syz147064 5813871Syz147064 wl_list = malloc(state.cs_count * sizeof (dladm_wlan_attr_t *)); 5823871Syz147064 if (wl_list == NULL) { 5833871Syz147064 status = DLADM_STATUS_NOMEM; 5843871Syz147064 goto done; 5853871Syz147064 } 5863871Syz147064 5873871Syz147064 nodep = state.cs_list; 5883871Syz147064 for (i = 0; i < state.cs_count; i++) { 5893871Syz147064 wl_list[i] = &nodep->an_attr; 5903871Syz147064 nodep = nodep->an_next; 5913871Syz147064 } 5923871Syz147064 qsort(wl_list, state.cs_count, sizeof (dladm_wlan_attr_t *), 5933871Syz147064 attr_compare); 5943871Syz147064 5953871Syz147064 for (i = 0; i < state.cs_count; i++) { 5963871Syz147064 dladm_wlan_attr_t *ap = wl_list[i]; 5973871Syz147064 5985895Syz147064 status = do_connect(linkid, gbuf, ap, create_ibss, keys, 5993871Syz147064 key_count, timeout); 6003871Syz147064 if (status == DLADM_STATUS_OK) 6013871Syz147064 break; 6023871Syz147064 6033871Syz147064 if (!set_authmode) { 6043871Syz147064 ap->wa_auth = DLADM_WLAN_AUTH_SHARED; 6053871Syz147064 ap->wa_valid |= DLADM_WLAN_ATTR_AUTH; 6065895Syz147064 status = do_connect(linkid, gbuf, ap, create_ibss, keys, 6075895Syz147064 key_count, timeout); 6083871Syz147064 if (status == DLADM_STATUS_OK) 6093871Syz147064 break; 6103871Syz147064 } 6113871Syz147064 } 6123871Syz147064 done: 6133871Syz147064 if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN)) 6145895Syz147064 (void) do_disconnect(linkid, gbuf); 6153871Syz147064 6163871Syz147064 while (state.cs_list != NULL) { 6173871Syz147064 nodep = state.cs_list; 6183871Syz147064 state.cs_list = nodep->an_next; 6193871Syz147064 free(nodep); 6203871Syz147064 } 6213871Syz147064 free(gbuf); 6223871Syz147064 free(wl_list); 6233871Syz147064 return (status); 6243871Syz147064 } 6253871Syz147064 6263871Syz147064 dladm_status_t 6275895Syz147064 dladm_wlan_disconnect(datalink_id_t linkid) 6283871Syz147064 { 6293871Syz147064 wldp_t *gbuf; 6303871Syz147064 dladm_status_t status; 6313871Syz147064 6325895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 6335895Syz147064 return (status); 6343871Syz147064 6353871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 6363871Syz147064 status = DLADM_STATUS_NOMEM; 6373871Syz147064 goto done; 6383871Syz147064 } 6393871Syz147064 6405895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 6413871Syz147064 goto done; 6423871Syz147064 6433871Syz147064 if (!IS_CONNECTED(gbuf)) { 6443871Syz147064 status = DLADM_STATUS_NOTCONN; 6453871Syz147064 goto done; 6463871Syz147064 } 6473871Syz147064 6485895Syz147064 if ((status = do_disconnect(linkid, gbuf)) != DLADM_STATUS_OK) 6493871Syz147064 goto done; 6503871Syz147064 6515895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 6523871Syz147064 goto done; 6533871Syz147064 6543871Syz147064 if (IS_CONNECTED(gbuf)) { 6553871Syz147064 status = DLADM_STATUS_FAILED; 6563871Syz147064 goto done; 6573871Syz147064 } 6583871Syz147064 6593871Syz147064 status = DLADM_STATUS_OK; 6603871Syz147064 done: 6613871Syz147064 free(gbuf); 6623871Syz147064 return (status); 6633871Syz147064 } 6643871Syz147064 6655895Syz147064 dladm_status_t 6665895Syz147064 dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) 6673871Syz147064 { 6683871Syz147064 wldp_t *gbuf; 6693871Syz147064 wl_rssi_t signal; 6703871Syz147064 wl_bss_type_t bsstype; 6713871Syz147064 wl_authmode_t authmode; 6723871Syz147064 wl_encryption_t encryption; 6733871Syz147064 wl_rates_t *ratesp; 6743871Syz147064 dladm_wlan_attr_t *wl_attrp; 6755895Syz147064 dladm_status_t status; 6763871Syz147064 6773871Syz147064 if (attrp == NULL) 6783871Syz147064 return (DLADM_STATUS_BADARG); 6793871Syz147064 6805895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 6815895Syz147064 goto done; 6823871Syz147064 6833871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 6843871Syz147064 status = DLADM_STATUS_NOMEM; 6853871Syz147064 goto done; 6863871Syz147064 } 6873871Syz147064 6883871Syz147064 (void) memset(attrp, 0, sizeof (*attrp)); 6893871Syz147064 wl_attrp = &attrp->la_wlan_attr; 6903871Syz147064 6915895Syz147064 if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) 6923871Syz147064 goto done; 6933871Syz147064 6943871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS; 6955895Syz147064 if (!IS_CONNECTED(gbuf)) 6965895Syz147064 attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED; 6975895Syz147064 else 6985895Syz147064 attrp->la_status = DLADM_WLAN_LINK_CONNECTED; 6993871Syz147064 7005895Syz147064 if ((status = do_get_essid(linkid, gbuf)) != DLADM_STATUS_OK) 7013871Syz147064 goto done; 7023871Syz147064 7033871Syz147064 (void) strlcpy(wl_attrp->wa_essid.we_bytes, 7043871Syz147064 ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid, 7053871Syz147064 DLADM_WLAN_MAX_ESSID_LEN); 7063871Syz147064 7073871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 7083871Syz147064 7095895Syz147064 if ((status = do_get_bssid(linkid, gbuf)) != DLADM_STATUS_OK) 7103871Syz147064 goto done; 7113871Syz147064 7123871Syz147064 (void) memcpy(wl_attrp->wa_bssid.wb_bytes, gbuf->wldp_buf, 7133871Syz147064 DLADM_WLAN_BSSID_LEN); 7143871Syz147064 7153871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 7163871Syz147064 7175895Syz147064 if (attrp->la_status == DLADM_WLAN_LINK_DISCONNECTED) { 7184126Szf162725 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 7194126Szf162725 status = DLADM_STATUS_OK; 7204126Szf162725 goto done; 7214126Szf162725 } 7224126Szf162725 7235895Syz147064 if ((status = do_get_encryption(linkid, gbuf)) != DLADM_STATUS_OK) 7243871Syz147064 goto done; 7253871Syz147064 7263871Syz147064 encryption = *(wl_encryption_t *)(gbuf->wldp_buf); 7273871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 7283871Syz147064 7293871Syz147064 switch (encryption) { 7303871Syz147064 case WL_NOENCRYPTION: 7313871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_NONE; 7323871Syz147064 break; 7333871Syz147064 case WL_ENC_WEP: 7343871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP; 7353871Syz147064 break; 7364126Szf162725 case WL_ENC_WPA: 7374126Szf162725 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 7384126Szf162725 break; 7393871Syz147064 default: 7403871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE; 7413871Syz147064 break; 7423871Syz147064 } 7433871Syz147064 7445895Syz147064 if ((status = do_get_signal(linkid, gbuf)) != DLADM_STATUS_OK) 7453871Syz147064 goto done; 7463871Syz147064 7473871Syz147064 signal = *(wl_rssi_t *)(gbuf->wldp_buf); 7483871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 7493871Syz147064 wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal); 7503871Syz147064 7515895Syz147064 if ((status = do_get_rate(linkid, gbuf)) != DLADM_STATUS_OK) 7523871Syz147064 goto done; 7533871Syz147064 7543871Syz147064 ratesp = (wl_rates_t *)(gbuf->wldp_buf); 7553871Syz147064 if (ratesp->wl_rates_num > 0) { 7563871Syz147064 uint_t i, r = 0; 7573871Syz147064 7583871Syz147064 for (i = 0; i < ratesp->wl_rates_num; i++) { 7593871Syz147064 if (ratesp->wl_rates_rates[i] > r) 7603871Syz147064 r = ratesp->wl_rates_rates[i]; 7613871Syz147064 } 7623871Syz147064 wl_attrp->wa_speed = r; 7633871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 7643871Syz147064 } 7653871Syz147064 7665895Syz147064 if ((status = do_get_authmode(linkid, gbuf)) != DLADM_STATUS_OK) 7673871Syz147064 goto done; 7683871Syz147064 7693871Syz147064 authmode = *(wl_authmode_t *)(gbuf->wldp_buf); 7703871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 7713871Syz147064 7723871Syz147064 switch (authmode) { 7733871Syz147064 case WL_OPENSYSTEM: 7743871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN; 7753871Syz147064 break; 7763871Syz147064 case WL_SHAREDKEY: 7773871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED; 7783871Syz147064 break; 7793871Syz147064 default: 7803871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH; 7813871Syz147064 break; 7823871Syz147064 } 7833871Syz147064 7845895Syz147064 if ((status = do_get_bsstype(linkid, gbuf)) != DLADM_STATUS_OK) 7853871Syz147064 goto done; 7863871Syz147064 7873871Syz147064 bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf); 7883871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 7893871Syz147064 7903871Syz147064 switch (bsstype) { 7913871Syz147064 case WL_BSS_BSS: 7923871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS; 7933871Syz147064 break; 7943871Syz147064 case WL_BSS_IBSS: 7953871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS; 7963871Syz147064 break; 7973871Syz147064 case WL_BSS_ANY: 7983871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY; 7993871Syz147064 break; 8003871Syz147064 default: 8013871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE; 8023871Syz147064 break; 8033871Syz147064 } 8043871Syz147064 8055895Syz147064 if ((status = do_get_mode(linkid, gbuf)) != DLADM_STATUS_OK) 8063871Syz147064 goto done; 8073871Syz147064 8083871Syz147064 wl_attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)(gbuf->wldp_buf)); 8093871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8103871Syz147064 if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE) 8113871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8123871Syz147064 8133871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 8143871Syz147064 status = DLADM_STATUS_OK; 8153871Syz147064 8163871Syz147064 done: 8173871Syz147064 free(gbuf); 8183871Syz147064 return (status); 8193871Syz147064 } 8203871Syz147064 8213871Syz147064 static dladm_status_t 8225895Syz147064 dladm_wlan_validate(datalink_id_t linkid) 8233871Syz147064 { 8245895Syz147064 wldp_t *gbuf; 8253871Syz147064 dladm_status_t status; 8263871Syz147064 8273871Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { 8283871Syz147064 status = DLADM_STATUS_NOMEM; 8293871Syz147064 goto done; 8303871Syz147064 } 8313871Syz147064 8325895Syz147064 /* 8335895Syz147064 * Check to see if the link is wireless. 8345895Syz147064 */ 8355895Syz147064 if ((status = do_get_bsstype(linkid, gbuf)) != DLADM_STATUS_OK) { 8365895Syz147064 status = DLADM_STATUS_LINKINVAL; 8375895Syz147064 goto done; 8385895Syz147064 } 8393871Syz147064 8403871Syz147064 done: 8413871Syz147064 free(gbuf); 8423871Syz147064 return (status); 8433871Syz147064 } 8443871Syz147064 8453871Syz147064 static boolean_t 8463871Syz147064 find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp) 8473871Syz147064 { 8483871Syz147064 int i; 8493871Syz147064 8503871Syz147064 for (i = 0; i < cnt; i++) { 8513871Syz147064 if (strcasecmp(str, vdp[i].vd_name) == 0) { 8523871Syz147064 *valp = vdp[i].vd_val; 8533871Syz147064 return (B_TRUE); 8543871Syz147064 } 8553871Syz147064 } 8563871Syz147064 return (B_FALSE); 8573871Syz147064 } 8583871Syz147064 8593871Syz147064 static boolean_t 8603871Syz147064 find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp) 8613871Syz147064 { 8623871Syz147064 int i; 8633871Syz147064 8643871Syz147064 for (i = 0; i < cnt; i++) { 8653871Syz147064 if (val == vdp[i].vd_val) { 8663871Syz147064 *strp = vdp[i].vd_name; 8673871Syz147064 return (B_TRUE); 8683871Syz147064 } 8693871Syz147064 } 8703871Syz147064 return (B_FALSE); 8713871Syz147064 } 8723871Syz147064 8733871Syz147064 const char * 8743871Syz147064 dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf) 8753871Syz147064 { 8763871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes); 8773871Syz147064 return (buf); 8783871Syz147064 } 8793871Syz147064 8803871Syz147064 const char * 8813871Syz147064 dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf) 8823871Syz147064 { 8833871Syz147064 return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN, 8843871Syz147064 IFT_OTHER)); 8853871Syz147064 } 8863871Syz147064 8873871Syz147064 static const char * 8883871Syz147064 dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf) 8893871Syz147064 { 8903871Syz147064 char *s; 8913871Syz147064 8923871Syz147064 if (!find_name_by_val(val, vdp, cnt, &s)) 8933871Syz147064 s = ""; 8943871Syz147064 8953871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 8963871Syz147064 return (buf); 8973871Syz147064 } 8983871Syz147064 8993871Syz147064 const char * 9003871Syz147064 dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf) 9013871Syz147064 { 9023871Syz147064 return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals, 9033871Syz147064 VALCNT(secmode_vals), buf)); 9043871Syz147064 } 9053871Syz147064 9063871Syz147064 const char * 9073871Syz147064 dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf) 9083871Syz147064 { 9093871Syz147064 return (dladm_wlan_val2str((uint_t)*strength, strength_vals, 9103871Syz147064 VALCNT(strength_vals), buf)); 9113871Syz147064 } 9123871Syz147064 9133871Syz147064 const char * 9143871Syz147064 dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf) 9153871Syz147064 { 9163871Syz147064 return (dladm_wlan_val2str((uint_t)*mode, mode_vals, 9173871Syz147064 VALCNT(mode_vals), buf)); 9183871Syz147064 } 9193871Syz147064 9203871Syz147064 const char * 9213871Syz147064 dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf) 9223871Syz147064 { 9233871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2, 9243871Syz147064 (float)(*speed) / 2); 9253871Syz147064 return (buf); 9263871Syz147064 } 9273871Syz147064 9283871Syz147064 const char * 9293871Syz147064 dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf) 9303871Syz147064 { 9313871Syz147064 return (dladm_wlan_val2str((uint_t)*auth, auth_vals, 9323871Syz147064 VALCNT(auth_vals), buf)); 9333871Syz147064 } 9343871Syz147064 9353871Syz147064 const char * 9363871Syz147064 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf) 9373871Syz147064 { 9383871Syz147064 return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals, 9393871Syz147064 VALCNT(bsstype_vals), buf)); 9403871Syz147064 } 9413871Syz147064 9423871Syz147064 const char * 9433871Syz147064 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf) 9443871Syz147064 { 9453871Syz147064 return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals, 9463871Syz147064 VALCNT(linkstatus_vals), buf)); 9473871Syz147064 } 9483871Syz147064 9493871Syz147064 dladm_status_t 9503871Syz147064 dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid) 9513871Syz147064 { 9523871Syz147064 if (str[0] == '\0') 9533871Syz147064 return (DLADM_STATUS_BADARG); 9543871Syz147064 9553871Syz147064 (void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN); 9563871Syz147064 return (DLADM_STATUS_OK); 9573871Syz147064 } 9583871Syz147064 9593871Syz147064 dladm_status_t 9603871Syz147064 dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid) 9613871Syz147064 { 9623871Syz147064 int len; 9633871Syz147064 uchar_t *buf; 9643871Syz147064 9653871Syz147064 buf = _link_aton(str, &len); 9663871Syz147064 if (buf == NULL) 9673871Syz147064 return (DLADM_STATUS_BADARG); 9683871Syz147064 9693871Syz147064 if (len != DLADM_WLAN_BSSID_LEN) { 9703871Syz147064 free(buf); 9713871Syz147064 return (DLADM_STATUS_BADARG); 9723871Syz147064 } 9733871Syz147064 9743871Syz147064 (void) memcpy(bssid->wb_bytes, buf, len); 9753871Syz147064 free(buf); 9763871Syz147064 return (DLADM_STATUS_OK); 9773871Syz147064 } 9783871Syz147064 9793871Syz147064 dladm_status_t 9803871Syz147064 dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode) 9813871Syz147064 { 9823871Syz147064 uint_t val; 9833871Syz147064 9843871Syz147064 if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val)) 9853871Syz147064 return (DLADM_STATUS_BADARG); 9863871Syz147064 9873871Syz147064 *secmode = (dladm_wlan_secmode_t)val; 9883871Syz147064 return (DLADM_STATUS_OK); 9893871Syz147064 } 9903871Syz147064 9913871Syz147064 dladm_status_t 9923871Syz147064 dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength) 9933871Syz147064 { 9943871Syz147064 uint_t val; 9953871Syz147064 9963871Syz147064 if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val)) 9973871Syz147064 return (DLADM_STATUS_BADARG); 9983871Syz147064 9993871Syz147064 *strength = (dladm_wlan_strength_t)val; 10003871Syz147064 return (DLADM_STATUS_OK); 10013871Syz147064 } 10023871Syz147064 10033871Syz147064 dladm_status_t 10043871Syz147064 dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode) 10053871Syz147064 { 10063871Syz147064 uint_t val; 10073871Syz147064 10083871Syz147064 if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val)) 10093871Syz147064 return (DLADM_STATUS_BADARG); 10103871Syz147064 10113871Syz147064 *mode = (dladm_wlan_mode_t)val; 10123871Syz147064 return (DLADM_STATUS_OK); 10133871Syz147064 } 10143871Syz147064 10153871Syz147064 dladm_status_t 10163871Syz147064 dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed) 10173871Syz147064 { 10183871Syz147064 *speed = (dladm_wlan_speed_t)(atof(str) * 2); 10193871Syz147064 return (DLADM_STATUS_OK); 10203871Syz147064 } 10213871Syz147064 10223871Syz147064 dladm_status_t 10233871Syz147064 dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth) 10243871Syz147064 { 10253871Syz147064 uint_t val; 10263871Syz147064 10273871Syz147064 if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val)) 10283871Syz147064 return (DLADM_STATUS_BADARG); 10293871Syz147064 10303871Syz147064 *auth = (dladm_wlan_auth_t)val; 10313871Syz147064 return (DLADM_STATUS_OK); 10323871Syz147064 } 10333871Syz147064 10343871Syz147064 dladm_status_t 10353871Syz147064 dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype) 10363871Syz147064 { 10373871Syz147064 uint_t val; 10383871Syz147064 10393871Syz147064 if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val)) 10403871Syz147064 return (DLADM_STATUS_BADARG); 10413871Syz147064 10423871Syz147064 *bsstype = (dladm_wlan_bsstype_t)val; 10433871Syz147064 return (DLADM_STATUS_OK); 10443871Syz147064 } 10453871Syz147064 10463871Syz147064 dladm_status_t 10473871Syz147064 dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus) 10483871Syz147064 { 10493871Syz147064 uint_t val; 10503871Syz147064 10515895Syz147064 if (!find_val_by_name(str, linkstatus_vals, 10525895Syz147064 VALCNT(linkstatus_vals), &val)) { 10533871Syz147064 return (DLADM_STATUS_BADARG); 10545895Syz147064 } 10553871Syz147064 10563871Syz147064 *linkstatus = (dladm_wlan_linkstatus_t)val; 10573871Syz147064 return (DLADM_STATUS_OK); 10583871Syz147064 } 10593871Syz147064 10605895Syz147064 dladm_status_t 10615895Syz147064 i_dladm_wlan_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id, size_t len, 10625895Syz147064 uint_t cmd, size_t cmdlen) 10633871Syz147064 { 10645895Syz147064 char linkname[MAXPATHLEN]; 10655895Syz147064 int fd, rc; 10663871Syz147064 struct strioctl stri; 10675895Syz147064 uint32_t flags; 10685895Syz147064 dladm_status_t status; 10695895Syz147064 uint32_t media; 10705895Syz147064 char link[MAXLINKNAMELEN]; 10715895Syz147064 10725895Syz147064 if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media, 10735895Syz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 10745895Syz147064 return (status); 10755895Syz147064 } 10765895Syz147064 10775895Syz147064 if (media != DL_WIFI) 10785895Syz147064 return (DLADM_STATUS_BADARG); 10795895Syz147064 10805895Syz147064 if (!(flags & DLADM_OPT_ACTIVE)) 10815895Syz147064 return (DLADM_STATUS_TEMPONLY); 10825895Syz147064 10835895Syz147064 /* 10845895Syz147064 * dlpi_open() is not used here because libdlpi depends on libdladm, 10855895Syz147064 * and we do not want to introduce recursive dependencies. 10865895Syz147064 */ 10875895Syz147064 (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link); 10885895Syz147064 if ((fd = open(linkname, O_RDWR)) < 0) 10895895Syz147064 return (DLADM_STATUS_LINKINVAL); 10903871Syz147064 10913871Syz147064 gbuf->wldp_type = NET_802_11; 10923871Syz147064 gbuf->wldp_id = id; 10933871Syz147064 gbuf->wldp_length = len; 10943871Syz147064 10953871Syz147064 stri.ic_timout = 0; 10963871Syz147064 stri.ic_dp = (char *)gbuf; 10973871Syz147064 stri.ic_cmd = cmd; 10983871Syz147064 stri.ic_len = cmdlen; 10993871Syz147064 11003871Syz147064 if ((rc = ioctl(fd, I_STR, &stri)) != 0) { 11015895Syz147064 if (rc > 0) { 11025895Syz147064 /* 11035895Syz147064 * Non-negative return value indicates the specific 11045895Syz147064 * operation failed and the reason for the failure 11055895Syz147064 * was stored in gbuf->wldp_result. 11065895Syz147064 */ 11075895Syz147064 status = dladm_wlan_wlresult2status(gbuf); 11085895Syz147064 } else { 11095895Syz147064 /* 11105895Syz147064 * Negative return value indicates the ioctl failed. 11115895Syz147064 */ 11125895Syz147064 status = dladm_errno2status(errno); 11135895Syz147064 } 11143871Syz147064 } 11155895Syz147064 (void) close(fd); 11165895Syz147064 return (status); 11173871Syz147064 } 11183871Syz147064 11195895Syz147064 dladm_status_t 11205895Syz147064 i_dladm_wlan_get_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id) 11213871Syz147064 { 11223871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11235895Syz147064 return (i_dladm_wlan_ioctl(linkid, gbuf, id, MAX_BUF_LEN, 11245895Syz147064 WLAN_GET_PARAM, MAX_BUF_LEN)); 11253871Syz147064 } 11263871Syz147064 11275895Syz147064 dladm_status_t 11285895Syz147064 i_dladm_wlan_set_ioctl(datalink_id_t linkid, uint_t id, void *buf, 11295895Syz147064 uint_t buflen) 11303871Syz147064 { 11315895Syz147064 wldp_t *gbuf; 11325895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 11335895Syz147064 11345895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 11355895Syz147064 return (DLADM_STATUS_NOMEM); 11365895Syz147064 11373871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11383871Syz147064 (void) memcpy(gbuf->wldp_buf, buf, buflen); 11393871Syz147064 buflen += WIFI_BUF_OFFSET; 11405895Syz147064 status = i_dladm_wlan_ioctl(linkid, gbuf, id, buflen, 11415895Syz147064 WLAN_SET_PARAM, buflen); 11425895Syz147064 11435895Syz147064 free(gbuf); 11445895Syz147064 return (status); 11453871Syz147064 } 11463871Syz147064 11475895Syz147064 static dladm_status_t 11485895Syz147064 do_cmd_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t cmd) 11493871Syz147064 { 11503871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11515895Syz147064 return (i_dladm_wlan_ioctl(linkid, gbuf, cmd, sizeof (wldp_t), 11525895Syz147064 WLAN_COMMAND, sizeof (wldp_t))); 11533871Syz147064 } 11543871Syz147064 11555895Syz147064 static dladm_status_t 11565895Syz147064 do_scan(datalink_id_t linkid, wldp_t *gbuf) 11573871Syz147064 { 11585895Syz147064 return (do_cmd_ioctl(linkid, gbuf, WL_SCAN)); 11593871Syz147064 } 11603871Syz147064 11615895Syz147064 static dladm_status_t 11625895Syz147064 do_disconnect(datalink_id_t linkid, wldp_t *gbuf) 11633871Syz147064 { 11645895Syz147064 if (do_get_wpamode(linkid, gbuf) == 0 && 11655895Syz147064 ((wl_wpa_t *)(gbuf->wldp_buf))->wpa_flag > 0) 11665895Syz147064 (void) wpa_instance_delete(linkid); 11674126Szf162725 11685895Syz147064 return (do_cmd_ioctl(linkid, gbuf, WL_DISASSOCIATE)); 11693871Syz147064 } 11703871Syz147064 11715895Syz147064 static dladm_status_t 11725895Syz147064 do_get_esslist(datalink_id_t linkid, wldp_t *gbuf) 11733871Syz147064 { 11743871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11755895Syz147064 return (i_dladm_wlan_ioctl(linkid, gbuf, WL_ESS_LIST, MAX_BUF_LEN, 11763871Syz147064 WLAN_GET_PARAM, sizeof (wldp_t))); 11773871Syz147064 } 11783871Syz147064 11795895Syz147064 static dladm_status_t 11805895Syz147064 do_get_bssid(datalink_id_t linkid, wldp_t *gbuf) 11813871Syz147064 { 11825895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSSID)); 11833871Syz147064 } 11843871Syz147064 11855895Syz147064 static dladm_status_t 11865895Syz147064 do_get_essid(datalink_id_t linkid, wldp_t *gbuf) 11873871Syz147064 { 11885895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ESSID)); 11893871Syz147064 } 11903871Syz147064 11915895Syz147064 static dladm_status_t 11925895Syz147064 do_get_bsstype(datalink_id_t linkid, wldp_t *gbuf) 11933871Syz147064 { 11945895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSS_TYPE)); 11953871Syz147064 } 11963871Syz147064 11975895Syz147064 static dladm_status_t 11985895Syz147064 do_get_linkstatus(datalink_id_t linkid, wldp_t *gbuf) 11993871Syz147064 { 12005895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_LINKSTATUS)); 12013871Syz147064 } 12023871Syz147064 12033871Syz147064 static dladm_status_t 12045895Syz147064 do_get_rate(datalink_id_t linkid, wldp_t *gbuf) 12053871Syz147064 { 12065895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_DESIRED_RATES)); 12073871Syz147064 } 12083871Syz147064 12093871Syz147064 static dladm_status_t 12105895Syz147064 do_get_authmode(datalink_id_t linkid, wldp_t *gbuf) 12113871Syz147064 { 12125895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_AUTH_MODE)); 12133871Syz147064 } 12143871Syz147064 12153871Syz147064 static dladm_status_t 12165895Syz147064 do_get_encryption(datalink_id_t linkid, wldp_t *gbuf) 12173871Syz147064 { 12185895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ENCRYPTION)); 12193871Syz147064 } 12203871Syz147064 12213871Syz147064 static dladm_status_t 12225895Syz147064 do_get_signal(datalink_id_t linkid, wldp_t *gbuf) 12233871Syz147064 { 12245895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RSSI)); 12253871Syz147064 } 12263871Syz147064 12273871Syz147064 static dladm_status_t 12285895Syz147064 do_get_mode(datalink_id_t linkid, wldp_t *gbuf) 12293871Syz147064 { 12305895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); 12313871Syz147064 } 12323871Syz147064 12335895Syz147064 static dladm_status_t 12345895Syz147064 do_set_bsstype(datalink_id_t linkid, dladm_wlan_bsstype_t *bsstype) 12353871Syz147064 { 12363871Syz147064 wl_bss_type_t ibsstype; 12373871Syz147064 12383871Syz147064 switch (*bsstype) { 12393871Syz147064 case DLADM_WLAN_BSSTYPE_BSS: 12403871Syz147064 ibsstype = WL_BSS_BSS; 12413871Syz147064 break; 12423871Syz147064 case DLADM_WLAN_BSSTYPE_IBSS: 12433871Syz147064 ibsstype = WL_BSS_IBSS; 12443871Syz147064 break; 12453871Syz147064 default: 12463871Syz147064 ibsstype = WL_BSS_ANY; 12473871Syz147064 break; 12483871Syz147064 } 12495895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_BSS_TYPE, &ibsstype, 12503871Syz147064 sizeof (ibsstype))); 12513871Syz147064 } 12523871Syz147064 12535895Syz147064 static dladm_status_t 12545895Syz147064 do_set_authmode(datalink_id_t linkid, dladm_wlan_auth_t *auth) 12553871Syz147064 { 12563871Syz147064 wl_authmode_t auth_mode; 12573871Syz147064 12583871Syz147064 switch (*auth) { 12593871Syz147064 case DLADM_WLAN_AUTH_OPEN: 12603871Syz147064 auth_mode = WL_OPENSYSTEM; 12613871Syz147064 break; 12623871Syz147064 case DLADM_WLAN_AUTH_SHARED: 12633871Syz147064 auth_mode = WL_SHAREDKEY; 12643871Syz147064 break; 12653871Syz147064 default: 12665895Syz147064 return (DLADM_STATUS_NOTSUP); 12673871Syz147064 } 12685895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_AUTH_MODE, &auth_mode, 12693871Syz147064 sizeof (auth_mode))); 12703871Syz147064 } 12713871Syz147064 12725895Syz147064 static dladm_status_t 12735895Syz147064 do_set_encryption(datalink_id_t linkid, dladm_wlan_secmode_t *secmode) 12743871Syz147064 { 12753871Syz147064 wl_encryption_t encryption; 12763871Syz147064 12773871Syz147064 switch (*secmode) { 12783871Syz147064 case DLADM_WLAN_SECMODE_NONE: 12793871Syz147064 encryption = WL_NOENCRYPTION; 12803871Syz147064 break; 12813871Syz147064 case DLADM_WLAN_SECMODE_WEP: 12823871Syz147064 encryption = WL_ENC_WEP; 12833871Syz147064 break; 12844126Szf162725 case DLADM_WLAN_SECMODE_WPA: 12854126Szf162725 return (0); 12863871Syz147064 default: 12875895Syz147064 return (DLADM_STATUS_NOTSUP); 12883871Syz147064 } 12895895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_ENCRYPTION, &encryption, 12903871Syz147064 sizeof (encryption))); 12913871Syz147064 } 12923871Syz147064 12935895Syz147064 static dladm_status_t 12945895Syz147064 do_set_key(datalink_id_t linkid, dladm_wlan_key_t *keys, 12953871Syz147064 uint_t key_count) 12963871Syz147064 { 12973871Syz147064 int i; 12983871Syz147064 wl_wep_key_t *wkp; 12993871Syz147064 wl_wep_key_tab_t wepkey_tab; 13004126Szf162725 dladm_wlan_key_t *kp; 13013871Syz147064 13023871Syz147064 if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL) 13035895Syz147064 return (DLADM_STATUS_BADARG); 13043871Syz147064 13053871Syz147064 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab)); 13063871Syz147064 for (i = 0; i < MAX_NWEPKEYS; i++) 13073871Syz147064 wepkey_tab[i].wl_wep_operation = WL_NUL; 13083871Syz147064 13093871Syz147064 for (i = 0; i < key_count; i++) { 13103871Syz147064 kp = &keys[i]; 13113871Syz147064 if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS) 13125895Syz147064 return (DLADM_STATUS_BADARG); 13133871Syz147064 if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN && 13143871Syz147064 kp->wk_len != DLADM_WLAN_WEPKEY128_LEN) 13155895Syz147064 return (DLADM_STATUS_BADARG); 13163871Syz147064 13173871Syz147064 wkp = &wepkey_tab[kp->wk_idx - 1]; 13183871Syz147064 wkp->wl_wep_operation = WL_ADD; 13193871Syz147064 wkp->wl_wep_length = kp->wk_len; 13203871Syz147064 (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len); 13213871Syz147064 } 13223871Syz147064 13235895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_WEP_KEY_TAB, &wepkey_tab, 13243871Syz147064 sizeof (wepkey_tab))); 13253871Syz147064 } 13263871Syz147064 13275895Syz147064 static dladm_status_t 13285895Syz147064 do_set_essid(datalink_id_t linkid, dladm_wlan_essid_t *essid) 13293871Syz147064 { 13303871Syz147064 wl_essid_t iessid; 13313871Syz147064 13323871Syz147064 (void) memset(&iessid, 0, sizeof (essid)); 13333871Syz147064 13343871Syz147064 if (essid != NULL && essid->we_bytes[0] != '\0') { 13353871Syz147064 iessid.wl_essid_length = strlen(essid->we_bytes); 13363871Syz147064 (void) strlcpy(iessid.wl_essid_essid, essid->we_bytes, 13373871Syz147064 sizeof (iessid.wl_essid_essid)); 13383871Syz147064 } else { 13395895Syz147064 return (DLADM_STATUS_BADARG); 13405102Syz147064 } 13415895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_ESSID, &iessid, 13425895Syz147064 sizeof (iessid))); 13433871Syz147064 } 13443871Syz147064 13453871Syz147064 static dladm_status_t 13465895Syz147064 do_set_channel(datalink_id_t linkid, dladm_wlan_channel_t *channel) 13473871Syz147064 { 13483871Syz147064 wl_phy_conf_t phy_conf; 13493871Syz147064 13503871Syz147064 if (*channel > MAX_CHANNEL_NUM) 13515895Syz147064 return (DLADM_STATUS_BADVAL); 13523871Syz147064 13533871Syz147064 (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); 13543871Syz147064 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel; 13553871Syz147064 13565895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_PHY_CONFIG, &phy_conf, 13573871Syz147064 sizeof (phy_conf))); 13583871Syz147064 } 13593871Syz147064 13605895Syz147064 static dladm_status_t 13615895Syz147064 do_set_createibss(datalink_id_t linkid, boolean_t *create_ibss) 13623871Syz147064 { 13633871Syz147064 wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss); 13643871Syz147064 13655895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_CREATE_IBSS, 13665895Syz147064 &cr, sizeof (cr))); 13673871Syz147064 } 13683871Syz147064 13693871Syz147064 static void 13703871Syz147064 generate_essid(dladm_wlan_essid_t *essid) 13713871Syz147064 { 13723871Syz147064 srandom(gethrtime()); 13733871Syz147064 (void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d", 13743871Syz147064 random()); 13753871Syz147064 } 13764126Szf162725 13775895Syz147064 static dladm_status_t 13785895Syz147064 do_get_capability(datalink_id_t linkid, wldp_t *gbuf) 13794126Szf162725 { 13805895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_CAPABILITY)); 13814126Szf162725 } 13824126Szf162725 13834126Szf162725 static dladm_status_t 13845895Syz147064 do_get_wpamode(datalink_id_t linkid, wldp_t *gbuf) 13854126Szf162725 { 13865895Syz147064 return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_WPA)); 13874126Szf162725 } 13884126Szf162725 13894126Szf162725 dladm_status_t 13905895Syz147064 dladm_wlan_wpa_get_sr(datalink_id_t linkid, dladm_wlan_ess_t *sr, 13915895Syz147064 uint_t escnt, uint_t *estot) 13924126Szf162725 { 13934126Szf162725 int i, n; 13944126Szf162725 wldp_t *gbuf; 13954126Szf162725 wl_wpa_ess_t *es; 13964126Szf162725 dladm_status_t status; 13974126Szf162725 13984126Szf162725 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 13994126Szf162725 return (DLADM_STATUS_NOMEM); 14004126Szf162725 14015895Syz147064 status = i_dladm_wlan_get_ioctl(linkid, gbuf, WL_SCANRESULTS); 14024126Szf162725 14034126Szf162725 if (status == DLADM_STATUS_OK) { 14044126Szf162725 es = (wl_wpa_ess_t *)(gbuf->wldp_buf); 14054126Szf162725 n = (es->count > escnt) ? escnt : es->count; 14064126Szf162725 for (i = 0; i < n; i ++) { 14074126Szf162725 (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid, 14084126Szf162725 DLADM_WLAN_BSSID_LEN); 14094126Szf162725 sr[i].we_ssid_len = es->ess[i].ssid_len; 14104126Szf162725 (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid, 14114126Szf162725 es->ess[i].ssid_len); 14124126Szf162725 sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len; 14134126Szf162725 (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie, 14144126Szf162725 es->ess[i].wpa_ie_len); 14154126Szf162725 sr[i].we_freq = es->ess[i].freq; 14164126Szf162725 } 14174126Szf162725 *estot = n; 14184126Szf162725 } 14194126Szf162725 14204126Szf162725 free(gbuf); 14214126Szf162725 return (status); 14224126Szf162725 } 14234126Szf162725 14244126Szf162725 dladm_status_t 14255895Syz147064 dladm_wlan_wpa_set_ie(datalink_id_t linkid, uint8_t *wpa_ie, uint_t wpa_ie_len) 14264126Szf162725 { 14274126Szf162725 wl_wpa_ie_t *ie; 14284126Szf162725 uint_t len; 14294126Szf162725 dladm_status_t status; 14304126Szf162725 14314126Szf162725 if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN) 14324126Szf162725 return (DLADM_STATUS_BADARG); 14334126Szf162725 len = sizeof (wl_wpa_ie_t) + wpa_ie_len; 14344126Szf162725 ie = malloc(len); 14354126Szf162725 if (ie == NULL) 14364126Szf162725 return (DLADM_STATUS_NOMEM); 14374126Szf162725 14384126Szf162725 (void) memset(ie, 0, len); 14394126Szf162725 ie->wpa_ie_len = wpa_ie_len; 14404126Szf162725 (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len); 14414126Szf162725 14425895Syz147064 status = i_dladm_wlan_set_ioctl(linkid, WL_SETOPTIE, ie, len); 14434126Szf162725 free(ie); 14444126Szf162725 14454126Szf162725 return (status); 14464126Szf162725 } 14474126Szf162725 14484126Szf162725 dladm_status_t 14495895Syz147064 dladm_wlan_wpa_set_wpa(datalink_id_t linkid, boolean_t flag) 14504126Szf162725 { 14515895Syz147064 wl_wpa_t wpa; 14524126Szf162725 14534126Szf162725 wpa.wpa_flag = flag; 14545895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_WPA, &wpa, 14555895Syz147064 sizeof (wl_wpa_t))); 14564126Szf162725 } 14574126Szf162725 14584126Szf162725 dladm_status_t 14595895Syz147064 dladm_wlan_wpa_del_key(datalink_id_t linkid, uint_t key_idx, 14604126Szf162725 const dladm_wlan_bssid_t *addr) 14614126Szf162725 { 14625895Syz147064 wl_del_key_t wk; 14634126Szf162725 14644126Szf162725 wk.idk_keyix = key_idx; 14654126Szf162725 if (addr != NULL) 14664126Szf162725 (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes, 14674126Szf162725 DLADM_WLAN_BSSID_LEN); 14684126Szf162725 14695895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_DELKEY, &wk, 14705895Syz147064 sizeof (wl_del_key_t))); 14714126Szf162725 } 14724126Szf162725 14734126Szf162725 dladm_status_t 14745895Syz147064 dladm_wlan_wpa_set_key(datalink_id_t linkid, dladm_wlan_cipher_t cipher, 14754126Szf162725 const dladm_wlan_bssid_t *addr, boolean_t set_tx, uint64_t seq, 14764126Szf162725 uint_t key_idx, uint8_t *key, uint_t key_len) 14774126Szf162725 { 14785895Syz147064 wl_key_t wk; 14794126Szf162725 14804126Szf162725 (void) memset(&wk, 0, sizeof (wl_key_t)); 14814126Szf162725 switch (cipher) { 14824126Szf162725 case DLADM_WLAN_CIPHER_WEP: 14834126Szf162725 wk.ik_type = IEEE80211_CIPHER_WEP; 14844126Szf162725 break; 14854126Szf162725 case DLADM_WLAN_CIPHER_TKIP: 14864126Szf162725 wk.ik_type = IEEE80211_CIPHER_TKIP; 14874126Szf162725 break; 14884126Szf162725 case DLADM_WLAN_CIPHER_AES_OCB: 14894126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_OCB; 14904126Szf162725 break; 14914126Szf162725 case DLADM_WLAN_CIPHER_AES_CCM: 14924126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_CCM; 14934126Szf162725 break; 14944126Szf162725 case DLADM_WLAN_CIPHER_CKIP: 14954126Szf162725 wk.ik_type = IEEE80211_CIPHER_CKIP; 14964126Szf162725 break; 14974126Szf162725 case DLADM_WLAN_CIPHER_NONE: 14984126Szf162725 wk.ik_type = IEEE80211_CIPHER_NONE; 14994126Szf162725 break; 15004126Szf162725 default: 15014126Szf162725 return (DLADM_STATUS_BADARG); 15024126Szf162725 } 15034126Szf162725 wk.ik_flags = IEEE80211_KEY_RECV; 15044126Szf162725 if (set_tx) { 15054126Szf162725 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; 15064126Szf162725 (void) memcpy(wk.ik_macaddr, addr->wb_bytes, 15074126Szf162725 DLADM_WLAN_BSSID_LEN); 15084126Szf162725 } else 15094126Szf162725 (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN); 15104126Szf162725 wk.ik_keyix = key_idx; 15114126Szf162725 wk.ik_keylen = key_len; 15124126Szf162725 (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */ 15134126Szf162725 (void) memcpy(wk.ik_keydata, key, key_len); 15144126Szf162725 15155895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_KEY, &wk, sizeof (wl_key_t))); 15164126Szf162725 } 15174126Szf162725 15184126Szf162725 dladm_status_t 15195895Syz147064 dladm_wlan_wpa_set_mlme(datalink_id_t linkid, dladm_wlan_mlme_op_t op, 15204126Szf162725 dladm_wlan_reason_t reason, dladm_wlan_bssid_t *bssid) 15214126Szf162725 { 15224126Szf162725 wl_mlme_t mlme; 15234126Szf162725 15244126Szf162725 (void) memset(&mlme, 0, sizeof (wl_mlme_t)); 15254126Szf162725 switch (op) { 15264126Szf162725 case DLADM_WLAN_MLME_ASSOC: 15274126Szf162725 mlme.im_op = IEEE80211_MLME_ASSOC; 15284126Szf162725 break; 15294126Szf162725 case DLADM_WLAN_MLME_DISASSOC: 15304126Szf162725 mlme.im_op = IEEE80211_MLME_DISASSOC; 15314126Szf162725 break; 15324126Szf162725 default: 15334126Szf162725 return (DLADM_STATUS_BADARG); 15344126Szf162725 } 15354126Szf162725 mlme.im_reason = reason; 15364126Szf162725 if (bssid != NULL) 15374126Szf162725 (void) memcpy(mlme.im_macaddr, bssid->wb_bytes, 15384126Szf162725 DLADM_WLAN_BSSID_LEN); 15394126Szf162725 15405895Syz147064 return (i_dladm_wlan_set_ioctl(linkid, WL_MLME, &mlme, 15415895Syz147064 sizeof (wl_mlme_t))); 15424126Szf162725 } 15434126Szf162725 15444126Szf162725 /* 15454126Szf162725 * routines of create instance 15464126Szf162725 */ 15474126Szf162725 static scf_propertygroup_t * 15484126Szf162725 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance, 15494126Szf162725 const char *pg_name, const char *pg_type) 15504126Szf162725 { 15514126Szf162725 scf_propertygroup_t *pg; 15524126Szf162725 15534126Szf162725 pg = scf_pg_create(handle); 15544126Szf162725 if (pg == NULL) 15554126Szf162725 return (NULL); 15564126Szf162725 15574126Szf162725 if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) { 15584126Szf162725 scf_pg_destroy(pg); 15594126Szf162725 return (NULL); 15604126Szf162725 } 15614126Szf162725 15624126Szf162725 return (pg); 15634126Szf162725 } 15644126Szf162725 15655895Syz147064 static dladm_status_t 15664126Szf162725 add_new_property(scf_handle_t *handle, const char *prop_name, 15674126Szf162725 scf_type_t type, const char *val, scf_transaction_t *tx) 15684126Szf162725 { 15694126Szf162725 scf_value_t *value = NULL; 15704126Szf162725 scf_transaction_entry_t *entry = NULL; 15714126Szf162725 15724126Szf162725 entry = scf_entry_create(handle); 15734126Szf162725 if (entry == NULL) 15744126Szf162725 goto out; 15754126Szf162725 15764126Szf162725 value = scf_value_create(handle); 15774126Szf162725 if (value == NULL) 15784126Szf162725 goto out; 15794126Szf162725 15804126Szf162725 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) 15814126Szf162725 goto out; 15824126Szf162725 15834126Szf162725 if (scf_value_set_from_string(value, type, val) != 0) 15844126Szf162725 goto out; 15854126Szf162725 15864126Szf162725 if (scf_entry_add_value(entry, value) != 0) 15874126Szf162725 goto out; 15884126Szf162725 15895895Syz147064 return (DLADM_STATUS_OK); 15904126Szf162725 15914126Szf162725 out: 15924126Szf162725 if (value != NULL) 15934126Szf162725 scf_value_destroy(value); 15944126Szf162725 if (entry != NULL) 15954126Szf162725 scf_entry_destroy(entry); 15964126Szf162725 15975895Syz147064 return (DLADM_STATUS_FAILED); 15984126Szf162725 } 15994126Szf162725 16005895Syz147064 static dladm_status_t 16014126Szf162725 add_pg_method(scf_handle_t *handle, scf_instance_t *instance, 16024126Szf162725 const char *pg_name, const char *flags) 16034126Szf162725 { 16044126Szf162725 int rv, size; 16055895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 16064126Szf162725 char *command = NULL; 16074126Szf162725 scf_transaction_t *tran = NULL; 16084126Szf162725 scf_propertygroup_t *pg; 16094126Szf162725 16104126Szf162725 pg = add_property_group_to_instance(handle, instance, 16114126Szf162725 pg_name, SCF_GROUP_METHOD); 16124126Szf162725 if (pg == NULL) 16134126Szf162725 goto out; 16144126Szf162725 16154126Szf162725 tran = scf_transaction_create(handle); 16164126Szf162725 if (tran == NULL) 16174126Szf162725 goto out; 16184126Szf162725 16194126Szf162725 size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1; 16204126Szf162725 command = malloc(size); 16214126Szf162725 if (command == NULL) { 16225895Syz147064 status = DLADM_STATUS_NOMEM; 16234126Szf162725 goto out; 16244126Szf162725 } 16254126Szf162725 (void) snprintf(command, size, "%s %s", SVC_METHOD, flags); 16264126Szf162725 16274126Szf162725 do { 16284126Szf162725 if (scf_transaction_start(tran, pg) != 0) 16294126Szf162725 goto out; 16304126Szf162725 16314126Szf162725 if (add_new_property(handle, SCF_PROPERTY_EXEC, 16325895Syz147064 SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) { 16334126Szf162725 goto out; 16344126Szf162725 } 16354126Szf162725 16364126Szf162725 rv = scf_transaction_commit(tran); 16374126Szf162725 switch (rv) { 16384126Szf162725 case 1: 16395895Syz147064 status = DLADM_STATUS_OK; 16404126Szf162725 goto out; 16414126Szf162725 case 0: 16424126Szf162725 scf_transaction_destroy_children(tran); 16434126Szf162725 if (scf_pg_update(pg) == -1) { 16444126Szf162725 goto out; 16454126Szf162725 } 16464126Szf162725 break; 16474126Szf162725 case -1: 16484126Szf162725 default: 16494126Szf162725 goto out; 16504126Szf162725 } 16514126Szf162725 } while (rv == 0); 16524126Szf162725 16534126Szf162725 out: 16544126Szf162725 if (tran != NULL) { 16554126Szf162725 scf_transaction_destroy_children(tran); 16564126Szf162725 scf_transaction_destroy(tran); 16574126Szf162725 } 16584126Szf162725 16594126Szf162725 if (pg != NULL) 16604126Szf162725 scf_pg_destroy(pg); 16614126Szf162725 16624126Szf162725 if (command != NULL) 16634126Szf162725 free(command); 16644126Szf162725 16654126Szf162725 return (status); 16664126Szf162725 } 16674126Szf162725 16685895Syz147064 static dladm_status_t 16694126Szf162725 do_create_instance(scf_handle_t *handle, scf_service_t *svc, 16704126Szf162725 const char *instance_name, const char *command) 16714126Szf162725 { 16725895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 16734126Szf162725 char *buf; 16744126Szf162725 ssize_t max_fmri_len; 16754126Szf162725 scf_instance_t *instance; 16764126Szf162725 16774126Szf162725 instance = scf_instance_create(handle); 16784126Szf162725 if (instance == NULL) 16794126Szf162725 goto out; 16804126Szf162725 16814126Szf162725 if (scf_service_add_instance(svc, instance_name, instance) != 0) { 16824126Szf162725 if (scf_error() == SCF_ERROR_EXISTS) 16834126Szf162725 /* Let the caller deal with the duplicate instance */ 16845895Syz147064 status = DLADM_STATUS_EXIST; 16854126Szf162725 goto out; 16864126Szf162725 } 16874126Szf162725 16884126Szf162725 if (add_pg_method(handle, instance, "start", 16895895Syz147064 command) != DLADM_STATUS_OK) { 16904126Szf162725 goto out; 16914126Szf162725 } 16924126Szf162725 16934126Szf162725 /* enabling the instance */ 16944126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 16954126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) 16964126Szf162725 goto out; 16974126Szf162725 16984126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 16994126Szf162725 if ((smf_disable_instance(buf, 0) != 0) || 17004126Szf162725 (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) { 17014126Szf162725 goto out; 17024126Szf162725 } 17035895Syz147064 status = DLADM_STATUS_OK; 17044126Szf162725 } 17054126Szf162725 17064126Szf162725 out: 17074126Szf162725 if (instance != NULL) 17084126Szf162725 scf_instance_destroy(instance); 17094126Szf162725 return (status); 17104126Szf162725 } 17114126Szf162725 17125895Syz147064 static dladm_status_t 17134126Szf162725 create_instance(const char *instance_name, const char *command) 17144126Szf162725 { 17155895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17164126Szf162725 scf_service_t *svc = NULL; 17174126Szf162725 scf_handle_t *handle = NULL; 17184126Szf162725 17194126Szf162725 handle = scf_handle_create(SCF_VERSION); 17204126Szf162725 if (handle == NULL) 17214126Szf162725 goto out; 17224126Szf162725 17234126Szf162725 if (scf_handle_bind(handle) == -1) 17244126Szf162725 goto out; 17254126Szf162725 17264126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 17274126Szf162725 goto out; 17284126Szf162725 17294126Szf162725 if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc, 17304126Szf162725 NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) 17314126Szf162725 goto out; 17324126Szf162725 17334126Szf162725 status = do_create_instance(handle, svc, instance_name, command); 17344126Szf162725 17354126Szf162725 out: 17364126Szf162725 if (svc != NULL) 17374126Szf162725 scf_service_destroy(svc); 17384126Szf162725 17394126Szf162725 if (handle != NULL) { 17404126Szf162725 (void) scf_handle_unbind(handle); 17414126Szf162725 scf_handle_destroy(handle); 17424126Szf162725 } 17434126Szf162725 17444126Szf162725 return (status); 17454126Szf162725 } 17464126Szf162725 17474126Szf162725 /* 17484126Szf162725 * routines of delete instance 17494126Szf162725 */ 17504126Szf162725 #define DEFAULT_TIMEOUT 60000000 17514126Szf162725 #define INIT_WAIT_USECS 50000 17524126Szf162725 17534126Szf162725 static void 17544126Szf162725 wait_until_disabled(scf_handle_t *handle, char *fmri) 17554126Szf162725 { 17564126Szf162725 char *state; 17574126Szf162725 useconds_t max; 17584126Szf162725 useconds_t usecs; 17594126Szf162725 uint64_t *cp = NULL; 17604126Szf162725 scf_simple_prop_t *sp = NULL; 17614126Szf162725 17624126Szf162725 max = DEFAULT_TIMEOUT; 17634126Szf162725 17644126Szf162725 if (((sp = scf_simple_prop_get(handle, fmri, "stop", 17654126Szf162725 SCF_PROPERTY_TIMEOUT)) != NULL) && 17664126Szf162725 ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0)) 17674126Szf162725 max = (*cp) * 1000000; /* convert to usecs */ 17684126Szf162725 17694126Szf162725 if (sp != NULL) 17704126Szf162725 scf_simple_prop_free(sp); 17714126Szf162725 17724126Szf162725 for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) { 17734126Szf162725 /* incremental wait */ 17744126Szf162725 usecs *= 2; 17754126Szf162725 usecs = (usecs > max) ? max : usecs; 17764126Szf162725 17774126Szf162725 (void) usleep(usecs); 17784126Szf162725 17794126Szf162725 /* Check state after the wait */ 17804126Szf162725 if ((state = smf_get_state(fmri)) != NULL) { 17814126Szf162725 if (strcmp(state, "disabled") == 0) 17824126Szf162725 return; 17834126Szf162725 } 17844126Szf162725 } 17854126Szf162725 } 17864126Szf162725 17875895Syz147064 static dladm_status_t 17884126Szf162725 delete_instance(const char *instance_name) 17894126Szf162725 { 17905895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17914126Szf162725 char *buf; 17924126Szf162725 ssize_t max_fmri_len; 17934126Szf162725 scf_scope_t *scope = NULL; 17944126Szf162725 scf_service_t *svc = NULL; 17954126Szf162725 scf_handle_t *handle = NULL; 17964126Szf162725 scf_instance_t *instance; 17974126Szf162725 17984126Szf162725 handle = scf_handle_create(SCF_VERSION); 17994126Szf162725 if (handle == NULL) 18004126Szf162725 goto out; 18014126Szf162725 18024126Szf162725 if (scf_handle_bind(handle) == -1) 18034126Szf162725 goto out; 18044126Szf162725 18054126Szf162725 if ((scope = scf_scope_create(handle)) == NULL) 18064126Szf162725 goto out; 18074126Szf162725 18084126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 18094126Szf162725 goto out; 18104126Szf162725 18114126Szf162725 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1) 18124126Szf162725 goto out; 18134126Szf162725 18144126Szf162725 if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0) 18154126Szf162725 goto out; 18164126Szf162725 18174126Szf162725 instance = scf_instance_create(handle); 18184126Szf162725 if (instance == NULL) 18194126Szf162725 goto out; 18204126Szf162725 18214126Szf162725 if (scf_service_get_instance(svc, instance_name, instance) != 0) { 18224126Szf162725 scf_error_t scf_errnum = scf_error(); 18234126Szf162725 18244126Szf162725 if (scf_errnum == SCF_ERROR_NOT_FOUND) 18255895Syz147064 status = DLADM_STATUS_OK; 18264126Szf162725 18274126Szf162725 scf_instance_destroy(instance); 18284126Szf162725 goto out; 18294126Szf162725 } 18304126Szf162725 18314126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 18324126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) { 18334126Szf162725 scf_instance_destroy(instance); 18344126Szf162725 goto out; 18354126Szf162725 } 18364126Szf162725 18374126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 18384126Szf162725 char *state; 18394126Szf162725 18404126Szf162725 state = smf_get_state(buf); 18414126Szf162725 if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 || 18424126Szf162725 strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) { 18434126Szf162725 if (smf_disable_instance(buf, 0) == 0) { 18444126Szf162725 /* 18454126Szf162725 * Wait for some time till timeout to avoid 18464126Szf162725 * a race with scf_instance_delete() below. 18474126Szf162725 */ 18484126Szf162725 wait_until_disabled(handle, buf); 18494126Szf162725 } 18504126Szf162725 } 18514126Szf162725 } 18524126Szf162725 18534126Szf162725 if (scf_instance_delete(instance) != 0) { 18544126Szf162725 scf_instance_destroy(instance); 18554126Szf162725 goto out; 18564126Szf162725 } 18574126Szf162725 18584126Szf162725 scf_instance_destroy(instance); 18594126Szf162725 18605895Syz147064 status = DLADM_STATUS_OK; 18614126Szf162725 18624126Szf162725 out: 18634126Szf162725 if (svc != NULL) 18644126Szf162725 scf_service_destroy(svc); 18654126Szf162725 18664126Szf162725 if (scope != NULL) 18674126Szf162725 scf_scope_destroy(scope); 18684126Szf162725 18694126Szf162725 if (handle != NULL) { 18704126Szf162725 (void) scf_handle_unbind(handle); 18714126Szf162725 scf_handle_destroy(handle); 18724126Szf162725 } 18734126Szf162725 18744126Szf162725 return (status); 18754126Szf162725 } 18764126Szf162725 18775895Syz147064 static dladm_status_t 18785895Syz147064 wpa_instance_create(datalink_id_t linkid, void *key) 18794126Szf162725 { 18805895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 18814126Szf162725 char *command = NULL; 18824126Szf162725 char *wk_name = ((dladm_wlan_key_t *)key)->wk_name; 18834126Szf162725 int size; 18845895Syz147064 char instance_name[MAXLINKNAMELEN]; 18855895Syz147064 18865895Syz147064 /* 18875895Syz147064 * Use the link name as the instance name of the network/wpad service. 18885895Syz147064 */ 18895895Syz147064 status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name, 18905895Syz147064 sizeof (instance_name)); 18915895Syz147064 if (status != DLADM_STATUS_OK) 18925895Syz147064 goto out; 18934126Szf162725 18944126Szf162725 size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1; 18954126Szf162725 command = malloc(size); 18964126Szf162725 if (command == NULL) { 18975895Syz147064 status = DLADM_STATUS_NOMEM; 18984126Szf162725 goto out; 18994126Szf162725 } 19004126Szf162725 (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name); 19014126Szf162725 19024126Szf162725 status = create_instance(instance_name, command); 19035895Syz147064 if (status == DLADM_STATUS_EXIST) { 19044126Szf162725 /* 19054126Szf162725 * Delete the existing instance and create a new instance 19064126Szf162725 * with the supplied arguments. 19074126Szf162725 */ 19084126Szf162725 if ((status = delete_instance(instance_name)) == 19095895Syz147064 DLADM_STATUS_OK) { 19104126Szf162725 status = create_instance(instance_name, command); 19114126Szf162725 } 19124126Szf162725 } 19134126Szf162725 19144126Szf162725 out: 19154126Szf162725 if (command != NULL) 19164126Szf162725 free(command); 19174126Szf162725 19184126Szf162725 return (status); 19194126Szf162725 } 19204126Szf162725 19215895Syz147064 static dladm_status_t 19225895Syz147064 wpa_instance_delete(datalink_id_t linkid) 19234126Szf162725 { 19245895Syz147064 char instance_name[MAXLINKNAMELEN]; 19254126Szf162725 19265895Syz147064 /* 19275895Syz147064 * Get the instance name of the network/wpad service (the same as 19285895Syz147064 * the link name). 19295895Syz147064 */ 19305895Syz147064 if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name, 19315895Syz147064 sizeof (instance_name)) != DLADM_STATUS_OK) 19325895Syz147064 return (DLADM_STATUS_FAILED); 19334126Szf162725 19345895Syz147064 return (delete_instance(instance_name)); 19354126Szf162725 } 1936