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 #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 465895Syz147064 static dladm_status_t wpa_instance_create(datalink_id_t, void *); 475895Syz147064 static dladm_status_t wpa_instance_delete(datalink_id_t); 483871Syz147064 49*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_bsstype(datalink_id_t, void *, int); 50*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_essid(datalink_id_t, void *, int); 51*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_bssid(datalink_id_t, void *, int); 52*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_signal(datalink_id_t, void *, int); 53*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_encryption(datalink_id_t, void *, int); 54*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_authmode(datalink_id_t, void *, int); 55*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_linkstatus(datalink_id_t, void *, int); 56*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_esslist(datalink_id_t, void *, int); 57*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_rate(datalink_id_t, void *, int); 58*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_mode(datalink_id_t, void *, int); 59*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_capability(datalink_id_t, void *, int); 60*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_get_wpamode(datalink_id_t, void *, int); 614126Szf162725 625895Syz147064 static dladm_status_t do_set_bsstype(datalink_id_t, dladm_wlan_bsstype_t *); 635895Syz147064 static dladm_status_t do_set_authmode(datalink_id_t, dladm_wlan_auth_t *); 645895Syz147064 static dladm_status_t do_set_encryption(datalink_id_t, 655895Syz147064 dladm_wlan_secmode_t *); 665895Syz147064 static dladm_status_t do_set_essid(datalink_id_t, dladm_wlan_essid_t *); 675895Syz147064 static dladm_status_t do_set_createibss(datalink_id_t, boolean_t *); 685895Syz147064 static dladm_status_t do_set_key(datalink_id_t, dladm_wlan_key_t *, uint_t); 695895Syz147064 static dladm_status_t do_set_channel(datalink_id_t, dladm_wlan_channel_t *); 703871Syz147064 71*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_scan(datalink_id_t, void *, int); 72*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_connect(datalink_id_t, void *, int, 73*7663SSowmini.Varadhan@Sun.COM dladm_wlan_attr_t *, boolean_t, void *, uint_t, 74*7663SSowmini.Varadhan@Sun.COM int); 75*7663SSowmini.Varadhan@Sun.COM static dladm_status_t do_disconnect(datalink_id_t, void *, int); 765895Syz147064 static boolean_t find_val_by_name(const char *, val_desc_t *, 775895Syz147064 uint_t, uint_t *); 785895Syz147064 static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **); 795895Syz147064 static void generate_essid(dladm_wlan_essid_t *); 803871Syz147064 813871Syz147064 static dladm_status_t dladm_wlan_wlresult2status(wldp_t *); 825895Syz147064 static dladm_status_t dladm_wlan_validate(datalink_id_t); 833871Syz147064 843871Syz147064 static val_desc_t linkstatus_vals[] = { 855903Ssowmini { "disconnected", DLADM_WLAN_LINK_DISCONNECTED }, 865903Ssowmini { "connected", DLADM_WLAN_LINK_CONNECTED } 873871Syz147064 }; 883871Syz147064 893871Syz147064 static val_desc_t secmode_vals[] = { 905903Ssowmini { "none", DLADM_WLAN_SECMODE_NONE }, 915903Ssowmini { "wep", DLADM_WLAN_SECMODE_WEP }, 925903Ssowmini { "wpa", DLADM_WLAN_SECMODE_WPA } 933871Syz147064 }; 943871Syz147064 953871Syz147064 static val_desc_t strength_vals[] = { 965903Ssowmini { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK }, 975895Syz147064 { "weak", DLADM_WLAN_STRENGTH_WEAK }, 985895Syz147064 { "good", DLADM_WLAN_STRENGTH_GOOD }, 995903Ssowmini { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD }, 1005903Ssowmini { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT } 1013871Syz147064 }; 1023871Syz147064 1033871Syz147064 static val_desc_t mode_vals[] = { 1045903Ssowmini { "a", DLADM_WLAN_MODE_80211A }, 1055903Ssowmini { "b", DLADM_WLAN_MODE_80211B }, 1065903Ssowmini { "g", DLADM_WLAN_MODE_80211G }, 1073871Syz147064 }; 1083871Syz147064 1093871Syz147064 static val_desc_t auth_vals[] = { 1105895Syz147064 { "open", DLADM_WLAN_AUTH_OPEN }, 1115903Ssowmini { "shared", DLADM_WLAN_AUTH_SHARED } 1123871Syz147064 }; 1133871Syz147064 1143871Syz147064 static val_desc_t bsstype_vals[] = { 1155903Ssowmini { "bss", DLADM_WLAN_BSSTYPE_BSS }, 1165903Ssowmini { "ibss", DLADM_WLAN_BSSTYPE_IBSS }, 1175903Ssowmini { "any", DLADM_WLAN_BSSTYPE_ANY } 1183871Syz147064 }; 1193871Syz147064 120*7663SSowmini.Varadhan@Sun.COM #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET) 1213871Syz147064 1223871Syz147064 static dladm_status_t 1233871Syz147064 dladm_wlan_wlresult2status(wldp_t *gbuf) 1243871Syz147064 { 1253871Syz147064 switch (gbuf->wldp_result) { 1263871Syz147064 case WL_SUCCESS: 1273871Syz147064 return (DLADM_STATUS_OK); 1283871Syz147064 1293871Syz147064 case WL_NOTSUPPORTED: 1303871Syz147064 case WL_LACK_FEATURE: 1313871Syz147064 return (DLADM_STATUS_NOTSUP); 1323871Syz147064 1333871Syz147064 case WL_READONLY: 1343871Syz147064 return (DLADM_STATUS_PROPRDONLY); 1353871Syz147064 1363871Syz147064 default: 1373871Syz147064 break; 1383871Syz147064 } 1393871Syz147064 1403871Syz147064 return (DLADM_STATUS_FAILED); 1413871Syz147064 } 1423871Syz147064 1433871Syz147064 static dladm_wlan_mode_t 1443871Syz147064 do_convert_mode(wl_phy_conf_t *phyp) 1453871Syz147064 { 1463871Syz147064 switch (phyp->wl_phy_fhss_conf.wl_fhss_subtype) { 1473871Syz147064 case WL_ERP: 1483871Syz147064 return (DLADM_WLAN_MODE_80211G); 1493871Syz147064 case WL_OFDM: 1503871Syz147064 return (DLADM_WLAN_MODE_80211A); 1513871Syz147064 case WL_DSSS: 1523871Syz147064 case WL_FHSS: 1533871Syz147064 return (DLADM_WLAN_MODE_80211B); 1543871Syz147064 default: 1553871Syz147064 break; 1563871Syz147064 } 1573871Syz147064 1583871Syz147064 return (DLADM_WLAN_MODE_NONE); 1593871Syz147064 } 1603871Syz147064 1615895Syz147064 boolean_t 1625895Syz147064 i_dladm_wlan_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp) 1633871Syz147064 { 1643871Syz147064 wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf; 1653871Syz147064 wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf; 1663871Syz147064 1673871Syz147064 switch (wlfp->wl_fhss_subtype) { 1683871Syz147064 case WL_FHSS: 1693871Syz147064 case WL_DSSS: 1703871Syz147064 case WL_IRBASE: 1713871Syz147064 case WL_HRDS: 1723871Syz147064 case WL_ERP: 1733871Syz147064 *channelp = wlfp->wl_fhss_channel; 1743871Syz147064 break; 1753871Syz147064 case WL_OFDM: 1763871Syz147064 *channelp = DLADM_WLAN_OFDM2CHAN(wlop->wl_ofdm_frequency); 1773871Syz147064 break; 1783871Syz147064 default: 1793871Syz147064 return (B_FALSE); 1803871Syz147064 } 1813871Syz147064 return (B_TRUE); 1823871Syz147064 } 1833871Syz147064 1843871Syz147064 #define IEEE80211_RATE 0x7f 1853871Syz147064 static void 1863871Syz147064 fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp) 1873871Syz147064 { 1883871Syz147064 int i; 1893871Syz147064 1903871Syz147064 (void) memset(attrp, 0, sizeof (*attrp)); 1913871Syz147064 1923871Syz147064 (void) snprintf(attrp->wa_essid.we_bytes, DLADM_WLAN_MAX_ESSID_LEN, 1933871Syz147064 "%s", wlp->wl_ess_conf_essid.wl_essid_essid); 1943871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 1953871Syz147064 1963871Syz147064 (void) memcpy(attrp->wa_bssid.wb_bytes, wlp->wl_ess_conf_bssid, 1973871Syz147064 DLADM_WLAN_BSSID_LEN); 1983871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 1993871Syz147064 2003871Syz147064 attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled == 2013871Syz147064 WL_ENC_WEP ? DLADM_WLAN_SECMODE_WEP : DLADM_WLAN_SECMODE_NONE); 2024126Szf162725 if (wlp->wl_ess_conf_reserved[0] > 0) 2034126Szf162725 attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 2043871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 2053871Syz147064 2063871Syz147064 attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ? 2073871Syz147064 DLADM_WLAN_BSSTYPE_BSS : DLADM_WLAN_BSSTYPE_IBSS); 2083871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 2093871Syz147064 2103871Syz147064 attrp->wa_auth = (wlp->wl_ess_conf_authmode == 0 ? 2113871Syz147064 DLADM_WLAN_AUTH_OPEN : DLADM_WLAN_AUTH_SHARED); 2123871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 2133871Syz147064 2143871Syz147064 attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(wlp->wl_ess_conf_sl); 2153871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 2163871Syz147064 2173871Syz147064 attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)&wlp->wl_phy_conf); 2183871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 2193871Syz147064 2203871Syz147064 for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) { 2213871Syz147064 wlp->wl_supported_rates[i] &= IEEE80211_RATE; 2223871Syz147064 if (wlp->wl_supported_rates[i] > attrp->wa_speed) 2233871Syz147064 attrp->wa_speed = wlp->wl_supported_rates[i]; 2243871Syz147064 } 2253871Syz147064 if (attrp->wa_speed > 0) 2263871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 2273871Syz147064 2285895Syz147064 if (i_dladm_wlan_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf, 2293871Syz147064 &attrp->wa_channel)) 2303871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_CHANNEL; 2313871Syz147064 } 2323871Syz147064 2333871Syz147064 dladm_status_t 2345895Syz147064 dladm_wlan_scan(datalink_id_t linkid, void *arg, 2353871Syz147064 boolean_t (*func)(void *, dladm_wlan_attr_t *)) 2363871Syz147064 { 2375895Syz147064 int i; 2383871Syz147064 uint32_t count; 2393871Syz147064 wl_ess_conf_t *wlp; 240*7663SSowmini.Varadhan@Sun.COM wl_ess_list_t *wls = NULL; 241*7663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 242*7663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 2433871Syz147064 dladm_wlan_attr_t wlattr; 2443871Syz147064 dladm_status_t status; 2453871Syz147064 2465895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 2475895Syz147064 goto done; 2483871Syz147064 249*7663SSowmini.Varadhan@Sun.COM status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status)); 250*7663SSowmini.Varadhan@Sun.COM if (status != DLADM_STATUS_OK) 2513871Syz147064 goto done; 2523871Syz147064 253*7663SSowmini.Varadhan@Sun.COM if ((status = do_scan(linkid, buf, sizeof (buf))) != DLADM_STATUS_OK) 2543871Syz147064 goto done; 2553871Syz147064 2564126Szf162725 if (func == NULL) { 2574126Szf162725 status = DLADM_STATUS_OK; 2584126Szf162725 goto done; 2594126Szf162725 } 2604126Szf162725 261*7663SSowmini.Varadhan@Sun.COM wls = malloc(WLDP_BUFSIZE); 262*7663SSowmini.Varadhan@Sun.COM if (wls == NULL) { 263*7663SSowmini.Varadhan@Sun.COM status = DLADM_STATUS_NOMEM; 264*7663SSowmini.Varadhan@Sun.COM goto done; 265*7663SSowmini.Varadhan@Sun.COM } 266*7663SSowmini.Varadhan@Sun.COM 267*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_esslist(linkid, wls, WLDP_BUFSIZE)) 268*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 2693871Syz147064 goto done; 2703871Syz147064 271*7663SSowmini.Varadhan@Sun.COM wlp = wls->wl_ess_list_ess; 272*7663SSowmini.Varadhan@Sun.COM count = wls->wl_ess_list_num; 2733871Syz147064 2743871Syz147064 for (i = 0; i < count; i++, wlp++) { 2753871Syz147064 fill_wlan_attr(wlp, &wlattr); 2763871Syz147064 if (!func(arg, &wlattr)) 2773871Syz147064 break; 2783871Syz147064 } 2793871Syz147064 280*7663SSowmini.Varadhan@Sun.COM if (wl_status != WL_CONNECTED) { 281*7663SSowmini.Varadhan@Sun.COM status = do_get_linkstatus(linkid, &wl_status, 282*7663SSowmini.Varadhan@Sun.COM sizeof (&wl_status)); 2835895Syz147064 if (status != DLADM_STATUS_OK) 2843871Syz147064 goto done; 285*7663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) 286*7663SSowmini.Varadhan@Sun.COM (void) do_disconnect(linkid, buf, sizeof (buf)); 2873871Syz147064 } 2883871Syz147064 2893871Syz147064 status = DLADM_STATUS_OK; 2903871Syz147064 done: 291*7663SSowmini.Varadhan@Sun.COM free(wls); 2923871Syz147064 return (status); 2933871Syz147064 } 2943871Syz147064 2953871Syz147064 /* 2963871Syz147064 * Structures used in building the list of eligible WLANs to connect to. 2973871Syz147064 * Specifically, `connect_state' has the WLAN attributes that must be matched 2983871Syz147064 * (in `cs_attr') and a growing list of WLANs that matched those attributes 2993871Syz147064 * chained through `cs_list'. Each element in the list is of type `attr_node' 3003871Syz147064 * and has the matching WLAN's attributes and a pointer to the next element. 3013871Syz147064 * For convenience, `cs_count' tracks the number of elements in the list. 3023871Syz147064 */ 3033871Syz147064 typedef struct attr_node { 3043871Syz147064 dladm_wlan_attr_t an_attr; 3053871Syz147064 struct attr_node *an_next; 3063871Syz147064 } attr_node_t; 3073871Syz147064 3083871Syz147064 typedef struct connect_state { 3093871Syz147064 dladm_wlan_attr_t *cs_attr; 3103871Syz147064 uint_t cs_count; 3113871Syz147064 attr_node_t *cs_list; 3123871Syz147064 } connect_state_t; 3133871Syz147064 3143871Syz147064 /* 3153871Syz147064 * Compare two sets of WLAN attributes. For now, we only consider strength 3163871Syz147064 * and speed (in that order), which matches the documented default policy for 3173871Syz147064 * dladm_wlan_connect(). 3183871Syz147064 */ 3193871Syz147064 static int 3203871Syz147064 attr_compare(const void *p1, const void *p2) 3213871Syz147064 { 3223871Syz147064 dladm_wlan_attr_t *attrp1, *attrp2; 3233871Syz147064 3243871Syz147064 attrp1 = (*(dladm_wlan_attr_t **)p1); 3253871Syz147064 attrp2 = (*(dladm_wlan_attr_t **)p2); 3263871Syz147064 3273871Syz147064 if (attrp1->wa_strength < attrp2->wa_strength) 3283871Syz147064 return (1); 3293871Syz147064 3303871Syz147064 if (attrp1->wa_strength > attrp2->wa_strength) 3313871Syz147064 return (-1); 3323871Syz147064 3333871Syz147064 return (attrp2->wa_speed - attrp1->wa_speed); 3343871Syz147064 } 3353871Syz147064 3363871Syz147064 /* 3373871Syz147064 * Callback function used by dladm_wlan_connect() to filter out unwanted 3383871Syz147064 * WLANs when scanning for available WLANs. Always returns B_TRUE to 3393871Syz147064 * continue the scan. 3403871Syz147064 */ 3413871Syz147064 static boolean_t 3423871Syz147064 connect_cb(void *arg, dladm_wlan_attr_t *attrp) 3433871Syz147064 { 3443871Syz147064 attr_node_t *nodep; 3453871Syz147064 dladm_wlan_attr_t *fattrp; 3463871Syz147064 connect_state_t *statep = (connect_state_t *)arg; 3473871Syz147064 3483871Syz147064 fattrp = statep->cs_attr; 3493871Syz147064 if (fattrp == NULL) 3503871Syz147064 goto append; 3513871Syz147064 3523871Syz147064 if ((fattrp->wa_valid & attrp->wa_valid) != fattrp->wa_valid) 3533871Syz147064 return (B_TRUE); 3543871Syz147064 3553871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0 && 3563871Syz147064 strncmp(fattrp->wa_essid.we_bytes, attrp->wa_essid.we_bytes, 3573871Syz147064 DLADM_WLAN_MAX_ESSID_LEN) != 0) 3583871Syz147064 return (B_TRUE); 3593871Syz147064 3603871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 3613871Syz147064 fattrp->wa_secmode != attrp->wa_secmode) 3623871Syz147064 return (B_TRUE); 3633871Syz147064 3643871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0 && 3653871Syz147064 fattrp->wa_mode != attrp->wa_mode) 3663871Syz147064 return (B_TRUE); 3673871Syz147064 3683871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_STRENGTH) != 0 && 3693871Syz147064 fattrp->wa_strength != attrp->wa_strength) 3703871Syz147064 return (B_TRUE); 3713871Syz147064 3723871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SPEED) != 0 && 3733871Syz147064 fattrp->wa_speed != attrp->wa_speed) 3743871Syz147064 return (B_TRUE); 3753871Syz147064 3763871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) { 3773871Syz147064 attrp->wa_auth = fattrp->wa_auth; 3783871Syz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 3793871Syz147064 } 3803871Syz147064 3813871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 3823871Syz147064 fattrp->wa_bsstype != attrp->wa_bsstype) 3833871Syz147064 return (B_TRUE); 3843871Syz147064 3853871Syz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSID) != 0 && 3863871Syz147064 memcmp(fattrp->wa_bssid.wb_bytes, attrp->wa_bssid.wb_bytes, 3873871Syz147064 DLADM_WLAN_BSSID_LEN) != 0) 3883871Syz147064 return (B_TRUE); 3893871Syz147064 append: 3903871Syz147064 nodep = malloc(sizeof (attr_node_t)); 3913871Syz147064 if (nodep == NULL) 3923871Syz147064 return (B_TRUE); 3933871Syz147064 3943871Syz147064 (void) memcpy(&nodep->an_attr, attrp, sizeof (dladm_wlan_attr_t)); 3953871Syz147064 nodep->an_next = statep->cs_list; 3963871Syz147064 statep->cs_list = nodep; 3973871Syz147064 statep->cs_count++; 3983871Syz147064 3993871Syz147064 return (B_TRUE); 4003871Syz147064 } 4013871Syz147064 4024126Szf162725 #define IEEE80211_C_WPA 0x01800000 4034126Szf162725 4043871Syz147064 static dladm_status_t 405*7663SSowmini.Varadhan@Sun.COM do_connect(datalink_id_t linkid, void *buf, int bufsize, 406*7663SSowmini.Varadhan@Sun.COM dladm_wlan_attr_t *attrp, boolean_t create_ibss, void *keys, 407*7663SSowmini.Varadhan@Sun.COM uint_t key_count, int timeout) 4083871Syz147064 { 4095895Syz147064 dladm_wlan_secmode_t secmode; 4105895Syz147064 dladm_wlan_auth_t authmode; 4115895Syz147064 dladm_wlan_bsstype_t bsstype; 4125895Syz147064 dladm_wlan_essid_t essid; 4135895Syz147064 boolean_t essid_valid = B_FALSE; 4145895Syz147064 dladm_status_t status; 4155895Syz147064 dladm_wlan_channel_t channel; 4165895Syz147064 hrtime_t start; 4175895Syz147064 wl_capability_t *caps; 418*7663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 4193871Syz147064 4203871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) { 4213871Syz147064 channel = attrp->wa_channel; 4225895Syz147064 status = do_set_channel(linkid, &channel); 4235895Syz147064 if (status != DLADM_STATUS_OK) 4243871Syz147064 goto fail; 4253871Syz147064 } 4263871Syz147064 4273871Syz147064 secmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) ? 4283871Syz147064 attrp->wa_secmode : DLADM_WLAN_SECMODE_NONE; 4293871Syz147064 4305895Syz147064 if ((status = do_set_encryption(linkid, &secmode)) != DLADM_STATUS_OK) 4313871Syz147064 goto fail; 4323871Syz147064 4333871Syz147064 authmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) ? 4343871Syz147064 attrp->wa_auth : DLADM_WLAN_AUTH_OPEN; 4353871Syz147064 4365895Syz147064 if ((status = do_set_authmode(linkid, &authmode)) != DLADM_STATUS_OK) 4373871Syz147064 goto fail; 4383871Syz147064 4393871Syz147064 bsstype = ((attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0) ? 4403871Syz147064 attrp->wa_bsstype : DLADM_WLAN_BSSTYPE_BSS; 4413871Syz147064 4425895Syz147064 if ((status = do_set_bsstype(linkid, &bsstype)) != DLADM_STATUS_OK) 4433871Syz147064 goto fail; 4443871Syz147064 4453871Syz147064 if (secmode == DLADM_WLAN_SECMODE_WEP) { 4465895Syz147064 if (keys == NULL || key_count == 0 || 4475895Syz147064 key_count > MAX_NWEPKEYS) { 4485895Syz147064 status = DLADM_STATUS_BADARG; 4495895Syz147064 goto fail; 4505895Syz147064 } 4515895Syz147064 status = do_set_key(linkid, keys, key_count); 4525895Syz147064 if (status != DLADM_STATUS_OK) 4533871Syz147064 goto fail; 4544126Szf162725 } else if (secmode == DLADM_WLAN_SECMODE_WPA) { 4555895Syz147064 if (keys == NULL || key_count == 0 || 4565895Syz147064 key_count > MAX_NWEPKEYS) { 4575895Syz147064 status = DLADM_STATUS_BADARG; 4585895Syz147064 goto fail; 4595895Syz147064 } 460*7663SSowmini.Varadhan@Sun.COM status = do_get_capability(linkid, buf, bufsize); 4615895Syz147064 if (status != DLADM_STATUS_OK) 4624126Szf162725 goto fail; 463*7663SSowmini.Varadhan@Sun.COM caps = (wl_capability_t *)buf; 4644126Szf162725 if ((caps->caps & IEEE80211_C_WPA) == 0) 4654126Szf162725 return (DLADM_STATUS_NOTSUP); 4663871Syz147064 } 4673871Syz147064 4683871Syz147064 if (create_ibss) { 4695895Syz147064 status = do_set_channel(linkid, &channel); 4705895Syz147064 if (status != DLADM_STATUS_OK) 4713871Syz147064 goto fail; 4723871Syz147064 4735895Syz147064 status = do_set_createibss(linkid, &create_ibss); 4745895Syz147064 if (status != DLADM_STATUS_OK) 4753871Syz147064 goto fail; 4763871Syz147064 4773871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0) { 4783871Syz147064 generate_essid(&essid); 4793871Syz147064 essid_valid = B_TRUE; 4803871Syz147064 } 4813871Syz147064 } 4823871Syz147064 4833871Syz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0) { 4843871Syz147064 essid = attrp->wa_essid; 4853871Syz147064 essid_valid = B_TRUE; 4863871Syz147064 } 4873871Syz147064 4885895Syz147064 if (!essid_valid) { 4895895Syz147064 status = DLADM_STATUS_FAILED; 4905895Syz147064 goto fail; 4915895Syz147064 } 4925895Syz147064 4935895Syz147064 if ((status = do_set_essid(linkid, &essid)) != DLADM_STATUS_OK) 4943871Syz147064 goto fail; 4953871Syz147064 4964126Szf162725 /* 4974126Szf162725 * Because wpa daemon needs getting essid from driver, 4984126Szf162725 * we need call do_set_essid() first, then call wpa_instance_create(). 4994126Szf162725 */ 5004126Szf162725 if (secmode == DLADM_WLAN_SECMODE_WPA && keys != NULL) 5015895Syz147064 (void) wpa_instance_create(linkid, keys); 5024126Szf162725 5033871Syz147064 start = gethrtime(); 5043871Syz147064 for (;;) { 505*7663SSowmini.Varadhan@Sun.COM status = do_get_linkstatus(linkid, &wl_status, 506*7663SSowmini.Varadhan@Sun.COM sizeof (wl_status)); 5075895Syz147064 if (status != DLADM_STATUS_OK) 5083871Syz147064 goto fail; 5093871Syz147064 510*7663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) 5113871Syz147064 break; 5123871Syz147064 5133871Syz147064 (void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE); 5143871Syz147064 if ((timeout >= 0) && (gethrtime() - start) / 5155895Syz147064 NANOSEC >= timeout) { 5165895Syz147064 status = DLADM_STATUS_TIMEDOUT; 5175895Syz147064 goto fail; 5185895Syz147064 } 5193871Syz147064 } 5205895Syz147064 status = DLADM_STATUS_OK; 5213871Syz147064 fail: 5225895Syz147064 return (status); 5233871Syz147064 } 5243871Syz147064 5253871Syz147064 dladm_status_t 5265895Syz147064 dladm_wlan_connect(datalink_id_t linkid, dladm_wlan_attr_t *attrp, 5273871Syz147064 int timeout, void *keys, uint_t key_count, uint_t flags) 5283871Syz147064 { 5295895Syz147064 int i; 530*7663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 5313871Syz147064 connect_state_t state = {0, NULL, NULL}; 5323871Syz147064 attr_node_t *nodep = NULL; 5333871Syz147064 boolean_t create_ibss, set_authmode; 5343871Syz147064 dladm_wlan_attr_t **wl_list = NULL; 5355895Syz147064 dladm_status_t status; 536*7663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 5373871Syz147064 5385895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 5396233Syz147064 return (status); 5403871Syz147064 541*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) 542*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 5433871Syz147064 goto done; 5443871Syz147064 545*7663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) { 5463871Syz147064 status = DLADM_STATUS_ISCONN; 5473871Syz147064 goto done; 5483871Syz147064 } 5493871Syz147064 5503871Syz147064 set_authmode = ((attrp != NULL) && 5513871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0); 5523871Syz147064 create_ibss = ((flags & DLADM_WLAN_CONNECT_CREATEIBSS) != 0 && 5533871Syz147064 attrp != NULL && 5543871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 && 5553871Syz147064 attrp->wa_bsstype == DLADM_WLAN_BSSTYPE_IBSS); 5563871Syz147064 5573871Syz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 || 5583871Syz147064 (create_ibss && attrp != NULL && 5593871Syz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) { 560*7663SSowmini.Varadhan@Sun.COM status = do_connect(linkid, buf, sizeof (buf), attrp, 561*7663SSowmini.Varadhan@Sun.COM create_ibss, keys, key_count, timeout); 5623871Syz147064 goto done; 5633871Syz147064 } 5643871Syz147064 5653871Syz147064 state.cs_attr = attrp; 5663871Syz147064 state.cs_list = NULL; 5673871Syz147064 state.cs_count = 0; 5683871Syz147064 5695895Syz147064 status = dladm_wlan_scan(linkid, &state, connect_cb); 5703871Syz147064 if (status != DLADM_STATUS_OK) 5713871Syz147064 goto done; 5723871Syz147064 5733871Syz147064 if (state.cs_count == 0) { 5743871Syz147064 if (!create_ibss) { 5753871Syz147064 status = DLADM_STATUS_NOTFOUND; 5763871Syz147064 goto done; 5773871Syz147064 } 578*7663SSowmini.Varadhan@Sun.COM status = do_connect(linkid, buf, sizeof (buf), 579*7663SSowmini.Varadhan@Sun.COM attrp, create_ibss, keys, key_count, timeout); 5803871Syz147064 goto done; 5813871Syz147064 } 5823871Syz147064 5833871Syz147064 wl_list = malloc(state.cs_count * sizeof (dladm_wlan_attr_t *)); 5843871Syz147064 if (wl_list == NULL) { 5853871Syz147064 status = DLADM_STATUS_NOMEM; 5863871Syz147064 goto done; 5873871Syz147064 } 5883871Syz147064 5893871Syz147064 nodep = state.cs_list; 5903871Syz147064 for (i = 0; i < state.cs_count; i++) { 5913871Syz147064 wl_list[i] = &nodep->an_attr; 5923871Syz147064 nodep = nodep->an_next; 5933871Syz147064 } 5943871Syz147064 qsort(wl_list, state.cs_count, sizeof (dladm_wlan_attr_t *), 5953871Syz147064 attr_compare); 5963871Syz147064 5973871Syz147064 for (i = 0; i < state.cs_count; i++) { 5983871Syz147064 dladm_wlan_attr_t *ap = wl_list[i]; 5993871Syz147064 600*7663SSowmini.Varadhan@Sun.COM status = do_connect(linkid, buf, sizeof (buf), 601*7663SSowmini.Varadhan@Sun.COM ap, create_ibss, keys, key_count, timeout); 6023871Syz147064 if (status == DLADM_STATUS_OK) 6033871Syz147064 break; 6043871Syz147064 6053871Syz147064 if (!set_authmode) { 6063871Syz147064 ap->wa_auth = DLADM_WLAN_AUTH_SHARED; 6073871Syz147064 ap->wa_valid |= DLADM_WLAN_ATTR_AUTH; 608*7663SSowmini.Varadhan@Sun.COM status = do_connect(linkid, buf, sizeof (buf), 609*7663SSowmini.Varadhan@Sun.COM ap, create_ibss, keys, key_count, timeout); 6103871Syz147064 if (status == DLADM_STATUS_OK) 6113871Syz147064 break; 6123871Syz147064 } 6133871Syz147064 } 6143871Syz147064 done: 6153871Syz147064 if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN)) 616*7663SSowmini.Varadhan@Sun.COM (void) do_disconnect(linkid, buf, sizeof (buf)); 6173871Syz147064 6183871Syz147064 while (state.cs_list != NULL) { 6193871Syz147064 nodep = state.cs_list; 6203871Syz147064 state.cs_list = nodep->an_next; 6213871Syz147064 free(nodep); 6223871Syz147064 } 6233871Syz147064 free(wl_list); 6243871Syz147064 return (status); 6253871Syz147064 } 6263871Syz147064 6273871Syz147064 dladm_status_t 6285895Syz147064 dladm_wlan_disconnect(datalink_id_t linkid) 6293871Syz147064 { 630*7663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 6313871Syz147064 dladm_status_t status; 632*7663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 6333871Syz147064 6345895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 6355895Syz147064 return (status); 6363871Syz147064 637*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) 638*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 6393871Syz147064 goto done; 6403871Syz147064 641*7663SSowmini.Varadhan@Sun.COM if (wl_status != WL_CONNECTED) { 6423871Syz147064 status = DLADM_STATUS_NOTCONN; 6433871Syz147064 goto done; 6443871Syz147064 } 6453871Syz147064 646*7663SSowmini.Varadhan@Sun.COM if ((status = do_disconnect(linkid, buf, sizeof (buf))) 647*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 6483871Syz147064 goto done; 6493871Syz147064 650*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) 651*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 6523871Syz147064 goto done; 6533871Syz147064 654*7663SSowmini.Varadhan@Sun.COM if (wl_status == WL_CONNECTED) { 6553871Syz147064 status = DLADM_STATUS_FAILED; 6563871Syz147064 goto done; 6573871Syz147064 } 6583871Syz147064 6593871Syz147064 status = DLADM_STATUS_OK; 6603871Syz147064 done: 6613871Syz147064 return (status); 6623871Syz147064 } 6633871Syz147064 6645895Syz147064 dladm_status_t 6655895Syz147064 dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) 6663871Syz147064 { 6673871Syz147064 wl_rssi_t signal; 6683871Syz147064 wl_bss_type_t bsstype; 6693871Syz147064 wl_authmode_t authmode; 6703871Syz147064 wl_encryption_t encryption; 671*7663SSowmini.Varadhan@Sun.COM wl_rates_t *ratesp = NULL; 6723871Syz147064 dladm_wlan_attr_t *wl_attrp; 6735895Syz147064 dladm_status_t status; 674*7663SSowmini.Varadhan@Sun.COM char buf[WLDP_BUFSIZE]; 675*7663SSowmini.Varadhan@Sun.COM wl_essid_t wls; 676*7663SSowmini.Varadhan@Sun.COM wl_phy_conf_t wl_phy_conf; 677*7663SSowmini.Varadhan@Sun.COM wl_linkstatus_t wl_status; 6783871Syz147064 6793871Syz147064 if (attrp == NULL) 6803871Syz147064 return (DLADM_STATUS_BADARG); 6813871Syz147064 6825895Syz147064 if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) 6835895Syz147064 goto done; 6843871Syz147064 6853871Syz147064 (void) memset(attrp, 0, sizeof (*attrp)); 6863871Syz147064 wl_attrp = &attrp->la_wlan_attr; 6873871Syz147064 688*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) 689*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 6903871Syz147064 goto done; 6913871Syz147064 6923871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS; 693*7663SSowmini.Varadhan@Sun.COM if (wl_status != WL_CONNECTED) 6945895Syz147064 attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED; 6955895Syz147064 else 6965895Syz147064 attrp->la_status = DLADM_WLAN_LINK_CONNECTED; 6973871Syz147064 698*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_essid(linkid, &wls, sizeof (wls))) 699*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7003871Syz147064 goto done; 7013871Syz147064 702*7663SSowmini.Varadhan@Sun.COM (void) strlcpy(wl_attrp->wa_essid.we_bytes, wls.wl_essid_essid, 7033871Syz147064 DLADM_WLAN_MAX_ESSID_LEN); 7043871Syz147064 7053871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; 7063871Syz147064 707*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_bssid(linkid, buf, sizeof (buf))) 708*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7093871Syz147064 goto done; 7103871Syz147064 711*7663SSowmini.Varadhan@Sun.COM (void) memcpy(wl_attrp->wa_bssid.wb_bytes, buf, DLADM_WLAN_BSSID_LEN); 7123871Syz147064 7133871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; 7143871Syz147064 7155895Syz147064 if (attrp->la_status == DLADM_WLAN_LINK_DISCONNECTED) { 7164126Szf162725 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 7174126Szf162725 status = DLADM_STATUS_OK; 7184126Szf162725 goto done; 7194126Szf162725 } 7204126Szf162725 721*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_encryption(linkid, &encryption, 722*7663SSowmini.Varadhan@Sun.COM sizeof (encryption))) != DLADM_STATUS_OK) 7233871Syz147064 goto done; 7243871Syz147064 7253871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; 7263871Syz147064 7273871Syz147064 switch (encryption) { 7283871Syz147064 case WL_NOENCRYPTION: 7293871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_NONE; 7303871Syz147064 break; 7313871Syz147064 case WL_ENC_WEP: 7323871Syz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP; 7333871Syz147064 break; 7344126Szf162725 case WL_ENC_WPA: 7354126Szf162725 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA; 7364126Szf162725 break; 7373871Syz147064 default: 7383871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE; 7393871Syz147064 break; 7403871Syz147064 } 7413871Syz147064 742*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_signal(linkid, &signal, sizeof (signal))) 743*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7443871Syz147064 goto done; 7453871Syz147064 7463871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; 7473871Syz147064 wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal); 7483871Syz147064 749*7663SSowmini.Varadhan@Sun.COM ratesp = malloc(WLDP_BUFSIZE); 750*7663SSowmini.Varadhan@Sun.COM if (ratesp == NULL) { 751*7663SSowmini.Varadhan@Sun.COM status = DLADM_STATUS_NOMEM; 752*7663SSowmini.Varadhan@Sun.COM goto done; 753*7663SSowmini.Varadhan@Sun.COM } 754*7663SSowmini.Varadhan@Sun.COM 755*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_rate(linkid, ratesp, WLDP_BUFSIZE)) 756*7663SSowmini.Varadhan@Sun.COM != DLADM_STATUS_OK) 7573871Syz147064 goto done; 7583871Syz147064 7593871Syz147064 if (ratesp->wl_rates_num > 0) { 7603871Syz147064 uint_t i, r = 0; 7613871Syz147064 7623871Syz147064 for (i = 0; i < ratesp->wl_rates_num; i++) { 7633871Syz147064 if (ratesp->wl_rates_rates[i] > r) 7643871Syz147064 r = ratesp->wl_rates_rates[i]; 7653871Syz147064 } 7663871Syz147064 wl_attrp->wa_speed = r; 7673871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; 7683871Syz147064 } 7693871Syz147064 770*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_authmode(linkid, &authmode, 771*7663SSowmini.Varadhan@Sun.COM sizeof (authmode))) != DLADM_STATUS_OK) 7723871Syz147064 goto done; 7733871Syz147064 7743871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; 7753871Syz147064 7763871Syz147064 switch (authmode) { 7773871Syz147064 case WL_OPENSYSTEM: 7783871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN; 7793871Syz147064 break; 7803871Syz147064 case WL_SHAREDKEY: 7813871Syz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED; 7823871Syz147064 break; 7833871Syz147064 default: 7843871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH; 7853871Syz147064 break; 7863871Syz147064 } 7873871Syz147064 788*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_bsstype(linkid, &bsstype, 789*7663SSowmini.Varadhan@Sun.COM sizeof (bsstype))) != DLADM_STATUS_OK) 7903871Syz147064 goto done; 7913871Syz147064 7923871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 7933871Syz147064 7943871Syz147064 switch (bsstype) { 7953871Syz147064 case WL_BSS_BSS: 7963871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS; 7973871Syz147064 break; 7983871Syz147064 case WL_BSS_IBSS: 7993871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS; 8003871Syz147064 break; 8013871Syz147064 case WL_BSS_ANY: 8023871Syz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY; 8033871Syz147064 break; 8043871Syz147064 default: 8053871Syz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE; 8063871Syz147064 break; 8073871Syz147064 } 8083871Syz147064 809*7663SSowmini.Varadhan@Sun.COM if ((status = do_get_mode(linkid, &wl_phy_conf, 810*7663SSowmini.Varadhan@Sun.COM sizeof (wl_phy_conf))) != DLADM_STATUS_OK) 8113871Syz147064 goto done; 8123871Syz147064 813*7663SSowmini.Varadhan@Sun.COM wl_attrp->wa_mode = do_convert_mode(&wl_phy_conf); 8143871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8153871Syz147064 if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE) 8163871Syz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; 8173871Syz147064 8183871Syz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN; 8193871Syz147064 status = DLADM_STATUS_OK; 8203871Syz147064 8213871Syz147064 done: 822*7663SSowmini.Varadhan@Sun.COM free(ratesp); 8233871Syz147064 return (status); 8243871Syz147064 } 8253871Syz147064 8267408SSebastien.Roy@Sun.COM /* 8277408SSebastien.Roy@Sun.COM * Check to see if the link is wireless. 8287408SSebastien.Roy@Sun.COM */ 8293871Syz147064 static dladm_status_t 8305895Syz147064 dladm_wlan_validate(datalink_id_t linkid) 8313871Syz147064 { 8327408SSebastien.Roy@Sun.COM uint32_t media; 8333871Syz147064 dladm_status_t status; 8343871Syz147064 8357408SSebastien.Roy@Sun.COM status = dladm_datalink_id2info(linkid, NULL, NULL, &media, NULL, 0); 8367408SSebastien.Roy@Sun.COM if (status == DLADM_STATUS_OK) { 8377408SSebastien.Roy@Sun.COM if (media != DL_WIFI) 8387408SSebastien.Roy@Sun.COM status = DLADM_STATUS_LINKINVAL; 8393871Syz147064 } 8403871Syz147064 return (status); 8413871Syz147064 } 8423871Syz147064 8433871Syz147064 static boolean_t 8443871Syz147064 find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp) 8453871Syz147064 { 8463871Syz147064 int i; 8473871Syz147064 8483871Syz147064 for (i = 0; i < cnt; i++) { 8493871Syz147064 if (strcasecmp(str, vdp[i].vd_name) == 0) { 8503871Syz147064 *valp = vdp[i].vd_val; 8513871Syz147064 return (B_TRUE); 8523871Syz147064 } 8533871Syz147064 } 8543871Syz147064 return (B_FALSE); 8553871Syz147064 } 8563871Syz147064 8573871Syz147064 static boolean_t 8583871Syz147064 find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp) 8593871Syz147064 { 8603871Syz147064 int i; 8613871Syz147064 8623871Syz147064 for (i = 0; i < cnt; i++) { 8633871Syz147064 if (val == vdp[i].vd_val) { 8643871Syz147064 *strp = vdp[i].vd_name; 8653871Syz147064 return (B_TRUE); 8663871Syz147064 } 8673871Syz147064 } 8683871Syz147064 return (B_FALSE); 8693871Syz147064 } 8703871Syz147064 8713871Syz147064 const char * 8723871Syz147064 dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf) 8733871Syz147064 { 8743871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes); 8753871Syz147064 return (buf); 8763871Syz147064 } 8773871Syz147064 8783871Syz147064 const char * 8793871Syz147064 dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf) 8803871Syz147064 { 8813871Syz147064 return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN, 8823871Syz147064 IFT_OTHER)); 8833871Syz147064 } 8843871Syz147064 8853871Syz147064 static const char * 8863871Syz147064 dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf) 8873871Syz147064 { 8883871Syz147064 char *s; 8893871Syz147064 8903871Syz147064 if (!find_name_by_val(val, vdp, cnt, &s)) 8913871Syz147064 s = ""; 8923871Syz147064 8933871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 8943871Syz147064 return (buf); 8953871Syz147064 } 8963871Syz147064 8973871Syz147064 const char * 8983871Syz147064 dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf) 8993871Syz147064 { 9003871Syz147064 return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals, 9013871Syz147064 VALCNT(secmode_vals), buf)); 9023871Syz147064 } 9033871Syz147064 9043871Syz147064 const char * 9053871Syz147064 dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf) 9063871Syz147064 { 9073871Syz147064 return (dladm_wlan_val2str((uint_t)*strength, strength_vals, 9083871Syz147064 VALCNT(strength_vals), buf)); 9093871Syz147064 } 9103871Syz147064 9113871Syz147064 const char * 9123871Syz147064 dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf) 9133871Syz147064 { 9143871Syz147064 return (dladm_wlan_val2str((uint_t)*mode, mode_vals, 9153871Syz147064 VALCNT(mode_vals), buf)); 9163871Syz147064 } 9173871Syz147064 9183871Syz147064 const char * 9193871Syz147064 dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf) 9203871Syz147064 { 9213871Syz147064 (void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2, 9223871Syz147064 (float)(*speed) / 2); 9233871Syz147064 return (buf); 9243871Syz147064 } 9253871Syz147064 9263871Syz147064 const char * 9273871Syz147064 dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf) 9283871Syz147064 { 9293871Syz147064 return (dladm_wlan_val2str((uint_t)*auth, auth_vals, 9303871Syz147064 VALCNT(auth_vals), buf)); 9313871Syz147064 } 9323871Syz147064 9333871Syz147064 const char * 9343871Syz147064 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf) 9353871Syz147064 { 9363871Syz147064 return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals, 9373871Syz147064 VALCNT(bsstype_vals), buf)); 9383871Syz147064 } 9393871Syz147064 9403871Syz147064 const char * 9413871Syz147064 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf) 9423871Syz147064 { 9433871Syz147064 return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals, 9443871Syz147064 VALCNT(linkstatus_vals), buf)); 9453871Syz147064 } 9463871Syz147064 9473871Syz147064 dladm_status_t 9483871Syz147064 dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid) 9493871Syz147064 { 9506834Sff224033 if (str[0] == '\0' || strlen(str) > DLADM_WLAN_MAX_ESSID_LEN - 1) 9513871Syz147064 return (DLADM_STATUS_BADARG); 9523871Syz147064 9533871Syz147064 (void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN); 9543871Syz147064 return (DLADM_STATUS_OK); 9553871Syz147064 } 9563871Syz147064 9573871Syz147064 dladm_status_t 9583871Syz147064 dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid) 9593871Syz147064 { 9603871Syz147064 int len; 9613871Syz147064 uchar_t *buf; 9623871Syz147064 9633871Syz147064 buf = _link_aton(str, &len); 9643871Syz147064 if (buf == NULL) 9653871Syz147064 return (DLADM_STATUS_BADARG); 9663871Syz147064 9673871Syz147064 if (len != DLADM_WLAN_BSSID_LEN) { 9683871Syz147064 free(buf); 9693871Syz147064 return (DLADM_STATUS_BADARG); 9703871Syz147064 } 9713871Syz147064 9723871Syz147064 (void) memcpy(bssid->wb_bytes, buf, len); 9733871Syz147064 free(buf); 9743871Syz147064 return (DLADM_STATUS_OK); 9753871Syz147064 } 9763871Syz147064 9773871Syz147064 dladm_status_t 9783871Syz147064 dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode) 9793871Syz147064 { 9803871Syz147064 uint_t val; 9813871Syz147064 9823871Syz147064 if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val)) 9833871Syz147064 return (DLADM_STATUS_BADARG); 9843871Syz147064 9853871Syz147064 *secmode = (dladm_wlan_secmode_t)val; 9863871Syz147064 return (DLADM_STATUS_OK); 9873871Syz147064 } 9883871Syz147064 9893871Syz147064 dladm_status_t 9903871Syz147064 dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength) 9913871Syz147064 { 9923871Syz147064 uint_t val; 9933871Syz147064 9943871Syz147064 if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val)) 9953871Syz147064 return (DLADM_STATUS_BADARG); 9963871Syz147064 9973871Syz147064 *strength = (dladm_wlan_strength_t)val; 9983871Syz147064 return (DLADM_STATUS_OK); 9993871Syz147064 } 10003871Syz147064 10013871Syz147064 dladm_status_t 10023871Syz147064 dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode) 10033871Syz147064 { 10043871Syz147064 uint_t val; 10053871Syz147064 10063871Syz147064 if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val)) 10073871Syz147064 return (DLADM_STATUS_BADARG); 10083871Syz147064 10093871Syz147064 *mode = (dladm_wlan_mode_t)val; 10103871Syz147064 return (DLADM_STATUS_OK); 10113871Syz147064 } 10123871Syz147064 10133871Syz147064 dladm_status_t 10143871Syz147064 dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed) 10153871Syz147064 { 10163871Syz147064 *speed = (dladm_wlan_speed_t)(atof(str) * 2); 10173871Syz147064 return (DLADM_STATUS_OK); 10183871Syz147064 } 10193871Syz147064 10203871Syz147064 dladm_status_t 10213871Syz147064 dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth) 10223871Syz147064 { 10233871Syz147064 uint_t val; 10243871Syz147064 10253871Syz147064 if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val)) 10263871Syz147064 return (DLADM_STATUS_BADARG); 10273871Syz147064 10283871Syz147064 *auth = (dladm_wlan_auth_t)val; 10293871Syz147064 return (DLADM_STATUS_OK); 10303871Syz147064 } 10313871Syz147064 10323871Syz147064 dladm_status_t 10333871Syz147064 dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype) 10343871Syz147064 { 10353871Syz147064 uint_t val; 10363871Syz147064 10373871Syz147064 if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val)) 10383871Syz147064 return (DLADM_STATUS_BADARG); 10393871Syz147064 10403871Syz147064 *bsstype = (dladm_wlan_bsstype_t)val; 10413871Syz147064 return (DLADM_STATUS_OK); 10423871Syz147064 } 10433871Syz147064 10443871Syz147064 dladm_status_t 10453871Syz147064 dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus) 10463871Syz147064 { 10473871Syz147064 uint_t val; 10483871Syz147064 10495895Syz147064 if (!find_val_by_name(str, linkstatus_vals, 10505895Syz147064 VALCNT(linkstatus_vals), &val)) { 10513871Syz147064 return (DLADM_STATUS_BADARG); 10525895Syz147064 } 10533871Syz147064 10543871Syz147064 *linkstatus = (dladm_wlan_linkstatus_t)val; 10553871Syz147064 return (DLADM_STATUS_OK); 10563871Syz147064 } 10573871Syz147064 10585895Syz147064 dladm_status_t 1059*7663SSowmini.Varadhan@Sun.COM i_dladm_wlan_legacy_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id, 1060*7663SSowmini.Varadhan@Sun.COM size_t len, uint_t cmd, size_t cmdlen) 10613871Syz147064 { 10625895Syz147064 char linkname[MAXPATHLEN]; 10635895Syz147064 int fd, rc; 10643871Syz147064 struct strioctl stri; 10655895Syz147064 uint32_t flags; 10665895Syz147064 dladm_status_t status; 10675895Syz147064 uint32_t media; 10685895Syz147064 char link[MAXLINKNAMELEN]; 10695895Syz147064 10705895Syz147064 if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media, 10715895Syz147064 link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 10725895Syz147064 return (status); 10735895Syz147064 } 10745895Syz147064 10755895Syz147064 if (media != DL_WIFI) 10765895Syz147064 return (DLADM_STATUS_BADARG); 10775895Syz147064 10785895Syz147064 if (!(flags & DLADM_OPT_ACTIVE)) 10795895Syz147064 return (DLADM_STATUS_TEMPONLY); 10805895Syz147064 10815895Syz147064 /* 10825895Syz147064 * dlpi_open() is not used here because libdlpi depends on libdladm, 10835895Syz147064 * and we do not want to introduce recursive dependencies. 10845895Syz147064 */ 10855895Syz147064 (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link); 10865895Syz147064 if ((fd = open(linkname, O_RDWR)) < 0) 10877408SSebastien.Roy@Sun.COM return (dladm_errno2status(errno)); 10883871Syz147064 10893871Syz147064 gbuf->wldp_type = NET_802_11; 10903871Syz147064 gbuf->wldp_id = id; 10913871Syz147064 gbuf->wldp_length = len; 10923871Syz147064 10933871Syz147064 stri.ic_timout = 0; 10943871Syz147064 stri.ic_dp = (char *)gbuf; 10953871Syz147064 stri.ic_cmd = cmd; 10963871Syz147064 stri.ic_len = cmdlen; 10973871Syz147064 10983871Syz147064 if ((rc = ioctl(fd, I_STR, &stri)) != 0) { 10995895Syz147064 if (rc > 0) { 11005895Syz147064 /* 11015895Syz147064 * Non-negative return value indicates the specific 11025895Syz147064 * operation failed and the reason for the failure 11035895Syz147064 * was stored in gbuf->wldp_result. 11045895Syz147064 */ 11055895Syz147064 status = dladm_wlan_wlresult2status(gbuf); 11065895Syz147064 } else { 11075895Syz147064 /* 11085895Syz147064 * Negative return value indicates the ioctl failed. 11095895Syz147064 */ 11105895Syz147064 status = dladm_errno2status(errno); 11115895Syz147064 } 11123871Syz147064 } 11135895Syz147064 (void) close(fd); 11145895Syz147064 return (status); 11153871Syz147064 } 11163871Syz147064 1117*7663SSowmini.Varadhan@Sun.COM static dladm_status_t 1118*7663SSowmini.Varadhan@Sun.COM do_cmd_ioctl(datalink_id_t linkid, void *buf, int buflen, uint_t cmd) 11193871Syz147064 { 11205895Syz147064 wldp_t *gbuf; 11215895Syz147064 dladm_status_t status = DLADM_STATUS_OK; 11225895Syz147064 11235895Syz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) 11245895Syz147064 return (DLADM_STATUS_NOMEM); 11255895Syz147064 11263871Syz147064 (void) memset(gbuf, 0, MAX_BUF_LEN); 1127*7663SSowmini.Varadhan@Sun.COM status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, cmd, WLDP_BUFSIZE, 1128*7663SSowmini.Varadhan@Sun.COM WLAN_COMMAND, sizeof (wldp_t)); 1129*7663SSowmini.Varadhan@Sun.COM (void) memcpy(buf, gbuf->wldp_buf, buflen); 11305895Syz147064 free(gbuf); 11315895Syz147064 return (status); 11323871Syz147064 } 11333871Syz147064 11345895Syz147064 static dladm_status_t 1135*7663SSowmini.Varadhan@Sun.COM do_scan(datalink_id_t linkid, void *buf, int buflen) 11363871Syz147064 { 1137*7663SSowmini.Varadhan@Sun.COM return (do_cmd_ioctl(linkid, buf, buflen, WL_SCAN)); 11383871Syz147064 } 11393871Syz147064 11405895Syz147064 static dladm_status_t 1141*7663SSowmini.Varadhan@Sun.COM do_disconnect(datalink_id_t linkid, void *buf, int buflen) 11423871Syz147064 { 1143*7663SSowmini.Varadhan@Sun.COM if (do_get_wpamode(linkid, buf, buflen) == 0 && 1144*7663SSowmini.Varadhan@Sun.COM ((wl_wpa_t *)(buf))->wpa_flag > 0) 1145*7663SSowmini.Varadhan@Sun.COM (void) wpa_instance_delete(linkid); 1146*7663SSowmini.Varadhan@Sun.COM 1147*7663SSowmini.Varadhan@Sun.COM return (do_cmd_ioctl(linkid, buf, buflen, WL_DISASSOCIATE)); 11483871Syz147064 } 11493871Syz147064 11505895Syz147064 static dladm_status_t 1151*7663SSowmini.Varadhan@Sun.COM do_get_esslist(datalink_id_t linkid, void *buf, int buflen) 11523871Syz147064 { 1153*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_ESS_LIST, buflen, 1154*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 11553871Syz147064 } 11563871Syz147064 11575895Syz147064 static dladm_status_t 1158*7663SSowmini.Varadhan@Sun.COM do_get_bssid(datalink_id_t linkid, void *buf, int buflen) 11593871Syz147064 { 1160*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_BSSID, buflen, 1161*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 11623871Syz147064 } 11633871Syz147064 11645895Syz147064 static dladm_status_t 1165*7663SSowmini.Varadhan@Sun.COM do_get_essid(datalink_id_t linkid, void *buf, int buflen) 11663871Syz147064 { 1167*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_ESSID, buflen, 1168*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 11693871Syz147064 } 11703871Syz147064 11715895Syz147064 static dladm_status_t 1172*7663SSowmini.Varadhan@Sun.COM do_get_bsstype(datalink_id_t linkid, void *buf, int buflen) 11733871Syz147064 { 1174*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_BSSTYPE, buflen, 1175*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 11763871Syz147064 } 11773871Syz147064 11785895Syz147064 static dladm_status_t 1179*7663SSowmini.Varadhan@Sun.COM do_get_linkstatus(datalink_id_t linkid, void *buf, int buflen) 11803871Syz147064 { 1181*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_LINKSTATUS, buflen, 1182*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 11833871Syz147064 } 11843871Syz147064 11855895Syz147064 static dladm_status_t 1186*7663SSowmini.Varadhan@Sun.COM do_get_rate(datalink_id_t linkid, void *buf, int buflen) 11873871Syz147064 { 1188*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_DESIRED_RATES, 1189*7663SSowmini.Varadhan@Sun.COM buflen, B_FALSE)); 11903871Syz147064 } 11913871Syz147064 11923871Syz147064 static dladm_status_t 1193*7663SSowmini.Varadhan@Sun.COM do_get_authmode(datalink_id_t linkid, void *buf, int buflen) 11943871Syz147064 { 1195*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_AUTH_MODE, buflen, 1196*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 11973871Syz147064 } 11983871Syz147064 11993871Syz147064 static dladm_status_t 1200*7663SSowmini.Varadhan@Sun.COM do_get_encryption(datalink_id_t linkid, void *buf, int buflen) 12013871Syz147064 { 1202*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_ENCRYPTION, buflen, 1203*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 12043871Syz147064 } 12053871Syz147064 12063871Syz147064 static dladm_status_t 1207*7663SSowmini.Varadhan@Sun.COM do_get_signal(datalink_id_t linkid, void *buf, int buflen) 12083871Syz147064 { 1209*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_RSSI, buflen, 1210*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 12113871Syz147064 } 12123871Syz147064 12133871Syz147064 static dladm_status_t 1214*7663SSowmini.Varadhan@Sun.COM do_get_mode(datalink_id_t linkid, void *buf, int buflen) 12153871Syz147064 { 1216*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_PHY_CONFIG, 1217*7663SSowmini.Varadhan@Sun.COM buflen, B_FALSE)); 12183871Syz147064 } 12193871Syz147064 12205895Syz147064 static dladm_status_t 12215895Syz147064 do_set_bsstype(datalink_id_t linkid, dladm_wlan_bsstype_t *bsstype) 12223871Syz147064 { 12233871Syz147064 wl_bss_type_t ibsstype; 12243871Syz147064 12253871Syz147064 switch (*bsstype) { 12263871Syz147064 case DLADM_WLAN_BSSTYPE_BSS: 12273871Syz147064 ibsstype = WL_BSS_BSS; 12283871Syz147064 break; 12293871Syz147064 case DLADM_WLAN_BSSTYPE_IBSS: 12303871Syz147064 ibsstype = WL_BSS_IBSS; 12313871Syz147064 break; 12323871Syz147064 default: 12333871Syz147064 ibsstype = WL_BSS_ANY; 12343871Syz147064 break; 12353871Syz147064 } 1236*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &ibsstype, MAC_PROP_WL_BSSTYPE, 1237*7663SSowmini.Varadhan@Sun.COM sizeof (ibsstype), B_TRUE)); 12383871Syz147064 } 12393871Syz147064 12405895Syz147064 static dladm_status_t 12415895Syz147064 do_set_authmode(datalink_id_t linkid, dladm_wlan_auth_t *auth) 12423871Syz147064 { 12433871Syz147064 wl_authmode_t auth_mode; 12443871Syz147064 12453871Syz147064 switch (*auth) { 12463871Syz147064 case DLADM_WLAN_AUTH_OPEN: 12473871Syz147064 auth_mode = WL_OPENSYSTEM; 12483871Syz147064 break; 12493871Syz147064 case DLADM_WLAN_AUTH_SHARED: 12503871Syz147064 auth_mode = WL_SHAREDKEY; 12513871Syz147064 break; 12523871Syz147064 default: 12535895Syz147064 return (DLADM_STATUS_NOTSUP); 12543871Syz147064 } 1255*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &auth_mode, MAC_PROP_WL_AUTH_MODE, 1256*7663SSowmini.Varadhan@Sun.COM sizeof (auth_mode), B_TRUE)); 12573871Syz147064 } 12583871Syz147064 12595895Syz147064 static dladm_status_t 12605895Syz147064 do_set_encryption(datalink_id_t linkid, dladm_wlan_secmode_t *secmode) 12613871Syz147064 { 12623871Syz147064 wl_encryption_t encryption; 12633871Syz147064 12643871Syz147064 switch (*secmode) { 12653871Syz147064 case DLADM_WLAN_SECMODE_NONE: 12663871Syz147064 encryption = WL_NOENCRYPTION; 12673871Syz147064 break; 12683871Syz147064 case DLADM_WLAN_SECMODE_WEP: 12693871Syz147064 encryption = WL_ENC_WEP; 12703871Syz147064 break; 12714126Szf162725 case DLADM_WLAN_SECMODE_WPA: 12724126Szf162725 return (0); 12733871Syz147064 default: 12745895Syz147064 return (DLADM_STATUS_NOTSUP); 12753871Syz147064 } 1276*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &encryption, MAC_PROP_WL_ENCRYPTION, 1277*7663SSowmini.Varadhan@Sun.COM sizeof (encryption), B_TRUE)); 12783871Syz147064 } 12793871Syz147064 12805895Syz147064 static dladm_status_t 12815895Syz147064 do_set_key(datalink_id_t linkid, dladm_wlan_key_t *keys, 12823871Syz147064 uint_t key_count) 12833871Syz147064 { 12843871Syz147064 int i; 12853871Syz147064 wl_wep_key_t *wkp; 12863871Syz147064 wl_wep_key_tab_t wepkey_tab; 12874126Szf162725 dladm_wlan_key_t *kp; 12883871Syz147064 12893871Syz147064 if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL) 12905895Syz147064 return (DLADM_STATUS_BADARG); 12913871Syz147064 12923871Syz147064 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab)); 12933871Syz147064 for (i = 0; i < MAX_NWEPKEYS; i++) 12943871Syz147064 wepkey_tab[i].wl_wep_operation = WL_NUL; 12953871Syz147064 12963871Syz147064 for (i = 0; i < key_count; i++) { 12973871Syz147064 kp = &keys[i]; 12983871Syz147064 if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS) 12995895Syz147064 return (DLADM_STATUS_BADARG); 13003871Syz147064 if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN && 13013871Syz147064 kp->wk_len != DLADM_WLAN_WEPKEY128_LEN) 13025895Syz147064 return (DLADM_STATUS_BADARG); 13033871Syz147064 13043871Syz147064 wkp = &wepkey_tab[kp->wk_idx - 1]; 13053871Syz147064 wkp->wl_wep_operation = WL_ADD; 13063871Syz147064 wkp->wl_wep_length = kp->wk_len; 13073871Syz147064 (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len); 13083871Syz147064 } 13093871Syz147064 1310*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &wepkey_tab, MAC_PROP_WL_KEY_TAB, 1311*7663SSowmini.Varadhan@Sun.COM sizeof (wepkey_tab), B_TRUE)); 13123871Syz147064 } 13133871Syz147064 13145895Syz147064 static dladm_status_t 13155895Syz147064 do_set_essid(datalink_id_t linkid, dladm_wlan_essid_t *essid) 13163871Syz147064 { 13173871Syz147064 wl_essid_t iessid; 13183871Syz147064 13193871Syz147064 (void) memset(&iessid, 0, sizeof (essid)); 13203871Syz147064 13213871Syz147064 if (essid != NULL && essid->we_bytes[0] != '\0') { 13223871Syz147064 iessid.wl_essid_length = strlen(essid->we_bytes); 13233871Syz147064 (void) strlcpy(iessid.wl_essid_essid, essid->we_bytes, 13243871Syz147064 sizeof (iessid.wl_essid_essid)); 13253871Syz147064 } else { 13265895Syz147064 return (DLADM_STATUS_BADARG); 13275102Syz147064 } 1328*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &iessid, MAC_PROP_WL_ESSID, 1329*7663SSowmini.Varadhan@Sun.COM sizeof (iessid), B_TRUE)); 13303871Syz147064 } 13313871Syz147064 13323871Syz147064 static dladm_status_t 13335895Syz147064 do_set_channel(datalink_id_t linkid, dladm_wlan_channel_t *channel) 13343871Syz147064 { 13353871Syz147064 wl_phy_conf_t phy_conf; 13363871Syz147064 13373871Syz147064 if (*channel > MAX_CHANNEL_NUM) 13385895Syz147064 return (DLADM_STATUS_BADVAL); 13393871Syz147064 13403871Syz147064 (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); 13413871Syz147064 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel; 13423871Syz147064 1343*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &phy_conf, MAC_PROP_WL_PHY_CONFIG, 1344*7663SSowmini.Varadhan@Sun.COM sizeof (phy_conf), B_TRUE)); 13453871Syz147064 } 13463871Syz147064 13475895Syz147064 static dladm_status_t 13485895Syz147064 do_set_createibss(datalink_id_t linkid, boolean_t *create_ibss) 13493871Syz147064 { 13503871Syz147064 wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss); 13513871Syz147064 1352*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &cr, MAC_PROP_WL_CREATE_IBSS, 1353*7663SSowmini.Varadhan@Sun.COM sizeof (cr), B_TRUE)); 13543871Syz147064 } 13553871Syz147064 13563871Syz147064 static void 13573871Syz147064 generate_essid(dladm_wlan_essid_t *essid) 13583871Syz147064 { 13593871Syz147064 srandom(gethrtime()); 13603871Syz147064 (void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d", 13613871Syz147064 random()); 13623871Syz147064 } 13634126Szf162725 13645895Syz147064 static dladm_status_t 1365*7663SSowmini.Varadhan@Sun.COM do_get_capability(datalink_id_t linkid, void *buf, int buflen) 13664126Szf162725 { 1367*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_CAPABILITY, 1368*7663SSowmini.Varadhan@Sun.COM buflen, B_FALSE)); 13694126Szf162725 } 13704126Szf162725 13714126Szf162725 static dladm_status_t 1372*7663SSowmini.Varadhan@Sun.COM do_get_wpamode(datalink_id_t linkid, void *buf, int buflen) 13734126Szf162725 { 1374*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_WPA, buflen, 1375*7663SSowmini.Varadhan@Sun.COM B_FALSE)); 13764126Szf162725 } 13774126Szf162725 13784126Szf162725 dladm_status_t 13795895Syz147064 dladm_wlan_wpa_get_sr(datalink_id_t linkid, dladm_wlan_ess_t *sr, 13805895Syz147064 uint_t escnt, uint_t *estot) 13814126Szf162725 { 13824126Szf162725 int i, n; 13834126Szf162725 wl_wpa_ess_t *es; 13844126Szf162725 dladm_status_t status; 13854126Szf162725 1386*7663SSowmini.Varadhan@Sun.COM es = malloc(WLDP_BUFSIZE); 1387*7663SSowmini.Varadhan@Sun.COM if (es == NULL) 13884126Szf162725 return (DLADM_STATUS_NOMEM); 13894126Szf162725 1390*7663SSowmini.Varadhan@Sun.COM status = i_dladm_wlan_param(linkid, es, MAC_PROP_WL_SCANRESULTS, 1391*7663SSowmini.Varadhan@Sun.COM WLDP_BUFSIZE, B_FALSE); 13924126Szf162725 13934126Szf162725 if (status == DLADM_STATUS_OK) { 13944126Szf162725 n = (es->count > escnt) ? escnt : es->count; 13954126Szf162725 for (i = 0; i < n; i ++) { 13964126Szf162725 (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid, 13974126Szf162725 DLADM_WLAN_BSSID_LEN); 13984126Szf162725 sr[i].we_ssid_len = es->ess[i].ssid_len; 13994126Szf162725 (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid, 14004126Szf162725 es->ess[i].ssid_len); 14014126Szf162725 sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len; 14024126Szf162725 (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie, 14034126Szf162725 es->ess[i].wpa_ie_len); 14044126Szf162725 sr[i].we_freq = es->ess[i].freq; 14054126Szf162725 } 14064126Szf162725 *estot = n; 14074126Szf162725 } 14084126Szf162725 1409*7663SSowmini.Varadhan@Sun.COM free(es); 14104126Szf162725 return (status); 14114126Szf162725 } 14124126Szf162725 14134126Szf162725 dladm_status_t 14145895Syz147064 dladm_wlan_wpa_set_ie(datalink_id_t linkid, uint8_t *wpa_ie, uint_t wpa_ie_len) 14154126Szf162725 { 14164126Szf162725 wl_wpa_ie_t *ie; 14174126Szf162725 uint_t len; 14184126Szf162725 dladm_status_t status; 14194126Szf162725 14204126Szf162725 if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN) 14214126Szf162725 return (DLADM_STATUS_BADARG); 14224126Szf162725 len = sizeof (wl_wpa_ie_t) + wpa_ie_len; 14234126Szf162725 ie = malloc(len); 14244126Szf162725 if (ie == NULL) 14254126Szf162725 return (DLADM_STATUS_NOMEM); 14264126Szf162725 14274126Szf162725 (void) memset(ie, 0, len); 14284126Szf162725 ie->wpa_ie_len = wpa_ie_len; 14294126Szf162725 (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len); 14304126Szf162725 1431*7663SSowmini.Varadhan@Sun.COM status = i_dladm_wlan_param(linkid, ie, MAC_PROP_WL_SETOPTIE, len, 1432*7663SSowmini.Varadhan@Sun.COM B_TRUE); 14334126Szf162725 free(ie); 14344126Szf162725 14354126Szf162725 return (status); 14364126Szf162725 } 14374126Szf162725 14384126Szf162725 dladm_status_t 14395895Syz147064 dladm_wlan_wpa_set_wpa(datalink_id_t linkid, boolean_t flag) 14404126Szf162725 { 14415895Syz147064 wl_wpa_t wpa; 14424126Szf162725 14434126Szf162725 wpa.wpa_flag = flag; 1444*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &wpa, MAC_PROP_WL_WPA, 1445*7663SSowmini.Varadhan@Sun.COM sizeof (wpa), B_TRUE)); 14464126Szf162725 } 14474126Szf162725 14484126Szf162725 dladm_status_t 14495895Syz147064 dladm_wlan_wpa_del_key(datalink_id_t linkid, uint_t key_idx, 14504126Szf162725 const dladm_wlan_bssid_t *addr) 14514126Szf162725 { 14525895Syz147064 wl_del_key_t wk; 14534126Szf162725 14544126Szf162725 wk.idk_keyix = key_idx; 14554126Szf162725 if (addr != NULL) 14564126Szf162725 (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes, 14574126Szf162725 DLADM_WLAN_BSSID_LEN); 14584126Szf162725 1459*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &wk, MAC_PROP_WL_DELKEY, 1460*7663SSowmini.Varadhan@Sun.COM sizeof (wk), B_TRUE)); 14614126Szf162725 } 14624126Szf162725 14634126Szf162725 dladm_status_t 14645895Syz147064 dladm_wlan_wpa_set_key(datalink_id_t linkid, dladm_wlan_cipher_t cipher, 14654126Szf162725 const dladm_wlan_bssid_t *addr, boolean_t set_tx, uint64_t seq, 14664126Szf162725 uint_t key_idx, uint8_t *key, uint_t key_len) 14674126Szf162725 { 14685895Syz147064 wl_key_t wk; 14694126Szf162725 14704126Szf162725 (void) memset(&wk, 0, sizeof (wl_key_t)); 14714126Szf162725 switch (cipher) { 14724126Szf162725 case DLADM_WLAN_CIPHER_WEP: 14734126Szf162725 wk.ik_type = IEEE80211_CIPHER_WEP; 14744126Szf162725 break; 14754126Szf162725 case DLADM_WLAN_CIPHER_TKIP: 14764126Szf162725 wk.ik_type = IEEE80211_CIPHER_TKIP; 14774126Szf162725 break; 14784126Szf162725 case DLADM_WLAN_CIPHER_AES_OCB: 14794126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_OCB; 14804126Szf162725 break; 14814126Szf162725 case DLADM_WLAN_CIPHER_AES_CCM: 14824126Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_CCM; 14834126Szf162725 break; 14844126Szf162725 case DLADM_WLAN_CIPHER_CKIP: 14854126Szf162725 wk.ik_type = IEEE80211_CIPHER_CKIP; 14864126Szf162725 break; 14874126Szf162725 case DLADM_WLAN_CIPHER_NONE: 14884126Szf162725 wk.ik_type = IEEE80211_CIPHER_NONE; 14894126Szf162725 break; 14904126Szf162725 default: 14914126Szf162725 return (DLADM_STATUS_BADARG); 14924126Szf162725 } 14934126Szf162725 wk.ik_flags = IEEE80211_KEY_RECV; 14944126Szf162725 if (set_tx) { 14954126Szf162725 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; 14964126Szf162725 (void) memcpy(wk.ik_macaddr, addr->wb_bytes, 14974126Szf162725 DLADM_WLAN_BSSID_LEN); 14984126Szf162725 } else 14994126Szf162725 (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN); 15004126Szf162725 wk.ik_keyix = key_idx; 15014126Szf162725 wk.ik_keylen = key_len; 15024126Szf162725 (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */ 15034126Szf162725 (void) memcpy(wk.ik_keydata, key, key_len); 15044126Szf162725 1505*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &wk, MAC_PROP_WL_KEY, 1506*7663SSowmini.Varadhan@Sun.COM sizeof (wk), B_TRUE)); 15074126Szf162725 } 15084126Szf162725 15094126Szf162725 dladm_status_t 15105895Syz147064 dladm_wlan_wpa_set_mlme(datalink_id_t linkid, dladm_wlan_mlme_op_t op, 15114126Szf162725 dladm_wlan_reason_t reason, dladm_wlan_bssid_t *bssid) 15124126Szf162725 { 15134126Szf162725 wl_mlme_t mlme; 15144126Szf162725 15154126Szf162725 (void) memset(&mlme, 0, sizeof (wl_mlme_t)); 15164126Szf162725 switch (op) { 15174126Szf162725 case DLADM_WLAN_MLME_ASSOC: 15184126Szf162725 mlme.im_op = IEEE80211_MLME_ASSOC; 15194126Szf162725 break; 15204126Szf162725 case DLADM_WLAN_MLME_DISASSOC: 15214126Szf162725 mlme.im_op = IEEE80211_MLME_DISASSOC; 15224126Szf162725 break; 15234126Szf162725 default: 15244126Szf162725 return (DLADM_STATUS_BADARG); 15254126Szf162725 } 15264126Szf162725 mlme.im_reason = reason; 15274126Szf162725 if (bssid != NULL) 15284126Szf162725 (void) memcpy(mlme.im_macaddr, bssid->wb_bytes, 15294126Szf162725 DLADM_WLAN_BSSID_LEN); 15304126Szf162725 1531*7663SSowmini.Varadhan@Sun.COM return (i_dladm_wlan_param(linkid, &mlme, MAC_PROP_WL_MLME, 1532*7663SSowmini.Varadhan@Sun.COM sizeof (mlme), B_TRUE)); 15334126Szf162725 } 15344126Szf162725 15354126Szf162725 /* 15364126Szf162725 * routines of create instance 15374126Szf162725 */ 15384126Szf162725 static scf_propertygroup_t * 15394126Szf162725 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance, 15404126Szf162725 const char *pg_name, const char *pg_type) 15414126Szf162725 { 15424126Szf162725 scf_propertygroup_t *pg; 15434126Szf162725 15444126Szf162725 pg = scf_pg_create(handle); 15454126Szf162725 if (pg == NULL) 15464126Szf162725 return (NULL); 15474126Szf162725 15484126Szf162725 if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) { 15494126Szf162725 scf_pg_destroy(pg); 15504126Szf162725 return (NULL); 15514126Szf162725 } 15524126Szf162725 15534126Szf162725 return (pg); 15544126Szf162725 } 15554126Szf162725 15565895Syz147064 static dladm_status_t 15574126Szf162725 add_new_property(scf_handle_t *handle, const char *prop_name, 15584126Szf162725 scf_type_t type, const char *val, scf_transaction_t *tx) 15594126Szf162725 { 15604126Szf162725 scf_value_t *value = NULL; 15614126Szf162725 scf_transaction_entry_t *entry = NULL; 15624126Szf162725 15634126Szf162725 entry = scf_entry_create(handle); 15644126Szf162725 if (entry == NULL) 15654126Szf162725 goto out; 15664126Szf162725 15674126Szf162725 value = scf_value_create(handle); 15684126Szf162725 if (value == NULL) 15694126Szf162725 goto out; 15704126Szf162725 15714126Szf162725 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) 15724126Szf162725 goto out; 15734126Szf162725 15744126Szf162725 if (scf_value_set_from_string(value, type, val) != 0) 15754126Szf162725 goto out; 15764126Szf162725 15774126Szf162725 if (scf_entry_add_value(entry, value) != 0) 15784126Szf162725 goto out; 15794126Szf162725 15805895Syz147064 return (DLADM_STATUS_OK); 15814126Szf162725 15824126Szf162725 out: 15834126Szf162725 if (value != NULL) 15844126Szf162725 scf_value_destroy(value); 15854126Szf162725 if (entry != NULL) 15864126Szf162725 scf_entry_destroy(entry); 15874126Szf162725 15885895Syz147064 return (DLADM_STATUS_FAILED); 15894126Szf162725 } 15904126Szf162725 15915895Syz147064 static dladm_status_t 15924126Szf162725 add_pg_method(scf_handle_t *handle, scf_instance_t *instance, 15934126Szf162725 const char *pg_name, const char *flags) 15944126Szf162725 { 15954126Szf162725 int rv, size; 15965895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 15974126Szf162725 char *command = NULL; 15984126Szf162725 scf_transaction_t *tran = NULL; 15994126Szf162725 scf_propertygroup_t *pg; 16004126Szf162725 16014126Szf162725 pg = add_property_group_to_instance(handle, instance, 16024126Szf162725 pg_name, SCF_GROUP_METHOD); 16034126Szf162725 if (pg == NULL) 16044126Szf162725 goto out; 16054126Szf162725 16064126Szf162725 tran = scf_transaction_create(handle); 16074126Szf162725 if (tran == NULL) 16084126Szf162725 goto out; 16094126Szf162725 16104126Szf162725 size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1; 16114126Szf162725 command = malloc(size); 16124126Szf162725 if (command == NULL) { 16135895Syz147064 status = DLADM_STATUS_NOMEM; 16144126Szf162725 goto out; 16154126Szf162725 } 16164126Szf162725 (void) snprintf(command, size, "%s %s", SVC_METHOD, flags); 16174126Szf162725 16184126Szf162725 do { 16194126Szf162725 if (scf_transaction_start(tran, pg) != 0) 16204126Szf162725 goto out; 16214126Szf162725 16224126Szf162725 if (add_new_property(handle, SCF_PROPERTY_EXEC, 16235895Syz147064 SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) { 16244126Szf162725 goto out; 16254126Szf162725 } 16264126Szf162725 16274126Szf162725 rv = scf_transaction_commit(tran); 16284126Szf162725 switch (rv) { 16294126Szf162725 case 1: 16305895Syz147064 status = DLADM_STATUS_OK; 16314126Szf162725 goto out; 16324126Szf162725 case 0: 16334126Szf162725 scf_transaction_destroy_children(tran); 16344126Szf162725 if (scf_pg_update(pg) == -1) { 16354126Szf162725 goto out; 16364126Szf162725 } 16374126Szf162725 break; 16384126Szf162725 case -1: 16394126Szf162725 default: 16404126Szf162725 goto out; 16414126Szf162725 } 16424126Szf162725 } while (rv == 0); 16434126Szf162725 16444126Szf162725 out: 16454126Szf162725 if (tran != NULL) { 16464126Szf162725 scf_transaction_destroy_children(tran); 16474126Szf162725 scf_transaction_destroy(tran); 16484126Szf162725 } 16494126Szf162725 16504126Szf162725 if (pg != NULL) 16514126Szf162725 scf_pg_destroy(pg); 16524126Szf162725 16534126Szf162725 if (command != NULL) 16544126Szf162725 free(command); 16554126Szf162725 16564126Szf162725 return (status); 16574126Szf162725 } 16584126Szf162725 16595895Syz147064 static dladm_status_t 16604126Szf162725 do_create_instance(scf_handle_t *handle, scf_service_t *svc, 16614126Szf162725 const char *instance_name, const char *command) 16624126Szf162725 { 16635895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 16644126Szf162725 char *buf; 16654126Szf162725 ssize_t max_fmri_len; 16664126Szf162725 scf_instance_t *instance; 16674126Szf162725 16684126Szf162725 instance = scf_instance_create(handle); 16694126Szf162725 if (instance == NULL) 16704126Szf162725 goto out; 16714126Szf162725 16724126Szf162725 if (scf_service_add_instance(svc, instance_name, instance) != 0) { 16734126Szf162725 if (scf_error() == SCF_ERROR_EXISTS) 16744126Szf162725 /* Let the caller deal with the duplicate instance */ 16755895Syz147064 status = DLADM_STATUS_EXIST; 16764126Szf162725 goto out; 16774126Szf162725 } 16784126Szf162725 16794126Szf162725 if (add_pg_method(handle, instance, "start", 16805895Syz147064 command) != DLADM_STATUS_OK) { 16814126Szf162725 goto out; 16824126Szf162725 } 16834126Szf162725 16844126Szf162725 /* enabling the instance */ 16854126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 16864126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) 16874126Szf162725 goto out; 16884126Szf162725 16894126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 16904126Szf162725 if ((smf_disable_instance(buf, 0) != 0) || 16914126Szf162725 (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) { 16924126Szf162725 goto out; 16934126Szf162725 } 16945895Syz147064 status = DLADM_STATUS_OK; 16954126Szf162725 } 16964126Szf162725 16974126Szf162725 out: 16984126Szf162725 if (instance != NULL) 16994126Szf162725 scf_instance_destroy(instance); 17004126Szf162725 return (status); 17014126Szf162725 } 17024126Szf162725 17035895Syz147064 static dladm_status_t 17044126Szf162725 create_instance(const char *instance_name, const char *command) 17054126Szf162725 { 17065895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17074126Szf162725 scf_service_t *svc = NULL; 17084126Szf162725 scf_handle_t *handle = NULL; 17094126Szf162725 17104126Szf162725 handle = scf_handle_create(SCF_VERSION); 17114126Szf162725 if (handle == NULL) 17124126Szf162725 goto out; 17134126Szf162725 17144126Szf162725 if (scf_handle_bind(handle) == -1) 17154126Szf162725 goto out; 17164126Szf162725 17174126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 17184126Szf162725 goto out; 17194126Szf162725 17204126Szf162725 if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc, 17214126Szf162725 NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) 17224126Szf162725 goto out; 17234126Szf162725 17244126Szf162725 status = do_create_instance(handle, svc, instance_name, command); 17254126Szf162725 17264126Szf162725 out: 17274126Szf162725 if (svc != NULL) 17284126Szf162725 scf_service_destroy(svc); 17294126Szf162725 17304126Szf162725 if (handle != NULL) { 17314126Szf162725 (void) scf_handle_unbind(handle); 17324126Szf162725 scf_handle_destroy(handle); 17334126Szf162725 } 17344126Szf162725 17354126Szf162725 return (status); 17364126Szf162725 } 17374126Szf162725 17384126Szf162725 /* 17394126Szf162725 * routines of delete instance 17404126Szf162725 */ 17414126Szf162725 #define DEFAULT_TIMEOUT 60000000 17424126Szf162725 #define INIT_WAIT_USECS 50000 17434126Szf162725 17444126Szf162725 static void 17454126Szf162725 wait_until_disabled(scf_handle_t *handle, char *fmri) 17464126Szf162725 { 17474126Szf162725 char *state; 17484126Szf162725 useconds_t max; 17494126Szf162725 useconds_t usecs; 17504126Szf162725 uint64_t *cp = NULL; 17514126Szf162725 scf_simple_prop_t *sp = NULL; 17524126Szf162725 17534126Szf162725 max = DEFAULT_TIMEOUT; 17544126Szf162725 17554126Szf162725 if (((sp = scf_simple_prop_get(handle, fmri, "stop", 17564126Szf162725 SCF_PROPERTY_TIMEOUT)) != NULL) && 17574126Szf162725 ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0)) 17584126Szf162725 max = (*cp) * 1000000; /* convert to usecs */ 17594126Szf162725 17604126Szf162725 if (sp != NULL) 17614126Szf162725 scf_simple_prop_free(sp); 17624126Szf162725 17634126Szf162725 for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) { 17644126Szf162725 /* incremental wait */ 17654126Szf162725 usecs *= 2; 17664126Szf162725 usecs = (usecs > max) ? max : usecs; 17674126Szf162725 17684126Szf162725 (void) usleep(usecs); 17694126Szf162725 17704126Szf162725 /* Check state after the wait */ 17714126Szf162725 if ((state = smf_get_state(fmri)) != NULL) { 17724126Szf162725 if (strcmp(state, "disabled") == 0) 17734126Szf162725 return; 17744126Szf162725 } 17754126Szf162725 } 17764126Szf162725 } 17774126Szf162725 17785895Syz147064 static dladm_status_t 17794126Szf162725 delete_instance(const char *instance_name) 17804126Szf162725 { 17815895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 17824126Szf162725 char *buf; 17834126Szf162725 ssize_t max_fmri_len; 17844126Szf162725 scf_scope_t *scope = NULL; 17854126Szf162725 scf_service_t *svc = NULL; 17864126Szf162725 scf_handle_t *handle = NULL; 17874126Szf162725 scf_instance_t *instance; 17884126Szf162725 17894126Szf162725 handle = scf_handle_create(SCF_VERSION); 17904126Szf162725 if (handle == NULL) 17914126Szf162725 goto out; 17924126Szf162725 17934126Szf162725 if (scf_handle_bind(handle) == -1) 17944126Szf162725 goto out; 17954126Szf162725 17964126Szf162725 if ((scope = scf_scope_create(handle)) == NULL) 17974126Szf162725 goto out; 17984126Szf162725 17994126Szf162725 if ((svc = scf_service_create(handle)) == NULL) 18004126Szf162725 goto out; 18014126Szf162725 18024126Szf162725 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1) 18034126Szf162725 goto out; 18044126Szf162725 18054126Szf162725 if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0) 18064126Szf162725 goto out; 18074126Szf162725 18084126Szf162725 instance = scf_instance_create(handle); 18094126Szf162725 if (instance == NULL) 18104126Szf162725 goto out; 18114126Szf162725 18124126Szf162725 if (scf_service_get_instance(svc, instance_name, instance) != 0) { 18134126Szf162725 scf_error_t scf_errnum = scf_error(); 18144126Szf162725 18154126Szf162725 if (scf_errnum == SCF_ERROR_NOT_FOUND) 18165895Syz147064 status = DLADM_STATUS_OK; 18174126Szf162725 18184126Szf162725 scf_instance_destroy(instance); 18194126Szf162725 goto out; 18204126Szf162725 } 18214126Szf162725 18224126Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 18234126Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) { 18244126Szf162725 scf_instance_destroy(instance); 18254126Szf162725 goto out; 18264126Szf162725 } 18274126Szf162725 18284126Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) { 18294126Szf162725 char *state; 18304126Szf162725 18314126Szf162725 state = smf_get_state(buf); 18324126Szf162725 if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 || 18334126Szf162725 strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) { 18344126Szf162725 if (smf_disable_instance(buf, 0) == 0) { 18354126Szf162725 /* 18364126Szf162725 * Wait for some time till timeout to avoid 18374126Szf162725 * a race with scf_instance_delete() below. 18384126Szf162725 */ 18394126Szf162725 wait_until_disabled(handle, buf); 18404126Szf162725 } 18414126Szf162725 } 18424126Szf162725 } 18434126Szf162725 18444126Szf162725 if (scf_instance_delete(instance) != 0) { 18454126Szf162725 scf_instance_destroy(instance); 18464126Szf162725 goto out; 18474126Szf162725 } 18484126Szf162725 18494126Szf162725 scf_instance_destroy(instance); 18504126Szf162725 18515895Syz147064 status = DLADM_STATUS_OK; 18524126Szf162725 18534126Szf162725 out: 18544126Szf162725 if (svc != NULL) 18554126Szf162725 scf_service_destroy(svc); 18564126Szf162725 18574126Szf162725 if (scope != NULL) 18584126Szf162725 scf_scope_destroy(scope); 18594126Szf162725 18604126Szf162725 if (handle != NULL) { 18614126Szf162725 (void) scf_handle_unbind(handle); 18624126Szf162725 scf_handle_destroy(handle); 18634126Szf162725 } 18644126Szf162725 18654126Szf162725 return (status); 18664126Szf162725 } 18674126Szf162725 18685895Syz147064 static dladm_status_t 18695895Syz147064 wpa_instance_create(datalink_id_t linkid, void *key) 18704126Szf162725 { 18715895Syz147064 dladm_status_t status = DLADM_STATUS_FAILED; 18724126Szf162725 char *command = NULL; 18734126Szf162725 char *wk_name = ((dladm_wlan_key_t *)key)->wk_name; 18744126Szf162725 int size; 18755895Syz147064 char instance_name[MAXLINKNAMELEN]; 18765895Syz147064 18775895Syz147064 /* 18785895Syz147064 * Use the link name as the instance name of the network/wpad service. 18795895Syz147064 */ 18805895Syz147064 status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name, 18815895Syz147064 sizeof (instance_name)); 18825895Syz147064 if (status != DLADM_STATUS_OK) 18835895Syz147064 goto out; 18844126Szf162725 18854126Szf162725 size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1; 18864126Szf162725 command = malloc(size); 18874126Szf162725 if (command == NULL) { 18885895Syz147064 status = DLADM_STATUS_NOMEM; 18894126Szf162725 goto out; 18904126Szf162725 } 18914126Szf162725 (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name); 18924126Szf162725 18934126Szf162725 status = create_instance(instance_name, command); 18945895Syz147064 if (status == DLADM_STATUS_EXIST) { 18954126Szf162725 /* 18964126Szf162725 * Delete the existing instance and create a new instance 18974126Szf162725 * with the supplied arguments. 18984126Szf162725 */ 18994126Szf162725 if ((status = delete_instance(instance_name)) == 19005895Syz147064 DLADM_STATUS_OK) { 19014126Szf162725 status = create_instance(instance_name, command); 19024126Szf162725 } 19034126Szf162725 } 19044126Szf162725 19054126Szf162725 out: 19064126Szf162725 if (command != NULL) 19074126Szf162725 free(command); 19084126Szf162725 19094126Szf162725 return (status); 19104126Szf162725 } 19114126Szf162725 19125895Syz147064 static dladm_status_t 19135895Syz147064 wpa_instance_delete(datalink_id_t linkid) 19144126Szf162725 { 19155895Syz147064 char instance_name[MAXLINKNAMELEN]; 19164126Szf162725 19175895Syz147064 /* 19185895Syz147064 * Get the instance name of the network/wpad service (the same as 19195895Syz147064 * the link name). 19205895Syz147064 */ 19215895Syz147064 if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name, 19225895Syz147064 sizeof (instance_name)) != DLADM_STATUS_OK) 19235895Syz147064 return (DLADM_STATUS_FAILED); 19244126Szf162725 19255895Syz147064 return (delete_instance(instance_name)); 19264126Szf162725 } 1927