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 /* 22*10266SQuaker.Fang@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 233871Syz147064 * Use is subject to license terms. 243871Syz147064 */ 253871Syz147064 263871Syz147064 #include <libintl.h> 273871Syz147064 #include <stdio.h> 283871Syz147064 #include <stdlib.h> 293871Syz147064 #include <unistd.h> 303871Syz147064 #include <fcntl.h> 315895Syz147064 #include <stddef.h> 323871Syz147064 #include <string.h> 333871Syz147064 #include <stropts.h> 343871Syz147064 #include <libdevinfo.h> 353871Syz147064 #include <net/if.h> 363871Syz147064 #include <net/if_dl.h> 373871Syz147064 #include <net/if_types.h> 385895Syz147064 #include <libdlpi.h> 395895Syz147064 #include <libdllink.h> 404126Szf162725 #include <libscf.h> 413871Syz147064 #include <libdlwlan.h> 425895Syz147064 #include <libdladm_impl.h> 433871Syz147064 #include <libdlwlan_impl.h> 444126Szf162725 #include <net/wpa.h> 453871Syz147064 468453SAnurag.Maskey@Sun.COM static dladm_status_t wpa_instance_create(dladm_handle_t, datalink_id_t, 478453SAnurag.Maskey@Sun.COM void *); 488453SAnurag.Maskey@Sun.COM static dladm_status_t wpa_instance_delete(dladm_handle_t, datalink_id_t); 493871Syz147064 508453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_bsstype(dladm_handle_t, datalink_id_t, void *, 518453SAnurag.Maskey@Sun.COM int); 528453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_essid(dladm_handle_t, datalink_id_t, void *, 538453SAnurag.Maskey@Sun.COM int); 548453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_bssid(dladm_handle_t, datalink_id_t, void *, 558453SAnurag.Maskey@Sun.COM int); 568453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_signal(dladm_handle_t, datalink_id_t, void *, 578453SAnurag.Maskey@Sun.COM int); 588453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_encryption(dladm_handle_t, datalink_id_t, void *, 598453SAnurag.Maskey@Sun.COM int); 608453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_authmode(dladm_handle_t, datalink_id_t, void *, 618453SAnurag.Maskey@Sun.COM int); 628453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_linkstatus(dladm_handle_t, datalink_id_t, void *, 638453SAnurag.Maskey@Sun.COM int); 648453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_esslist(dladm_handle_t, datalink_id_t, void *, 658453SAnurag.Maskey@Sun.COM int); 668453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_rate(dladm_handle_t, datalink_id_t, void *, int); 678453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_mode(dladm_handle_t, datalink_id_t, void *, int); 688453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_capability(dladm_handle_t, datalink_id_t, void *, 698453SAnurag.Maskey@Sun.COM int); 708453SAnurag.Maskey@Sun.COM static dladm_status_t do_get_wpamode(dladm_handle_t, datalink_id_t, void *, 718453SAnurag.Maskey@Sun.COM int); 724126Szf162725 738453SAnurag.Maskey@Sun.COM static dladm_status_t do_set_bsstype(dladm_handle_t, datalink_id_t, 748453SAnurag.Maskey@Sun.COM dladm_wlan_bsstype_t *); 758453SAnurag.Maskey@Sun.COM static dladm_status_t do_set_authmode(dladm_handle_t, datalink_id_t, 768453SAnurag.Maskey@Sun.COM dladm_wlan_auth_t *); 778453SAnurag.Maskey@Sun.COM static dladm_status_t do_set_encryption(dladm_handle_t, datalink_id_t, 785895Syz147064 dladm_wlan_secmode_t *); 798453SAnurag.Maskey@Sun.COM static dladm_status_t do_set_essid(dladm_handle_t, datalink_id_t, 808453SAnurag.Maskey@Sun.COM dladm_wlan_essid_t *); 818453SAnurag.Maskey@Sun.COM static dladm_status_t do_set_createibss(dladm_handle_t, datalink_id_t, 828453SAnurag.Maskey@Sun.COM boolean_t *); 838453SAnurag.Maskey@Sun.COM static dladm_status_t do_set_key(dladm_handle_t, datalink_id_t, 848453SAnurag.Maskey@Sun.COM dladm_wlan_key_t *, uint_t); 858453SAnurag.Maskey@Sun.COM static dladm_status_t do_set_channel(dladm_handle_t, datalink_id_t, 868453SAnurag.Maskey@Sun.COM dladm_wlan_channel_t *); 873871Syz147064 888453SAnurag.Maskey@Sun.COM static dladm_status_t do_scan(dladm_handle_t, datalink_id_t, void *, int); 898453SAnurag.Maskey@Sun.COM static dladm_status_t do_connect(dladm_handle_t, datalink_id_t, void *, int, 907663SSowmini.Varadhan@Sun.COM dladm_wlan_attr_t *, boolean_t, void *, uint_t, 917663SSowmini.Varadhan@Sun.COM int); 928453SAnurag.Maskey@Sun.COM static dladm_status_t do_disconnect(dladm_handle_t, datalink_id_t, void *, 938453SAnurag.Maskey@Sun.COM int); 945895Syz147064 static boolean_t find_val_by_name(const char *, val_desc_t *, 955895Syz147064 uint_t, uint_t *); 965895Syz147064 static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **); 975895Syz147064 static void generate_essid(dladm_wlan_essid_t *); 983871Syz147064 993871Syz147064 static dladm_status_t dladm_wlan_wlresult2status(wldp_t *); 1008453SAnurag.Maskey@Sun.COM static dladm_status_t dladm_wlan_validate(dladm_handle_t, datalink_id_t); 1013871Syz147064 1023871Syz147064 static val_desc_t linkstatus_vals[] = { 1035903Ssowmini { "disconnected", DLADM_WLAN_LINK_DISCONNECTED }, 1045903Ssowmini { "connected", DLADM_WLAN_LINK_CONNECTED } 1053871Syz147064 }; 1063871Syz147064 1073871Syz147064 static val_desc_t secmode_vals[] = { 1085903Ssowmini { "none", DLADM_WLAN_SECMODE_NONE }, 1095903Ssowmini { "wep", DLADM_WLAN_SECMODE_WEP }, 1105903Ssowmini { "wpa", DLADM_WLAN_SECMODE_WPA } 1113871Syz147064 }; 1123871Syz147064 1133871Syz147064 static val_desc_t strength_vals[] = { 1145903Ssowmini { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK }, 1155895Syz147064 { "weak", DLADM_WLAN_STRENGTH_WEAK }, 1165895Syz147064 { "good", DLADM_WLAN_STRENGTH_GOOD }, 1175903Ssowmini { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD }, 1185903Ssowmini { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT } 1193871Syz147064 }; 1203871Syz147064 1213871Syz147064 static val_desc_t mode_vals[] = { 1225903Ssowmini { "a", DLADM_WLAN_MODE_80211A }, 1235903Ssowmini { "b", DLADM_WLAN_MODE_80211B }, 1245903Ssowmini { "g", DLADM_WLAN_MODE_80211G }, 125*10266SQuaker.Fang@Sun.COM { "n", DLADM_WLAN_MODE_80211GN }, 126*10266SQuaker.Fang@Sun.COM { "n", DLADM_WLAN_MODE_80211AN } 1273871Syz147064 }; 1283871Syz147064 1293871Syz147064 static val_desc_t auth_vals[] = { 1305895Syz147064 { "open", DLADM_WLAN_AUTH_OPEN }, 1315903Ssowmini { "shared", DLADM_WLAN_AUTH_SHARED } 1323871Syz147064 }; 1333871Syz147064 1343871Syz147064 static val_desc_t bsstype_vals[] = { 1355903Ssowmini { "bss", DLADM_WLAN_BSSTYPE_BSS }, 1365903Ssowmini { "ibss", DLADM_WLAN_BSSTYPE_IBSS }, 1375903Ssowmini { "any", DLADM_WLAN_BSSTYPE_ANY } 1383871Syz147064 }; 1393871Syz147064 1407663SSowmini.Varadhan@Sun.COM #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET) 1413871Syz147064 1423871Syz147064 static dladm_status_t 1433871Syz147064 dladm_wlan_wlresult2status(wldp_t *gbuf) 1443871Syz147064 { 1453871Syz147064 switch (gbuf->wldp_result) { 1463871Syz147064 case WL_SUCCESS: 1473871Syz147064 return (DLADM_STATUS_OK); 1483871Syz147064 1493871Syz147064 case WL_NOTSUPPORTED: 1503871Syz147064 case WL_LACK_FEATURE: 1513871Syz147064 return (DLADM_STATUS_NOTSUP); 1523871Syz147064 1533871Syz147064 case WL_READONLY: 1543871Syz147064 return (DLADM_STATUS_PROPRDONLY); 1553871Syz147064 1563871Syz147064 default: 1573871Syz147064 break; 1583871Syz147064 } 1593871Syz147064 1603871Syz147064 return (DLADM_STATUS_FAILED); 1613871Syz147064 } 1623871Syz147064 1633871Syz147064 static dladm_wlan_mode_t 1643871Syz147064 do_convert_mode(wl_phy_conf_t *phyp) 1653871Syz147064 { 166*10266SQuaker.Fang@Sun.COM wl_erp_t *wlep = &phyp->wl_phy_erp_conf; 167*10266SQuaker.Fang@Sun.COM wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf; 168*10266SQuaker.Fang@Sun.COM 1693871Syz147064 switch (phyp->wl_phy_fhss_conf.wl_fhss_subtype) { 1703871Syz147064 case WL_ERP: 171*10266SQuaker.Fang@Sun.COM return (wlep->wl_erp_ht_enabled ? 172*10266SQuaker.Fang@Sun.COM DLADM_WLAN_MODE_80211GN : DLADM_WLAN_MODE_80211G); 1733871Syz147064 case WL_OFDM: 174*10266SQuaker.Fang@Sun.COM return (wlop->wl_ofdm_ht_enabled ? 175*10266SQuaker.Fang@Sun.COM DLADM_WLAN_MODE_80211AN : DLADM_WLAN_MODE_80211A); 1763871Syz147064 case WL_DSSS: 1773871Syz147064 case WL_FHSS: 1783871Syz147064 return (DLADM_WLAN_MODE_80211B); 1793871Syz147064 default: 1803871Syz147064 break; 1813871Syz147064 } 1823871Syz147064 1833871Syz147064 return (DLADM_WLAN_MODE_NONE); 1843871Syz147064 } 1853871Syz147064 1865895Syz147064 boolean_t 1875895Syz147064 i_dladm_wlan_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp) 1883871Syz147064 { 1893871Syz147064 wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf; 1903871Syz147064 wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf; 1913871Syz147064 1923871Syz147064 switch (wlfp->wl_fhss_subtype) { 1933871Syz147064 case WL_FHSS: 1943871Syz147064 case WL_DSSS: 1953871Syz147064 case WL_IRBASE: 1963871Syz147064 case WL_HRDS: 1973871Syz147064 case WL_ERP: 1983871Syz147064 *channelp = wlfp->wl_fhss_channel; 1993871Syz147064 break; 2003871Syz147064 case WL_OFDM: 2013871Syz147064 *channelp = DLADM_WLAN_OFDM2CHAN(wlop->wl_ofdm_frequency); 2023871Syz147064 break; 2033871Syz147064 default: 2043871Syz147064 return (B_FALSE); 2053871Syz147064 } 2063871Syz147064 return (B_TRUE); 2073871Syz147064 } 2083871Syz147064 2093871Syz147064 #define IEEE80211_RATE 0x7f 2103871Syz147064 static void 2113871Syz147064 fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp) 2123871Syz147064 { 2133871Syz147064 int i; 2143871Syz147064 2153871Syz147064 (void) memset(attrp, 0, sizeof (*attrp)); 2163871Syz147064 2173871Syz147064 (void) snprintf(attrp->wa_essid.we_bytes, DLADM_WLAN_MAX_ESSID_LEN, 2183871Syz147064 "%s", wlp->wl_ess_conf_essid.wl_essid_essid); 2193871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 2203871Syz147064 2213871Syz147064 (void) memcpy(attrp->wa_bssid.wb_bytes, wlp->wl_ess_conf_bssid, 2223871Syz147064 DLADM_WLAN_BSSID_LEN); 2233871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 2243871Syz147064 2253871Syz147064 attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled == 2263871Syz147064 WL_ENC_WEP ? DLADM_WLAN_SECMODE_WEP : DLADM_WLAN_SECMODE_NONE); 2274126Szf162725 if (wlp->wl_ess_conf_reserved[0] > 0) 2284126Szf162725 attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 2293871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 2303871Syz147064 2313871Syz147064 attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ? 2323871Syz147064 DLADM_WLAN_BSSTYPE_BSS : DLADM_WLAN_BSSTYPE_IBSS); 2333871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 2343871Syz147064 2353871Syz147064 attrp->wa_auth = (wlp->wl_ess_conf_authmode == 0 ? 2363871Syz147064 DLADM_WLAN_AUTH_OPEN : DLADM_WLAN_AUTH_SHARED); 2373871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 2383871Syz147064 2393871Syz147064 attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(wlp->wl_ess_conf_sl); 2403871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 2413871Syz147064 2423871Syz147064 attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)&wlp->wl_phy_conf); 2433871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 2443871Syz147064 2453871Syz147064 for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) { 2463871Syz147064 wlp->wl_supported_rates[i] &= IEEE80211_RATE; 2473871Syz147064 if (wlp->wl_supported_rates[i] > attrp->wa_speed) 2483871Syz147064 attrp->wa_speed = wlp->wl_supported_rates[i]; 2493871Syz147064 } 2503871Syz147064 if (attrp->wa_speed > 0) 2513871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 2523871Syz147064 2535895Syz147064 if (i_dladm_wlan_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf, 2543871Syz147064 &attrp->wa_channel)) 2553871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_CHANNEL; 2563871Syz147064 } 2573871Syz147064 2583871Syz147064 dladm_status_t 2598453SAnurag.Maskey@Sun.COM dladm_wlan_scan(dladm_handle_t handle, datalink_id_t linkid, void *arg, 2603871Syz147064 boolean_t (*func)(void *, dladm_wlan_attr_t *)) 2613871Syz147064 { 2625895Syz147064 int i; 2633871Syz147064 uint32_t count; 2643871Syz147064 wl_ess_conf_t *wlp; 2657663SSowmini.Varadhan@Sun.COM wl_ess_list_t *wls = NULL; 2667663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 2677663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 2683871Syz147064 dladm_wlan_attr_t wlattr; 2693871Syz147064 dladm_status_t status; 2703871Syz147064 2718453SAnurag.Maskey@Sun.COM if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 2725895Syz147064 goto done; 2733871Syz147064 2748453SAnurag.Maskey@Sun.COM status = do_get_linkstatus(handle, linkid, &wl_status, 2758453SAnurag.Maskey@Sun.COM sizeof (wl_status)); 2767663SSowmini.Varadhan@Sun.COM if (status != DLADM_STATUS_OK) 2773871Syz147064 goto done; 2783871Syz147064 2798453SAnurag.Maskey@Sun.COM if ((status = do_scan(handle, linkid, buf, sizeof (buf))) != 2808453SAnurag.Maskey@Sun.COM DLADM_STATUS_OK) 2813871Syz147064 goto done; 2823871Syz147064 2834126Szf162725 if (func == NULL) { 2844126Szf162725 status = DLADM_STATUS_OK; 2854126Szf162725 goto done; 2864126Szf162725 } 2874126Szf162725 2887663SSowmini.Varadhan@Sun.COM wls = malloc(WLDP_BUFSIZE); 2897663SSowmini.Varadhan@Sun.COM if (wls == NULL) { 2907663SSowmini.Varadhan@Sun.COM status = DLADM_STATUS_NOMEM; 2917663SSowmini.Varadhan@Sun.COM goto done; 2927663SSowmini.Varadhan@Sun.COM } 2937663SSowmini.Varadhan@Sun.COM 2948453SAnurag.Maskey@Sun.COM if ((status = do_get_esslist(handle, linkid, wls, WLDP_BUFSIZE)) 2957663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 2963871Syz147064 goto done; 2973871Syz147064 2987663SSowmini.Varadhan@Sun.COM wlp = wls->wl_ess_list_ess; 2997663SSowmini.Varadhan@Sun.COM count = wls->wl_ess_list_num; 3003871Syz147064 3013871Syz147064 for (i = 0; i < count; i++, wlp++) { 3023871Syz147064 fill_wlan_attr(wlp, &wlattr); 3033871Syz147064 if (!func(arg, &wlattr)) 3043871Syz147064 break; 3053871Syz147064 } 3063871Syz147064 3077663SSowmini.Varadhan@Sun.COM if (wl_status != WL_CONNECTED) { 3088453SAnurag.Maskey@Sun.COM status = do_get_linkstatus(handle, linkid, &wl_status, 3097663SSowmini.Varadhan@Sun.COM sizeof (&wl_status)); 3105895Syz147064 if (status != DLADM_STATUS_OK) 3113871Syz147064 goto done; 3127663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) 3138453SAnurag.Maskey@Sun.COM (void) do_disconnect(handle, linkid, buf, sizeof (buf)); 3143871Syz147064 } 3153871Syz147064 3163871Syz147064 status = DLADM_STATUS_OK; 3173871Syz147064 done: 3187663SSowmini.Varadhan@Sun.COM free(wls); 3193871Syz147064 return (status); 3203871Syz147064 } 3213871Syz147064 3223871Syz147064 /* 3233871Syz147064 * Structures used in building the list of eligible WLANs to connect to. 3243871Syz147064 * Specifically, `connect_state' has the WLAN attributes that must be matched 3253871Syz147064 * (in `cs_attr') and a growing list of WLANs that matched those attributes 3263871Syz147064 * chained through `cs_list'. Each element in the list is of type `attr_node' 3273871Syz147064 * and has the matching WLAN's attributes and a pointer to the next element. 3283871Syz147064 * For convenience, `cs_count' tracks the number of elements in the list. 3293871Syz147064 */ 3303871Syz147064 typedef struct attr_node { 3313871Syz147064 dladm_wlan_attr_t an_attr; 3323871Syz147064 struct attr_node *an_next; 3333871Syz147064 } attr_node_t; 3343871Syz147064 3353871Syz147064 typedef struct connect_state { 3363871Syz147064 dladm_wlan_attr_t *cs_attr; 3373871Syz147064 uint_t cs_count; 3383871Syz147064 attr_node_t *cs_list; 3393871Syz147064 } connect_state_t; 3403871Syz147064 3413871Syz147064 /* 3423871Syz147064 * Compare two sets of WLAN attributes. For now, we only consider strength 3433871Syz147064 * and speed (in that order), which matches the documented default policy for 3443871Syz147064 * dladm_wlan_connect(). 3453871Syz147064 */ 3463871Syz147064 static int 3473871Syz147064 attr_compare(const void *p1, const void *p2) 3483871Syz147064 { 3493871Syz147064 dladm_wlan_attr_t *attrp1, *attrp2; 3503871Syz147064 3513871Syz147064 attrp1 = (*(dladm_wlan_attr_t **)p1); 3523871Syz147064 attrp2 = (*(dladm_wlan_attr_t **)p2); 3533871Syz147064 3543871Syz147064 if (attrp1->wa_strength < attrp2->wa_strength) 3553871Syz147064 return (1); 3563871Syz147064 3573871Syz147064 if (attrp1->wa_strength > attrp2->wa_strength) 3583871Syz147064 return (-1); 3593871Syz147064 3603871Syz147064 return (attrp2->wa_speed - attrp1->wa_speed); 3613871Syz147064 } 3623871Syz147064 3633871Syz147064 /* 3643871Syz147064 * Callback function used by dladm_wlan_connect() to filter out unwanted 3653871Syz147064 * WLANs when scanning for available WLANs. Always returns B_TRUE to 3663871Syz147064 * continue the scan. 3673871Syz147064 */ 3683871Syz147064 static boolean_t 3693871Syz147064 connect_cb(void *arg, dladm_wlan_attr_t *attrp) 3703871Syz147064 { 3713871Syz147064 attr_node_t *nodep; 3723871Syz147064 dladm_wlan_attr_t *fattrp; 3733871Syz147064 connect_state_t *statep = (connect_state_t *)arg; 3743871Syz147064 3753871Syz147064 fattrp = statep->cs_attr; 3763871Syz147064 if (fattrp == NULL) 3773871Syz147064 goto append; 3783871Syz147064 3793871Syz147064 if ((fattrp->wa_valid & attrp->wa_valid) != fattrp->wa_valid) 3803871Syz147064 return (B_TRUE); 3813871Syz147064 3823871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0 && 3833871Syz147064 strncmp(fattrp->wa_essid.we_bytes, attrp->wa_essid.we_bytes, 3843871Syz147064 DLADM_WLAN_MAX_ESSID_LEN) != 0) 3853871Syz147064 return (B_TRUE); 3863871Syz147064 3873871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 3883871Syz147064 fattrp->wa_secmode != attrp->wa_secmode) 3893871Syz147064 return (B_TRUE); 3903871Syz147064 3913871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0 && 3923871Syz147064 fattrp->wa_mode != attrp->wa_mode) 3933871Syz147064 return (B_TRUE); 3943871Syz147064 3953871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_STRENGTH) != 0 && 3963871Syz147064 fattrp->wa_strength != attrp->wa_strength) 3973871Syz147064 return (B_TRUE); 3983871Syz147064 3993871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SPEED) != 0 && 4003871Syz147064 fattrp->wa_speed != attrp->wa_speed) 4013871Syz147064 return (B_TRUE); 4023871Syz147064 4033871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) { 4043871Syz147064 attrp->wa_auth = fattrp->wa_auth; 4053871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 4063871Syz147064 } 4073871Syz147064 4083871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 4093871Syz147064 fattrp->wa_bsstype != attrp->wa_bsstype) 4103871Syz147064 return (B_TRUE); 4113871Syz147064 4123871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSID) != 0 && 4133871Syz147064 memcmp(fattrp->wa_bssid.wb_bytes, attrp->wa_bssid.wb_bytes, 4143871Syz147064 DLADM_WLAN_BSSID_LEN) != 0) 4153871Syz147064 return (B_TRUE); 4163871Syz147064 append: 4173871Syz147064 nodep = malloc(sizeof (attr_node_t)); 4183871Syz147064 if (nodep == NULL) 4193871Syz147064 return (B_TRUE); 4203871Syz147064 4213871Syz147064 (void) memcpy(&nodep->an_attr, attrp, sizeof (dladm_wlan_attr_t)); 4223871Syz147064 nodep->an_next = statep->cs_list; 4233871Syz147064 statep->cs_list = nodep; 4243871Syz147064 statep->cs_count++; 4253871Syz147064 4263871Syz147064 return (B_TRUE); 4273871Syz147064 } 4283871Syz147064 4294126Szf162725 #define IEEE80211_C_WPA 0x01800000 4304126Szf162725 4313871Syz147064 static dladm_status_t 4328453SAnurag.Maskey@Sun.COM do_connect(dladm_handle_t handle, datalink_id_t linkid, void *buf, int bufsize, 4337663SSowmini.Varadhan@Sun.COM dladm_wlan_attr_t *attrp, boolean_t create_ibss, void *keys, 4347663SSowmini.Varadhan@Sun.COM uint_t key_count, int timeout) 4353871Syz147064 { 4365895Syz147064 dladm_wlan_secmode_t secmode; 4375895Syz147064 dladm_wlan_auth_t authmode; 4385895Syz147064 dladm_wlan_bsstype_t bsstype; 4395895Syz147064 dladm_wlan_essid_t essid; 4405895Syz147064 boolean_t essid_valid = B_FALSE; 4415895Syz147064 dladm_status_t status; 4425895Syz147064 dladm_wlan_channel_t channel; 4435895Syz147064 hrtime_t start; 4445895Syz147064 wl_capability_t *caps; 4457663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 4463871Syz147064 4473871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) { 4483871Syz147064 channel = attrp->wa_channel; 4498453SAnurag.Maskey@Sun.COM status = do_set_channel(handle, linkid, &channel); 4505895Syz147064 if (status != DLADM_STATUS_OK) 4513871Syz147064 goto fail; 4523871Syz147064 } 4533871Syz147064 4543871Syz147064 secmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) ? 4553871Syz147064 attrp->wa_secmode : DLADM_WLAN_SECMODE_NONE; 4563871Syz147064 4578453SAnurag.Maskey@Sun.COM if ((status = do_set_encryption(handle, linkid, &secmode)) != 4588453SAnurag.Maskey@Sun.COM DLADM_STATUS_OK) 4593871Syz147064 goto fail; 4603871Syz147064 4613871Syz147064 authmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) ? 4623871Syz147064 attrp->wa_auth : DLADM_WLAN_AUTH_OPEN; 4633871Syz147064 4648453SAnurag.Maskey@Sun.COM if ((status = do_set_authmode(handle, linkid, &authmode)) != 4658453SAnurag.Maskey@Sun.COM DLADM_STATUS_OK) 4663871Syz147064 goto fail; 4673871Syz147064 4683871Syz147064 bsstype = ((attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0) ? 4693871Syz147064 attrp->wa_bsstype : DLADM_WLAN_BSSTYPE_BSS; 4703871Syz147064 4718453SAnurag.Maskey@Sun.COM if ((status = do_set_bsstype(handle, linkid, &bsstype)) != 4728453SAnurag.Maskey@Sun.COM DLADM_STATUS_OK) 4733871Syz147064 goto fail; 4743871Syz147064 4753871Syz147064 if (secmode == DLADM_WLAN_SECMODE_WEP) { 4765895Syz147064 if (keys == NULL || key_count == 0 || 4775895Syz147064 key_count > MAX_NWEPKEYS) { 4785895Syz147064 status = DLADM_STATUS_BADARG; 4795895Syz147064 goto fail; 4805895Syz147064 } 4818453SAnurag.Maskey@Sun.COM status = do_set_key(handle, linkid, keys, key_count); 4825895Syz147064 if (status != DLADM_STATUS_OK) 4833871Syz147064 goto fail; 4844126Szf162725 } else if (secmode == DLADM_WLAN_SECMODE_WPA) { 4855895Syz147064 if (keys == NULL || key_count == 0 || 4865895Syz147064 key_count > MAX_NWEPKEYS) { 4875895Syz147064 status = DLADM_STATUS_BADARG; 4885895Syz147064 goto fail; 4895895Syz147064 } 4908453SAnurag.Maskey@Sun.COM status = do_get_capability(handle, linkid, buf, bufsize); 4915895Syz147064 if (status != DLADM_STATUS_OK) 4924126Szf162725 goto fail; 4937663SSowmini.Varadhan@Sun.COM caps = (wl_capability_t *)buf; 4944126Szf162725 if ((caps->caps & IEEE80211_C_WPA) == 0) 4954126Szf162725 return (DLADM_STATUS_NOTSUP); 4963871Syz147064 } 4973871Syz147064 4983871Syz147064 if (create_ibss) { 4998453SAnurag.Maskey@Sun.COM status = do_set_channel(handle, linkid, &channel); 5005895Syz147064 if (status != DLADM_STATUS_OK) 5013871Syz147064 goto fail; 5023871Syz147064 5038453SAnurag.Maskey@Sun.COM status = do_set_createibss(handle, linkid, &create_ibss); 5045895Syz147064 if (status != DLADM_STATUS_OK) 5053871Syz147064 goto fail; 5063871Syz147064 5073871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0) { 5083871Syz147064 generate_essid(&essid); 5093871Syz147064 essid_valid = B_TRUE; 5103871Syz147064 } 5113871Syz147064 } 5123871Syz147064 5133871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0) { 5143871Syz147064 essid = attrp->wa_essid; 5153871Syz147064 essid_valid = B_TRUE; 5163871Syz147064 } 5173871Syz147064 5185895Syz147064 if (!essid_valid) { 5195895Syz147064 status = DLADM_STATUS_FAILED; 5205895Syz147064 goto fail; 5215895Syz147064 } 5225895Syz147064 5238453SAnurag.Maskey@Sun.COM if ((status = do_set_essid(handle, linkid, &essid)) != DLADM_STATUS_OK) 5243871Syz147064 goto fail; 5253871Syz147064 5264126Szf162725 /* 5274126Szf162725 * Because wpa daemon needs getting essid from driver, 5284126Szf162725 * we need call do_set_essid() first, then call wpa_instance_create(). 5294126Szf162725 */ 5304126Szf162725 if (secmode == DLADM_WLAN_SECMODE_WPA && keys != NULL) 5318453SAnurag.Maskey@Sun.COM (void) wpa_instance_create(handle, linkid, keys); 5324126Szf162725 5333871Syz147064 start = gethrtime(); 5343871Syz147064 for (;;) { 5358453SAnurag.Maskey@Sun.COM status = do_get_linkstatus(handle, linkid, &wl_status, 5367663SSowmini.Varadhan@Sun.COM sizeof (wl_status)); 5375895Syz147064 if (status != DLADM_STATUS_OK) 5383871Syz147064 goto fail; 5393871Syz147064 5407663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) 5413871Syz147064 break; 5423871Syz147064 5433871Syz147064 (void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE); 5443871Syz147064 if ((timeout >= 0) && (gethrtime() - start) / 5455895Syz147064 NANOSEC >= timeout) { 5465895Syz147064 status = DLADM_STATUS_TIMEDOUT; 5475895Syz147064 goto fail; 5485895Syz147064 } 5493871Syz147064 } 5505895Syz147064 status = DLADM_STATUS_OK; 5513871Syz147064 fail: 5525895Syz147064 return (status); 5533871Syz147064 } 5543871Syz147064 5553871Syz147064 dladm_status_t 5568453SAnurag.Maskey@Sun.COM dladm_wlan_connect(dladm_handle_t handle, datalink_id_t linkid, 5578453SAnurag.Maskey@Sun.COM dladm_wlan_attr_t *attrp, int timeout, void *keys, uint_t key_count, 5588453SAnurag.Maskey@Sun.COM uint_t flags) 5593871Syz147064 { 5605895Syz147064 int i; 5617663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 5623871Syz147064 connect_state_t state = {0, NULL, NULL}; 5633871Syz147064 attr_node_t *nodep = NULL; 5643871Syz147064 boolean_t create_ibss, set_authmode; 5653871Syz147064 dladm_wlan_attr_t **wl_list = NULL; 5665895Syz147064 dladm_status_t status; 5677663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 5683871Syz147064 5698453SAnurag.Maskey@Sun.COM if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 5706233Syz147064 return (status); 5713871Syz147064 5728453SAnurag.Maskey@Sun.COM if ((status = do_get_linkstatus(handle, linkid, &wl_status, 5738453SAnurag.Maskey@Sun.COM sizeof (wl_status))) != DLADM_STATUS_OK) 5743871Syz147064 goto done; 5753871Syz147064 5767663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) { 5773871Syz147064 status = DLADM_STATUS_ISCONN; 5783871Syz147064 goto done; 5793871Syz147064 } 5803871Syz147064 5813871Syz147064 set_authmode = ((attrp != NULL) && 5823871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0); 5833871Syz147064 create_ibss = ((flags & DLADM_WLAN_CONNECT_CREATEIBSS) != 0 && 5843871Syz147064 attrp != NULL && 5853871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 5863871Syz147064 attrp->wa_bsstype == DLADM_WLAN_BSSTYPE_IBSS); 5873871Syz147064 5883871Syz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 || 5893871Syz147064 (create_ibss && attrp != NULL && 5903871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) { 5918453SAnurag.Maskey@Sun.COM status = do_connect(handle, linkid, buf, sizeof (buf), attrp, 5927663SSowmini.Varadhan@Sun.COM create_ibss, keys, key_count, timeout); 5933871Syz147064 goto done; 5943871Syz147064 } 5953871Syz147064 5963871Syz147064 state.cs_attr = attrp; 5973871Syz147064 state.cs_list = NULL; 5983871Syz147064 state.cs_count = 0; 5993871Syz147064 6008453SAnurag.Maskey@Sun.COM status = dladm_wlan_scan(handle, linkid, &state, connect_cb); 6013871Syz147064 if (status != DLADM_STATUS_OK) 6023871Syz147064 goto done; 6033871Syz147064 6043871Syz147064 if (state.cs_count == 0) { 6053871Syz147064 if (!create_ibss) { 6063871Syz147064 status = DLADM_STATUS_NOTFOUND; 6073871Syz147064 goto done; 6083871Syz147064 } 6098453SAnurag.Maskey@Sun.COM status = do_connect(handle, linkid, buf, sizeof (buf), 6107663SSowmini.Varadhan@Sun.COM attrp, create_ibss, keys, key_count, timeout); 6113871Syz147064 goto done; 6123871Syz147064 } 6133871Syz147064 6143871Syz147064 wl_list = malloc(state.cs_count * sizeof (dladm_wlan_attr_t *)); 6153871Syz147064 if (wl_list == NULL) { 6163871Syz147064 status = DLADM_STATUS_NOMEM; 6173871Syz147064 goto done; 6183871Syz147064 } 6193871Syz147064 6203871Syz147064 nodep = state.cs_list; 6213871Syz147064 for (i = 0; i < state.cs_count; i++) { 6223871Syz147064 wl_list[i] = &nodep->an_attr; 6233871Syz147064 nodep = nodep->an_next; 6243871Syz147064 } 6253871Syz147064 qsort(wl_list, state.cs_count, sizeof (dladm_wlan_attr_t *), 6263871Syz147064 attr_compare); 6273871Syz147064 6283871Syz147064 for (i = 0; i < state.cs_count; i++) { 6293871Syz147064 dladm_wlan_attr_t *ap = wl_list[i]; 6303871Syz147064 6318453SAnurag.Maskey@Sun.COM status = do_connect(handle, linkid, buf, sizeof (buf), 6327663SSowmini.Varadhan@Sun.COM ap, create_ibss, keys, key_count, timeout); 6333871Syz147064 if (status == DLADM_STATUS_OK) 6343871Syz147064 break; 6353871Syz147064 6363871Syz147064 if (!set_authmode) { 6373871Syz147064 ap->wa_auth = DLADM_WLAN_AUTH_SHARED; 6383871Syz147064 ap->wa_valid |= DLADM_WLAN_ATTR_AUTH; 6398453SAnurag.Maskey@Sun.COM status = do_connect(handle, linkid, buf, sizeof (buf), 6407663SSowmini.Varadhan@Sun.COM ap, create_ibss, keys, key_count, timeout); 6413871Syz147064 if (status == DLADM_STATUS_OK) 6423871Syz147064 break; 6433871Syz147064 } 6443871Syz147064 } 6453871Syz147064 done: 6463871Syz147064 if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN)) 6478453SAnurag.Maskey@Sun.COM (void) do_disconnect(handle, linkid, buf, sizeof (buf)); 6483871Syz147064 6493871Syz147064 while (state.cs_list != NULL) { 6503871Syz147064 nodep = state.cs_list; 6513871Syz147064 state.cs_list = nodep->an_next; 6523871Syz147064 free(nodep); 6533871Syz147064 } 6543871Syz147064 free(wl_list); 6553871Syz147064 return (status); 6563871Syz147064 } 6573871Syz147064 6583871Syz147064 dladm_status_t 6598453SAnurag.Maskey@Sun.COM dladm_wlan_disconnect(dladm_handle_t handle, datalink_id_t linkid) 6603871Syz147064 { 6617663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 6623871Syz147064 dladm_status_t status; 6637663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 6643871Syz147064 6658453SAnurag.Maskey@Sun.COM if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 6665895Syz147064 return (status); 6673871Syz147064 6688453SAnurag.Maskey@Sun.COM if ((status = do_get_linkstatus(handle, linkid, &wl_status, 6698453SAnurag.Maskey@Sun.COM sizeof (wl_status))) != DLADM_STATUS_OK) 6703871Syz147064 goto done; 6713871Syz147064 6727663SSowmini.Varadhan@Sun.COM if (wl_status != WL_CONNECTED) { 6733871Syz147064 status = DLADM_STATUS_NOTCONN; 6743871Syz147064 goto done; 6753871Syz147064 } 6763871Syz147064 6778453SAnurag.Maskey@Sun.COM if ((status = do_disconnect(handle, linkid, buf, sizeof (buf))) 6787663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 6793871Syz147064 goto done; 6803871Syz147064 6818453SAnurag.Maskey@Sun.COM if ((status = do_get_linkstatus(handle, linkid, &wl_status, 6828453SAnurag.Maskey@Sun.COM sizeof (wl_status))) != DLADM_STATUS_OK) 6833871Syz147064 goto done; 6843871Syz147064 6857663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) { 6863871Syz147064 status = DLADM_STATUS_FAILED; 6873871Syz147064 goto done; 6883871Syz147064 } 6893871Syz147064 6903871Syz147064 status = DLADM_STATUS_OK; 6913871Syz147064 done: 6923871Syz147064 return (status); 6933871Syz147064 } 6943871Syz147064 6955895Syz147064 dladm_status_t 6968453SAnurag.Maskey@Sun.COM dladm_wlan_get_linkattr(dladm_handle_t handle, datalink_id_t linkid, 6978453SAnurag.Maskey@Sun.COM dladm_wlan_linkattr_t *attrp) 6983871Syz147064 { 6993871Syz147064 wl_rssi_t signal; 7003871Syz147064 wl_bss_type_t bsstype; 7013871Syz147064 wl_authmode_t authmode; 7023871Syz147064 wl_encryption_t encryption; 7037663SSowmini.Varadhan@Sun.COM wl_rates_t *ratesp = NULL; 7043871Syz147064 dladm_wlan_attr_t *wl_attrp; 7055895Syz147064 dladm_status_t status; 7067663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 7077663SSowmini.Varadhan@Sun.COM wl_essid_t wls; 7087663SSowmini.Varadhan@Sun.COM wl_phy_conf_t wl_phy_conf; 7097663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 7103871Syz147064 7113871Syz147064 if (attrp == NULL) 7123871Syz147064 return (DLADM_STATUS_BADARG); 7133871Syz147064 7148453SAnurag.Maskey@Sun.COM if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK) 7155895Syz147064 goto done; 7163871Syz147064 7173871Syz147064 (void) memset(attrp, 0, sizeof (*attrp)); 7183871Syz147064 wl_attrp = &attrp->la_wlan_attr; 7193871Syz147064 7208453SAnurag.Maskey@Sun.COM if ((status = do_get_linkstatus(handle, linkid, &wl_status, 7218453SAnurag.Maskey@Sun.COM sizeof (wl_status))) != DLADM_STATUS_OK) 7223871Syz147064 goto done; 7233871Syz147064 7243871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS; 7257663SSowmini.Varadhan@Sun.COM if (wl_status != WL_CONNECTED) 7265895Syz147064 attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED; 7275895Syz147064 else 7285895Syz147064 attrp->la_status = DLADM_WLAN_LINK_CONNECTED; 7293871Syz147064 7308453SAnurag.Maskey@Sun.COM if ((status = do_get_essid(handle, linkid, &wls, sizeof (wls))) 7317663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7323871Syz147064 goto done; 7333871Syz147064 7347663SSowmini.Varadhan@Sun.COM (void) strlcpy(wl_attrp->wa_essid.we_bytes, wls.wl_essid_essid, 7353871Syz147064 DLADM_WLAN_MAX_ESSID_LEN); 7363871Syz147064 7373871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 7383871Syz147064 7398453SAnurag.Maskey@Sun.COM if ((status = do_get_bssid(handle, linkid, buf, sizeof (buf))) 7407663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7413871Syz147064 goto done; 7423871Syz147064 7437663SSowmini.Varadhan@Sun.COM (void) memcpy(wl_attrp->wa_bssid.wb_bytes, buf, DLADM_WLAN_BSSID_LEN); 7443871Syz147064 7453871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 7463871Syz147064 7475895Syz147064 if (attrp->la_status == DLADM_WLAN_LINK_DISCONNECTED) { 7484126Szf162725 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 7494126Szf162725 status = DLADM_STATUS_OK; 7504126Szf162725 goto done; 7514126Szf162725 } 7524126Szf162725 7538453SAnurag.Maskey@Sun.COM if ((status = do_get_encryption(handle, linkid, &encryption, 7547663SSowmini.Varadhan@Sun.COM sizeof (encryption))) != DLADM_STATUS_OK) 7553871Syz147064 goto done; 7563871Syz147064 7573871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 7583871Syz147064 7593871Syz147064 switch (encryption) { 7603871Syz147064 case WL_NOENCRYPTION: 7613871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_NONE; 7623871Syz147064 break; 7633871Syz147064 case WL_ENC_WEP: 7643871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP; 7653871Syz147064 break; 7664126Szf162725 case WL_ENC_WPA: 7674126Szf162725 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 7684126Szf162725 break; 7693871Syz147064 default: 7703871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE; 7713871Syz147064 break; 7723871Syz147064 } 7733871Syz147064 7748453SAnurag.Maskey@Sun.COM if ((status = do_get_signal(handle, linkid, &signal, sizeof (signal))) 7757663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7763871Syz147064 goto done; 7773871Syz147064 7783871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 7793871Syz147064 wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal); 7803871Syz147064 7817663SSowmini.Varadhan@Sun.COM ratesp = malloc(WLDP_BUFSIZE); 7827663SSowmini.Varadhan@Sun.COM if (ratesp == NULL) { 7837663SSowmini.Varadhan@Sun.COM status = DLADM_STATUS_NOMEM; 7847663SSowmini.Varadhan@Sun.COM goto done; 7857663SSowmini.Varadhan@Sun.COM } 7867663SSowmini.Varadhan@Sun.COM 7878453SAnurag.Maskey@Sun.COM if ((status = do_get_rate(handle, linkid, ratesp, WLDP_BUFSIZE)) 7887663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7893871Syz147064 goto done; 7903871Syz147064 7913871Syz147064 if (ratesp->wl_rates_num > 0) { 7923871Syz147064 uint_t i, r = 0; 7933871Syz147064 7943871Syz147064 for (i = 0; i < ratesp->wl_rates_num; i++) { 7953871Syz147064 if (ratesp->wl_rates_rates[i] > r) 7963871Syz147064 r = ratesp->wl_rates_rates[i]; 7973871Syz147064 } 7983871Syz147064 wl_attrp->wa_speed = r; 7993871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 8003871Syz147064 } 8013871Syz147064 8028453SAnurag.Maskey@Sun.COM if ((status = do_get_authmode(handle, linkid, &authmode, 8037663SSowmini.Varadhan@Sun.COM sizeof (authmode))) != DLADM_STATUS_OK) 8043871Syz147064 goto done; 8053871Syz147064 8063871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 8073871Syz147064 8083871Syz147064 switch (authmode) { 8093871Syz147064 case WL_OPENSYSTEM: 8103871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN; 8113871Syz147064 break; 8123871Syz147064 case WL_SHAREDKEY: 8133871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED; 8143871Syz147064 break; 8153871Syz147064 default: 8163871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH; 8173871Syz147064 break; 8183871Syz147064 } 8193871Syz147064 8208453SAnurag.Maskey@Sun.COM if ((status = do_get_bsstype(handle, linkid, &bsstype, 8217663SSowmini.Varadhan@Sun.COM sizeof (bsstype))) != DLADM_STATUS_OK) 8223871Syz147064 goto done; 8233871Syz147064 8243871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 8253871Syz147064 8263871Syz147064 switch (bsstype) { 8273871Syz147064 case WL_BSS_BSS: 8283871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS; 8293871Syz147064 break; 8303871Syz147064 case WL_BSS_IBSS: 8313871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS; 8323871Syz147064 break; 8333871Syz147064 case WL_BSS_ANY: 8343871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY; 8353871Syz147064 break; 8363871Syz147064 default: 8373871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE; 8383871Syz147064 break; 8393871Syz147064 } 8403871Syz147064 8418453SAnurag.Maskey@Sun.COM if ((status = do_get_mode(handle, linkid, &wl_phy_conf, 8427663SSowmini.Varadhan@Sun.COM sizeof (wl_phy_conf))) != DLADM_STATUS_OK) 8433871Syz147064 goto done; 8443871Syz147064 8457663SSowmini.Varadhan@Sun.COM wl_attrp->wa_mode = do_convert_mode(&wl_phy_conf); 8463871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8473871Syz147064 if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE) 8483871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8493871Syz147064 8503871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 8513871Syz147064 status = DLADM_STATUS_OK; 8523871Syz147064 8533871Syz147064 done: 8547663SSowmini.Varadhan@Sun.COM free(ratesp); 8553871Syz147064 return (status); 8563871Syz147064 } 8573871Syz147064 8587408SSebastien.Roy@Sun.COM /* 8597408SSebastien.Roy@Sun.COM * Check to see if the link is wireless. 8607408SSebastien.Roy@Sun.COM */ 8613871Syz147064 static dladm_status_t 8628453SAnurag.Maskey@Sun.COM dladm_wlan_validate(dladm_handle_t handle, datalink_id_t linkid) 8633871Syz147064 { 8647408SSebastien.Roy@Sun.COM uint32_t media; 8653871Syz147064 dladm_status_t status; 8663871Syz147064 8678453SAnurag.Maskey@Sun.COM status = dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, 8688453SAnurag.Maskey@Sun.COM NULL, 0); 8697408SSebastien.Roy@Sun.COM if (status == DLADM_STATUS_OK) { 8707408SSebastien.Roy@Sun.COM if (media != DL_WIFI) 8717408SSebastien.Roy@Sun.COM status = DLADM_STATUS_LINKINVAL; 8723871Syz147064 } 8733871Syz147064 return (status); 8743871Syz147064 } 8753871Syz147064 8763871Syz147064 static boolean_t 8773871Syz147064 find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp) 8783871Syz147064 { 8793871Syz147064 int i; 8803871Syz147064 8813871Syz147064 for (i = 0; i < cnt; i++) { 8823871Syz147064 if (strcasecmp(str, vdp[i].vd_name) == 0) { 8833871Syz147064 *valp = vdp[i].vd_val; 8843871Syz147064 return (B_TRUE); 8853871Syz147064 } 8863871Syz147064 } 8873871Syz147064 return (B_FALSE); 8883871Syz147064 } 8893871Syz147064 8903871Syz147064 static boolean_t 8913871Syz147064 find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp) 8923871Syz147064 { 8933871Syz147064 int i; 8943871Syz147064 8953871Syz147064 for (i = 0; i < cnt; i++) { 8963871Syz147064 if (val == vdp[i].vd_val) { 8973871Syz147064 *strp = vdp[i].vd_name; 8983871Syz147064 return (B_TRUE); 8993871Syz147064 } 9003871Syz147064 } 9013871Syz147064 return (B_FALSE); 9023871Syz147064 } 9033871Syz147064 9043871Syz147064 const char * 9053871Syz147064 dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf) 9063871Syz147064 { 9073871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes); 9083871Syz147064 return (buf); 9093871Syz147064 } 9103871Syz147064 9113871Syz147064 const char * 9123871Syz147064 dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf) 9133871Syz147064 { 9143871Syz147064 return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN, 9153871Syz147064 IFT_OTHER)); 9163871Syz147064 } 9173871Syz147064 9183871Syz147064 static const char * 9193871Syz147064 dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf) 9203871Syz147064 { 9213871Syz147064 char *s; 9223871Syz147064 9233871Syz147064 if (!find_name_by_val(val, vdp, cnt, &s)) 9243871Syz147064 s = ""; 9253871Syz147064 9263871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 9273871Syz147064 return (buf); 9283871Syz147064 } 9293871Syz147064 9303871Syz147064 const char * 9313871Syz147064 dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf) 9323871Syz147064 { 9333871Syz147064 return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals, 9343871Syz147064 VALCNT(secmode_vals), buf)); 9353871Syz147064 } 9363871Syz147064 9373871Syz147064 const char * 9383871Syz147064 dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf) 9393871Syz147064 { 9403871Syz147064 return (dladm_wlan_val2str((uint_t)*strength, strength_vals, 9413871Syz147064 VALCNT(strength_vals), buf)); 9423871Syz147064 } 9433871Syz147064 9443871Syz147064 const char * 9453871Syz147064 dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf) 9463871Syz147064 { 9473871Syz147064 return (dladm_wlan_val2str((uint_t)*mode, mode_vals, 9483871Syz147064 VALCNT(mode_vals), buf)); 9493871Syz147064 } 9503871Syz147064 9513871Syz147064 const char * 9523871Syz147064 dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf) 9533871Syz147064 { 9543871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2, 9553871Syz147064 (float)(*speed) / 2); 9563871Syz147064 return (buf); 9573871Syz147064 } 9583871Syz147064 9593871Syz147064 const char * 9603871Syz147064 dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf) 9613871Syz147064 { 9623871Syz147064 return (dladm_wlan_val2str((uint_t)*auth, auth_vals, 9633871Syz147064 VALCNT(auth_vals), buf)); 9643871Syz147064 } 9653871Syz147064 9663871Syz147064 const char * 9673871Syz147064 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf) 9683871Syz147064 { 9693871Syz147064 return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals, 9703871Syz147064 VALCNT(bsstype_vals), buf)); 9713871Syz147064 } 9723871Syz147064 9733871Syz147064 const char * 9743871Syz147064 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf) 9753871Syz147064 { 9763871Syz147064 return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals, 9773871Syz147064 VALCNT(linkstatus_vals), buf)); 9783871Syz147064 } 9793871Syz147064 9803871Syz147064 dladm_status_t 9813871Syz147064 dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid) 9823871Syz147064 { 9836834Sff224033 if (str[0] == '\0' || strlen(str) > DLADM_WLAN_MAX_ESSID_LEN - 1) 9843871Syz147064 return (DLADM_STATUS_BADARG); 9853871Syz147064 9863871Syz147064 (void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN); 9873871Syz147064 return (DLADM_STATUS_OK); 9883871Syz147064 } 9893871Syz147064 9903871Syz147064 dladm_status_t 9913871Syz147064 dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid) 9923871Syz147064 { 9933871Syz147064 int len; 9943871Syz147064 uchar_t *buf; 9953871Syz147064 9963871Syz147064 buf = _link_aton(str, &len); 9973871Syz147064 if (buf == NULL) 9983871Syz147064 return (DLADM_STATUS_BADARG); 9993871Syz147064 10003871Syz147064 if (len != DLADM_WLAN_BSSID_LEN) { 10013871Syz147064 free(buf); 10023871Syz147064 return (DLADM_STATUS_BADARG); 10033871Syz147064 } 10043871Syz147064 10053871Syz147064 (void) memcpy(bssid->wb_bytes, buf, len); 10063871Syz147064 free(buf); 10073871Syz147064 return (DLADM_STATUS_OK); 10083871Syz147064 } 10093871Syz147064 10103871Syz147064 dladm_status_t 10113871Syz147064 dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode) 10123871Syz147064 { 10133871Syz147064 uint_t val; 10143871Syz147064 10153871Syz147064 if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val)) 10163871Syz147064 return (DLADM_STATUS_BADARG); 10173871Syz147064 10183871Syz147064 *secmode = (dladm_wlan_secmode_t)val; 10193871Syz147064 return (DLADM_STATUS_OK); 10203871Syz147064 } 10213871Syz147064 10223871Syz147064 dladm_status_t 10233871Syz147064 dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength) 10243871Syz147064 { 10253871Syz147064 uint_t val; 10263871Syz147064 10273871Syz147064 if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val)) 10283871Syz147064 return (DLADM_STATUS_BADARG); 10293871Syz147064 10303871Syz147064 *strength = (dladm_wlan_strength_t)val; 10313871Syz147064 return (DLADM_STATUS_OK); 10323871Syz147064 } 10333871Syz147064 10343871Syz147064 dladm_status_t 10353871Syz147064 dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode) 10363871Syz147064 { 10373871Syz147064 uint_t val; 10383871Syz147064 10393871Syz147064 if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val)) 10403871Syz147064 return (DLADM_STATUS_BADARG); 10413871Syz147064 10423871Syz147064 *mode = (dladm_wlan_mode_t)val; 10433871Syz147064 return (DLADM_STATUS_OK); 10443871Syz147064 } 10453871Syz147064 10463871Syz147064 dladm_status_t 10473871Syz147064 dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed) 10483871Syz147064 { 10493871Syz147064 *speed = (dladm_wlan_speed_t)(atof(str) * 2); 10503871Syz147064 return (DLADM_STATUS_OK); 10513871Syz147064 } 10523871Syz147064 10533871Syz147064 dladm_status_t 10543871Syz147064 dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth) 10553871Syz147064 { 10563871Syz147064 uint_t val; 10573871Syz147064 10583871Syz147064 if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val)) 10593871Syz147064 return (DLADM_STATUS_BADARG); 10603871Syz147064 10613871Syz147064 *auth = (dladm_wlan_auth_t)val; 10623871Syz147064 return (DLADM_STATUS_OK); 10633871Syz147064 } 10643871Syz147064 10653871Syz147064 dladm_status_t 10663871Syz147064 dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype) 10673871Syz147064 { 10683871Syz147064 uint_t val; 10693871Syz147064 10703871Syz147064 if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val)) 10713871Syz147064 return (DLADM_STATUS_BADARG); 10723871Syz147064 10733871Syz147064 *bsstype = (dladm_wlan_bsstype_t)val; 10743871Syz147064 return (DLADM_STATUS_OK); 10753871Syz147064 } 10763871Syz147064 10773871Syz147064 dladm_status_t 10783871Syz147064 dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus) 10793871Syz147064 { 10803871Syz147064 uint_t val; 10813871Syz147064 10825895Syz147064 if (!find_val_by_name(str, linkstatus_vals, 10835895Syz147064 VALCNT(linkstatus_vals), &val)) { 10843871Syz147064 return (DLADM_STATUS_BADARG); 10855895Syz147064 } 10863871Syz147064 10873871Syz147064 *linkstatus = (dladm_wlan_linkstatus_t)val; 10883871Syz147064 return (DLADM_STATUS_OK); 10893871Syz147064 } 10903871Syz147064 10915895Syz147064 dladm_status_t 10928453SAnurag.Maskey@Sun.COM i_dladm_wlan_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid, 10938453SAnurag.Maskey@Sun.COM wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen) 10943871Syz147064 { 10955895Syz147064 char linkname[MAXPATHLEN]; 10965895Syz147064 int fd, rc; 10973871Syz147064 struct strioctl stri; 10985895Syz147064 uint32_t flags; 10995895Syz147064 dladm_status_t status; 11005895Syz147064 uint32_t media; 11015895Syz147064 char link[MAXLINKNAMELEN]; 11025895Syz147064 11038453SAnurag.Maskey@Sun.COM if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 11048453SAnurag.Maskey@Sun.COM &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 11055895Syz147064 return (status); 11065895Syz147064 } 11075895Syz147064 11085895Syz147064 if (media != DL_WIFI) 11095895Syz147064 return (DLADM_STATUS_BADARG); 11105895Syz147064 11115895Syz147064 if (!(flags & DLADM_OPT_ACTIVE)) 11125895Syz147064 return (DLADM_STATUS_TEMPONLY); 11135895Syz147064 11145895Syz147064 /* 11155895Syz147064 * dlpi_open() is not used here because libdlpi depends on libdladm, 11165895Syz147064 * and we do not want to introduce recursive dependencies. 11175895Syz147064 */ 11185895Syz147064 (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link); 11195895Syz147064 if ((fd = open(linkname, O_RDWR)) < 0) 11207408SSebastien.Roy@Sun.COM return (dladm_errno2status(errno)); 11213871Syz147064 11223871Syz147064 gbuf->wldp_type = NET_802_11; 11233871Syz147064 gbuf->wldp_id = id; 11243871Syz147064 gbuf->wldp_length = len; 11253871Syz147064 11263871Syz147064 stri.ic_timout = 0; 11273871Syz147064 stri.ic_dp = (char *)gbuf; 11283871Syz147064 stri.ic_cmd = cmd; 11293871Syz147064 stri.ic_len = cmdlen; 11303871Syz147064 11313871Syz147064 if ((rc = ioctl(fd, I_STR, &stri)) != 0) { 11325895Syz147064 if (rc > 0) { 11335895Syz147064 /* 11345895Syz147064 * Non-negative return value indicates the specific 11355895Syz147064 * operation failed and the reason for the failure 11365895Syz147064 * was stored in gbuf->wldp_result. 11375895Syz147064 */ 11385895Syz147064 status = dladm_wlan_wlresult2status(gbuf); 11395895Syz147064 } else { 11405895Syz147064 /* 11415895Syz147064 * Negative return value indicates the ioctl failed. 11425895Syz147064 */ 11435895Syz147064 status = dladm_errno2status(errno); 11445895Syz147064 } 11453871Syz147064 } 11465895Syz147064 (void) close(fd); 11475895Syz147064 return (status); 11483871Syz147064 } 11493871Syz147064 11507663SSowmini.Varadhan@Sun.COM static dladm_status_t 11518453SAnurag.Maskey@Sun.COM do_cmd_ioctl(dladm_handle_t handle, datalink_id_t linkid, void *buf, 11528453SAnurag.Maskey@Sun.COM int buflen, uint_t cmd) 11533871Syz147064 { 11545895Syz147064 wldp_t *gbuf; 11555895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 11565895Syz147064 11575895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 11585895Syz147064 return (DLADM_STATUS_NOMEM); 11595895Syz147064 11603871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 11618453SAnurag.Maskey@Sun.COM status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, cmd, 11628453SAnurag.Maskey@Sun.COM WLDP_BUFSIZE, WLAN_COMMAND, sizeof (wldp_t)); 11637663SSowmini.Varadhan@Sun.COM (void) memcpy(buf, gbuf->wldp_buf, buflen); 11645895Syz147064 free(gbuf); 11655895Syz147064 return (status); 11663871Syz147064 } 11673871Syz147064 11685895Syz147064 static dladm_status_t 11698453SAnurag.Maskey@Sun.COM do_scan(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 11703871Syz147064 { 11718453SAnurag.Maskey@Sun.COM return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_SCAN)); 11723871Syz147064 } 11733871Syz147064 11745895Syz147064 static dladm_status_t 11758453SAnurag.Maskey@Sun.COM do_disconnect(dladm_handle_t handle, datalink_id_t linkid, void *buf, 11768453SAnurag.Maskey@Sun.COM int buflen) 11773871Syz147064 { 11788453SAnurag.Maskey@Sun.COM if (do_get_wpamode(handle, linkid, buf, buflen) == 0 && 11797663SSowmini.Varadhan@Sun.COM ((wl_wpa_t *)(buf))->wpa_flag > 0) 11808453SAnurag.Maskey@Sun.COM (void) wpa_instance_delete(handle, linkid); 11817663SSowmini.Varadhan@Sun.COM 11828453SAnurag.Maskey@Sun.COM return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_DISASSOCIATE)); 11833871Syz147064 } 11843871Syz147064 11855895Syz147064 static dladm_status_t 11868453SAnurag.Maskey@Sun.COM do_get_esslist(dladm_handle_t handle, datalink_id_t linkid, void *buf, 11878453SAnurag.Maskey@Sun.COM int buflen) 11883871Syz147064 { 11898453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESS_LIST, 11908453SAnurag.Maskey@Sun.COM buflen, B_FALSE)); 11913871Syz147064 } 11923871Syz147064 11935895Syz147064 static dladm_status_t 11948453SAnurag.Maskey@Sun.COM do_get_bssid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 11953871Syz147064 { 11968453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_BSSID, 11978453SAnurag.Maskey@Sun.COM buflen, B_FALSE)); 11983871Syz147064 } 11993871Syz147064 12005895Syz147064 static dladm_status_t 12018453SAnurag.Maskey@Sun.COM do_get_essid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 12023871Syz147064 { 12038453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESSID, 12048453SAnurag.Maskey@Sun.COM buflen, B_FALSE)); 12053871Syz147064 } 12063871Syz147064 12075895Syz147064 static dladm_status_t 12088453SAnurag.Maskey@Sun.COM do_get_bsstype(dladm_handle_t handle, datalink_id_t linkid, void *buf, 12098453SAnurag.Maskey@Sun.COM int buflen) 12103871Syz147064 { 12118453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_BSSTYPE, 12127663SSowmini.Varadhan@Sun.COM buflen, B_FALSE)); 12133871Syz147064 } 12143871Syz147064 12153871Syz147064 static dladm_status_t 12168453SAnurag.Maskey@Sun.COM do_get_linkstatus(dladm_handle_t handle, datalink_id_t linkid, void *buf, 12178453SAnurag.Maskey@Sun.COM int buflen) 12183871Syz147064 { 12198453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_LINKSTATUS, 12207663SSowmini.Varadhan@Sun.COM buflen, B_FALSE)); 12213871Syz147064 } 12223871Syz147064 12235895Syz147064 static dladm_status_t 12248453SAnurag.Maskey@Sun.COM do_get_rate(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 12258453SAnurag.Maskey@Sun.COM { 12268453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, 12278453SAnurag.Maskey@Sun.COM MAC_PROP_WL_DESIRED_RATES, buflen, B_FALSE)); 12288453SAnurag.Maskey@Sun.COM } 12298453SAnurag.Maskey@Sun.COM 12308453SAnurag.Maskey@Sun.COM static dladm_status_t 12318453SAnurag.Maskey@Sun.COM do_get_authmode(dladm_handle_t handle, datalink_id_t linkid, void *buf, 12328453SAnurag.Maskey@Sun.COM int buflen) 12338453SAnurag.Maskey@Sun.COM { 12348453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, 12358453SAnurag.Maskey@Sun.COM MAC_PROP_WL_AUTH_MODE, buflen, B_FALSE)); 12368453SAnurag.Maskey@Sun.COM } 12378453SAnurag.Maskey@Sun.COM 12388453SAnurag.Maskey@Sun.COM static dladm_status_t 12398453SAnurag.Maskey@Sun.COM do_get_encryption(dladm_handle_t handle, datalink_id_t linkid, void *buf, 12408453SAnurag.Maskey@Sun.COM int buflen) 12418453SAnurag.Maskey@Sun.COM { 12428453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, 12438453SAnurag.Maskey@Sun.COM MAC_PROP_WL_ENCRYPTION, buflen, B_FALSE)); 12448453SAnurag.Maskey@Sun.COM } 12458453SAnurag.Maskey@Sun.COM 12468453SAnurag.Maskey@Sun.COM static dladm_status_t 12478453SAnurag.Maskey@Sun.COM do_get_signal(dladm_handle_t handle, datalink_id_t linkid, void *buf, 12488453SAnurag.Maskey@Sun.COM int buflen) 12498453SAnurag.Maskey@Sun.COM { 12508453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RSSI, 12518453SAnurag.Maskey@Sun.COM buflen, B_FALSE)); 12528453SAnurag.Maskey@Sun.COM } 12538453SAnurag.Maskey@Sun.COM 12548453SAnurag.Maskey@Sun.COM static dladm_status_t 12558453SAnurag.Maskey@Sun.COM do_get_mode(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen) 12568453SAnurag.Maskey@Sun.COM { 12578453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG, 12588453SAnurag.Maskey@Sun.COM buflen, B_FALSE)); 12598453SAnurag.Maskey@Sun.COM } 12608453SAnurag.Maskey@Sun.COM 12618453SAnurag.Maskey@Sun.COM static dladm_status_t 12628453SAnurag.Maskey@Sun.COM do_set_bsstype(dladm_handle_t handle, datalink_id_t linkid, 12638453SAnurag.Maskey@Sun.COM dladm_wlan_bsstype_t *bsstype) 12643871Syz147064 { 12653871Syz147064 wl_bss_type_t ibsstype; 12663871Syz147064 12673871Syz147064 switch (*bsstype) { 12683871Syz147064 case DLADM_WLAN_BSSTYPE_BSS: 12693871Syz147064 ibsstype = WL_BSS_BSS; 12703871Syz147064 break; 12713871Syz147064 case DLADM_WLAN_BSSTYPE_IBSS: 12723871Syz147064 ibsstype = WL_BSS_IBSS; 12733871Syz147064 break; 12743871Syz147064 default: 12753871Syz147064 ibsstype = WL_BSS_ANY; 12763871Syz147064 break; 12773871Syz147064 } 12788453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &ibsstype, 12798453SAnurag.Maskey@Sun.COM MAC_PROP_WL_BSSTYPE, sizeof (ibsstype), B_TRUE)); 12803871Syz147064 } 12813871Syz147064 12825895Syz147064 static dladm_status_t 12838453SAnurag.Maskey@Sun.COM do_set_authmode(dladm_handle_t handle, datalink_id_t linkid, 12848453SAnurag.Maskey@Sun.COM dladm_wlan_auth_t *auth) 12853871Syz147064 { 12863871Syz147064 wl_authmode_t auth_mode; 12873871Syz147064 12883871Syz147064 switch (*auth) { 12893871Syz147064 case DLADM_WLAN_AUTH_OPEN: 12903871Syz147064 auth_mode = WL_OPENSYSTEM; 12913871Syz147064 break; 12923871Syz147064 case DLADM_WLAN_AUTH_SHARED: 12933871Syz147064 auth_mode = WL_SHAREDKEY; 12943871Syz147064 break; 12953871Syz147064 default: 12965895Syz147064 return (DLADM_STATUS_NOTSUP); 12973871Syz147064 } 12988453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &auth_mode, 12998453SAnurag.Maskey@Sun.COM MAC_PROP_WL_AUTH_MODE, sizeof (auth_mode), B_TRUE)); 13003871Syz147064 } 13013871Syz147064 13025895Syz147064 static dladm_status_t 13038453SAnurag.Maskey@Sun.COM do_set_encryption(dladm_handle_t handle, datalink_id_t linkid, 13048453SAnurag.Maskey@Sun.COM dladm_wlan_secmode_t *secmode) 13053871Syz147064 { 13063871Syz147064 wl_encryption_t encryption; 13073871Syz147064 13083871Syz147064 switch (*secmode) { 13093871Syz147064 case DLADM_WLAN_SECMODE_NONE: 13103871Syz147064 encryption = WL_NOENCRYPTION; 13113871Syz147064 break; 13123871Syz147064 case DLADM_WLAN_SECMODE_WEP: 13133871Syz147064 encryption = WL_ENC_WEP; 13143871Syz147064 break; 13154126Szf162725 case DLADM_WLAN_SECMODE_WPA: 13164126Szf162725 return (0); 13173871Syz147064 default: 13185895Syz147064 return (DLADM_STATUS_NOTSUP); 13193871Syz147064 } 13208453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &encryption, 13218453SAnurag.Maskey@Sun.COM MAC_PROP_WL_ENCRYPTION, sizeof (encryption), B_TRUE)); 13223871Syz147064 } 13233871Syz147064 13245895Syz147064 static dladm_status_t 13258453SAnurag.Maskey@Sun.COM do_set_key(dladm_handle_t handle, datalink_id_t linkid, dladm_wlan_key_t *keys, 13263871Syz147064 uint_t key_count) 13273871Syz147064 { 13283871Syz147064 int i; 13293871Syz147064 wl_wep_key_t *wkp; 13303871Syz147064 wl_wep_key_tab_t wepkey_tab; 13314126Szf162725 dladm_wlan_key_t *kp; 13323871Syz147064 13333871Syz147064 if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL) 13345895Syz147064 return (DLADM_STATUS_BADARG); 13353871Syz147064 13363871Syz147064 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab)); 13373871Syz147064 for (i = 0; i < MAX_NWEPKEYS; i++) 13383871Syz147064 wepkey_tab[i].wl_wep_operation = WL_NUL; 13393871Syz147064 13403871Syz147064 for (i = 0; i < key_count; i++) { 13413871Syz147064 kp = &keys[i]; 13423871Syz147064 if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS) 13435895Syz147064 return (DLADM_STATUS_BADARG); 13443871Syz147064 if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN && 13453871Syz147064 kp->wk_len != DLADM_WLAN_WEPKEY128_LEN) 13465895Syz147064 return (DLADM_STATUS_BADARG); 13473871Syz147064 13483871Syz147064 wkp = &wepkey_tab[kp->wk_idx - 1]; 13493871Syz147064 wkp->wl_wep_operation = WL_ADD; 13503871Syz147064 wkp->wl_wep_length = kp->wk_len; 13513871Syz147064 (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len); 13523871Syz147064 } 13533871Syz147064 13548453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &wepkey_tab, 13558453SAnurag.Maskey@Sun.COM MAC_PROP_WL_KEY_TAB, sizeof (wepkey_tab), B_TRUE)); 13563871Syz147064 } 13573871Syz147064 13585895Syz147064 static dladm_status_t 13598453SAnurag.Maskey@Sun.COM do_set_essid(dladm_handle_t handle, datalink_id_t linkid, 13608453SAnurag.Maskey@Sun.COM dladm_wlan_essid_t *essid) 13613871Syz147064 { 13623871Syz147064 wl_essid_t iessid; 13633871Syz147064 13643871Syz147064 (void) memset(&iessid, 0, sizeof (essid)); 13653871Syz147064 13663871Syz147064 if (essid != NULL && essid->we_bytes[0] != '\0') { 13673871Syz147064 iessid.wl_essid_length = strlen(essid->we_bytes); 13683871Syz147064 (void) strlcpy(iessid.wl_essid_essid, essid->we_bytes, 13693871Syz147064 sizeof (iessid.wl_essid_essid)); 13703871Syz147064 } else { 13715895Syz147064 return (DLADM_STATUS_BADARG); 13725102Syz147064 } 13738453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &iessid, MAC_PROP_WL_ESSID, 13747663SSowmini.Varadhan@Sun.COM sizeof (iessid), B_TRUE)); 13753871Syz147064 } 13763871Syz147064 13773871Syz147064 static dladm_status_t 13788453SAnurag.Maskey@Sun.COM do_set_channel(dladm_handle_t handle, datalink_id_t linkid, 13798453SAnurag.Maskey@Sun.COM dladm_wlan_channel_t *channel) 13803871Syz147064 { 13813871Syz147064 wl_phy_conf_t phy_conf; 13823871Syz147064 13833871Syz147064 if (*channel > MAX_CHANNEL_NUM) 13845895Syz147064 return (DLADM_STATUS_BADVAL); 13853871Syz147064 13863871Syz147064 (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); 13873871Syz147064 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel; 13883871Syz147064 13898453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &phy_conf, 13908453SAnurag.Maskey@Sun.COM MAC_PROP_WL_PHY_CONFIG, sizeof (phy_conf), B_TRUE)); 13913871Syz147064 } 13923871Syz147064 13935895Syz147064 static dladm_status_t 13948453SAnurag.Maskey@Sun.COM do_set_createibss(dladm_handle_t handle, datalink_id_t linkid, 13958453SAnurag.Maskey@Sun.COM boolean_t *create_ibss) 13963871Syz147064 { 13973871Syz147064 wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss); 13983871Syz147064 13998453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &cr, MAC_PROP_WL_CREATE_IBSS, 14007663SSowmini.Varadhan@Sun.COM sizeof (cr), B_TRUE)); 14013871Syz147064 } 14023871Syz147064 14033871Syz147064 static void 14043871Syz147064 generate_essid(dladm_wlan_essid_t *essid) 14053871Syz147064 { 14063871Syz147064 srandom(gethrtime()); 14073871Syz147064 (void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d", 14083871Syz147064 random()); 14093871Syz147064 } 14104126Szf162725 14115895Syz147064 static dladm_status_t 14128453SAnurag.Maskey@Sun.COM do_get_capability(dladm_handle_t handle, datalink_id_t linkid, void *buf, 14138453SAnurag.Maskey@Sun.COM int buflen) 14144126Szf162725 { 14158453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_CAPABILITY, 14167663SSowmini.Varadhan@Sun.COM buflen, B_FALSE)); 14174126Szf162725 } 14184126Szf162725 14194126Szf162725 static dladm_status_t 14208453SAnurag.Maskey@Sun.COM do_get_wpamode(dladm_handle_t handle, datalink_id_t linkid, void *buf, 14218453SAnurag.Maskey@Sun.COM int buflen) 14224126Szf162725 { 14238453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_WPA, buflen, 14247663SSowmini.Varadhan@Sun.COM B_FALSE)); 14254126Szf162725 } 14264126Szf162725 14274126Szf162725 dladm_status_t 14288453SAnurag.Maskey@Sun.COM dladm_wlan_wpa_get_sr(dladm_handle_t handle, datalink_id_t linkid, 14298453SAnurag.Maskey@Sun.COM dladm_wlan_ess_t *sr, uint_t escnt, uint_t *estot) 14304126Szf162725 { 14314126Szf162725 int i, n; 14324126Szf162725 wl_wpa_ess_t *es; 14334126Szf162725 dladm_status_t status; 14344126Szf162725 14357663SSowmini.Varadhan@Sun.COM es = malloc(WLDP_BUFSIZE); 14367663SSowmini.Varadhan@Sun.COM if (es == NULL) 14374126Szf162725 return (DLADM_STATUS_NOMEM); 14384126Szf162725 14398453SAnurag.Maskey@Sun.COM status = i_dladm_wlan_param(handle, linkid, es, MAC_PROP_WL_SCANRESULTS, 14407663SSowmini.Varadhan@Sun.COM WLDP_BUFSIZE, B_FALSE); 14414126Szf162725 14424126Szf162725 if (status == DLADM_STATUS_OK) { 14434126Szf162725 n = (es->count > escnt) ? escnt : es->count; 14444126Szf162725 for (i = 0; i < n; i ++) { 14454126Szf162725 (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid, 14464126Szf162725 DLADM_WLAN_BSSID_LEN); 14474126Szf162725 sr[i].we_ssid_len = es->ess[i].ssid_len; 14484126Szf162725 (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid, 14494126Szf162725 es->ess[i].ssid_len); 14504126Szf162725 sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len; 14514126Szf162725 (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie, 14524126Szf162725 es->ess[i].wpa_ie_len); 14534126Szf162725 sr[i].we_freq = es->ess[i].freq; 14544126Szf162725 } 14554126Szf162725 *estot = n; 14564126Szf162725 } 14574126Szf162725 14587663SSowmini.Varadhan@Sun.COM free(es); 14594126Szf162725 return (status); 14604126Szf162725 } 14614126Szf162725 14624126Szf162725 dladm_status_t 14638453SAnurag.Maskey@Sun.COM dladm_wlan_wpa_set_ie(dladm_handle_t handle, datalink_id_t linkid, 14648453SAnurag.Maskey@Sun.COM uint8_t *wpa_ie, uint_t wpa_ie_len) 14654126Szf162725 { 14664126Szf162725 wl_wpa_ie_t *ie; 14674126Szf162725 uint_t len; 14684126Szf162725 dladm_status_t status; 14694126Szf162725 14704126Szf162725 if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN) 14714126Szf162725 return (DLADM_STATUS_BADARG); 14724126Szf162725 len = sizeof (wl_wpa_ie_t) + wpa_ie_len; 14734126Szf162725 ie = malloc(len); 14744126Szf162725 if (ie == NULL) 14754126Szf162725 return (DLADM_STATUS_NOMEM); 14764126Szf162725 14774126Szf162725 (void) memset(ie, 0, len); 14784126Szf162725 ie->wpa_ie_len = wpa_ie_len; 14794126Szf162725 (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len); 14804126Szf162725 14818453SAnurag.Maskey@Sun.COM status = i_dladm_wlan_param(handle, linkid, ie, MAC_PROP_WL_SETOPTIE, 14828453SAnurag.Maskey@Sun.COM len, B_TRUE); 14834126Szf162725 free(ie); 14844126Szf162725 14854126Szf162725 return (status); 14864126Szf162725 } 14874126Szf162725 14884126Szf162725 dladm_status_t 14898453SAnurag.Maskey@Sun.COM dladm_wlan_wpa_set_wpa(dladm_handle_t handle, datalink_id_t linkid, 14908453SAnurag.Maskey@Sun.COM boolean_t flag) 14914126Szf162725 { 14925895Syz147064 wl_wpa_t wpa; 14934126Szf162725 14944126Szf162725 wpa.wpa_flag = flag; 14958453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &wpa, MAC_PROP_WL_WPA, 14967663SSowmini.Varadhan@Sun.COM sizeof (wpa), B_TRUE)); 14974126Szf162725 } 14984126Szf162725 14994126Szf162725 dladm_status_t 15008453SAnurag.Maskey@Sun.COM dladm_wlan_wpa_del_key(dladm_handle_t handle, datalink_id_t linkid, 15018453SAnurag.Maskey@Sun.COM uint_t key_idx, const dladm_wlan_bssid_t *addr) 15024126Szf162725 { 15035895Syz147064 wl_del_key_t wk; 15044126Szf162725 15054126Szf162725 wk.idk_keyix = key_idx; 15064126Szf162725 if (addr != NULL) 15074126Szf162725 (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes, 15084126Szf162725 DLADM_WLAN_BSSID_LEN); 15094126Szf162725 15108453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_DELKEY, 15117663SSowmini.Varadhan@Sun.COM sizeof (wk), B_TRUE)); 15124126Szf162725 } 15134126Szf162725 15144126Szf162725 dladm_status_t 15158453SAnurag.Maskey@Sun.COM dladm_wlan_wpa_set_key(dladm_handle_t handle, datalink_id_t linkid, 15168453SAnurag.Maskey@Sun.COM dladm_wlan_cipher_t cipher, const dladm_wlan_bssid_t *addr, 15178453SAnurag.Maskey@Sun.COM boolean_t set_tx, uint64_t seq, uint_t key_idx, uint8_t *key, 15188453SAnurag.Maskey@Sun.COM uint_t key_len) 15194126Szf162725 { 15205895Syz147064 wl_key_t wk; 15214126Szf162725 15224126Szf162725 (void) memset(&wk, 0, sizeof (wl_key_t)); 15234126Szf162725 switch (cipher) { 15244126Szf162725 case DLADM_WLAN_CIPHER_WEP: 15254126Szf162725 wk.ik_type = IEEE80211_CIPHER_WEP; 15264126Szf162725 break; 15274126Szf162725 case DLADM_WLAN_CIPHER_TKIP: 15284126Szf162725 wk.ik_type = IEEE80211_CIPHER_TKIP; 15294126Szf162725 break; 15304126Szf162725 case DLADM_WLAN_CIPHER_AES_OCB: 15314126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_OCB; 15324126Szf162725 break; 15334126Szf162725 case DLADM_WLAN_CIPHER_AES_CCM: 15344126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_CCM; 15354126Szf162725 break; 15364126Szf162725 case DLADM_WLAN_CIPHER_CKIP: 15374126Szf162725 wk.ik_type = IEEE80211_CIPHER_CKIP; 15384126Szf162725 break; 15394126Szf162725 case DLADM_WLAN_CIPHER_NONE: 15404126Szf162725 wk.ik_type = IEEE80211_CIPHER_NONE; 15414126Szf162725 break; 15424126Szf162725 default: 15434126Szf162725 return (DLADM_STATUS_BADARG); 15444126Szf162725 } 15454126Szf162725 wk.ik_flags = IEEE80211_KEY_RECV; 15464126Szf162725 if (set_tx) { 15474126Szf162725 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; 15484126Szf162725 (void) memcpy(wk.ik_macaddr, addr->wb_bytes, 15494126Szf162725 DLADM_WLAN_BSSID_LEN); 15504126Szf162725 } else 15514126Szf162725 (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN); 15524126Szf162725 wk.ik_keyix = key_idx; 15534126Szf162725 wk.ik_keylen = key_len; 15544126Szf162725 (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */ 15554126Szf162725 (void) memcpy(wk.ik_keydata, key, key_len); 15564126Szf162725 15578453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_KEY, 15587663SSowmini.Varadhan@Sun.COM sizeof (wk), B_TRUE)); 15594126Szf162725 } 15604126Szf162725 15614126Szf162725 dladm_status_t 15628453SAnurag.Maskey@Sun.COM dladm_wlan_wpa_set_mlme(dladm_handle_t handle, datalink_id_t linkid, 15638453SAnurag.Maskey@Sun.COM dladm_wlan_mlme_op_t op, dladm_wlan_reason_t reason, 15648453SAnurag.Maskey@Sun.COM dladm_wlan_bssid_t *bssid) 15654126Szf162725 { 15664126Szf162725 wl_mlme_t mlme; 15674126Szf162725 15684126Szf162725 (void) memset(&mlme, 0, sizeof (wl_mlme_t)); 15694126Szf162725 switch (op) { 15704126Szf162725 case DLADM_WLAN_MLME_ASSOC: 15714126Szf162725 mlme.im_op = IEEE80211_MLME_ASSOC; 15724126Szf162725 break; 15734126Szf162725 case DLADM_WLAN_MLME_DISASSOC: 15744126Szf162725 mlme.im_op = IEEE80211_MLME_DISASSOC; 15754126Szf162725 break; 15764126Szf162725 default: 15774126Szf162725 return (DLADM_STATUS_BADARG); 15784126Szf162725 } 15794126Szf162725 mlme.im_reason = reason; 15804126Szf162725 if (bssid != NULL) 15814126Szf162725 (void) memcpy(mlme.im_macaddr, bssid->wb_bytes, 15824126Szf162725 DLADM_WLAN_BSSID_LEN); 15834126Szf162725 15848453SAnurag.Maskey@Sun.COM return (i_dladm_wlan_param(handle, linkid, &mlme, MAC_PROP_WL_MLME, 15857663SSowmini.Varadhan@Sun.COM sizeof (mlme), B_TRUE)); 15864126Szf162725 } 15874126Szf162725 15884126Szf162725 /* 15894126Szf162725 * routines of create instance 15904126Szf162725 */ 15914126Szf162725 static scf_propertygroup_t * 15924126Szf162725 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance, 15934126Szf162725 const char *pg_name, const char *pg_type) 15944126Szf162725 { 15954126Szf162725 scf_propertygroup_t *pg; 15964126Szf162725 15974126Szf162725 pg = scf_pg_create(handle); 15984126Szf162725 if (pg == NULL) 15994126Szf162725 return (NULL); 16004126Szf162725 16014126Szf162725 if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) { 16024126Szf162725 scf_pg_destroy(pg); 16034126Szf162725 return (NULL); 16044126Szf162725 } 16054126Szf162725 16064126Szf162725 return (pg); 16074126Szf162725 } 16084126Szf162725 16095895Syz147064 static dladm_status_t 16104126Szf162725 add_new_property(scf_handle_t *handle, const char *prop_name, 16114126Szf162725 scf_type_t type, const char *val, scf_transaction_t *tx) 16124126Szf162725 { 16134126Szf162725 scf_value_t *value = NULL; 16144126Szf162725 scf_transaction_entry_t *entry = NULL; 16154126Szf162725 16164126Szf162725 entry = scf_entry_create(handle); 16174126Szf162725 if (entry == NULL) 16184126Szf162725 goto out; 16194126Szf162725 16204126Szf162725 value = scf_value_create(handle); 16214126Szf162725 if (value == NULL) 16224126Szf162725 goto out; 16234126Szf162725 16244126Szf162725 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) 16254126Szf162725 goto out; 16264126Szf162725 16274126Szf162725 if (scf_value_set_from_string(value, type, val) != 0) 16284126Szf162725 goto out; 16294126Szf162725 16304126Szf162725 if (scf_entry_add_value(entry, value) != 0) 16314126Szf162725 goto out; 16324126Szf162725 16335895Syz147064 return (DLADM_STATUS_OK); 16344126Szf162725 16354126Szf162725 out: 16364126Szf162725 if (value != NULL) 16374126Szf162725 scf_value_destroy(value); 16384126Szf162725 if (entry != NULL) 16394126Szf162725 scf_entry_destroy(entry); 16404126Szf162725 16415895Syz147064 return (DLADM_STATUS_FAILED); 16424126Szf162725 } 16434126Szf162725 16445895Syz147064 static dladm_status_t 16454126Szf162725 add_pg_method(scf_handle_t *handle, scf_instance_t *instance, 16464126Szf162725 const char *pg_name, const char *flags) 16474126Szf162725 { 16484126Szf162725 int rv, size; 16495895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 16504126Szf162725 char *command = NULL; 16514126Szf162725 scf_transaction_t *tran = NULL; 16524126Szf162725 scf_propertygroup_t *pg; 16534126Szf162725 16544126Szf162725 pg = add_property_group_to_instance(handle, instance, 16554126Szf162725 pg_name, SCF_GROUP_METHOD); 16564126Szf162725 if (pg == NULL) 16574126Szf162725 goto out; 16584126Szf162725 16594126Szf162725 tran = scf_transaction_create(handle); 16604126Szf162725 if (tran == NULL) 16614126Szf162725 goto out; 16624126Szf162725 16634126Szf162725 size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1; 16644126Szf162725 command = malloc(size); 16654126Szf162725 if (command == NULL) { 16665895Syz147064 status = DLADM_STATUS_NOMEM; 16674126Szf162725 goto out; 16684126Szf162725 } 16694126Szf162725 (void) snprintf(command, size, "%s %s", SVC_METHOD, flags); 16704126Szf162725 16714126Szf162725 do { 16724126Szf162725 if (scf_transaction_start(tran, pg) != 0) 16734126Szf162725 goto out; 16744126Szf162725 16754126Szf162725 if (add_new_property(handle, SCF_PROPERTY_EXEC, 16765895Syz147064 SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) { 16774126Szf162725 goto out; 16784126Szf162725 } 16794126Szf162725 16804126Szf162725 rv = scf_transaction_commit(tran); 16814126Szf162725 switch (rv) { 16824126Szf162725 case 1: 16835895Syz147064 status = DLADM_STATUS_OK; 16844126Szf162725 goto out; 16854126Szf162725 case 0: 16864126Szf162725 scf_transaction_destroy_children(tran); 16874126Szf162725 if (scf_pg_update(pg) == -1) { 16884126Szf162725 goto out; 16894126Szf162725 } 16904126Szf162725 break; 16914126Szf162725 case -1: 16924126Szf162725 default: 16934126Szf162725 goto out; 16944126Szf162725 } 16954126Szf162725 } while (rv == 0); 16964126Szf162725 16974126Szf162725 out: 16984126Szf162725 if (tran != NULL) { 16994126Szf162725 scf_transaction_destroy_children(tran); 17004126Szf162725 scf_transaction_destroy(tran); 17014126Szf162725 } 17024126Szf162725 17034126Szf162725 if (pg != NULL) 17044126Szf162725 scf_pg_destroy(pg); 17054126Szf162725 17064126Szf162725 if (command != NULL) 17074126Szf162725 free(command); 17084126Szf162725 17094126Szf162725 return (status); 17104126Szf162725 } 17114126Szf162725 17125895Syz147064 static dladm_status_t 17134126Szf162725 do_create_instance(scf_handle_t *handle, scf_service_t *svc, 17144126Szf162725 const char *instance_name, const char *command) 17154126Szf162725 { 17165895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17174126Szf162725 char *buf; 17184126Szf162725 ssize_t max_fmri_len; 17194126Szf162725 scf_instance_t *instance; 17204126Szf162725 17214126Szf162725 instance = scf_instance_create(handle); 17224126Szf162725 if (instance == NULL) 17234126Szf162725 goto out; 17244126Szf162725 17254126Szf162725 if (scf_service_add_instance(svc, instance_name, instance) != 0) { 17264126Szf162725 if (scf_error() == SCF_ERROR_EXISTS) 17274126Szf162725 /* Let the caller deal with the duplicate instance */ 17285895Syz147064 status = DLADM_STATUS_EXIST; 17294126Szf162725 goto out; 17304126Szf162725 } 17314126Szf162725 17324126Szf162725 if (add_pg_method(handle, instance, "start", 17335895Syz147064 command) != DLADM_STATUS_OK) { 17344126Szf162725 goto out; 17354126Szf162725 } 17364126Szf162725 17374126Szf162725 /* enabling the instance */ 17384126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 17394126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) 17404126Szf162725 goto out; 17414126Szf162725 17424126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 17434126Szf162725 if ((smf_disable_instance(buf, 0) != 0) || 17444126Szf162725 (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) { 17454126Szf162725 goto out; 17464126Szf162725 } 17475895Syz147064 status = DLADM_STATUS_OK; 17484126Szf162725 } 17494126Szf162725 17504126Szf162725 out: 17514126Szf162725 if (instance != NULL) 17524126Szf162725 scf_instance_destroy(instance); 17534126Szf162725 return (status); 17544126Szf162725 } 17554126Szf162725 17565895Syz147064 static dladm_status_t 17574126Szf162725 create_instance(const char *instance_name, const char *command) 17584126Szf162725 { 17595895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17604126Szf162725 scf_service_t *svc = NULL; 17614126Szf162725 scf_handle_t *handle = NULL; 17624126Szf162725 17634126Szf162725 handle = scf_handle_create(SCF_VERSION); 17644126Szf162725 if (handle == NULL) 17654126Szf162725 goto out; 17664126Szf162725 17674126Szf162725 if (scf_handle_bind(handle) == -1) 17684126Szf162725 goto out; 17694126Szf162725 17704126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 17714126Szf162725 goto out; 17724126Szf162725 17734126Szf162725 if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc, 17744126Szf162725 NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) 17754126Szf162725 goto out; 17764126Szf162725 17774126Szf162725 status = do_create_instance(handle, svc, instance_name, command); 17784126Szf162725 17794126Szf162725 out: 17804126Szf162725 if (svc != NULL) 17814126Szf162725 scf_service_destroy(svc); 17824126Szf162725 17834126Szf162725 if (handle != NULL) { 17844126Szf162725 (void) scf_handle_unbind(handle); 17854126Szf162725 scf_handle_destroy(handle); 17864126Szf162725 } 17874126Szf162725 17884126Szf162725 return (status); 17894126Szf162725 } 17904126Szf162725 17914126Szf162725 /* 17924126Szf162725 * routines of delete instance 17934126Szf162725 */ 17944126Szf162725 #define DEFAULT_TIMEOUT 60000000 17954126Szf162725 #define INIT_WAIT_USECS 50000 17964126Szf162725 17974126Szf162725 static void 17984126Szf162725 wait_until_disabled(scf_handle_t *handle, char *fmri) 17994126Szf162725 { 18004126Szf162725 char *state; 18014126Szf162725 useconds_t max; 18024126Szf162725 useconds_t usecs; 18034126Szf162725 uint64_t *cp = NULL; 18044126Szf162725 scf_simple_prop_t *sp = NULL; 18054126Szf162725 18064126Szf162725 max = DEFAULT_TIMEOUT; 18074126Szf162725 18084126Szf162725 if (((sp = scf_simple_prop_get(handle, fmri, "stop", 18094126Szf162725 SCF_PROPERTY_TIMEOUT)) != NULL) && 18104126Szf162725 ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0)) 18114126Szf162725 max = (*cp) * 1000000; /* convert to usecs */ 18124126Szf162725 18134126Szf162725 if (sp != NULL) 18144126Szf162725 scf_simple_prop_free(sp); 18154126Szf162725 18164126Szf162725 for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) { 18174126Szf162725 /* incremental wait */ 18184126Szf162725 usecs *= 2; 18194126Szf162725 usecs = (usecs > max) ? max : usecs; 18204126Szf162725 18214126Szf162725 (void) usleep(usecs); 18224126Szf162725 18234126Szf162725 /* Check state after the wait */ 18244126Szf162725 if ((state = smf_get_state(fmri)) != NULL) { 18254126Szf162725 if (strcmp(state, "disabled") == 0) 18264126Szf162725 return; 18274126Szf162725 } 18284126Szf162725 } 18294126Szf162725 } 18304126Szf162725 18315895Syz147064 static dladm_status_t 18324126Szf162725 delete_instance(const char *instance_name) 18334126Szf162725 { 18345895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 18354126Szf162725 char *buf; 18364126Szf162725 ssize_t max_fmri_len; 18374126Szf162725 scf_scope_t *scope = NULL; 18384126Szf162725 scf_service_t *svc = NULL; 18394126Szf162725 scf_handle_t *handle = NULL; 18404126Szf162725 scf_instance_t *instance; 18414126Szf162725 18424126Szf162725 handle = scf_handle_create(SCF_VERSION); 18434126Szf162725 if (handle == NULL) 18444126Szf162725 goto out; 18454126Szf162725 18464126Szf162725 if (scf_handle_bind(handle) == -1) 18474126Szf162725 goto out; 18484126Szf162725 18494126Szf162725 if ((scope = scf_scope_create(handle)) == NULL) 18504126Szf162725 goto out; 18514126Szf162725 18524126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 18534126Szf162725 goto out; 18544126Szf162725 18554126Szf162725 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1) 18564126Szf162725 goto out; 18574126Szf162725 18584126Szf162725 if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0) 18594126Szf162725 goto out; 18604126Szf162725 18614126Szf162725 instance = scf_instance_create(handle); 18624126Szf162725 if (instance == NULL) 18634126Szf162725 goto out; 18644126Szf162725 18654126Szf162725 if (scf_service_get_instance(svc, instance_name, instance) != 0) { 18664126Szf162725 scf_error_t scf_errnum = scf_error(); 18674126Szf162725 18684126Szf162725 if (scf_errnum == SCF_ERROR_NOT_FOUND) 18695895Syz147064 status = DLADM_STATUS_OK; 18704126Szf162725 18714126Szf162725 scf_instance_destroy(instance); 18724126Szf162725 goto out; 18734126Szf162725 } 18744126Szf162725 18754126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 18764126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) { 18774126Szf162725 scf_instance_destroy(instance); 18784126Szf162725 goto out; 18794126Szf162725 } 18804126Szf162725 18814126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 18824126Szf162725 char *state; 18834126Szf162725 18844126Szf162725 state = smf_get_state(buf); 18854126Szf162725 if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 || 18864126Szf162725 strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) { 18874126Szf162725 if (smf_disable_instance(buf, 0) == 0) { 18884126Szf162725 /* 18894126Szf162725 * Wait for some time till timeout to avoid 18904126Szf162725 * a race with scf_instance_delete() below. 18914126Szf162725 */ 18924126Szf162725 wait_until_disabled(handle, buf); 18934126Szf162725 } 18944126Szf162725 } 18954126Szf162725 } 18964126Szf162725 18974126Szf162725 if (scf_instance_delete(instance) != 0) { 18984126Szf162725 scf_instance_destroy(instance); 18994126Szf162725 goto out; 19004126Szf162725 } 19014126Szf162725 19024126Szf162725 scf_instance_destroy(instance); 19034126Szf162725 19045895Syz147064 status = DLADM_STATUS_OK; 19054126Szf162725 19064126Szf162725 out: 19074126Szf162725 if (svc != NULL) 19084126Szf162725 scf_service_destroy(svc); 19094126Szf162725 19104126Szf162725 if (scope != NULL) 19114126Szf162725 scf_scope_destroy(scope); 19124126Szf162725 19134126Szf162725 if (handle != NULL) { 19144126Szf162725 (void) scf_handle_unbind(handle); 19154126Szf162725 scf_handle_destroy(handle); 19164126Szf162725 } 19174126Szf162725 19184126Szf162725 return (status); 19194126Szf162725 } 19204126Szf162725 19215895Syz147064 static dladm_status_t 19228453SAnurag.Maskey@Sun.COM wpa_instance_create(dladm_handle_t handle, datalink_id_t linkid, void *key) 19234126Szf162725 { 19245895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 19254126Szf162725 char *command = NULL; 19264126Szf162725 char *wk_name = ((dladm_wlan_key_t *)key)->wk_name; 19274126Szf162725 int size; 19285895Syz147064 char instance_name[MAXLINKNAMELEN]; 19295895Syz147064 19305895Syz147064 /* 19315895Syz147064 * Use the link name as the instance name of the network/wpad service. 19325895Syz147064 */ 19338453SAnurag.Maskey@Sun.COM status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, 19348453SAnurag.Maskey@Sun.COM instance_name, sizeof (instance_name)); 19355895Syz147064 if (status != DLADM_STATUS_OK) 19365895Syz147064 goto out; 19374126Szf162725 19384126Szf162725 size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1; 19394126Szf162725 command = malloc(size); 19404126Szf162725 if (command == NULL) { 19415895Syz147064 status = DLADM_STATUS_NOMEM; 19424126Szf162725 goto out; 19434126Szf162725 } 19444126Szf162725 (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name); 19454126Szf162725 19464126Szf162725 status = create_instance(instance_name, command); 19475895Syz147064 if (status == DLADM_STATUS_EXIST) { 19484126Szf162725 /* 19494126Szf162725 * Delete the existing instance and create a new instance 19504126Szf162725 * with the supplied arguments. 19514126Szf162725 */ 19524126Szf162725 if ((status = delete_instance(instance_name)) == 19535895Syz147064 DLADM_STATUS_OK) { 19544126Szf162725 status = create_instance(instance_name, command); 19554126Szf162725 } 19564126Szf162725 } 19574126Szf162725 19584126Szf162725 out: 19594126Szf162725 if (command != NULL) 19604126Szf162725 free(command); 19614126Szf162725 19624126Szf162725 return (status); 19634126Szf162725 } 19644126Szf162725 19655895Syz147064 static dladm_status_t 19668453SAnurag.Maskey@Sun.COM wpa_instance_delete(dladm_handle_t handle, datalink_id_t linkid) 19674126Szf162725 { 19685895Syz147064 char instance_name[MAXLINKNAMELEN]; 19694126Szf162725 19705895Syz147064 /* 19715895Syz147064 * Get the instance name of the network/wpad service (the same as 19725895Syz147064 * the link name). 19735895Syz147064 */ 19748453SAnurag.Maskey@Sun.COM if (dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, 19758453SAnurag.Maskey@Sun.COM instance_name, sizeof (instance_name)) != DLADM_STATUS_OK) 19765895Syz147064 return (DLADM_STATUS_FAILED); 19774126Szf162725 19785895Syz147064 return (delete_instance(instance_name)); 19794126Szf162725 } 1980