10ba2cbe9Sxc151355 /* 2*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 30ba2cbe9Sxc151355 * Use is subject to license terms. 40ba2cbe9Sxc151355 */ 50ba2cbe9Sxc151355 60ba2cbe9Sxc151355 /* 70ba2cbe9Sxc151355 * Redistribution and use in source and binary forms, with or without 80ba2cbe9Sxc151355 * modification, are permitted provided that the following conditions 90ba2cbe9Sxc151355 * are met: 100ba2cbe9Sxc151355 * 1. Redistributions of source code must retain the above copyright 110ba2cbe9Sxc151355 * notice, this list of conditions and the following disclaimer. 120ba2cbe9Sxc151355 * 2. Redistributions in binary form must reproduce the above copyright 130ba2cbe9Sxc151355 * notice, this list of conditions and the following disclaimer in the 140ba2cbe9Sxc151355 * documentation and/or other materials provided with the distribution. 150ba2cbe9Sxc151355 * 3. The name of the author may not be used to endorse or promote products 160ba2cbe9Sxc151355 * derived from this software without specific prior written permission. 170ba2cbe9Sxc151355 * 180ba2cbe9Sxc151355 * Alternatively, this software may be distributed under the terms of the 190ba2cbe9Sxc151355 * GNU General Public License ("GPL") version 2 as published by the Free 200ba2cbe9Sxc151355 * Software Foundation. 210ba2cbe9Sxc151355 * 220ba2cbe9Sxc151355 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 230ba2cbe9Sxc151355 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 240ba2cbe9Sxc151355 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 250ba2cbe9Sxc151355 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 260ba2cbe9Sxc151355 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 270ba2cbe9Sxc151355 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 280ba2cbe9Sxc151355 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 290ba2cbe9Sxc151355 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 300ba2cbe9Sxc151355 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 310ba2cbe9Sxc151355 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 320ba2cbe9Sxc151355 */ 330ba2cbe9Sxc151355 34bcb5c89dSSowmini Varadhan 350ba2cbe9Sxc151355 #include <sys/param.h> 360ba2cbe9Sxc151355 #include <sys/types.h> 370ba2cbe9Sxc151355 #include <sys/errno.h> 380ba2cbe9Sxc151355 #include <sys/strsun.h> 390ba2cbe9Sxc151355 #include <sys/policy.h> 400ba2cbe9Sxc151355 #include <inet/common.h> 410ba2cbe9Sxc151355 #include <inet/nd.h> 420ba2cbe9Sxc151355 #include <inet/mi.h> 430ba2cbe9Sxc151355 #include <sys/note.h> 44da14cebeSEric Cheng #include <sys/mac_provider.h> 450ba2cbe9Sxc151355 #include <inet/wifi_ioctl.h> 460ba2cbe9Sxc151355 #include "net80211_impl.h" 470ba2cbe9Sxc151355 48bcb5c89dSSowmini Varadhan static int wl_set_essid(struct ieee80211com *, const void *); 49bcb5c89dSSowmini Varadhan static void wl_get_essid(struct ieee80211com *, void *); 50bcb5c89dSSowmini Varadhan static int wl_set_bssid(struct ieee80211com *, const void *); 51bcb5c89dSSowmini Varadhan static void wl_get_bssid(struct ieee80211com *, void *); 52bcb5c89dSSowmini Varadhan static int wl_set_bsstype(struct ieee80211com *, const void *); 53bcb5c89dSSowmini Varadhan static void wl_get_bsstype(struct ieee80211com *, void *); 54bcb5c89dSSowmini Varadhan static void wl_get_linkstatus(struct ieee80211com *, void *); 55bcb5c89dSSowmini Varadhan static int wl_set_desrates(struct ieee80211com *, const void *); 56bcb5c89dSSowmini Varadhan static void wl_get_desrates(struct ieee80211com *, void *); 57bcb5c89dSSowmini Varadhan static int wl_set_authmode(struct ieee80211com *, const void *); 58bcb5c89dSSowmini Varadhan static void wl_get_authmode(struct ieee80211com *, void *); 59bcb5c89dSSowmini Varadhan static int wl_set_encrypt(struct ieee80211com *, const void *); 60bcb5c89dSSowmini Varadhan static void wl_get_encrypt(struct ieee80211com *, void *); 61bcb5c89dSSowmini Varadhan static void wl_get_rssi(struct ieee80211com *, void *); 62bcb5c89dSSowmini Varadhan static int wl_set_phy(struct ieee80211com *, const void *); 63bcb5c89dSSowmini Varadhan static int wl_get_phy(struct ieee80211com *, void *); 64bcb5c89dSSowmini Varadhan static void wl_get_capability(struct ieee80211com *, void *); 65bcb5c89dSSowmini Varadhan static int wl_set_wpa(struct ieee80211com *, const void *); 66bcb5c89dSSowmini Varadhan static void wl_get_wpa(struct ieee80211com *, void *); 67bcb5c89dSSowmini Varadhan static void wl_get_scanresults(struct ieee80211com *, void *); 68bcb5c89dSSowmini Varadhan static void wl_get_esslist(struct ieee80211com *, void *); 69bcb5c89dSSowmini Varadhan static int wl_set_wepkey(struct ieee80211com *, const void *); 70bcb5c89dSSowmini Varadhan static int wl_set_optie(struct ieee80211com *, const void *); 71bcb5c89dSSowmini Varadhan static int wl_set_delkey(struct ieee80211com *, const void *); 72bcb5c89dSSowmini Varadhan static int wl_set_mlme(struct ieee80211com *, const void *); 73bcb5c89dSSowmini Varadhan static int wl_set_wpakey(struct ieee80211com *, const void *); 74bcb5c89dSSowmini Varadhan static void wl_get_suprates(struct ieee80211com *, void *); 75127ac1c2Sfei feng - Sun Microsystems - Beijing China static int wl_set_createibss(struct ieee80211com *, const void *); 76127ac1c2Sfei feng - Sun Microsystems - Beijing China static void wl_get_createibss(struct ieee80211com *, void *); 77bcb5c89dSSowmini Varadhan 780ba2cbe9Sxc151355 static size_t 790ba2cbe9Sxc151355 wifi_strnlen(const char *s, size_t n) 800ba2cbe9Sxc151355 { 810ba2cbe9Sxc151355 size_t i; 820ba2cbe9Sxc151355 830ba2cbe9Sxc151355 for (i = 0; i < n && s[i] != '\0'; i++) 840ba2cbe9Sxc151355 /* noop */; 850ba2cbe9Sxc151355 return (i); 860ba2cbe9Sxc151355 } 870ba2cbe9Sxc151355 880ba2cbe9Sxc151355 /* 890ba2cbe9Sxc151355 * Initialize an output message block by copying from an 900ba2cbe9Sxc151355 * input message block. The message is of type wldp_t. 910ba2cbe9Sxc151355 * mp input message block 920ba2cbe9Sxc151355 * buflen length of wldp_buf 930ba2cbe9Sxc151355 */ 940ba2cbe9Sxc151355 static void 950ba2cbe9Sxc151355 wifi_setupoutmsg(mblk_t *mp, int buflen) 960ba2cbe9Sxc151355 { 970ba2cbe9Sxc151355 wldp_t *wp; 980ba2cbe9Sxc151355 990ba2cbe9Sxc151355 wp = (wldp_t *)mp->b_rptr; 1000ba2cbe9Sxc151355 wp->wldp_length = WIFI_BUF_OFFSET + buflen; 1010ba2cbe9Sxc151355 wp->wldp_result = WL_SUCCESS; 1020ba2cbe9Sxc151355 mp->b_wptr = mp->b_rptr + wp->wldp_length; 1030ba2cbe9Sxc151355 } 1040ba2cbe9Sxc151355 1050ba2cbe9Sxc151355 /* 1060ba2cbe9Sxc151355 * Allocate and initialize an output message. 1070ba2cbe9Sxc151355 */ 1080ba2cbe9Sxc151355 static mblk_t * 1090ba2cbe9Sxc151355 wifi_getoutmsg(mblk_t *mp, uint32_t cmd, int buflen) 1100ba2cbe9Sxc151355 { 1110ba2cbe9Sxc151355 mblk_t *mp1; 1120ba2cbe9Sxc151355 int size; 1130ba2cbe9Sxc151355 1140ba2cbe9Sxc151355 size = WIFI_BUF_OFFSET; 1150ba2cbe9Sxc151355 if (cmd == WLAN_GET_PARAM) 1160ba2cbe9Sxc151355 size += buflen; /* to hold output parameters */ 1170ba2cbe9Sxc151355 mp1 = allocb(size, BPRI_HI); 1180ba2cbe9Sxc151355 if (mp1 == NULL) { 1190ba2cbe9Sxc151355 ieee80211_err("wifi_getoutbuf: allocb %d bytes failed!\n", 1200ba2cbe9Sxc151355 size); 1210ba2cbe9Sxc151355 return (NULL); 1220ba2cbe9Sxc151355 } 1230ba2cbe9Sxc151355 1240ba2cbe9Sxc151355 bzero(mp1->b_rptr, size); 1250ba2cbe9Sxc151355 bcopy(mp->b_rptr, mp1->b_rptr, WIFI_BUF_OFFSET); 1260ba2cbe9Sxc151355 wifi_setupoutmsg(mp1, size - WIFI_BUF_OFFSET); 1270ba2cbe9Sxc151355 1280ba2cbe9Sxc151355 return (mp1); 1290ba2cbe9Sxc151355 } 1300ba2cbe9Sxc151355 1310ba2cbe9Sxc151355 static int 1320ba2cbe9Sxc151355 wifi_cfg_essid(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 1330ba2cbe9Sxc151355 { 1340ba2cbe9Sxc151355 mblk_t *omp; 1350ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 1360ba2cbe9Sxc151355 wldp_t *outp; 1370ba2cbe9Sxc151355 wl_essid_t *iw_essid = (wl_essid_t *)inp->wldp_buf; 1380ba2cbe9Sxc151355 wl_essid_t *ow_essid; 1390ba2cbe9Sxc151355 int err = 0; 1400ba2cbe9Sxc151355 1410ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_essid_t))) == NULL) 1420ba2cbe9Sxc151355 return (ENOMEM); 1430ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 1440ba2cbe9Sxc151355 ow_essid = (wl_essid_t *)outp->wldp_buf; 1450ba2cbe9Sxc151355 1460ba2cbe9Sxc151355 switch (cmd) { 1470ba2cbe9Sxc151355 case WLAN_GET_PARAM: 148bcb5c89dSSowmini Varadhan wl_get_essid(ic, ow_essid); 1490ba2cbe9Sxc151355 break; 1500ba2cbe9Sxc151355 case WLAN_SET_PARAM: 151bcb5c89dSSowmini Varadhan err = wl_set_essid(ic, iw_essid); 1520ba2cbe9Sxc151355 break; 1530ba2cbe9Sxc151355 default: 1540ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_essid: unknown command %x\n", cmd); 1550ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 1560ba2cbe9Sxc151355 err = EINVAL; 1570ba2cbe9Sxc151355 break; 1580ba2cbe9Sxc151355 } 1590ba2cbe9Sxc151355 1600ba2cbe9Sxc151355 freemsg(*mp); 1610ba2cbe9Sxc151355 *mp = omp; 1620ba2cbe9Sxc151355 return (err); 1630ba2cbe9Sxc151355 } 1640ba2cbe9Sxc151355 1650ba2cbe9Sxc151355 static int 1660ba2cbe9Sxc151355 wifi_cfg_bssid(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 1670ba2cbe9Sxc151355 { 1680ba2cbe9Sxc151355 mblk_t *omp; 1690ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 1700ba2cbe9Sxc151355 wldp_t *outp; 1710ba2cbe9Sxc151355 int err = 0; 1720ba2cbe9Sxc151355 1730ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_bssid_t))) == NULL) 1740ba2cbe9Sxc151355 return (ENOMEM); 1750ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 1760ba2cbe9Sxc151355 1770ba2cbe9Sxc151355 switch (cmd) { 1780ba2cbe9Sxc151355 case WLAN_GET_PARAM: 179bcb5c89dSSowmini Varadhan wl_get_bssid(ic, outp->wldp_buf); 1800ba2cbe9Sxc151355 break; 1810ba2cbe9Sxc151355 case WLAN_SET_PARAM: 182bcb5c89dSSowmini Varadhan err = wl_set_bssid(ic, inp->wldp_buf); 1830ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_bssid: " 1840ba2cbe9Sxc151355 "set bssid=%s\n", 1850ba2cbe9Sxc151355 ieee80211_macaddr_sprintf(inp->wldp_buf)); 1860ba2cbe9Sxc151355 break; 1870ba2cbe9Sxc151355 default: 1880ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_bssid: unknown command %x\n", cmd); 1890ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 1900ba2cbe9Sxc151355 err = EINVAL; 1910ba2cbe9Sxc151355 break; 1920ba2cbe9Sxc151355 } 1930ba2cbe9Sxc151355 1940ba2cbe9Sxc151355 freemsg(*mp); 1950ba2cbe9Sxc151355 *mp = omp; 1960ba2cbe9Sxc151355 return (err); 1970ba2cbe9Sxc151355 } 1980ba2cbe9Sxc151355 1990ba2cbe9Sxc151355 static int 2000ba2cbe9Sxc151355 wifi_cfg_nodename(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 2010ba2cbe9Sxc151355 { 2020ba2cbe9Sxc151355 mblk_t *omp; 2030ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 2040ba2cbe9Sxc151355 wldp_t *outp; 2050ba2cbe9Sxc151355 wl_nodename_t *iw_name = (wl_nodename_t *)inp->wldp_buf; 2060ba2cbe9Sxc151355 wl_nodename_t *ow_name; 2070ba2cbe9Sxc151355 char *nodename; 2080ba2cbe9Sxc151355 int len, err; 2090ba2cbe9Sxc151355 2100ba2cbe9Sxc151355 err = 0; 2110ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_nodename_t))) == NULL) 2120ba2cbe9Sxc151355 return (ENOMEM); 2130ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 2140ba2cbe9Sxc151355 ow_name = (wl_nodename_t *)outp->wldp_buf; 2150ba2cbe9Sxc151355 2160ba2cbe9Sxc151355 switch (cmd) { 2170ba2cbe9Sxc151355 case WLAN_GET_PARAM: 2180ba2cbe9Sxc151355 len = wifi_strnlen((const char *)ic->ic_nickname, 2190ba2cbe9Sxc151355 IEEE80211_NWID_LEN); 2200ba2cbe9Sxc151355 ow_name->wl_nodename_length = len; 2210ba2cbe9Sxc151355 bcopy(ic->ic_nickname, ow_name->wl_nodename_name, len); 2220ba2cbe9Sxc151355 break; 2230ba2cbe9Sxc151355 case WLAN_SET_PARAM: 2240ba2cbe9Sxc151355 if (iw_name->wl_nodename_length > IEEE80211_NWID_LEN) { 2250ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_nodename: " 2260ba2cbe9Sxc151355 "node name too long, %u\n", 2270ba2cbe9Sxc151355 iw_name->wl_nodename_length); 2280ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 2290ba2cbe9Sxc151355 err = EINVAL; 2300ba2cbe9Sxc151355 break; 2310ba2cbe9Sxc151355 } 2320ba2cbe9Sxc151355 nodename = iw_name->wl_nodename_name; 2330ba2cbe9Sxc151355 nodename[IEEE80211_NWID_LEN] = 0; 2340ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CONFIG, 2350ba2cbe9Sxc151355 "wifi_cfg_nodename: set nodename %s, len=%d\n", 2360ba2cbe9Sxc151355 nodename, iw_name->wl_nodename_length); 2370ba2cbe9Sxc151355 2380ba2cbe9Sxc151355 len = iw_name->wl_nodename_length; 2390ba2cbe9Sxc151355 if (len > 0) 2400ba2cbe9Sxc151355 bcopy(nodename, ic->ic_nickname, len); 2410ba2cbe9Sxc151355 if (len < IEEE80211_NWID_LEN) 2420ba2cbe9Sxc151355 ic->ic_nickname[len] = 0; 2430ba2cbe9Sxc151355 break; 2440ba2cbe9Sxc151355 default: 2450ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_nodename: unknown command %x\n", cmd); 2460ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 2470ba2cbe9Sxc151355 err = EINVAL; 2480ba2cbe9Sxc151355 break; 2490ba2cbe9Sxc151355 } 2500ba2cbe9Sxc151355 2510ba2cbe9Sxc151355 freemsg(*mp); 2520ba2cbe9Sxc151355 *mp = omp; 2530ba2cbe9Sxc151355 return (err); 2540ba2cbe9Sxc151355 } 2550ba2cbe9Sxc151355 2560ba2cbe9Sxc151355 static int 2570ba2cbe9Sxc151355 wifi_cfg_phy(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 2580ba2cbe9Sxc151355 { 2590ba2cbe9Sxc151355 mblk_t *omp; 2600ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 2610ba2cbe9Sxc151355 wldp_t *outp; 2620ba2cbe9Sxc151355 wl_phy_conf_t *iw_phy = (wl_phy_conf_t *)inp->wldp_buf; 2630ba2cbe9Sxc151355 wl_phy_conf_t *ow_phy; 2640ba2cbe9Sxc151355 int err = 0; 2650ba2cbe9Sxc151355 2660ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_phy_conf_t))) == NULL) 2670ba2cbe9Sxc151355 return (ENOMEM); 2680ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 2690ba2cbe9Sxc151355 ow_phy = (wl_phy_conf_t *)outp->wldp_buf; 2700ba2cbe9Sxc151355 2710ba2cbe9Sxc151355 switch (cmd) { 272bcb5c89dSSowmini Varadhan case WLAN_GET_PARAM: 273bcb5c89dSSowmini Varadhan err = wl_get_phy(ic, ow_phy); 274bcb5c89dSSowmini Varadhan break; 2750ba2cbe9Sxc151355 276bcb5c89dSSowmini Varadhan case WLAN_SET_PARAM: 277bcb5c89dSSowmini Varadhan err = wl_set_phy(ic, iw_phy); 2780ba2cbe9Sxc151355 break; 2790ba2cbe9Sxc151355 2800ba2cbe9Sxc151355 default: 2810ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_phy: unknown command %x\n", cmd); 2820ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 2830ba2cbe9Sxc151355 err = EINVAL; 2840ba2cbe9Sxc151355 break; 2850ba2cbe9Sxc151355 } /* switch (cmd) */ 2860ba2cbe9Sxc151355 2870ba2cbe9Sxc151355 freemsg(*mp); 2880ba2cbe9Sxc151355 *mp = omp; 2890ba2cbe9Sxc151355 return (err); 2900ba2cbe9Sxc151355 } 2910ba2cbe9Sxc151355 2920ba2cbe9Sxc151355 static int 2930ba2cbe9Sxc151355 wifi_cfg_wepkey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 2940ba2cbe9Sxc151355 { 2950ba2cbe9Sxc151355 mblk_t *omp; 2960ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 2970ba2cbe9Sxc151355 wldp_t *outp; 2980ba2cbe9Sxc151355 wl_wep_key_t *iw_wepkey = (wl_wep_key_t *)inp->wldp_buf; 2990ba2cbe9Sxc151355 int err = 0; 3000ba2cbe9Sxc151355 3010ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) 3020ba2cbe9Sxc151355 return (ENOMEM); 3030ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 3040ba2cbe9Sxc151355 3050ba2cbe9Sxc151355 switch (cmd) { 3060ba2cbe9Sxc151355 case WLAN_GET_PARAM: 3070ba2cbe9Sxc151355 outp->wldp_result = WL_WRITEONLY; 3080ba2cbe9Sxc151355 err = EINVAL; 3090ba2cbe9Sxc151355 break; 3100ba2cbe9Sxc151355 case WLAN_SET_PARAM: 3110ba2cbe9Sxc151355 if (inp->wldp_length < sizeof (wl_wep_key_tab_t)) { 3120ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_wepkey: " 3130ba2cbe9Sxc151355 "parameter too short, %d, expected %d\n", 3140ba2cbe9Sxc151355 inp->wldp_length, sizeof (wl_wep_key_tab_t)); 3150ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 3160ba2cbe9Sxc151355 err = EINVAL; 3170ba2cbe9Sxc151355 break; 3180ba2cbe9Sxc151355 } 3190ba2cbe9Sxc151355 320bcb5c89dSSowmini Varadhan err = wl_set_wepkey(ic, iw_wepkey); 3210ba2cbe9Sxc151355 break; 3220ba2cbe9Sxc151355 default: 3230ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_wepkey: unknown command %x\n", cmd); 3240ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 3250ba2cbe9Sxc151355 err = EINVAL; 3260ba2cbe9Sxc151355 break; 3270ba2cbe9Sxc151355 } 3280ba2cbe9Sxc151355 3290ba2cbe9Sxc151355 freemsg(*mp); 3300ba2cbe9Sxc151355 *mp = omp; 3310ba2cbe9Sxc151355 return (err); 3320ba2cbe9Sxc151355 } 3330ba2cbe9Sxc151355 3340ba2cbe9Sxc151355 static int 3350ba2cbe9Sxc151355 wifi_cfg_keyid(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 3360ba2cbe9Sxc151355 { 3370ba2cbe9Sxc151355 mblk_t *omp; 3380ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 3390ba2cbe9Sxc151355 wldp_t *outp; 3400ba2cbe9Sxc151355 wl_wep_key_id_t *iw_kid = (wl_wep_key_id_t *)inp->wldp_buf; 3410ba2cbe9Sxc151355 wl_wep_key_id_t *ow_kid; 3420ba2cbe9Sxc151355 int err = 0; 3430ba2cbe9Sxc151355 3440ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_wep_key_id_t))) == NULL) 3450ba2cbe9Sxc151355 return (ENOMEM); 3460ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 3470ba2cbe9Sxc151355 ow_kid = (wl_wep_key_id_t *)outp->wldp_buf; 3480ba2cbe9Sxc151355 3490ba2cbe9Sxc151355 switch (cmd) { 3500ba2cbe9Sxc151355 case WLAN_GET_PARAM: 3510ba2cbe9Sxc151355 *ow_kid = (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) ? 3520ba2cbe9Sxc151355 0 : ic->ic_def_txkey; 3530ba2cbe9Sxc151355 break; 3540ba2cbe9Sxc151355 case WLAN_SET_PARAM: 3550ba2cbe9Sxc151355 if (*iw_kid >= MAX_NWEPKEYS) { 3560ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_keyid: " 3570ba2cbe9Sxc151355 "keyid too large, %u\n", *iw_kid); 3580ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 3590ba2cbe9Sxc151355 err = EINVAL; 3600ba2cbe9Sxc151355 } else { 3610ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_keyid: " 3620ba2cbe9Sxc151355 "set keyid=%u\n", *iw_kid); 3630ba2cbe9Sxc151355 ic->ic_def_txkey = *iw_kid; 3640ba2cbe9Sxc151355 err = ENETRESET; 3650ba2cbe9Sxc151355 } 3660ba2cbe9Sxc151355 break; 3670ba2cbe9Sxc151355 default: 3680ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_keyid: unknown command %x\n", cmd); 3690ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 3700ba2cbe9Sxc151355 err = EINVAL; 3710ba2cbe9Sxc151355 break; 3720ba2cbe9Sxc151355 } 3730ba2cbe9Sxc151355 3740ba2cbe9Sxc151355 freemsg(*mp); 3750ba2cbe9Sxc151355 *mp = omp; 3760ba2cbe9Sxc151355 return (err); 3770ba2cbe9Sxc151355 } 3780ba2cbe9Sxc151355 3790ba2cbe9Sxc151355 static int 3800ba2cbe9Sxc151355 wifi_cfg_authmode(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 3810ba2cbe9Sxc151355 { 3820ba2cbe9Sxc151355 mblk_t *omp; 3830ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 3840ba2cbe9Sxc151355 wldp_t *outp; 3850ba2cbe9Sxc151355 wl_authmode_t *iw_auth = (wl_authmode_t *)inp->wldp_buf; 3860ba2cbe9Sxc151355 wl_authmode_t *ow_auth; 3870ba2cbe9Sxc151355 int err = 0; 3880ba2cbe9Sxc151355 3890ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_authmode_t))) == NULL) 3900ba2cbe9Sxc151355 return (ENOMEM); 3910ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 3920ba2cbe9Sxc151355 ow_auth = (wl_authmode_t *)outp->wldp_buf; 3930ba2cbe9Sxc151355 3940ba2cbe9Sxc151355 switch (cmd) { 3950ba2cbe9Sxc151355 case WLAN_GET_PARAM: 396bcb5c89dSSowmini Varadhan wl_get_authmode(ic, ow_auth); 3970ba2cbe9Sxc151355 break; 3980ba2cbe9Sxc151355 case WLAN_SET_PARAM: 399bcb5c89dSSowmini Varadhan err = wl_set_authmode(ic, iw_auth); 4000ba2cbe9Sxc151355 break; 4010ba2cbe9Sxc151355 default: 4020ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_authmode: unknown command %x\n", cmd); 4030ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 4040ba2cbe9Sxc151355 err = EINVAL; 4050ba2cbe9Sxc151355 break; 4060ba2cbe9Sxc151355 } 4070ba2cbe9Sxc151355 4080ba2cbe9Sxc151355 freemsg(*mp); 4090ba2cbe9Sxc151355 *mp = omp; 4100ba2cbe9Sxc151355 return (err); 4110ba2cbe9Sxc151355 } 4120ba2cbe9Sxc151355 4130ba2cbe9Sxc151355 static int 4140ba2cbe9Sxc151355 wifi_cfg_encrypt(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 4150ba2cbe9Sxc151355 { 4160ba2cbe9Sxc151355 mblk_t *omp; 4170ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 4180ba2cbe9Sxc151355 wldp_t *outp; 4190ba2cbe9Sxc151355 wl_encryption_t *iw_encryp = (wl_encryption_t *)inp->wldp_buf; 4200ba2cbe9Sxc151355 wl_encryption_t *ow_encryp; 4210ba2cbe9Sxc151355 int err = 0; 4220ba2cbe9Sxc151355 4230ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_encryption_t))) == NULL) 4240ba2cbe9Sxc151355 return (ENOMEM); 4250ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 4260ba2cbe9Sxc151355 ow_encryp = (wl_encryption_t *)outp->wldp_buf; 4270ba2cbe9Sxc151355 4280ba2cbe9Sxc151355 switch (cmd) { 4290ba2cbe9Sxc151355 case WLAN_GET_PARAM: 430bcb5c89dSSowmini Varadhan wl_get_encrypt(ic, ow_encryp); 4310ba2cbe9Sxc151355 break; 4320ba2cbe9Sxc151355 case WLAN_SET_PARAM: 433bcb5c89dSSowmini Varadhan err = wl_set_encrypt(ic, iw_encryp); 4340ba2cbe9Sxc151355 break; 4350ba2cbe9Sxc151355 default: 4360ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_encrypt: unknown command %x\n", cmd); 4370ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 4380ba2cbe9Sxc151355 err = EINVAL; 4390ba2cbe9Sxc151355 break; 4400ba2cbe9Sxc151355 } 4410ba2cbe9Sxc151355 4420ba2cbe9Sxc151355 freemsg(*mp); 4430ba2cbe9Sxc151355 *mp = omp; 4440ba2cbe9Sxc151355 return (err); 4450ba2cbe9Sxc151355 } 4460ba2cbe9Sxc151355 4470ba2cbe9Sxc151355 static int 4480ba2cbe9Sxc151355 wifi_cfg_bsstype(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 4490ba2cbe9Sxc151355 { 4500ba2cbe9Sxc151355 mblk_t *omp; 4510ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 4520ba2cbe9Sxc151355 wldp_t *outp; 4530ba2cbe9Sxc151355 wl_bss_type_t *iw_opmode = (wl_bss_type_t *)inp->wldp_buf; 4540ba2cbe9Sxc151355 wl_bss_type_t *ow_opmode; 4550ba2cbe9Sxc151355 int err = 0; 4560ba2cbe9Sxc151355 4570ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_bss_type_t))) == NULL) 4580ba2cbe9Sxc151355 return (ENOMEM); 4590ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 4600ba2cbe9Sxc151355 ow_opmode = (wl_bss_type_t *)outp->wldp_buf; 4610ba2cbe9Sxc151355 4620ba2cbe9Sxc151355 switch (cmd) { 4630ba2cbe9Sxc151355 case WLAN_GET_PARAM: 464bcb5c89dSSowmini Varadhan wl_get_bsstype(ic, ow_opmode); 4650ba2cbe9Sxc151355 break; 4660ba2cbe9Sxc151355 case WLAN_SET_PARAM: 46719d332feSfei feng - Sun Microsystems - Beijing China if (*iw_opmode == ic->ic_opmode) 46819d332feSfei feng - Sun Microsystems - Beijing China break; 46919d332feSfei feng - Sun Microsystems - Beijing China 470bcb5c89dSSowmini Varadhan err = wl_set_bsstype(ic, iw_opmode); 4710ba2cbe9Sxc151355 break; 4720ba2cbe9Sxc151355 default: 4730ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_bsstype: unknown command %x\n", cmd); 4740ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 4750ba2cbe9Sxc151355 err = EINVAL; 4760ba2cbe9Sxc151355 break; 4770ba2cbe9Sxc151355 } 4780ba2cbe9Sxc151355 4790ba2cbe9Sxc151355 freemsg(*mp); 4800ba2cbe9Sxc151355 *mp = omp; 4810ba2cbe9Sxc151355 return (err); 4820ba2cbe9Sxc151355 } 4830ba2cbe9Sxc151355 4840ba2cbe9Sxc151355 static int 48519d332feSfei feng - Sun Microsystems - Beijing China wifi_cfg_createibss(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 48619d332feSfei feng - Sun Microsystems - Beijing China { 48719d332feSfei feng - Sun Microsystems - Beijing China mblk_t *omp; 48819d332feSfei feng - Sun Microsystems - Beijing China wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 48919d332feSfei feng - Sun Microsystems - Beijing China wldp_t *outp; 49019d332feSfei feng - Sun Microsystems - Beijing China wl_create_ibss_t *iw_ibss = (wl_create_ibss_t *)inp->wldp_buf; 49119d332feSfei feng - Sun Microsystems - Beijing China wl_create_ibss_t *ow_ibss; 49219d332feSfei feng - Sun Microsystems - Beijing China int err = 0; 49319d332feSfei feng - Sun Microsystems - Beijing China 49419d332feSfei feng - Sun Microsystems - Beijing China if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_create_ibss_t))) == NULL) 49519d332feSfei feng - Sun Microsystems - Beijing China return (ENOMEM); 49619d332feSfei feng - Sun Microsystems - Beijing China outp = (wldp_t *)omp->b_rptr; 49719d332feSfei feng - Sun Microsystems - Beijing China ow_ibss = (wl_create_ibss_t *)outp->wldp_buf; 49819d332feSfei feng - Sun Microsystems - Beijing China 49919d332feSfei feng - Sun Microsystems - Beijing China switch (cmd) { 50019d332feSfei feng - Sun Microsystems - Beijing China case WLAN_GET_PARAM: 501127ac1c2Sfei feng - Sun Microsystems - Beijing China wl_get_createibss(ic, ow_ibss); 50219d332feSfei feng - Sun Microsystems - Beijing China break; 50319d332feSfei feng - Sun Microsystems - Beijing China case WLAN_SET_PARAM: 504127ac1c2Sfei feng - Sun Microsystems - Beijing China err = wl_set_createibss(ic, iw_ibss); 50519d332feSfei feng - Sun Microsystems - Beijing China break; 50619d332feSfei feng - Sun Microsystems - Beijing China default: 50719d332feSfei feng - Sun Microsystems - Beijing China ieee80211_err("wifi_cfg_bsstype: unknown command %x\n", cmd); 50819d332feSfei feng - Sun Microsystems - Beijing China outp->wldp_result = WL_NOTSUPPORTED; 50919d332feSfei feng - Sun Microsystems - Beijing China err = EINVAL; 51019d332feSfei feng - Sun Microsystems - Beijing China break; 51119d332feSfei feng - Sun Microsystems - Beijing China } 51219d332feSfei feng - Sun Microsystems - Beijing China 51319d332feSfei feng - Sun Microsystems - Beijing China freemsg(*mp); 51419d332feSfei feng - Sun Microsystems - Beijing China *mp = omp; 51519d332feSfei feng - Sun Microsystems - Beijing China return (err); 51619d332feSfei feng - Sun Microsystems - Beijing China } 51719d332feSfei feng - Sun Microsystems - Beijing China 51819d332feSfei feng - Sun Microsystems - Beijing China static int 5190ba2cbe9Sxc151355 wifi_cfg_linkstatus(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 5200ba2cbe9Sxc151355 { 5210ba2cbe9Sxc151355 mblk_t *omp; 5220ba2cbe9Sxc151355 wldp_t *outp; 5230ba2cbe9Sxc151355 wl_linkstatus_t *ow_linkstat; 5240ba2cbe9Sxc151355 int err = 0; 5250ba2cbe9Sxc151355 5260ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_linkstatus_t))) == NULL) 5270ba2cbe9Sxc151355 return (ENOMEM); 5280ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 5290ba2cbe9Sxc151355 ow_linkstat = (wl_linkstatus_t *)outp->wldp_buf; 5300ba2cbe9Sxc151355 5310ba2cbe9Sxc151355 switch (cmd) { 5320ba2cbe9Sxc151355 case WLAN_GET_PARAM: 533bcb5c89dSSowmini Varadhan wl_get_linkstatus(ic, ow_linkstat); 5340ba2cbe9Sxc151355 break; 5350ba2cbe9Sxc151355 case WLAN_SET_PARAM: 5360ba2cbe9Sxc151355 outp->wldp_result = WL_READONLY; 5370ba2cbe9Sxc151355 err = EINVAL; 5380ba2cbe9Sxc151355 break; 5390ba2cbe9Sxc151355 default: 5400ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_linkstatus: unknown command %x\n", cmd); 5410ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 5420ba2cbe9Sxc151355 err = EINVAL; 5430ba2cbe9Sxc151355 break; 5440ba2cbe9Sxc151355 } 5450ba2cbe9Sxc151355 5460ba2cbe9Sxc151355 freemsg(*mp); 5470ba2cbe9Sxc151355 *mp = omp; 5480ba2cbe9Sxc151355 return (err); 5490ba2cbe9Sxc151355 } 5500ba2cbe9Sxc151355 5510ba2cbe9Sxc151355 static int 5520ba2cbe9Sxc151355 wifi_cfg_suprates(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 5530ba2cbe9Sxc151355 { 5540ba2cbe9Sxc151355 mblk_t *omp; 5550ba2cbe9Sxc151355 wldp_t *outp; 5560ba2cbe9Sxc151355 wl_rates_t *ow_rates; 557bcb5c89dSSowmini Varadhan int err, buflen; 5580ba2cbe9Sxc151355 5590ba2cbe9Sxc151355 err = 0; 5600ba2cbe9Sxc151355 /* rate value (wl_rates_rates) is of type char */ 5610ba2cbe9Sxc151355 buflen = offsetof(wl_rates_t, wl_rates_rates) + 5620ba2cbe9Sxc151355 sizeof (char) * IEEE80211_MODE_MAX * IEEE80211_RATE_MAXSIZE; 5630ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, buflen)) == NULL) 5640ba2cbe9Sxc151355 return (ENOMEM); 5650ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 5660ba2cbe9Sxc151355 ow_rates = (wl_rates_t *)outp->wldp_buf; 5670ba2cbe9Sxc151355 5680ba2cbe9Sxc151355 switch (cmd) { 5690ba2cbe9Sxc151355 case WLAN_GET_PARAM: 570bcb5c89dSSowmini Varadhan (void) wl_get_suprates(ic, ow_rates); 5710ba2cbe9Sxc151355 break; 5720ba2cbe9Sxc151355 case WLAN_SET_PARAM: 5730ba2cbe9Sxc151355 outp->wldp_result = WL_READONLY; 5740ba2cbe9Sxc151355 err = EINVAL; 5750ba2cbe9Sxc151355 break; 5760ba2cbe9Sxc151355 default: 5770ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_suprates: unknown command %x\n", cmd); 5780ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 5790ba2cbe9Sxc151355 err = EINVAL; 5800ba2cbe9Sxc151355 break; 5810ba2cbe9Sxc151355 } 5820ba2cbe9Sxc151355 5830ba2cbe9Sxc151355 freemsg(*mp); 5840ba2cbe9Sxc151355 *mp = omp; 5850ba2cbe9Sxc151355 return (err); 5860ba2cbe9Sxc151355 } 5870ba2cbe9Sxc151355 5880ba2cbe9Sxc151355 static int 5890ba2cbe9Sxc151355 wifi_cfg_desrates(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 5900ba2cbe9Sxc151355 { 5910ba2cbe9Sxc151355 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 5920ba2cbe9Sxc151355 wl_rates_t *iw_rates = (wl_rates_t *)inp->wldp_buf; 5930ba2cbe9Sxc151355 mblk_t *omp; 5940ba2cbe9Sxc151355 wldp_t *outp; 5950ba2cbe9Sxc151355 wl_rates_t *ow_rates; 596bcb5c89dSSowmini Varadhan int err; 5970ba2cbe9Sxc151355 5980ba2cbe9Sxc151355 err = 0; 5990ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_rates_t))) == NULL) 6000ba2cbe9Sxc151355 return (ENOMEM); 6010ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 6020ba2cbe9Sxc151355 ow_rates = (wl_rates_t *)outp->wldp_buf; 6030ba2cbe9Sxc151355 6040ba2cbe9Sxc151355 switch (cmd) { 6050ba2cbe9Sxc151355 case WLAN_GET_PARAM: 606bcb5c89dSSowmini Varadhan wl_get_desrates(ic, ow_rates); 6070ba2cbe9Sxc151355 break; 6080ba2cbe9Sxc151355 case WLAN_SET_PARAM: 609bcb5c89dSSowmini Varadhan err = wl_set_desrates(ic, iw_rates); 6100ba2cbe9Sxc151355 break; 6110ba2cbe9Sxc151355 default: 6120ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_desrates: unknown command %x\n", cmd); 6130ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 6140ba2cbe9Sxc151355 err = EINVAL; 6150ba2cbe9Sxc151355 break; 6160ba2cbe9Sxc151355 } 6170ba2cbe9Sxc151355 6180ba2cbe9Sxc151355 freemsg(*mp); 6190ba2cbe9Sxc151355 *mp = omp; 6200ba2cbe9Sxc151355 return (err); 6210ba2cbe9Sxc151355 } 6220ba2cbe9Sxc151355 6230ba2cbe9Sxc151355 /* 6240ba2cbe9Sxc151355 * Rescale device's RSSI value to (0, 15) as required by WiFi 6250ba2cbe9Sxc151355 * driver IOCTLs (PSARC/2003/722) 6260ba2cbe9Sxc151355 */ 6270ba2cbe9Sxc151355 static wl_rssi_t 6280ba2cbe9Sxc151355 wifi_getrssi(struct ieee80211_node *in) 6290ba2cbe9Sxc151355 { 6300ba2cbe9Sxc151355 struct ieee80211com *ic = in->in_ic; 6310ba2cbe9Sxc151355 wl_rssi_t rssi, max_rssi; 6320ba2cbe9Sxc151355 6330ba2cbe9Sxc151355 rssi = ic->ic_node_getrssi(in); 6340ba2cbe9Sxc151355 max_rssi = (ic->ic_maxrssi == 0) ? IEEE80211_MAXRSSI : ic->ic_maxrssi; 6350ba2cbe9Sxc151355 if (rssi == 0) 6360ba2cbe9Sxc151355 rssi = 0; 6370ba2cbe9Sxc151355 else if (rssi >= max_rssi) 6380ba2cbe9Sxc151355 rssi = MAX_RSSI; 6390ba2cbe9Sxc151355 else 6400ba2cbe9Sxc151355 rssi = rssi * MAX_RSSI / max_rssi + 1; 6410ba2cbe9Sxc151355 6420ba2cbe9Sxc151355 return (rssi); 6430ba2cbe9Sxc151355 } 6440ba2cbe9Sxc151355 6450ba2cbe9Sxc151355 static int 6460ba2cbe9Sxc151355 wifi_cfg_rssi(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 6470ba2cbe9Sxc151355 { 6480ba2cbe9Sxc151355 mblk_t *omp; 6490ba2cbe9Sxc151355 wldp_t *outp; 6500ba2cbe9Sxc151355 wl_rssi_t *ow_rssi; 6510ba2cbe9Sxc151355 int err = 0; 6520ba2cbe9Sxc151355 6530ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_rssi_t))) == NULL) 6540ba2cbe9Sxc151355 return (ENOMEM); 6550ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 6560ba2cbe9Sxc151355 ow_rssi = (wl_rssi_t *)outp->wldp_buf; 6570ba2cbe9Sxc151355 6580ba2cbe9Sxc151355 switch (cmd) { 6590ba2cbe9Sxc151355 case WLAN_GET_PARAM: 6600ba2cbe9Sxc151355 *ow_rssi = wifi_getrssi(ic->ic_bss); 6610ba2cbe9Sxc151355 break; 6620ba2cbe9Sxc151355 case WLAN_SET_PARAM: 6630ba2cbe9Sxc151355 outp->wldp_result = WL_READONLY; 6640ba2cbe9Sxc151355 err = EINVAL; 6650ba2cbe9Sxc151355 break; 6660ba2cbe9Sxc151355 default: 6670ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_rssi: unknown command %x\n", cmd); 6680ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 6690ba2cbe9Sxc151355 return (EINVAL); 6700ba2cbe9Sxc151355 } 6710ba2cbe9Sxc151355 6720ba2cbe9Sxc151355 freemsg(*mp); 6730ba2cbe9Sxc151355 *mp = omp; 6740ba2cbe9Sxc151355 return (err); 6750ba2cbe9Sxc151355 } 6760ba2cbe9Sxc151355 6770ba2cbe9Sxc151355 /* 6780ba2cbe9Sxc151355 * maximum scan wait time in second. 6790ba2cbe9Sxc151355 * Time spent on scaning one channel is usually 100~200ms. The maximum 6800ba2cbe9Sxc151355 * number of channels defined in wifi_ioctl.h is 99 (MAX_CHANNEL_NUM). 6810ba2cbe9Sxc151355 * As a result the maximum total scan time is defined as below in ms. 6820ba2cbe9Sxc151355 */ 6830ba2cbe9Sxc151355 #define WAIT_SCAN_MAX (200 * MAX_CHANNEL_NUM) 6840ba2cbe9Sxc151355 6850ba2cbe9Sxc151355 static void 6860ba2cbe9Sxc151355 wifi_wait_scan(struct ieee80211com *ic) 6870ba2cbe9Sxc151355 { 6880ba2cbe9Sxc151355 ieee80211_impl_t *im = ic->ic_private; 689d3d50737SRafael Vanoni clock_t delta = drv_usectohz(WAIT_SCAN_MAX * 1000); 6900ba2cbe9Sxc151355 6910ba2cbe9Sxc151355 while ((ic->ic_flags & (IEEE80211_F_SCAN | IEEE80211_F_ASCAN)) != 0) { 692d3d50737SRafael Vanoni if (cv_reltimedwait_sig(&im->im_scan_cv, &ic->ic_genlock, 693d3d50737SRafael Vanoni delta, TR_CLOCK_TICK) != 0) { 6940ba2cbe9Sxc151355 break; 6950ba2cbe9Sxc151355 } 6960ba2cbe9Sxc151355 } 6970ba2cbe9Sxc151355 } 6980ba2cbe9Sxc151355 6990ba2cbe9Sxc151355 #define WIFI_HAVE_CAP(in, flag) (((in)->in_capinfo & (flag)) ? 1 : 0) 700e2cf88acSQuaker Fang #define WIFI_HAVE_HTCAP(in) (((in)->in_htcap != 0) ? 1 : 0) 7010ba2cbe9Sxc151355 7020ba2cbe9Sxc151355 /* 7030ba2cbe9Sxc151355 * Callback function used by ieee80211_iterate_nodes() in 7040ba2cbe9Sxc151355 * wifi_cfg_esslist() to get info of each node in a node table 7050ba2cbe9Sxc151355 * arg output buffer, pointer to wl_ess_list_t 7060ba2cbe9Sxc151355 * in each node in the node table 7070ba2cbe9Sxc151355 */ 7080ba2cbe9Sxc151355 static void 7090ba2cbe9Sxc151355 wifi_read_ap(void *arg, struct ieee80211_node *in) 7100ba2cbe9Sxc151355 { 7110ba2cbe9Sxc151355 wl_ess_list_t *aps = arg; 7120ba2cbe9Sxc151355 ieee80211com_t *ic = in->in_ic; 7130ba2cbe9Sxc151355 struct ieee80211_channel *chan = in->in_chan; 7140ba2cbe9Sxc151355 struct ieee80211_rateset *rates = &(in->in_rates); 7150ba2cbe9Sxc151355 wl_ess_conf_t *conf; 7160ba2cbe9Sxc151355 uint8_t *end; 7170ba2cbe9Sxc151355 uint_t i, nrates; 7180ba2cbe9Sxc151355 7190ba2cbe9Sxc151355 end = (uint8_t *)aps - WIFI_BUF_OFFSET + MAX_BUF_LEN - 7200ba2cbe9Sxc151355 sizeof (wl_ess_list_t); 7210ba2cbe9Sxc151355 conf = &aps->wl_ess_list_ess[aps->wl_ess_list_num]; 7220ba2cbe9Sxc151355 if ((uint8_t *)conf > end) 7230ba2cbe9Sxc151355 return; 7240ba2cbe9Sxc151355 72519d332feSfei feng - Sun Microsystems - Beijing China conf->wl_ess_conf_length = sizeof (struct wl_ess_conf); 72619d332feSfei feng - Sun Microsystems - Beijing China 7270ba2cbe9Sxc151355 /* skip newly allocated NULL bss node */ 7280ba2cbe9Sxc151355 if (IEEE80211_ADDR_EQ(in->in_macaddr, ic->ic_macaddr)) 7290ba2cbe9Sxc151355 return; 7300ba2cbe9Sxc151355 7310ba2cbe9Sxc151355 conf->wl_ess_conf_essid.wl_essid_length = in->in_esslen; 7320ba2cbe9Sxc151355 bcopy(in->in_essid, conf->wl_ess_conf_essid.wl_essid_essid, 7330ba2cbe9Sxc151355 in->in_esslen); 7340ba2cbe9Sxc151355 bcopy(in->in_bssid, conf->wl_ess_conf_bssid, IEEE80211_ADDR_LEN); 7350ba2cbe9Sxc151355 conf->wl_ess_conf_wepenabled = 7360ba2cbe9Sxc151355 (in->in_capinfo & IEEE80211_CAPINFO_PRIVACY ? 7370ba2cbe9Sxc151355 WL_ENC_WEP : WL_NOENCRYPTION); 7380ba2cbe9Sxc151355 conf->wl_ess_conf_bsstype = 7390ba2cbe9Sxc151355 (in->in_capinfo & IEEE80211_CAPINFO_ESS ? 7400ba2cbe9Sxc151355 WL_BSS_BSS : WL_BSS_IBSS); 7410ba2cbe9Sxc151355 conf->wl_ess_conf_sl = wifi_getrssi(in); 742a399b765Szf162725 conf->wl_ess_conf_reserved[0] = (in->in_wpa_ie == NULL? 0 : 1); 7430ba2cbe9Sxc151355 7440ba2cbe9Sxc151355 /* physical (FH, DS, ERP) parameters */ 7450ba2cbe9Sxc151355 if (IEEE80211_IS_CHAN_A(chan) || IEEE80211_IS_CHAN_T(chan)) { 7460ba2cbe9Sxc151355 wl_ofdm_t *ofdm = 7470ba2cbe9Sxc151355 (wl_ofdm_t *)&((conf->wl_phy_conf).wl_phy_ofdm_conf); 7480ba2cbe9Sxc151355 ofdm->wl_ofdm_subtype = WL_OFDM; 7490ba2cbe9Sxc151355 ofdm->wl_ofdm_frequency = chan->ich_freq; 750e2cf88acSQuaker Fang ofdm->wl_ofdm_ht_enabled = WIFI_HAVE_HTCAP(in); 7510ba2cbe9Sxc151355 } else { 7520ba2cbe9Sxc151355 switch (in->in_phytype) { 7530ba2cbe9Sxc151355 case IEEE80211_T_FH: { 7540ba2cbe9Sxc151355 wl_fhss_t *fhss = (wl_fhss_t *) 7550ba2cbe9Sxc151355 &((conf->wl_phy_conf).wl_phy_fhss_conf); 7560ba2cbe9Sxc151355 7570ba2cbe9Sxc151355 fhss->wl_fhss_subtype = WL_FHSS; 7580ba2cbe9Sxc151355 fhss->wl_fhss_channel = ieee80211_chan2ieee(ic, chan); 7590ba2cbe9Sxc151355 fhss->wl_fhss_dwelltime = in->in_fhdwell; 7600ba2cbe9Sxc151355 break; 7610ba2cbe9Sxc151355 } 7620ba2cbe9Sxc151355 case IEEE80211_T_DS: { 7630ba2cbe9Sxc151355 wl_dsss_t *dsss = (wl_dsss_t *) 7640ba2cbe9Sxc151355 &((conf->wl_phy_conf).wl_phy_dsss_conf); 7650ba2cbe9Sxc151355 7660ba2cbe9Sxc151355 dsss->wl_dsss_subtype = WL_DSSS; 7670ba2cbe9Sxc151355 dsss->wl_dsss_channel = ieee80211_chan2ieee(ic, chan); 7680ba2cbe9Sxc151355 dsss->wl_dsss_have_short_preamble = WIFI_HAVE_CAP(in, 7690ba2cbe9Sxc151355 IEEE80211_CAPINFO_SHORT_PREAMBLE); 7700ba2cbe9Sxc151355 dsss->wl_dsss_agility_enabled = WIFI_HAVE_CAP(in, 7710ba2cbe9Sxc151355 IEEE80211_CAPINFO_CHNL_AGILITY); 7720ba2cbe9Sxc151355 dsss->wl_dsss_have_pbcc = dsss->wl_dsss_pbcc_enable = 7730ba2cbe9Sxc151355 WIFI_HAVE_CAP(in, IEEE80211_CAPINFO_PBCC); 7740ba2cbe9Sxc151355 break; 7750ba2cbe9Sxc151355 } 7760ba2cbe9Sxc151355 case IEEE80211_T_OFDM: { 7770ba2cbe9Sxc151355 wl_erp_t *erp = (wl_erp_t *) 7780ba2cbe9Sxc151355 &((conf->wl_phy_conf).wl_phy_erp_conf); 7790ba2cbe9Sxc151355 7800ba2cbe9Sxc151355 erp->wl_erp_subtype = WL_ERP; 7810ba2cbe9Sxc151355 erp->wl_erp_channel = ieee80211_chan2ieee(ic, chan); 7820ba2cbe9Sxc151355 erp->wl_erp_have_short_preamble = WIFI_HAVE_CAP(in, 7830ba2cbe9Sxc151355 IEEE80211_CAPINFO_SHORT_PREAMBLE); 7840ba2cbe9Sxc151355 erp->wl_erp_have_agility = erp->wl_erp_agility_enabled = 7850ba2cbe9Sxc151355 WIFI_HAVE_CAP(in, IEEE80211_CAPINFO_CHNL_AGILITY); 7860ba2cbe9Sxc151355 erp->wl_erp_have_pbcc = erp->wl_erp_pbcc_enabled = 7870ba2cbe9Sxc151355 WIFI_HAVE_CAP(in, IEEE80211_CAPINFO_PBCC); 7880ba2cbe9Sxc151355 erp->wl_erp_dsss_ofdm_enabled = 7890ba2cbe9Sxc151355 WIFI_HAVE_CAP(in, IEEE80211_CAPINFO_DSSSOFDM); 7900ba2cbe9Sxc151355 erp->wl_erp_sst_enabled = WIFI_HAVE_CAP(in, 7910ba2cbe9Sxc151355 IEEE80211_CAPINFO_SHORT_SLOTTIME); 792e2cf88acSQuaker Fang erp->wl_erp_ht_enabled = WIFI_HAVE_HTCAP(in); 7930ba2cbe9Sxc151355 break; 7940ba2cbe9Sxc151355 } /* case IEEE80211_T_OFDM */ 7950ba2cbe9Sxc151355 } /* switch in->in_phytype */ 7960ba2cbe9Sxc151355 } 7970ba2cbe9Sxc151355 7980ba2cbe9Sxc151355 /* supported rates */ 7990ba2cbe9Sxc151355 nrates = MIN(rates->ir_nrates, MAX_SCAN_SUPPORT_RATES); 8000ba2cbe9Sxc151355 /* 8010ba2cbe9Sxc151355 * The number of supported rates might exceed 8020ba2cbe9Sxc151355 * MAX_SCAN_SUPPORT_RATES. Fill in highest rates 8030ba2cbe9Sxc151355 * first so userland command could properly show 8040ba2cbe9Sxc151355 * maximum speed of AP 8050ba2cbe9Sxc151355 */ 8060ba2cbe9Sxc151355 for (i = 0; i < nrates; i++) { 8070ba2cbe9Sxc151355 conf->wl_supported_rates[i] = 8080ba2cbe9Sxc151355 rates->ir_rates[rates->ir_nrates - i - 1]; 8090ba2cbe9Sxc151355 } 8100ba2cbe9Sxc151355 8110ba2cbe9Sxc151355 aps->wl_ess_list_num++; 8120ba2cbe9Sxc151355 } 8130ba2cbe9Sxc151355 8140ba2cbe9Sxc151355 static int 8150ba2cbe9Sxc151355 wifi_cfg_esslist(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 8160ba2cbe9Sxc151355 { 8170ba2cbe9Sxc151355 mblk_t *omp; 8180ba2cbe9Sxc151355 wldp_t *outp; 8190ba2cbe9Sxc151355 wl_ess_list_t *ow_aps; 8200ba2cbe9Sxc151355 int err = 0; 8210ba2cbe9Sxc151355 8220ba2cbe9Sxc151355 if ((omp = wifi_getoutmsg(*mp, cmd, MAX_BUF_LEN - WIFI_BUF_OFFSET)) == 8230ba2cbe9Sxc151355 NULL) { 8240ba2cbe9Sxc151355 return (ENOMEM); 8250ba2cbe9Sxc151355 } 8260ba2cbe9Sxc151355 outp = (wldp_t *)omp->b_rptr; 8270ba2cbe9Sxc151355 ow_aps = (wl_ess_list_t *)outp->wldp_buf; 8280ba2cbe9Sxc151355 8290ba2cbe9Sxc151355 switch (cmd) { 8300ba2cbe9Sxc151355 case WLAN_GET_PARAM: 8310ba2cbe9Sxc151355 ow_aps->wl_ess_list_num = 0; 8320ba2cbe9Sxc151355 ieee80211_iterate_nodes(&ic->ic_scan, wifi_read_ap, ow_aps); 8330ba2cbe9Sxc151355 outp->wldp_length = WIFI_BUF_OFFSET + 8340ba2cbe9Sxc151355 offsetof(wl_ess_list_t, wl_ess_list_ess) + 8350ba2cbe9Sxc151355 ow_aps->wl_ess_list_num * sizeof (wl_ess_conf_t); 8360ba2cbe9Sxc151355 omp->b_wptr = omp->b_rptr + outp->wldp_length; 8370ba2cbe9Sxc151355 break; 8380ba2cbe9Sxc151355 case WLAN_SET_PARAM: 8390ba2cbe9Sxc151355 outp->wldp_result = WL_READONLY; 8400ba2cbe9Sxc151355 err = EINVAL; 8410ba2cbe9Sxc151355 break; 8420ba2cbe9Sxc151355 default: 8430ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_esslist: unknown command %x\n", cmd); 8440ba2cbe9Sxc151355 outp->wldp_result = WL_NOTSUPPORTED; 8450ba2cbe9Sxc151355 err = EINVAL; 8460ba2cbe9Sxc151355 break; 8470ba2cbe9Sxc151355 } 8480ba2cbe9Sxc151355 8490ba2cbe9Sxc151355 freemsg(*mp); 8500ba2cbe9Sxc151355 *mp = omp; 8510ba2cbe9Sxc151355 return (err); 8520ba2cbe9Sxc151355 } 8530ba2cbe9Sxc151355 8540ba2cbe9Sxc151355 /* 8550ba2cbe9Sxc151355 * Scan the network for all available ESSs. 8560ba2cbe9Sxc151355 * IEEE80211_F_SCANONLY is set when current state is INIT. And 8570ba2cbe9Sxc151355 * with this flag, after scan the state will be changed back to 8580ba2cbe9Sxc151355 * INIT. The reason is at the end of SCAN stage, the STA will 8590ba2cbe9Sxc151355 * consequently connect to an AP. Then it looks unreasonable that 8600ba2cbe9Sxc151355 * for a disconnected device, A SCAN command causes it connected. 8610ba2cbe9Sxc151355 * So the state is changed back to INIT. 8620ba2cbe9Sxc151355 */ 8630ba2cbe9Sxc151355 static int 8640ba2cbe9Sxc151355 wifi_cmd_scan(struct ieee80211com *ic, mblk_t *mp) 8650ba2cbe9Sxc151355 { 8660ba2cbe9Sxc151355 int ostate = ic->ic_state; 8670ba2cbe9Sxc151355 8680ba2cbe9Sxc151355 /* 8690ba2cbe9Sxc151355 * Do not scan when current state is RUN. The reason is 8700ba2cbe9Sxc151355 * when connected, STA is on the same channel as AP. But 8710ba2cbe9Sxc151355 * to do scan, STA have to switch to each available channel, 8720ba2cbe9Sxc151355 * send probe request and wait certian time for probe 8730ba2cbe9Sxc151355 * response/beacon. Then when the STA switches to a channel 8740ba2cbe9Sxc151355 * different than AP's, as a result it cannot send/receive 8750ba2cbe9Sxc151355 * data packets to/from the connected WLAN. This eventually 8760ba2cbe9Sxc151355 * will cause data loss. 8770ba2cbe9Sxc151355 */ 8780ba2cbe9Sxc151355 if (ostate == IEEE80211_S_RUN) 8790ba2cbe9Sxc151355 return (0); 8800ba2cbe9Sxc151355 8810ba2cbe9Sxc151355 IEEE80211_UNLOCK(ic); 882a399b765Szf162725 8830ba2cbe9Sxc151355 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 8840ba2cbe9Sxc151355 IEEE80211_LOCK(ic); 8850ba2cbe9Sxc151355 if (ostate == IEEE80211_S_INIT) 8860ba2cbe9Sxc151355 ic->ic_flags |= IEEE80211_F_SCANONLY; 8870ba2cbe9Sxc151355 888a399b765Szf162725 /* Don't wait on WPA mode */ 889a399b765Szf162725 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) { 8900ba2cbe9Sxc151355 /* wait scan complete */ 8910ba2cbe9Sxc151355 wifi_wait_scan(ic); 892a399b765Szf162725 } 8930ba2cbe9Sxc151355 8940ba2cbe9Sxc151355 wifi_setupoutmsg(mp, 0); 8950ba2cbe9Sxc151355 return (0); 8960ba2cbe9Sxc151355 } 8970ba2cbe9Sxc151355 8980ba2cbe9Sxc151355 static void 8990ba2cbe9Sxc151355 wifi_loaddefdata(struct ieee80211com *ic) 9000ba2cbe9Sxc151355 { 9010ba2cbe9Sxc151355 struct ieee80211_node *in = ic->ic_bss; 9020ba2cbe9Sxc151355 int i; 9030ba2cbe9Sxc151355 9040ba2cbe9Sxc151355 ic->ic_des_esslen = 0; 9050ba2cbe9Sxc151355 bzero(ic->ic_des_essid, IEEE80211_NWID_LEN); 9060ba2cbe9Sxc151355 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 9070ba2cbe9Sxc151355 bzero(ic->ic_des_bssid, IEEE80211_ADDR_LEN); 9080ba2cbe9Sxc151355 bzero(ic->ic_bss->in_bssid, IEEE80211_ADDR_LEN); 9090ba2cbe9Sxc151355 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 9100ba2cbe9Sxc151355 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 9110ba2cbe9Sxc151355 bzero(ic->ic_nickname, IEEE80211_NWID_LEN); 9120ba2cbe9Sxc151355 in->in_authmode = IEEE80211_AUTH_OPEN; 9130ba2cbe9Sxc151355 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 914a399b765Szf162725 ic->ic_flags &= ~IEEE80211_F_WPA; /* mask WPA mode */ 915a399b765Szf162725 ic->ic_evq_head = ic->ic_evq_tail = 0; /* reset Queue */ 9160ba2cbe9Sxc151355 ic->ic_def_txkey = 0; 9170ba2cbe9Sxc151355 for (i = 0; i < MAX_NWEPKEYS; i++) { 9180ba2cbe9Sxc151355 ic->ic_nw_keys[i].wk_keylen = 0; 9190ba2cbe9Sxc151355 bzero(ic->ic_nw_keys[i].wk_key, IEEE80211_KEYBUF_SIZE); 9200ba2cbe9Sxc151355 } 9210ba2cbe9Sxc151355 ic->ic_curmode = IEEE80211_MODE_AUTO; 92219d332feSfei feng - Sun Microsystems - Beijing China ic->ic_flags &= ~IEEE80211_F_IBSSON; 92319d332feSfei feng - Sun Microsystems - Beijing China ic->ic_opmode = IEEE80211_M_STA; 9240ba2cbe9Sxc151355 } 9250ba2cbe9Sxc151355 9260ba2cbe9Sxc151355 static int 9270ba2cbe9Sxc151355 wifi_cmd_loaddefaults(struct ieee80211com *ic, mblk_t *mp) 9280ba2cbe9Sxc151355 { 9290ba2cbe9Sxc151355 wifi_loaddefdata(ic); 9300ba2cbe9Sxc151355 wifi_setupoutmsg(mp, 0); 9310ba2cbe9Sxc151355 return (ENETRESET); 9320ba2cbe9Sxc151355 } 9330ba2cbe9Sxc151355 9340ba2cbe9Sxc151355 static int 9350ba2cbe9Sxc151355 wifi_cmd_disassoc(struct ieee80211com *ic, mblk_t *mp) 9360ba2cbe9Sxc151355 { 9370ba2cbe9Sxc151355 if (ic->ic_state != IEEE80211_S_INIT) { 9380ba2cbe9Sxc151355 IEEE80211_UNLOCK(ic); 9390ba2cbe9Sxc151355 (void) ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 9400ba2cbe9Sxc151355 IEEE80211_LOCK(ic); 9410ba2cbe9Sxc151355 } 9420ba2cbe9Sxc151355 wifi_loaddefdata(ic); 9430ba2cbe9Sxc151355 wifi_setupoutmsg(mp, 0); 9440ba2cbe9Sxc151355 return (0); 9450ba2cbe9Sxc151355 } 9460ba2cbe9Sxc151355 947a399b765Szf162725 /* 948a399b765Szf162725 * Get the capabilities of drivers. 949a399b765Szf162725 */ 950a399b765Szf162725 static int 951a399b765Szf162725 wifi_cfg_caps(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 952a399b765Szf162725 { 953a399b765Szf162725 mblk_t *omp; 954a399b765Szf162725 wldp_t *outp; 955a399b765Szf162725 wl_capability_t *o_caps; 956a399b765Szf162725 int err = 0; 957a399b765Szf162725 958a399b765Szf162725 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_capability_t))) == NULL) 959a399b765Szf162725 return (ENOMEM); 960a399b765Szf162725 outp = (wldp_t *)omp->b_rptr; 961a399b765Szf162725 o_caps = (wl_capability_t *)outp->wldp_buf; 962a399b765Szf162725 963a399b765Szf162725 switch (cmd) { 964a399b765Szf162725 case WLAN_GET_PARAM: 965bcb5c89dSSowmini Varadhan wl_get_capability(ic, o_caps); 966a399b765Szf162725 break; 967a399b765Szf162725 case WLAN_SET_PARAM: 968a399b765Szf162725 outp->wldp_result = WL_READONLY; 969a399b765Szf162725 err = EINVAL; 970a399b765Szf162725 break; 971a399b765Szf162725 default: 972a399b765Szf162725 ieee80211_err("wifi_cfg_caps: unknown command %x\n", cmd); 973a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 974a399b765Szf162725 err = EINVAL; 975a399b765Szf162725 break; 976a399b765Szf162725 } 977a399b765Szf162725 978a399b765Szf162725 freemsg(*mp); 979a399b765Szf162725 *mp = omp; 980a399b765Szf162725 return (err); 981a399b765Szf162725 } 982a399b765Szf162725 983a399b765Szf162725 /* 984a399b765Szf162725 * Operating on WPA mode. 985a399b765Szf162725 */ 986a399b765Szf162725 static int 987a399b765Szf162725 wifi_cfg_wpa(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 988a399b765Szf162725 { 989a399b765Szf162725 mblk_t *omp; 990a399b765Szf162725 wldp_t *outp; 991a399b765Szf162725 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 992a399b765Szf162725 wl_wpa_t *wpa = (wl_wpa_t *)inp->wldp_buf; 993a399b765Szf162725 wl_wpa_t *o_wpa; 994a399b765Szf162725 int err = 0; 995a399b765Szf162725 996a399b765Szf162725 if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_wpa_t))) == NULL) 997a399b765Szf162725 return (ENOMEM); 998a399b765Szf162725 outp = (wldp_t *)omp->b_rptr; 999a399b765Szf162725 o_wpa = (wl_wpa_t *)outp->wldp_buf; 1000a399b765Szf162725 1001a399b765Szf162725 switch (cmd) { 1002a399b765Szf162725 case WLAN_GET_PARAM: 1003bcb5c89dSSowmini Varadhan wl_get_wpa(ic, o_wpa); 1004a399b765Szf162725 break; 1005a399b765Szf162725 case WLAN_SET_PARAM: 1006bcb5c89dSSowmini Varadhan err = wl_set_wpa(ic, wpa); 1007a399b765Szf162725 break; 1008a399b765Szf162725 default: 1009a399b765Szf162725 ieee80211_err("wifi_cfg_wpa: unknown command %x\n", cmd); 1010a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 1011a399b765Szf162725 err = EINVAL; 1012a399b765Szf162725 break; 1013a399b765Szf162725 } 1014a399b765Szf162725 1015a399b765Szf162725 freemsg(*mp); 1016a399b765Szf162725 *mp = omp; 1017a399b765Szf162725 return (err); 1018a399b765Szf162725 } 1019a399b765Szf162725 1020a399b765Szf162725 /* 1021a399b765Szf162725 * WPA daemon set the WPA keys. 1022a399b765Szf162725 * The WPA keys are negotiated with APs through wpa service. 1023a399b765Szf162725 */ 1024a399b765Szf162725 static int 1025a399b765Szf162725 wifi_cfg_wpakey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 1026a399b765Szf162725 { 1027a399b765Szf162725 mblk_t *omp; 1028a399b765Szf162725 wldp_t *outp; 1029a399b765Szf162725 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 1030a399b765Szf162725 wl_key_t *ik = (wl_key_t *)(inp->wldp_buf); 1031a399b765Szf162725 int err = 0; 1032a399b765Szf162725 1033a399b765Szf162725 if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) 1034a399b765Szf162725 return (ENOMEM); 1035a399b765Szf162725 outp = (wldp_t *)omp->b_rptr; 1036a399b765Szf162725 1037a399b765Szf162725 switch (cmd) { 1038a399b765Szf162725 case WLAN_GET_PARAM: 1039a399b765Szf162725 outp->wldp_result = WL_WRITEONLY; 1040a399b765Szf162725 err = EINVAL; 1041a399b765Szf162725 break; 1042a399b765Szf162725 case WLAN_SET_PARAM: 1043bcb5c89dSSowmini Varadhan err = wl_set_wpakey(ic, ik); 1044a399b765Szf162725 break; 1045a399b765Szf162725 default: 1046a399b765Szf162725 ieee80211_err("wifi_cfg_wpakey: unknown command %x\n", cmd); 1047a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 1048a399b765Szf162725 err = EINVAL; 1049a399b765Szf162725 break; 1050a399b765Szf162725 } 1051a399b765Szf162725 1052a399b765Szf162725 freemsg(*mp); 1053a399b765Szf162725 *mp = omp; 1054a399b765Szf162725 return (err); 1055a399b765Szf162725 } 1056a399b765Szf162725 1057a399b765Szf162725 /* 1058a399b765Szf162725 * Delete obsolete keys - keys are dynamically exchanged between APs 1059a399b765Szf162725 * and wpa daemon. 1060a399b765Szf162725 */ 1061a399b765Szf162725 static int 1062a399b765Szf162725 wifi_cfg_delkey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 1063a399b765Szf162725 { 1064a399b765Szf162725 mblk_t *omp; 1065a399b765Szf162725 wldp_t *outp; 1066a399b765Szf162725 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 1067a399b765Szf162725 wl_del_key_t *dk = (wl_del_key_t *)inp->wldp_buf; 1068a399b765Szf162725 int err = 0; 1069a399b765Szf162725 1070a399b765Szf162725 if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) 1071a399b765Szf162725 return (ENOMEM); 1072a399b765Szf162725 outp = (wldp_t *)omp->b_rptr; 1073a399b765Szf162725 1074a399b765Szf162725 switch (cmd) { 1075a399b765Szf162725 case WLAN_GET_PARAM: 1076a399b765Szf162725 outp->wldp_result = WL_WRITEONLY; 1077a399b765Szf162725 err = EINVAL; 1078a399b765Szf162725 break; 1079a399b765Szf162725 case WLAN_SET_PARAM: 1080bcb5c89dSSowmini Varadhan err = wl_set_delkey(ic, dk); 1081a399b765Szf162725 break; 1082a399b765Szf162725 default: 1083a399b765Szf162725 ieee80211_err("wifi_cfg_delkey: unknown command %x\n", cmd); 1084a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 1085a399b765Szf162725 err = EINVAL; 1086a399b765Szf162725 break; 1087a399b765Szf162725 } 1088a399b765Szf162725 1089a399b765Szf162725 freemsg(*mp); 1090a399b765Szf162725 *mp = omp; 1091a399b765Szf162725 return (err); 1092a399b765Szf162725 } 1093a399b765Szf162725 1094a399b765Szf162725 /* 1095a399b765Szf162725 * The OPTIE will be used in the association request. 1096a399b765Szf162725 */ 1097a399b765Szf162725 static int 1098a399b765Szf162725 wifi_cfg_setoptie(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 1099a399b765Szf162725 { 1100a399b765Szf162725 mblk_t *omp; 1101a399b765Szf162725 wldp_t *outp; 1102a399b765Szf162725 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 1103a399b765Szf162725 wl_wpa_ie_t *ie_in = (wl_wpa_ie_t *)inp->wldp_buf; 1104a399b765Szf162725 int err = 0; 1105a399b765Szf162725 1106a399b765Szf162725 if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) 1107a399b765Szf162725 return (ENOMEM); 1108a399b765Szf162725 outp = (wldp_t *)omp->b_rptr; 1109a399b765Szf162725 1110a399b765Szf162725 switch (cmd) { 1111a399b765Szf162725 case WLAN_GET_PARAM: 1112a399b765Szf162725 outp->wldp_result = WL_WRITEONLY; 1113a399b765Szf162725 err = EINVAL; 1114a399b765Szf162725 break; 1115a399b765Szf162725 case WLAN_SET_PARAM: 1116bcb5c89dSSowmini Varadhan if ((err = wl_set_optie(ic, ie_in)) == EINVAL) 1117a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 1118a399b765Szf162725 break; 1119a399b765Szf162725 default: 1120a399b765Szf162725 ieee80211_err("wifi_cfg_setoptie: unknown command %x\n", cmd); 1121a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 1122a399b765Szf162725 err = EINVAL; 1123a399b765Szf162725 break; 1124a399b765Szf162725 } 1125a399b765Szf162725 1126a399b765Szf162725 freemsg(*mp); 1127a399b765Szf162725 *mp = omp; 1128a399b765Szf162725 return (err); 1129a399b765Szf162725 } 1130a399b765Szf162725 1131a399b765Szf162725 /* 1132a399b765Szf162725 * To be compatible with drivers/tools of OpenSolaris.org, 1133a399b765Szf162725 * we use a different ID to filter out those APs of WPA mode. 1134a399b765Szf162725 */ 1135a399b765Szf162725 static int 1136a399b765Szf162725 wifi_cfg_scanresults(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 1137a399b765Szf162725 { 1138a399b765Szf162725 mblk_t *omp; 1139a399b765Szf162725 wldp_t *outp; 1140a399b765Szf162725 wl_wpa_ess_t *sr; 1141a399b765Szf162725 ieee80211_node_t *in; 1142a399b765Szf162725 ieee80211_node_table_t *nt; 1143a399b765Szf162725 int len, ap_num = 0; 1144a399b765Szf162725 int err = 0; 1145a399b765Szf162725 1146a399b765Szf162725 if ((omp = wifi_getoutmsg(*mp, cmd, MAX_BUF_LEN - WIFI_BUF_OFFSET)) == 1147a399b765Szf162725 NULL) { 1148a399b765Szf162725 return (ENOMEM); 1149a399b765Szf162725 } 1150a399b765Szf162725 outp = (wldp_t *)omp->b_rptr; 1151a399b765Szf162725 sr = (wl_wpa_ess_t *)outp->wldp_buf; 1152a399b765Szf162725 sr->count = 0; 1153a399b765Szf162725 1154a399b765Szf162725 switch (cmd) { 1155a399b765Szf162725 case WLAN_GET_PARAM: 1156a399b765Szf162725 ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_scanresults\n"); 1157a399b765Szf162725 nt = &ic->ic_scan; 1158a399b765Szf162725 IEEE80211_NODE_LOCK(nt); 1159a399b765Szf162725 in = list_head(&nt->nt_node); 1160a399b765Szf162725 while (in != NULL) { 1161a399b765Szf162725 /* filter out non-WPA APs */ 1162a399b765Szf162725 if (in->in_wpa_ie == NULL) { 1163a399b765Szf162725 in = list_next(&nt->nt_node, in); 1164a399b765Szf162725 continue; 1165a399b765Szf162725 } 1166a399b765Szf162725 bcopy(in->in_bssid, sr->ess[ap_num].bssid, 1167a399b765Szf162725 IEEE80211_ADDR_LEN); 1168a399b765Szf162725 sr->ess[ap_num].ssid_len = in->in_esslen; 1169a399b765Szf162725 bcopy(in->in_essid, sr->ess[ap_num].ssid, 1170a399b765Szf162725 in->in_esslen); 1171a399b765Szf162725 sr->ess[ap_num].freq = in->in_chan->ich_freq; 1172a399b765Szf162725 1173a399b765Szf162725 len = in->in_wpa_ie[1] + 2; 1174a399b765Szf162725 bcopy(in->in_wpa_ie, sr->ess[ap_num].wpa_ie, len); 1175a399b765Szf162725 sr->ess[ap_num].wpa_ie_len = len; 1176a399b765Szf162725 1177a399b765Szf162725 ap_num ++; 1178a399b765Szf162725 in = list_next(&nt->nt_node, in); 1179a399b765Szf162725 } 1180a399b765Szf162725 IEEE80211_NODE_UNLOCK(nt); 1181a399b765Szf162725 sr->count = ap_num; 1182a399b765Szf162725 outp->wldp_length = WIFI_BUF_OFFSET + 1183a399b765Szf162725 offsetof(wl_wpa_ess_t, ess) + 1184a399b765Szf162725 sr->count * sizeof (struct wpa_ess); 1185a399b765Szf162725 omp->b_wptr = omp->b_rptr + outp->wldp_length; 1186a399b765Szf162725 break; 1187a399b765Szf162725 case WLAN_SET_PARAM: 1188a399b765Szf162725 outp->wldp_result = WL_READONLY; 1189a399b765Szf162725 err = EINVAL; 1190a399b765Szf162725 break; 1191a399b765Szf162725 default: 1192a399b765Szf162725 ieee80211_err("wifi_cfg_scanresults: unknown cmmand %x\n", cmd); 1193a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 1194a399b765Szf162725 err = EINVAL; 1195a399b765Szf162725 break; 1196a399b765Szf162725 } 1197a399b765Szf162725 1198a399b765Szf162725 freemsg(*mp); 1199a399b765Szf162725 *mp = omp; 1200a399b765Szf162725 return (err); 1201a399b765Szf162725 } 1202a399b765Szf162725 1203a399b765Szf162725 /* 1204a399b765Szf162725 * Manually control the state of AUTH | DEAUTH | DEASSOC | ASSOC 1205a399b765Szf162725 */ 1206a399b765Szf162725 static int 1207a399b765Szf162725 wifi_cfg_setmlme(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) 1208a399b765Szf162725 { 1209a399b765Szf162725 mblk_t *omp; 1210a399b765Szf162725 wldp_t *outp; 1211a399b765Szf162725 wldp_t *inp = (wldp_t *)(*mp)->b_rptr; 1212a399b765Szf162725 wl_mlme_t *mlme = (wl_mlme_t *)inp->wldp_buf; 1213a399b765Szf162725 int err = 0; 1214a399b765Szf162725 1215a399b765Szf162725 if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) 1216a399b765Szf162725 return (ENOMEM); 1217a399b765Szf162725 outp = (wldp_t *)omp->b_rptr; 1218a399b765Szf162725 1219a399b765Szf162725 switch (cmd) { 1220a399b765Szf162725 case WLAN_GET_PARAM: 1221a399b765Szf162725 outp->wldp_result = WL_WRITEONLY; 1222a399b765Szf162725 err = EINVAL; 1223a399b765Szf162725 break; 1224a399b765Szf162725 case WLAN_SET_PARAM: 1225bcb5c89dSSowmini Varadhan err = wl_set_mlme(ic, mlme); 1226a399b765Szf162725 break; 1227a399b765Szf162725 default: 1228a399b765Szf162725 ieee80211_err("wifi_cfg_delkey: unknown command %x\n", cmd); 1229a399b765Szf162725 outp->wldp_result = WL_NOTSUPPORTED; 1230a399b765Szf162725 err = EINVAL; 1231a399b765Szf162725 break; 1232a399b765Szf162725 } 1233a399b765Szf162725 1234a399b765Szf162725 freemsg(*mp); 1235a399b765Szf162725 *mp = omp; 1236a399b765Szf162725 return (err); 1237a399b765Szf162725 } 1238a399b765Szf162725 12390ba2cbe9Sxc151355 static int 12400ba2cbe9Sxc151355 wifi_cfg_getset(struct ieee80211com *ic, mblk_t **mp, uint32_t cmd) 12410ba2cbe9Sxc151355 { 12420ba2cbe9Sxc151355 mblk_t *mp1 = *mp; 12430ba2cbe9Sxc151355 wldp_t *wp = (wldp_t *)mp1->b_rptr; 12440ba2cbe9Sxc151355 int err = 0; 12450ba2cbe9Sxc151355 12460ba2cbe9Sxc151355 ASSERT(ic != NULL && mp1 != NULL); 12470ba2cbe9Sxc151355 IEEE80211_LOCK_ASSERT(ic); 12480ba2cbe9Sxc151355 if (MBLKL(mp1) < WIFI_BUF_OFFSET) { 12490ba2cbe9Sxc151355 ieee80211_err("wifi_cfg_getset: " 12500ba2cbe9Sxc151355 "invalid input buffer, size=%d\n", MBLKL(mp1)); 12510ba2cbe9Sxc151355 return (EINVAL); 12520ba2cbe9Sxc151355 } 12530ba2cbe9Sxc151355 12540ba2cbe9Sxc151355 switch (wp->wldp_id) { 12550ba2cbe9Sxc151355 /* Commands */ 12560ba2cbe9Sxc151355 case WL_SCAN: 12570ba2cbe9Sxc151355 err = wifi_cmd_scan(ic, mp1); 12580ba2cbe9Sxc151355 break; 12590ba2cbe9Sxc151355 case WL_LOAD_DEFAULTS: 12600ba2cbe9Sxc151355 err = wifi_cmd_loaddefaults(ic, mp1); 12610ba2cbe9Sxc151355 break; 12620ba2cbe9Sxc151355 case WL_DISASSOCIATE: 12630ba2cbe9Sxc151355 err = wifi_cmd_disassoc(ic, mp1); 12640ba2cbe9Sxc151355 break; 12650ba2cbe9Sxc151355 /* Parameters */ 12660ba2cbe9Sxc151355 case WL_ESSID: 12670ba2cbe9Sxc151355 err = wifi_cfg_essid(ic, cmd, mp); 12680ba2cbe9Sxc151355 break; 12690ba2cbe9Sxc151355 case WL_BSSID: 12700ba2cbe9Sxc151355 err = wifi_cfg_bssid(ic, cmd, mp); 12710ba2cbe9Sxc151355 break; 12720ba2cbe9Sxc151355 case WL_NODE_NAME: 12730ba2cbe9Sxc151355 err = wifi_cfg_nodename(ic, cmd, mp); 12740ba2cbe9Sxc151355 break; 12750ba2cbe9Sxc151355 case WL_PHY_CONFIG: 12760ba2cbe9Sxc151355 err = wifi_cfg_phy(ic, cmd, mp); 12770ba2cbe9Sxc151355 break; 12780ba2cbe9Sxc151355 case WL_WEP_KEY_TAB: 12790ba2cbe9Sxc151355 err = wifi_cfg_wepkey(ic, cmd, mp); 12800ba2cbe9Sxc151355 break; 12810ba2cbe9Sxc151355 case WL_WEP_KEY_ID: 12820ba2cbe9Sxc151355 err = wifi_cfg_keyid(ic, cmd, mp); 12830ba2cbe9Sxc151355 break; 12840ba2cbe9Sxc151355 case WL_AUTH_MODE: 12850ba2cbe9Sxc151355 err = wifi_cfg_authmode(ic, cmd, mp); 12860ba2cbe9Sxc151355 break; 12870ba2cbe9Sxc151355 case WL_ENCRYPTION: 12880ba2cbe9Sxc151355 err = wifi_cfg_encrypt(ic, cmd, mp); 12890ba2cbe9Sxc151355 break; 12900ba2cbe9Sxc151355 case WL_BSS_TYPE: 12910ba2cbe9Sxc151355 err = wifi_cfg_bsstype(ic, cmd, mp); 12920ba2cbe9Sxc151355 break; 129319d332feSfei feng - Sun Microsystems - Beijing China case WL_CREATE_IBSS: 129419d332feSfei feng - Sun Microsystems - Beijing China err = wifi_cfg_createibss(ic, cmd, mp); 129519d332feSfei feng - Sun Microsystems - Beijing China break; 12960ba2cbe9Sxc151355 case WL_DESIRED_RATES: 12970ba2cbe9Sxc151355 err = wifi_cfg_desrates(ic, cmd, mp); 12980ba2cbe9Sxc151355 break; 12990ba2cbe9Sxc151355 case WL_LINKSTATUS: 13000ba2cbe9Sxc151355 err = wifi_cfg_linkstatus(ic, cmd, mp); 13010ba2cbe9Sxc151355 break; 13020ba2cbe9Sxc151355 case WL_ESS_LIST: 13030ba2cbe9Sxc151355 err = wifi_cfg_esslist(ic, cmd, mp); 13040ba2cbe9Sxc151355 break; 13050ba2cbe9Sxc151355 case WL_SUPPORTED_RATES: 13060ba2cbe9Sxc151355 err = wifi_cfg_suprates(ic, cmd, mp); 13070ba2cbe9Sxc151355 break; 13080ba2cbe9Sxc151355 case WL_RSSI: 13090ba2cbe9Sxc151355 err = wifi_cfg_rssi(ic, cmd, mp); 13100ba2cbe9Sxc151355 break; 1311a399b765Szf162725 /* 1312a399b765Szf162725 * WPA IOCTLs 1313a399b765Szf162725 */ 1314a399b765Szf162725 case WL_CAPABILITY: 1315a399b765Szf162725 err = wifi_cfg_caps(ic, cmd, mp); 1316a399b765Szf162725 break; 1317a399b765Szf162725 case WL_WPA: 1318a399b765Szf162725 err = wifi_cfg_wpa(ic, cmd, mp); 1319a399b765Szf162725 break; 1320a399b765Szf162725 case WL_KEY: 1321a399b765Szf162725 err = wifi_cfg_wpakey(ic, cmd, mp); 1322a399b765Szf162725 break; 1323a399b765Szf162725 case WL_DELKEY: 1324a399b765Szf162725 err = wifi_cfg_delkey(ic, cmd, mp); 1325a399b765Szf162725 break; 1326a399b765Szf162725 case WL_SETOPTIE: 1327a399b765Szf162725 err = wifi_cfg_setoptie(ic, cmd, mp); 1328a399b765Szf162725 break; 1329a399b765Szf162725 case WL_SCANRESULTS: 1330a399b765Szf162725 err = wifi_cfg_scanresults(ic, cmd, mp); 1331a399b765Szf162725 break; 1332a399b765Szf162725 case WL_MLME: 1333a399b765Szf162725 err = wifi_cfg_setmlme(ic, cmd, mp); 1334a399b765Szf162725 break; 13350ba2cbe9Sxc151355 default: 13360ba2cbe9Sxc151355 wifi_setupoutmsg(mp1, 0); 13370ba2cbe9Sxc151355 wp->wldp_result = WL_LACK_FEATURE; 13380ba2cbe9Sxc151355 err = ENOTSUP; 13390ba2cbe9Sxc151355 break; 13400ba2cbe9Sxc151355 } 13410ba2cbe9Sxc151355 13420ba2cbe9Sxc151355 return (err); 13430ba2cbe9Sxc151355 } 13440ba2cbe9Sxc151355 13450ba2cbe9Sxc151355 /* 13460ba2cbe9Sxc151355 * Typically invoked by drivers in response to requests for 13470ba2cbe9Sxc151355 * information or to change settings from the userland. 13480ba2cbe9Sxc151355 * 13490ba2cbe9Sxc151355 * Return value should be checked by WiFi drivers. Return 0 13500ba2cbe9Sxc151355 * on success. Otherwise, return non-zero value to indicate 13510ba2cbe9Sxc151355 * the error. Driver should operate as below when the return 13520ba2cbe9Sxc151355 * error is: 13530ba2cbe9Sxc151355 * ENETRESET Reset wireless network and re-start to join a 13540ba2cbe9Sxc151355 * WLAN. ENETRESET is returned when a configuration 13550ba2cbe9Sxc151355 * parameter has been changed. 13560ba2cbe9Sxc151355 * When acknowledge a M_IOCTL message, thie error 13570ba2cbe9Sxc151355 * is ignored. 13580ba2cbe9Sxc151355 */ 13590ba2cbe9Sxc151355 int 13600ba2cbe9Sxc151355 ieee80211_ioctl(struct ieee80211com *ic, queue_t *wq, mblk_t *mp) 13610ba2cbe9Sxc151355 { 13620ba2cbe9Sxc151355 struct iocblk *iocp; 13630ba2cbe9Sxc151355 int32_t cmd, err, len; 13640ba2cbe9Sxc151355 boolean_t need_privilege; 13650ba2cbe9Sxc151355 mblk_t *mp1; 13660ba2cbe9Sxc151355 13670ba2cbe9Sxc151355 if (MBLKL(mp) < sizeof (struct iocblk)) { 13680ba2cbe9Sxc151355 ieee80211_err("ieee80211_ioctl: ioctl buffer too short, %u\n", 13690ba2cbe9Sxc151355 MBLKL(mp)); 13700ba2cbe9Sxc151355 miocnak(wq, mp, 0, EINVAL); 13710ba2cbe9Sxc151355 return (EINVAL); 13720ba2cbe9Sxc151355 } 13730ba2cbe9Sxc151355 13740ba2cbe9Sxc151355 /* 13750ba2cbe9Sxc151355 * Validate the command 13760ba2cbe9Sxc151355 */ 13770ba2cbe9Sxc151355 iocp = (struct iocblk *)mp->b_rptr; 13780ba2cbe9Sxc151355 iocp->ioc_error = 0; 13790ba2cbe9Sxc151355 cmd = iocp->ioc_cmd; 13800ba2cbe9Sxc151355 need_privilege = B_TRUE; 13810ba2cbe9Sxc151355 switch (cmd) { 13820ba2cbe9Sxc151355 case WLAN_SET_PARAM: 13830ba2cbe9Sxc151355 case WLAN_COMMAND: 13840ba2cbe9Sxc151355 break; 13850ba2cbe9Sxc151355 case WLAN_GET_PARAM: 13860ba2cbe9Sxc151355 need_privilege = B_FALSE; 13870ba2cbe9Sxc151355 break; 13880ba2cbe9Sxc151355 default: 13890ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_ioctl(): " 13900ba2cbe9Sxc151355 "unknown cmd 0x%x\n", cmd); 13910ba2cbe9Sxc151355 miocnak(wq, mp, 0, EINVAL); 13920ba2cbe9Sxc151355 return (EINVAL); 13930ba2cbe9Sxc151355 } 13940ba2cbe9Sxc151355 1395eae72b5bSSebastien Roy if (need_privilege && (err = secpolicy_dl_config(iocp->ioc_cr)) != 0) { 13960ba2cbe9Sxc151355 miocnak(wq, mp, 0, err); 13970ba2cbe9Sxc151355 return (err); 13980ba2cbe9Sxc151355 } 13990ba2cbe9Sxc151355 14000ba2cbe9Sxc151355 IEEE80211_LOCK(ic); 14010ba2cbe9Sxc151355 14020ba2cbe9Sxc151355 /* sanity check */ 14030ba2cbe9Sxc151355 mp1 = mp->b_cont; 14040ba2cbe9Sxc151355 if (iocp->ioc_count == 0 || iocp->ioc_count < sizeof (wldp_t) || 14050ba2cbe9Sxc151355 mp1 == NULL) { 14060ba2cbe9Sxc151355 miocnak(wq, mp, 0, EINVAL); 14070ba2cbe9Sxc151355 IEEE80211_UNLOCK(ic); 14080ba2cbe9Sxc151355 return (EINVAL); 14090ba2cbe9Sxc151355 } 14100ba2cbe9Sxc151355 14110ba2cbe9Sxc151355 /* assuming single data block */ 14120ba2cbe9Sxc151355 if (mp1->b_cont != NULL) { 14130ba2cbe9Sxc151355 freemsg(mp1->b_cont); 14140ba2cbe9Sxc151355 mp1->b_cont = NULL; 14150ba2cbe9Sxc151355 } 14160ba2cbe9Sxc151355 14170ba2cbe9Sxc151355 err = wifi_cfg_getset(ic, &mp1, cmd); 14180ba2cbe9Sxc151355 mp->b_cont = mp1; 14190ba2cbe9Sxc151355 IEEE80211_UNLOCK(ic); 14200ba2cbe9Sxc151355 14210ba2cbe9Sxc151355 len = msgdsize(mp1); 14220ba2cbe9Sxc151355 /* ignore ENETRESET when acknowledge the M_IOCTL message */ 14230ba2cbe9Sxc151355 if (err == 0 || err == ENETRESET) 14240ba2cbe9Sxc151355 miocack(wq, mp, len, 0); 14250ba2cbe9Sxc151355 else 14260ba2cbe9Sxc151355 miocack(wq, mp, len, err); 14270ba2cbe9Sxc151355 14280ba2cbe9Sxc151355 return (err); 14290ba2cbe9Sxc151355 } 1430bcb5c89dSSowmini Varadhan 1431bcb5c89dSSowmini Varadhan /* 1432bcb5c89dSSowmini Varadhan * The following routines are for brussels support 1433bcb5c89dSSowmini Varadhan */ 1434bcb5c89dSSowmini Varadhan 1435bcb5c89dSSowmini Varadhan /* 1436bcb5c89dSSowmini Varadhan * MAC_PROP_WL_ESSID 1437bcb5c89dSSowmini Varadhan */ 1438bcb5c89dSSowmini Varadhan static int 1439bcb5c89dSSowmini Varadhan wl_set_essid(struct ieee80211com *ic, const void *wldp_buf) 1440bcb5c89dSSowmini Varadhan { 1441bcb5c89dSSowmini Varadhan int err = 0; 1442bcb5c89dSSowmini Varadhan char *essid; 1443bcb5c89dSSowmini Varadhan wl_essid_t *iw_essid = (wl_essid_t *)wldp_buf; 1444bcb5c89dSSowmini Varadhan 1445bcb5c89dSSowmini Varadhan if (iw_essid->wl_essid_length > IEEE80211_NWID_LEN) { 1446bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_essid: " 1447bcb5c89dSSowmini Varadhan "essid too long, %u, max %u\n", 1448bcb5c89dSSowmini Varadhan iw_essid->wl_essid_length, IEEE80211_NWID_LEN); 1449bcb5c89dSSowmini Varadhan 1450bcb5c89dSSowmini Varadhan err = EINVAL; 1451bcb5c89dSSowmini Varadhan return (err); 1452bcb5c89dSSowmini Varadhan } 1453bcb5c89dSSowmini Varadhan 1454bcb5c89dSSowmini Varadhan essid = iw_essid->wl_essid_essid; 1455bcb5c89dSSowmini Varadhan essid[IEEE80211_NWID_LEN] = 0; 1456bcb5c89dSSowmini Varadhan 1457bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_essid: " 1458bcb5c89dSSowmini Varadhan "set essid=%s length=%d\n", 1459bcb5c89dSSowmini Varadhan essid, iw_essid->wl_essid_length); 1460bcb5c89dSSowmini Varadhan 1461bcb5c89dSSowmini Varadhan ic->ic_des_esslen = iw_essid->wl_essid_length; 1462bcb5c89dSSowmini Varadhan if (ic->ic_des_esslen != 0) 1463bcb5c89dSSowmini Varadhan bcopy(essid, ic->ic_des_essid, ic->ic_des_esslen); 1464bcb5c89dSSowmini Varadhan if (ic->ic_des_esslen < IEEE80211_NWID_LEN) 1465bcb5c89dSSowmini Varadhan ic->ic_des_essid[ic->ic_des_esslen] = 0; 1466bcb5c89dSSowmini Varadhan 1467bcb5c89dSSowmini Varadhan err = ENETRESET; 1468bcb5c89dSSowmini Varadhan 1469bcb5c89dSSowmini Varadhan return (err); 1470bcb5c89dSSowmini Varadhan } 1471bcb5c89dSSowmini Varadhan 1472bcb5c89dSSowmini Varadhan static void 1473bcb5c89dSSowmini Varadhan wl_get_essid(struct ieee80211com *ic, void *wldp_buf) 1474bcb5c89dSSowmini Varadhan { 1475bcb5c89dSSowmini Varadhan char *essid; 1476bcb5c89dSSowmini Varadhan wl_essid_t ow_essid; 1477bcb5c89dSSowmini Varadhan 1478bcb5c89dSSowmini Varadhan essid = (char *)ic->ic_des_essid; 1479bcb5c89dSSowmini Varadhan if (essid[0] == '\0') 1480bcb5c89dSSowmini Varadhan essid = (char *)ic->ic_bss->in_essid; 1481bcb5c89dSSowmini Varadhan 1482bcb5c89dSSowmini Varadhan bzero(&ow_essid, sizeof (wl_essid_t)); 1483bcb5c89dSSowmini Varadhan ow_essid.wl_essid_length = wifi_strnlen((const char *)essid, 1484bcb5c89dSSowmini Varadhan IEEE80211_NWID_LEN); 1485bcb5c89dSSowmini Varadhan bcopy(essid, ow_essid.wl_essid_essid, 1486bcb5c89dSSowmini Varadhan ow_essid.wl_essid_length); 1487bcb5c89dSSowmini Varadhan bcopy(&ow_essid, wldp_buf, sizeof (wl_essid_t)); 1488bcb5c89dSSowmini Varadhan 1489bcb5c89dSSowmini Varadhan } 1490bcb5c89dSSowmini Varadhan 1491bcb5c89dSSowmini Varadhan /* 1492bcb5c89dSSowmini Varadhan * MAC_PROP_WL_BSSID 1493bcb5c89dSSowmini Varadhan */ 1494bcb5c89dSSowmini Varadhan static int 1495bcb5c89dSSowmini Varadhan wl_set_bssid(struct ieee80211com *ic, const void* wldp_buf) 1496bcb5c89dSSowmini Varadhan { 1497bcb5c89dSSowmini Varadhan 1498bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_bssid: " 1499bcb5c89dSSowmini Varadhan "set bssid=%s\n", 1500bcb5c89dSSowmini Varadhan ieee80211_macaddr_sprintf(wldp_buf)); 1501bcb5c89dSSowmini Varadhan 1502bcb5c89dSSowmini Varadhan bcopy(wldp_buf, ic->ic_des_bssid, sizeof (wl_bssid_t)); 1503bcb5c89dSSowmini Varadhan ic->ic_flags |= IEEE80211_F_DESBSSID; 1504bcb5c89dSSowmini Varadhan 1505bcb5c89dSSowmini Varadhan return (ENETRESET); 1506bcb5c89dSSowmini Varadhan } 1507bcb5c89dSSowmini Varadhan 1508bcb5c89dSSowmini Varadhan static void 1509bcb5c89dSSowmini Varadhan wl_get_bssid(struct ieee80211com *ic, void *wldp_buf) 1510bcb5c89dSSowmini Varadhan { 1511bcb5c89dSSowmini Varadhan uint8_t *bssid; 1512bcb5c89dSSowmini Varadhan 1513bcb5c89dSSowmini Varadhan if (ic->ic_flags & IEEE80211_F_DESBSSID) 1514bcb5c89dSSowmini Varadhan bssid = ic->ic_des_bssid; 1515bcb5c89dSSowmini Varadhan else 1516bcb5c89dSSowmini Varadhan bssid = ic->ic_bss->in_bssid; 1517bcb5c89dSSowmini Varadhan bcopy(bssid, wldp_buf, sizeof (wl_bssid_t)); 1518bcb5c89dSSowmini Varadhan 1519bcb5c89dSSowmini Varadhan } 1520bcb5c89dSSowmini Varadhan 1521bcb5c89dSSowmini Varadhan /* 1522bcb5c89dSSowmini Varadhan * MAC_PROP_WL_BSSTYP 1523bcb5c89dSSowmini Varadhan */ 1524bcb5c89dSSowmini Varadhan static int 1525bcb5c89dSSowmini Varadhan wl_set_bsstype(struct ieee80211com *ic, const void *wldp_buf) 1526bcb5c89dSSowmini Varadhan { 1527bcb5c89dSSowmini Varadhan int err = 0; 1528bcb5c89dSSowmini Varadhan wl_bss_type_t *iw_opmode = (wl_bss_type_t *)wldp_buf; 1529bcb5c89dSSowmini Varadhan 1530bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_bsstype: " 1531bcb5c89dSSowmini Varadhan "set bsstype=%u\n", *iw_opmode); 1532bcb5c89dSSowmini Varadhan 1533bcb5c89dSSowmini Varadhan switch (*iw_opmode) { 1534bcb5c89dSSowmini Varadhan case WL_BSS_BSS: 1535bcb5c89dSSowmini Varadhan ic->ic_flags &= ~IEEE80211_F_IBSSON; 1536bcb5c89dSSowmini Varadhan ic->ic_opmode = IEEE80211_M_STA; 1537bcb5c89dSSowmini Varadhan err = ENETRESET; 1538bcb5c89dSSowmini Varadhan break; 1539bcb5c89dSSowmini Varadhan case WL_BSS_IBSS: 1540bcb5c89dSSowmini Varadhan if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) { 1541bcb5c89dSSowmini Varadhan err = ENOTSUP; 1542bcb5c89dSSowmini Varadhan break; 1543bcb5c89dSSowmini Varadhan } 154419d332feSfei feng - Sun Microsystems - Beijing China 1545bcb5c89dSSowmini Varadhan ic->ic_opmode = IEEE80211_M_IBSS; 1546bcb5c89dSSowmini Varadhan err = ENETRESET; 1547bcb5c89dSSowmini Varadhan break; 1548bcb5c89dSSowmini Varadhan default: 1549bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_bsstype: " 1550bcb5c89dSSowmini Varadhan "unknown opmode\n"); 1551bcb5c89dSSowmini Varadhan err = EINVAL; 1552bcb5c89dSSowmini Varadhan break; 1553bcb5c89dSSowmini Varadhan } 1554bcb5c89dSSowmini Varadhan return (err); 1555bcb5c89dSSowmini Varadhan } 1556bcb5c89dSSowmini Varadhan 1557bcb5c89dSSowmini Varadhan static void 1558bcb5c89dSSowmini Varadhan wl_get_bsstype(struct ieee80211com *ic, void *wldp_buf) 1559bcb5c89dSSowmini Varadhan { 1560bcb5c89dSSowmini Varadhan wl_bss_type_t ow_opmode; 1561bcb5c89dSSowmini Varadhan 1562bcb5c89dSSowmini Varadhan switch (ic->ic_opmode) { 1563bcb5c89dSSowmini Varadhan case IEEE80211_M_STA: 1564bcb5c89dSSowmini Varadhan ow_opmode = WL_BSS_BSS; 1565bcb5c89dSSowmini Varadhan break; 1566bcb5c89dSSowmini Varadhan case IEEE80211_M_IBSS: 1567bcb5c89dSSowmini Varadhan ow_opmode = WL_BSS_IBSS; 1568bcb5c89dSSowmini Varadhan break; 1569bcb5c89dSSowmini Varadhan default: 1570bcb5c89dSSowmini Varadhan ow_opmode = WL_BSS_ANY; 1571bcb5c89dSSowmini Varadhan break; 1572bcb5c89dSSowmini Varadhan } 1573bcb5c89dSSowmini Varadhan 1574bcb5c89dSSowmini Varadhan bcopy(&ow_opmode, wldp_buf, sizeof (wl_bss_type_t)); 1575bcb5c89dSSowmini Varadhan } 1576bcb5c89dSSowmini Varadhan 1577bcb5c89dSSowmini Varadhan /* 1578bcb5c89dSSowmini Varadhan * MAC_PROP_WL_LINKSTATUS 1579bcb5c89dSSowmini Varadhan */ 1580bcb5c89dSSowmini Varadhan static void 1581bcb5c89dSSowmini Varadhan wl_get_linkstatus(struct ieee80211com *ic, void *wldp_buf) 1582bcb5c89dSSowmini Varadhan { 1583bcb5c89dSSowmini Varadhan wl_linkstatus_t ow_linkstat; 1584bcb5c89dSSowmini Varadhan 1585bcb5c89dSSowmini Varadhan ow_linkstat = (ic->ic_state == IEEE80211_S_RUN) ? 1586bcb5c89dSSowmini Varadhan WL_CONNECTED : WL_NOTCONNECTED; 1587bcb5c89dSSowmini Varadhan if ((ic->ic_flags & IEEE80211_F_WPA) && 1588bcb5c89dSSowmini Varadhan (ieee80211_crypto_getciphertype(ic) != WIFI_SEC_WPA)) { 1589bcb5c89dSSowmini Varadhan ow_linkstat = WL_NOTCONNECTED; 1590bcb5c89dSSowmini Varadhan } 1591bcb5c89dSSowmini Varadhan 1592bcb5c89dSSowmini Varadhan bcopy(&ow_linkstat, wldp_buf, sizeof (wl_linkstatus_t)); 1593bcb5c89dSSowmini Varadhan } 1594bcb5c89dSSowmini Varadhan 1595bcb5c89dSSowmini Varadhan /* 1596bcb5c89dSSowmini Varadhan * MAC_PROP_WL_DESIRED_RATESa 1597bcb5c89dSSowmini Varadhan */ 1598bcb5c89dSSowmini Varadhan static int 1599bcb5c89dSSowmini Varadhan wl_set_desrates(struct ieee80211com *ic, const void *wldp_buf) 1600bcb5c89dSSowmini Varadhan { 1601bcb5c89dSSowmini Varadhan int err = 0; 1602bcb5c89dSSowmini Varadhan int i, j; 1603bcb5c89dSSowmini Varadhan uint8_t drate; 1604bcb5c89dSSowmini Varadhan boolean_t isfound; 1605bcb5c89dSSowmini Varadhan wl_rates_t *iw_rates = (wl_rates_t *)wldp_buf; 1606bcb5c89dSSowmini Varadhan struct ieee80211_node *in = ic->ic_bss; 1607bcb5c89dSSowmini Varadhan struct ieee80211_rateset *rs = &in->in_rates; 1608bcb5c89dSSowmini Varadhan 1609bcb5c89dSSowmini Varadhan drate = iw_rates->wl_rates_rates[0]; 1610bcb5c89dSSowmini Varadhan if (ic->ic_fixed_rate == drate) 1611bcb5c89dSSowmini Varadhan return (err); 1612bcb5c89dSSowmini Varadhan 1613bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_desrates: " 1614bcb5c89dSSowmini Varadhan "set desired rate=%u\n", drate); 1615bcb5c89dSSowmini Varadhan 1616bcb5c89dSSowmini Varadhan if (drate == 0) { 1617bcb5c89dSSowmini Varadhan ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 1618bcb5c89dSSowmini Varadhan if (ic->ic_state == IEEE80211_S_RUN) { 1619bcb5c89dSSowmini Varadhan IEEE80211_UNLOCK(ic); 1620bcb5c89dSSowmini Varadhan ieee80211_new_state(ic, IEEE80211_S_ASSOC, 0); 1621bcb5c89dSSowmini Varadhan IEEE80211_LOCK(ic); 1622bcb5c89dSSowmini Varadhan } 1623bcb5c89dSSowmini Varadhan return (err); 1624bcb5c89dSSowmini Varadhan } 1625bcb5c89dSSowmini Varadhan 1626bcb5c89dSSowmini Varadhan /* 1627bcb5c89dSSowmini Varadhan * Set desired rate. The desired rate is for data transfer 1628bcb5c89dSSowmini Varadhan * and usally is checked and used when driver changes to 1629bcb5c89dSSowmini Varadhan * RUN state. 1630bcb5c89dSSowmini Varadhan * If the driver is in AUTH | ASSOC | RUN state, desired 1631bcb5c89dSSowmini Varadhan * rate is checked anainst rates supported by current ESS. 1632bcb5c89dSSowmini Varadhan * If it's supported and current state is AUTH|ASSOC, nothing 1633bcb5c89dSSowmini Varadhan * needs to be done by driver since the desired rate will 1634bcb5c89dSSowmini Varadhan * be enabled when the device changes to RUN state. And 1635bcb5c89dSSowmini Varadhan * when current state is RUN, Re-associate with the ESS to 1636bcb5c89dSSowmini Varadhan * enable the desired rate. 1637bcb5c89dSSowmini Varadhan */ 1638bcb5c89dSSowmini Varadhan 1639bcb5c89dSSowmini Varadhan if (ic->ic_state != IEEE80211_S_INIT && 1640bcb5c89dSSowmini Varadhan ic->ic_state != IEEE80211_S_SCAN) { 1641bcb5c89dSSowmini Varadhan for (i = 0; i < rs->ir_nrates; i++) { 1642bcb5c89dSSowmini Varadhan if (drate == IEEE80211_RV(rs->ir_rates[i])) 1643bcb5c89dSSowmini Varadhan break; 1644bcb5c89dSSowmini Varadhan } 1645bcb5c89dSSowmini Varadhan /* supported */ 1646bcb5c89dSSowmini Varadhan if (i < rs->ir_nrates) { 1647bcb5c89dSSowmini Varadhan ic->ic_fixed_rate = drate; 1648bcb5c89dSSowmini Varadhan if (ic->ic_state == IEEE80211_S_RUN) { 1649bcb5c89dSSowmini Varadhan IEEE80211_UNLOCK(ic); 1650bcb5c89dSSowmini Varadhan ieee80211_new_state(ic, 1651bcb5c89dSSowmini Varadhan IEEE80211_S_ASSOC, 0); 1652bcb5c89dSSowmini Varadhan IEEE80211_LOCK(ic); 1653bcb5c89dSSowmini Varadhan } 1654bcb5c89dSSowmini Varadhan return (err); 1655bcb5c89dSSowmini Varadhan } 1656bcb5c89dSSowmini Varadhan } 1657bcb5c89dSSowmini Varadhan 1658bcb5c89dSSowmini Varadhan /* 1659bcb5c89dSSowmini Varadhan * In INIT or SCAN state 1660bcb5c89dSSowmini Varadhan * check if the desired rate is supported by device 1661bcb5c89dSSowmini Varadhan */ 1662bcb5c89dSSowmini Varadhan isfound = B_FALSE; 1663bcb5c89dSSowmini Varadhan for (i = 0; i < IEEE80211_MODE_MAX; i++) { 1664bcb5c89dSSowmini Varadhan rs = &ic->ic_sup_rates[i]; 1665bcb5c89dSSowmini Varadhan for (j = 0; j < rs->ir_nrates; j++) { 1666bcb5c89dSSowmini Varadhan if (drate == IEEE80211_RV(rs->ir_rates[j])) { 1667bcb5c89dSSowmini Varadhan isfound = B_TRUE; 1668bcb5c89dSSowmini Varadhan break; 1669bcb5c89dSSowmini Varadhan } 1670bcb5c89dSSowmini Varadhan } 1671bcb5c89dSSowmini Varadhan if (isfound) 1672bcb5c89dSSowmini Varadhan break; 1673bcb5c89dSSowmini Varadhan } 1674bcb5c89dSSowmini Varadhan if (!isfound) { 1675bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_desrates: " 1676bcb5c89dSSowmini Varadhan "invald rate %d\n", drate); 1677bcb5c89dSSowmini Varadhan err = EINVAL; 1678bcb5c89dSSowmini Varadhan return (err); 1679bcb5c89dSSowmini Varadhan } 1680bcb5c89dSSowmini Varadhan ic->ic_fixed_rate = drate; 1681bcb5c89dSSowmini Varadhan if (ic->ic_state != IEEE80211_S_SCAN) 1682bcb5c89dSSowmini Varadhan err = ENETRESET; 1683bcb5c89dSSowmini Varadhan 1684bcb5c89dSSowmini Varadhan return (err); 1685bcb5c89dSSowmini Varadhan } 1686bcb5c89dSSowmini Varadhan 1687bcb5c89dSSowmini Varadhan static void 1688bcb5c89dSSowmini Varadhan wl_get_desrates(struct ieee80211com *ic, void *wldp_buf) 1689bcb5c89dSSowmini Varadhan { 1690bcb5c89dSSowmini Varadhan uint8_t srate; 1691bcb5c89dSSowmini Varadhan wl_rates_t ow_rates; 1692bcb5c89dSSowmini Varadhan struct ieee80211_node *in = ic->ic_bss; 1693bcb5c89dSSowmini Varadhan struct ieee80211_rateset *rs = &in->in_rates; 1694bcb5c89dSSowmini Varadhan 1695bcb5c89dSSowmini Varadhan srate = rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL; 1696bcb5c89dSSowmini Varadhan ow_rates.wl_rates_num = 1; 1697bcb5c89dSSowmini Varadhan ow_rates.wl_rates_rates[0] = 1698bcb5c89dSSowmini Varadhan (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 1699bcb5c89dSSowmini Varadhan srate : ic->ic_fixed_rate; 1700bcb5c89dSSowmini Varadhan bcopy(&ow_rates, wldp_buf, sizeof (wl_rates_t)); 1701bcb5c89dSSowmini Varadhan 1702bcb5c89dSSowmini Varadhan } 1703bcb5c89dSSowmini Varadhan 1704bcb5c89dSSowmini Varadhan /* 1705bcb5c89dSSowmini Varadhan * MAC_PROP_AUTH_MODE 1706bcb5c89dSSowmini Varadhan */ 1707bcb5c89dSSowmini Varadhan static int 1708bcb5c89dSSowmini Varadhan wl_set_authmode(struct ieee80211com *ic, const void *wldp_buf) 1709bcb5c89dSSowmini Varadhan { 1710bcb5c89dSSowmini Varadhan int err = 0; 1711bcb5c89dSSowmini Varadhan wl_authmode_t *iw_auth = (wl_authmode_t *)wldp_buf; 1712bcb5c89dSSowmini Varadhan 1713bcb5c89dSSowmini Varadhan if (*iw_auth == ic->ic_bss->in_authmode) 1714bcb5c89dSSowmini Varadhan return (err); 1715bcb5c89dSSowmini Varadhan 1716bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_authmode: " 1717bcb5c89dSSowmini Varadhan "set authmode=%u\n", *iw_auth); 1718bcb5c89dSSowmini Varadhan 1719bcb5c89dSSowmini Varadhan switch (*iw_auth) { 1720bcb5c89dSSowmini Varadhan case WL_OPENSYSTEM: 1721bcb5c89dSSowmini Varadhan case WL_SHAREDKEY: 1722bcb5c89dSSowmini Varadhan ic->ic_bss->in_authmode = *iw_auth; 1723bcb5c89dSSowmini Varadhan err = ENETRESET; 1724bcb5c89dSSowmini Varadhan break; 1725bcb5c89dSSowmini Varadhan default: 1726bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_authmode: " 1727bcb5c89dSSowmini Varadhan "unknown authmode %u\n", *iw_auth); 1728bcb5c89dSSowmini Varadhan err = EINVAL; 1729bcb5c89dSSowmini Varadhan break; 1730bcb5c89dSSowmini Varadhan } 1731bcb5c89dSSowmini Varadhan 1732bcb5c89dSSowmini Varadhan return (err); 1733bcb5c89dSSowmini Varadhan } 1734bcb5c89dSSowmini Varadhan 1735bcb5c89dSSowmini Varadhan static void 1736bcb5c89dSSowmini Varadhan wl_get_authmode(struct ieee80211com *ic, void *wldp_buf) 1737bcb5c89dSSowmini Varadhan { 1738bcb5c89dSSowmini Varadhan wl_authmode_t ow_auth; 1739bcb5c89dSSowmini Varadhan 1740bcb5c89dSSowmini Varadhan ow_auth = ic->ic_bss->in_authmode; 1741bcb5c89dSSowmini Varadhan bcopy(&ow_auth, wldp_buf, sizeof (wl_authmode_t)); 1742bcb5c89dSSowmini Varadhan 1743bcb5c89dSSowmini Varadhan } 1744bcb5c89dSSowmini Varadhan 1745bcb5c89dSSowmini Varadhan /* 1746bcb5c89dSSowmini Varadhan * MAC_PROP_WL_ENCRYPTION 1747bcb5c89dSSowmini Varadhan */ 1748bcb5c89dSSowmini Varadhan static int 1749bcb5c89dSSowmini Varadhan wl_set_encrypt(struct ieee80211com *ic, const void *wldp_buf) 1750bcb5c89dSSowmini Varadhan { 1751bcb5c89dSSowmini Varadhan int err = 0; 1752bcb5c89dSSowmini Varadhan uint32_t flags; 1753bcb5c89dSSowmini Varadhan wl_encryption_t *iw_encryp = (wl_encryption_t *)wldp_buf; 1754bcb5c89dSSowmini Varadhan 1755bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_encrypt: " 1756bcb5c89dSSowmini Varadhan "set encryption=%u\n", *iw_encryp); 1757bcb5c89dSSowmini Varadhan 1758bcb5c89dSSowmini Varadhan flags = ic->ic_flags; 1759bcb5c89dSSowmini Varadhan if (*iw_encryp == WL_NOENCRYPTION) 1760bcb5c89dSSowmini Varadhan flags &= ~IEEE80211_F_PRIVACY; 1761bcb5c89dSSowmini Varadhan else 1762bcb5c89dSSowmini Varadhan flags |= IEEE80211_F_PRIVACY; 1763bcb5c89dSSowmini Varadhan 1764bcb5c89dSSowmini Varadhan if (ic->ic_flags != flags) { 1765bcb5c89dSSowmini Varadhan ic->ic_flags = flags; 1766bcb5c89dSSowmini Varadhan err = ENETRESET; 1767bcb5c89dSSowmini Varadhan } 1768bcb5c89dSSowmini Varadhan 1769bcb5c89dSSowmini Varadhan return (err); 1770bcb5c89dSSowmini Varadhan } 1771bcb5c89dSSowmini Varadhan 1772bcb5c89dSSowmini Varadhan static void 1773bcb5c89dSSowmini Varadhan wl_get_encrypt(struct ieee80211com *ic, void *wldp_buf) 1774bcb5c89dSSowmini Varadhan { 1775bcb5c89dSSowmini Varadhan wl_encryption_t *ow_encryp; 1776bcb5c89dSSowmini Varadhan 1777bcb5c89dSSowmini Varadhan ow_encryp = (wl_encryption_t *)wldp_buf; 1778bcb5c89dSSowmini Varadhan *ow_encryp = (ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0; 1779bcb5c89dSSowmini Varadhan if (ic->ic_flags & IEEE80211_F_WPA) 1780bcb5c89dSSowmini Varadhan *ow_encryp = WL_ENC_WPA; 1781bcb5c89dSSowmini Varadhan 1782bcb5c89dSSowmini Varadhan } 1783bcb5c89dSSowmini Varadhan 1784bcb5c89dSSowmini Varadhan /* 1785bcb5c89dSSowmini Varadhan * MAC_PROP_WL_RSSI 1786bcb5c89dSSowmini Varadhan */ 1787bcb5c89dSSowmini Varadhan static void 1788bcb5c89dSSowmini Varadhan wl_get_rssi(struct ieee80211com *ic, void *wldp_buf) 1789bcb5c89dSSowmini Varadhan { 1790bcb5c89dSSowmini Varadhan wl_rssi_t *ow_rssi; 1791bcb5c89dSSowmini Varadhan 1792bcb5c89dSSowmini Varadhan ow_rssi = (wl_rssi_t *)wldp_buf; 1793bcb5c89dSSowmini Varadhan *ow_rssi = wifi_getrssi(ic->ic_bss); 1794bcb5c89dSSowmini Varadhan 1795bcb5c89dSSowmini Varadhan } 1796bcb5c89dSSowmini Varadhan 1797bcb5c89dSSowmini Varadhan /* 1798bcb5c89dSSowmini Varadhan * MAC_PROP_WL_PHY_CONFIG 1799bcb5c89dSSowmini Varadhan */ 1800bcb5c89dSSowmini Varadhan 1801bcb5c89dSSowmini Varadhan static int 1802bcb5c89dSSowmini Varadhan wl_set_phy(struct ieee80211com *ic, const void* wldp_buf) 1803bcb5c89dSSowmini Varadhan { 1804bcb5c89dSSowmini Varadhan int err = 0; 1805bcb5c89dSSowmini Varadhan int16_t ch; 1806bcb5c89dSSowmini Varadhan wl_dsss_t *dsss; 1807bcb5c89dSSowmini Varadhan wl_phy_conf_t *iw_phy = (wl_phy_conf_t *)wldp_buf; 1808bcb5c89dSSowmini Varadhan 1809bcb5c89dSSowmini Varadhan dsss = (wl_dsss_t *)iw_phy; 1810bcb5c89dSSowmini Varadhan ch = dsss->wl_dsss_channel; 1811bcb5c89dSSowmini Varadhan 1812bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_phy: " 1813bcb5c89dSSowmini Varadhan "set channel=%d\n", ch); 1814bcb5c89dSSowmini Varadhan 1815bcb5c89dSSowmini Varadhan if (ch == 0 || ch == (int16_t)IEEE80211_CHAN_ANY) { 1816bcb5c89dSSowmini Varadhan ic->ic_des_chan = IEEE80211_CHAN_ANYC; 1817bcb5c89dSSowmini Varadhan } else if ((uint_t)ch > IEEE80211_CHAN_MAX || 1818bcb5c89dSSowmini Varadhan ieee80211_isclr(ic->ic_chan_active, ch)) { 1819bcb5c89dSSowmini Varadhan err = EINVAL; 1820bcb5c89dSSowmini Varadhan return (err); 1821bcb5c89dSSowmini Varadhan } else { 1822bcb5c89dSSowmini Varadhan ic->ic_des_chan = ic->ic_ibss_chan = 1823bcb5c89dSSowmini Varadhan &ic->ic_sup_channels[ch]; 1824bcb5c89dSSowmini Varadhan } 1825bcb5c89dSSowmini Varadhan 1826bcb5c89dSSowmini Varadhan switch (ic->ic_state) { 1827bcb5c89dSSowmini Varadhan case IEEE80211_S_INIT: 1828bcb5c89dSSowmini Varadhan case IEEE80211_S_SCAN: 1829bcb5c89dSSowmini Varadhan err = ENETRESET; 1830bcb5c89dSSowmini Varadhan break; 1831bcb5c89dSSowmini Varadhan default: 1832bcb5c89dSSowmini Varadhan /* 1833bcb5c89dSSowmini Varadhan * If hte desired channel has changed (to something 1834bcb5c89dSSowmini Varadhan * other than any) and we're not already scanning, 1835bcb5c89dSSowmini Varadhan * then kick the state machine. 1836bcb5c89dSSowmini Varadhan */ 1837bcb5c89dSSowmini Varadhan if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 1838bcb5c89dSSowmini Varadhan ic->ic_bss->in_chan != ic->ic_des_chan && 1839bcb5c89dSSowmini Varadhan (ic->ic_flags & IEEE80211_F_SCAN) == 0) 1840bcb5c89dSSowmini Varadhan err = ENETRESET; 1841bcb5c89dSSowmini Varadhan break; 1842bcb5c89dSSowmini Varadhan } 1843bcb5c89dSSowmini Varadhan 1844bcb5c89dSSowmini Varadhan return (err); 1845bcb5c89dSSowmini Varadhan } 1846bcb5c89dSSowmini Varadhan 1847e2cf88acSQuaker Fang #define WIFI_HT_MODE(in) (((in)->in_flags & IEEE80211_NODE_HT) ? 1 : 0) 1848e2cf88acSQuaker Fang 1849bcb5c89dSSowmini Varadhan static int 1850bcb5c89dSSowmini Varadhan wl_get_phy(struct ieee80211com *ic, void *wldp_buf) 1851bcb5c89dSSowmini Varadhan { 1852bcb5c89dSSowmini Varadhan int err = 0; 1853bcb5c89dSSowmini Varadhan wl_phy_conf_t *ow_phy; 1854bcb5c89dSSowmini Varadhan struct ieee80211_channel *ch = ic->ic_curchan; 1855e2cf88acSQuaker Fang struct ieee80211_node *in = ic->ic_bss; 1856bcb5c89dSSowmini Varadhan 1857bcb5c89dSSowmini Varadhan ow_phy = (wl_phy_conf_t *)wldp_buf; 1858bcb5c89dSSowmini Varadhan bzero(wldp_buf, sizeof (wl_phy_conf_t)); 1859bcb5c89dSSowmini Varadhan 1860bcb5c89dSSowmini Varadhan /* get current phy parameters: FH|DS|ERP */ 1861bcb5c89dSSowmini Varadhan if (IEEE80211_IS_CHAN_A(ch) || IEEE80211_IS_CHAN_T(ch)) { 1862bcb5c89dSSowmini Varadhan wl_ofdm_t *ofdm = (wl_ofdm_t *)ow_phy; 1863bcb5c89dSSowmini Varadhan ofdm->wl_ofdm_subtype = WL_OFDM; 1864bcb5c89dSSowmini Varadhan ofdm->wl_ofdm_frequency = ch->ich_freq; 1865e2cf88acSQuaker Fang ofdm->wl_ofdm_ht_enabled = WIFI_HT_MODE(in); 1866bcb5c89dSSowmini Varadhan } else { 1867bcb5c89dSSowmini Varadhan switch (ic->ic_phytype) { 1868bcb5c89dSSowmini Varadhan case IEEE80211_T_FH: { 1869bcb5c89dSSowmini Varadhan wl_fhss_t *fhss = (wl_fhss_t *)ow_phy; 1870bcb5c89dSSowmini Varadhan fhss->wl_fhss_subtype = WL_FHSS; 1871bcb5c89dSSowmini Varadhan fhss->wl_fhss_channel = 1872bcb5c89dSSowmini Varadhan ieee80211_chan2ieee(ic, ch); 1873bcb5c89dSSowmini Varadhan break; 1874bcb5c89dSSowmini Varadhan } 1875bcb5c89dSSowmini Varadhan case IEEE80211_T_DS: { 1876bcb5c89dSSowmini Varadhan wl_dsss_t *dsss = (wl_dsss_t *)ow_phy; 1877bcb5c89dSSowmini Varadhan dsss->wl_dsss_subtype = WL_DSSS; 1878bcb5c89dSSowmini Varadhan dsss->wl_dsss_channel = 1879bcb5c89dSSowmini Varadhan ieee80211_chan2ieee(ic, ch); 1880bcb5c89dSSowmini Varadhan break; 1881bcb5c89dSSowmini Varadhan } 1882bcb5c89dSSowmini Varadhan case IEEE80211_T_OFDM: { 1883bcb5c89dSSowmini Varadhan wl_erp_t *erp = (wl_erp_t *)ow_phy; 1884bcb5c89dSSowmini Varadhan erp->wl_erp_subtype = WL_ERP; 1885bcb5c89dSSowmini Varadhan erp->wl_erp_channel = 1886bcb5c89dSSowmini Varadhan ieee80211_chan2ieee(ic, ch); 1887e2cf88acSQuaker Fang erp->wl_erp_ht_enabled = WIFI_HT_MODE(in); 1888bcb5c89dSSowmini Varadhan break; 1889bcb5c89dSSowmini Varadhan } 1890bcb5c89dSSowmini Varadhan default: 1891bcb5c89dSSowmini Varadhan ieee80211_err("wl_get_phy: " 1892bcb5c89dSSowmini Varadhan "unknown phy type, %x\n", ic->ic_phytype); 1893bcb5c89dSSowmini Varadhan err = EIO; 1894bcb5c89dSSowmini Varadhan break; 1895bcb5c89dSSowmini Varadhan } 1896bcb5c89dSSowmini Varadhan } 1897bcb5c89dSSowmini Varadhan 1898bcb5c89dSSowmini Varadhan return (err); 1899bcb5c89dSSowmini Varadhan } 1900bcb5c89dSSowmini Varadhan 1901bcb5c89dSSowmini Varadhan /* 1902bcb5c89dSSowmini Varadhan * MAC_PROP_WL_CAPABILITY 1903bcb5c89dSSowmini Varadhan */ 1904bcb5c89dSSowmini Varadhan static void 1905bcb5c89dSSowmini Varadhan wl_get_capability(struct ieee80211com *ic, void *wldp_buf) 1906bcb5c89dSSowmini Varadhan { 1907bcb5c89dSSowmini Varadhan wl_capability_t ow_caps; 1908bcb5c89dSSowmini Varadhan 1909bcb5c89dSSowmini Varadhan ow_caps.caps = ic->ic_caps; 1910bcb5c89dSSowmini Varadhan bcopy(&ow_caps, wldp_buf, sizeof (wl_capability_t)); 1911bcb5c89dSSowmini Varadhan 1912bcb5c89dSSowmini Varadhan } 1913bcb5c89dSSowmini Varadhan 1914bcb5c89dSSowmini Varadhan /* 1915bcb5c89dSSowmini Varadhan * MAC_PROP_WL_WPA 1916bcb5c89dSSowmini Varadhan */ 1917bcb5c89dSSowmini Varadhan static int 1918bcb5c89dSSowmini Varadhan wl_set_wpa(struct ieee80211com *ic, const void *wldp_buf) 1919bcb5c89dSSowmini Varadhan { 1920bcb5c89dSSowmini Varadhan int err = 0; 1921bcb5c89dSSowmini Varadhan wl_wpa_t *wpa = (wl_wpa_t *)wldp_buf; 1922bcb5c89dSSowmini Varadhan 1923bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_set_wpa: " 1924bcb5c89dSSowmini Varadhan "set wpa=%u\n", wpa->wpa_flag); 1925bcb5c89dSSowmini Varadhan 1926bcb5c89dSSowmini Varadhan if (wpa->wpa_flag > 0) { 1927bcb5c89dSSowmini Varadhan /* enable wpa mode */ 1928bcb5c89dSSowmini Varadhan ic->ic_flags |= IEEE80211_F_PRIVACY; 1929bcb5c89dSSowmini Varadhan ic->ic_flags |= IEEE80211_F_WPA; 1930bcb5c89dSSowmini Varadhan } else { 1931bcb5c89dSSowmini Varadhan ic->ic_flags &= ~IEEE80211_F_PRIVACY; 1932bcb5c89dSSowmini Varadhan ic->ic_flags &= ~IEEE80211_F_WPA; 1933bcb5c89dSSowmini Varadhan } 1934bcb5c89dSSowmini Varadhan 1935bcb5c89dSSowmini Varadhan return (err); 1936bcb5c89dSSowmini Varadhan } 1937bcb5c89dSSowmini Varadhan 1938bcb5c89dSSowmini Varadhan static void 1939bcb5c89dSSowmini Varadhan wl_get_wpa(struct ieee80211com *ic, void *wldp_buf) 1940bcb5c89dSSowmini Varadhan { 1941bcb5c89dSSowmini Varadhan wl_wpa_t *wpa; 1942bcb5c89dSSowmini Varadhan 1943bcb5c89dSSowmini Varadhan wpa = (wl_wpa_t *)wldp_buf; 1944bcb5c89dSSowmini Varadhan wpa->wpa_flag = ((ic->ic_flags & IEEE80211_F_WPA) ? 1 : 0); 1945bcb5c89dSSowmini Varadhan 1946bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_get_wpa: " 1947bcb5c89dSSowmini Varadhan "get wpa=%u\n", wpa->wpa_flag); 1948bcb5c89dSSowmini Varadhan 1949bcb5c89dSSowmini Varadhan } 1950bcb5c89dSSowmini Varadhan 1951bcb5c89dSSowmini Varadhan /* 1952bcb5c89dSSowmini Varadhan * MAC_PROP_WL_SCANRESULTS 1953bcb5c89dSSowmini Varadhan */ 1954bcb5c89dSSowmini Varadhan 1955bcb5c89dSSowmini Varadhan static void 1956bcb5c89dSSowmini Varadhan wl_get_scanresults(struct ieee80211com *ic, void *wldp_buf) 1957bcb5c89dSSowmini Varadhan { 1958bcb5c89dSSowmini Varadhan wl_wpa_ess_t *sr; 1959bcb5c89dSSowmini Varadhan ieee80211_node_t *in; 1960bcb5c89dSSowmini Varadhan ieee80211_node_table_t *nt; 1961bcb5c89dSSowmini Varadhan int ap_num; 1962bcb5c89dSSowmini Varadhan int len; 1963bcb5c89dSSowmini Varadhan 1964bcb5c89dSSowmini Varadhan sr = (wl_wpa_ess_t *)wldp_buf; 1965bcb5c89dSSowmini Varadhan sr->count = 0; 1966bcb5c89dSSowmini Varadhan ap_num = 0; 1967bcb5c89dSSowmini Varadhan 1968bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_WPA, "wl_get_scanrelults\n"); 1969bcb5c89dSSowmini Varadhan 1970bcb5c89dSSowmini Varadhan nt = &ic->ic_scan; 1971bcb5c89dSSowmini Varadhan IEEE80211_NODE_LOCK(nt); 1972bcb5c89dSSowmini Varadhan in = list_head(&nt->nt_node); 1973bcb5c89dSSowmini Varadhan 1974bcb5c89dSSowmini Varadhan while (in != NULL) { 1975bcb5c89dSSowmini Varadhan /* filter out non-wpa APs */ 1976bcb5c89dSSowmini Varadhan if (in->in_wpa_ie == NULL) { 1977bcb5c89dSSowmini Varadhan in = list_next(&nt->nt_node, in); 1978bcb5c89dSSowmini Varadhan continue; 1979bcb5c89dSSowmini Varadhan } 1980bcb5c89dSSowmini Varadhan bcopy(in->in_bssid, sr->ess[ap_num].bssid, 1981bcb5c89dSSowmini Varadhan IEEE80211_ADDR_LEN); 1982bcb5c89dSSowmini Varadhan sr->ess[ap_num].ssid_len = in->in_esslen; 1983bcb5c89dSSowmini Varadhan bcopy(in->in_essid, sr->ess[ap_num].ssid, 1984bcb5c89dSSowmini Varadhan in->in_esslen); 1985bcb5c89dSSowmini Varadhan sr->ess[ap_num].freq = in->in_chan->ich_freq; 1986bcb5c89dSSowmini Varadhan 1987bcb5c89dSSowmini Varadhan len = in->in_wpa_ie[1] + 2; 1988bcb5c89dSSowmini Varadhan bcopy(in->in_wpa_ie, sr->ess[ap_num].wpa_ie, len); 1989bcb5c89dSSowmini Varadhan sr->ess[ap_num].wpa_ie_len = len; 1990bcb5c89dSSowmini Varadhan 1991bcb5c89dSSowmini Varadhan ap_num++; 1992bcb5c89dSSowmini Varadhan in = list_next(&nt->nt_node, in); 1993bcb5c89dSSowmini Varadhan } 1994bcb5c89dSSowmini Varadhan IEEE80211_NODE_UNLOCK(nt); 1995bcb5c89dSSowmini Varadhan sr->count = ap_num; 1996bcb5c89dSSowmini Varadhan 1997bcb5c89dSSowmini Varadhan } 1998bcb5c89dSSowmini Varadhan 1999bcb5c89dSSowmini Varadhan /* 2000bcb5c89dSSowmini Varadhan * MAC_PROP_WL_ESS_LIST 2001bcb5c89dSSowmini Varadhan */ 2002bcb5c89dSSowmini Varadhan static void 2003bcb5c89dSSowmini Varadhan wl_get_esslist(struct ieee80211com *ic, void *wldp_buf) 2004bcb5c89dSSowmini Varadhan { 2005bcb5c89dSSowmini Varadhan wl_ess_list_t *ess_list; 2006bcb5c89dSSowmini Varadhan 2007bcb5c89dSSowmini Varadhan ess_list = (wl_ess_list_t *)wldp_buf; 2008bcb5c89dSSowmini Varadhan 2009bcb5c89dSSowmini Varadhan ess_list->wl_ess_list_num = 0; 2010bcb5c89dSSowmini Varadhan ieee80211_iterate_nodes(&ic->ic_scan, wifi_read_ap, ess_list); 2011bcb5c89dSSowmini Varadhan 2012bcb5c89dSSowmini Varadhan } 2013bcb5c89dSSowmini Varadhan 2014bcb5c89dSSowmini Varadhan /* 2015bcb5c89dSSowmini Varadhan * MAC_PROP_WL_WEP_KEY 2016bcb5c89dSSowmini Varadhan */ 2017bcb5c89dSSowmini Varadhan static int 2018bcb5c89dSSowmini Varadhan wl_set_wepkey(struct ieee80211com *ic, const void *wldp_buf) 2019bcb5c89dSSowmini Varadhan { 2020bcb5c89dSSowmini Varadhan int err = 0; 2021bcb5c89dSSowmini Varadhan uint16_t i; 2022bcb5c89dSSowmini Varadhan uint32_t klen; 2023bcb5c89dSSowmini Varadhan struct ieee80211_key *key; 2024bcb5c89dSSowmini Varadhan wl_wep_key_t *wepkey = (wl_wep_key_t *)wldp_buf; 2025bcb5c89dSSowmini Varadhan 2026bcb5c89dSSowmini Varadhan /* set all valid keys */ 2027bcb5c89dSSowmini Varadhan for (i = 0; i < MAX_NWEPKEYS; i++) { 2028bcb5c89dSSowmini Varadhan if (wepkey[i].wl_wep_operation != WL_ADD) 2029bcb5c89dSSowmini Varadhan continue; 2030bcb5c89dSSowmini Varadhan klen = wepkey[i].wl_wep_length; 2031bcb5c89dSSowmini Varadhan if (klen > IEEE80211_KEYBUF_SIZE) { 2032bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_wepkey: " 2033bcb5c89dSSowmini Varadhan "invalid wepkey length, %u\n", klen); 2034bcb5c89dSSowmini Varadhan err = EINVAL; 2035bcb5c89dSSowmini Varadhan continue; /* continue to set other keys */ 2036bcb5c89dSSowmini Varadhan } 2037bcb5c89dSSowmini Varadhan if (klen == 0) 2038bcb5c89dSSowmini Varadhan continue; 2039bcb5c89dSSowmini Varadhan 2040bcb5c89dSSowmini Varadhan /* 2041bcb5c89dSSowmini Varadhan * Set key contents. Only WEP is supported 2042bcb5c89dSSowmini Varadhan */ 2043bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_wepkey: " 2044bcb5c89dSSowmini Varadhan "set key %u, len=%u\n", i, klen); 2045bcb5c89dSSowmini Varadhan key = &ic->ic_nw_keys[i]; 2046bcb5c89dSSowmini Varadhan if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, 2047bcb5c89dSSowmini Varadhan IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key) == 0) { 2048bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_wepkey: " 2049bcb5c89dSSowmini Varadhan "abort, create key failed. id=%u\n", i); 2050bcb5c89dSSowmini Varadhan err = EIO; 2051bcb5c89dSSowmini Varadhan continue; 2052bcb5c89dSSowmini Varadhan } 2053bcb5c89dSSowmini Varadhan 2054bcb5c89dSSowmini Varadhan key->wk_keyix = i; 2055bcb5c89dSSowmini Varadhan key->wk_keylen = (uint8_t)klen; 2056bcb5c89dSSowmini Varadhan key->wk_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 2057bcb5c89dSSowmini Varadhan bzero(key->wk_key, IEEE80211_KEYBUF_SIZE); 2058bcb5c89dSSowmini Varadhan bcopy(wepkey[i].wl_wep_key, key->wk_key, klen); 2059bcb5c89dSSowmini Varadhan if (ieee80211_crypto_setkey(ic, key, ic->ic_macaddr) 2060bcb5c89dSSowmini Varadhan == 0) { 2061bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_wepkey: " 2062bcb5c89dSSowmini Varadhan "set key failed len=%u\n", klen); 2063bcb5c89dSSowmini Varadhan err = EIO; 2064bcb5c89dSSowmini Varadhan } 2065bcb5c89dSSowmini Varadhan } 2066bcb5c89dSSowmini Varadhan if (err == 0) 2067bcb5c89dSSowmini Varadhan err = ENETRESET; 2068bcb5c89dSSowmini Varadhan 2069bcb5c89dSSowmini Varadhan return (err); 2070bcb5c89dSSowmini Varadhan } 2071bcb5c89dSSowmini Varadhan 2072bcb5c89dSSowmini Varadhan /* 2073bcb5c89dSSowmini Varadhan * MAC_PROP_WL_SETOPTIE 2074bcb5c89dSSowmini Varadhan */ 2075bcb5c89dSSowmini Varadhan static int 2076bcb5c89dSSowmini Varadhan wl_set_optie(struct ieee80211com *ic, const void *wldp_buf) 2077bcb5c89dSSowmini Varadhan { 2078bcb5c89dSSowmini Varadhan int err = 0; 2079bcb5c89dSSowmini Varadhan char *ie; 2080bcb5c89dSSowmini Varadhan wl_wpa_ie_t *ie_in = (wl_wpa_ie_t *)wldp_buf; 2081bcb5c89dSSowmini Varadhan 2082bcb5c89dSSowmini Varadhan if (ic->ic_opmode != IEEE80211_M_STA) { 2083bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_optie: opmode err\n"); 2084bcb5c89dSSowmini Varadhan err = EINVAL; 2085bcb5c89dSSowmini Varadhan return (err); 2086bcb5c89dSSowmini Varadhan } 2087bcb5c89dSSowmini Varadhan if (ie_in->wpa_ie_len > IEEE80211_MAX_OPT_IE) { 2088bcb5c89dSSowmini Varadhan 2089bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_optie: optie is too long\n"); 2090bcb5c89dSSowmini Varadhan 2091bcb5c89dSSowmini Varadhan err = EINVAL; 2092bcb5c89dSSowmini Varadhan return (err); 2093bcb5c89dSSowmini Varadhan } 2094bcb5c89dSSowmini Varadhan 2095bcb5c89dSSowmini Varadhan ie = ieee80211_malloc(ie_in->wpa_ie_len); 2096bcb5c89dSSowmini Varadhan (void) memcpy(ie, ie_in->wpa_ie, ie_in->wpa_ie_len); 2097bcb5c89dSSowmini Varadhan if (ic->ic_opt_ie != NULL) { 2098bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_BRUSSELS, 2099bcb5c89dSSowmini Varadhan "wl_set_optie:ic_opt_ie!=NULL\n"); 2100bcb5c89dSSowmini Varadhan ieee80211_free(ic->ic_opt_ie); 2101bcb5c89dSSowmini Varadhan } 2102bcb5c89dSSowmini Varadhan ic->ic_opt_ie = ie; 2103bcb5c89dSSowmini Varadhan ic->ic_opt_ie_len = ie_in->wpa_ie_len; 2104bcb5c89dSSowmini Varadhan 2105bcb5c89dSSowmini Varadhan return (err); 2106bcb5c89dSSowmini Varadhan } 2107bcb5c89dSSowmini Varadhan 2108bcb5c89dSSowmini Varadhan /* 2109bcb5c89dSSowmini Varadhan * MAC_PROP_WL_DELKEY 2110bcb5c89dSSowmini Varadhan */ 2111bcb5c89dSSowmini Varadhan static int 2112bcb5c89dSSowmini Varadhan wl_set_delkey(struct ieee80211com *ic, const void *wldp_buf) 2113bcb5c89dSSowmini Varadhan { 2114bcb5c89dSSowmini Varadhan int err = 0; 2115bcb5c89dSSowmini Varadhan int kid; 2116bcb5c89dSSowmini Varadhan wl_del_key_t *dk = (wl_del_key_t *)wldp_buf; 2117bcb5c89dSSowmini Varadhan 2118bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_set_delkey(): " 2119bcb5c89dSSowmini Varadhan "keyix=%d\n", dk->idk_keyix); 2120bcb5c89dSSowmini Varadhan 2121bcb5c89dSSowmini Varadhan kid = dk->idk_keyix; 2122bcb5c89dSSowmini Varadhan 2123bcb5c89dSSowmini Varadhan if (kid == IEEE80211_KEYIX_NONE || 2124bcb5c89dSSowmini Varadhan kid >= IEEE80211_WEP_NKID) { 2125bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_delkey: incorrect keyix\n"); 2126bcb5c89dSSowmini Varadhan err = EINVAL; 2127bcb5c89dSSowmini Varadhan return (err); 2128bcb5c89dSSowmini Varadhan } else { 2129bcb5c89dSSowmini Varadhan (void) ieee80211_crypto_delkey(ic, 2130bcb5c89dSSowmini Varadhan &ic->ic_nw_keys[kid]); 2131bcb5c89dSSowmini Varadhan ieee80211_mac_update(ic); 2132bcb5c89dSSowmini Varadhan } 2133bcb5c89dSSowmini Varadhan 2134bcb5c89dSSowmini Varadhan return (err); 2135bcb5c89dSSowmini Varadhan } 2136bcb5c89dSSowmini Varadhan 2137bcb5c89dSSowmini Varadhan /* 2138bcb5c89dSSowmini Varadhan * MAC_PROP_WL_MLME 2139bcb5c89dSSowmini Varadhan */ 2140bcb5c89dSSowmini Varadhan 2141bcb5c89dSSowmini Varadhan static int 2142bcb5c89dSSowmini Varadhan wl_set_mlme(struct ieee80211com *ic, const void *wldp_buf) 2143bcb5c89dSSowmini Varadhan { 2144bcb5c89dSSowmini Varadhan int err = 0; 2145bcb5c89dSSowmini Varadhan uint32_t flags; 2146bcb5c89dSSowmini Varadhan ieee80211_node_t *in; 2147bcb5c89dSSowmini Varadhan wl_mlme_t *mlme = (wl_mlme_t *)wldp_buf; 2148bcb5c89dSSowmini Varadhan 2149bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_WPA, "wl_set_mlme: " 2150bcb5c89dSSowmini Varadhan "op=%d\n", mlme->im_op); 2151bcb5c89dSSowmini Varadhan 2152bcb5c89dSSowmini Varadhan switch (mlme->im_op) { 2153bcb5c89dSSowmini Varadhan case IEEE80211_MLME_DISASSOC: 2154bcb5c89dSSowmini Varadhan case IEEE80211_MLME_DEAUTH: 2155bcb5c89dSSowmini Varadhan if (ic->ic_opmode == IEEE80211_M_STA) { 2156bcb5c89dSSowmini Varadhan /* 2157bcb5c89dSSowmini Varadhan * Mask ic_flags of IEEE80211_F_WPA to disable 2158bcb5c89dSSowmini Varadhan * ieee80211_notify temporarily. 2159bcb5c89dSSowmini Varadhan */ 2160bcb5c89dSSowmini Varadhan flags = ic->ic_flags; 2161bcb5c89dSSowmini Varadhan ic->ic_flags &= ~IEEE80211_F_WPA; 2162bcb5c89dSSowmini Varadhan 2163bcb5c89dSSowmini Varadhan IEEE80211_UNLOCK(ic); 2164bcb5c89dSSowmini Varadhan ieee80211_new_state(ic, IEEE80211_S_INIT, 2165bcb5c89dSSowmini Varadhan mlme->im_reason); 2166bcb5c89dSSowmini Varadhan IEEE80211_LOCK(ic); 2167bcb5c89dSSowmini Varadhan 2168bcb5c89dSSowmini Varadhan ic->ic_flags = flags; 2169bcb5c89dSSowmini Varadhan } 2170bcb5c89dSSowmini Varadhan break; 2171bcb5c89dSSowmini Varadhan case IEEE80211_MLME_ASSOC: 2172bcb5c89dSSowmini Varadhan if (ic->ic_opmode != IEEE80211_M_STA) { 2173bcb5c89dSSowmini Varadhan ieee80211_err("wifi_cfg_setmlme: opmode err\n"); 2174bcb5c89dSSowmini Varadhan err = EINVAL; 2175bcb5c89dSSowmini Varadhan break; 2176bcb5c89dSSowmini Varadhan } 2177bcb5c89dSSowmini Varadhan if (ic->ic_des_esslen != 0) { 2178bcb5c89dSSowmini Varadhan /* 2179bcb5c89dSSowmini Varadhan * Desired ssid specified; must match both bssid and 2180bcb5c89dSSowmini Varadhan * ssid to distinguish ap advertising multiple ssid's. 2181bcb5c89dSSowmini Varadhan */ 2182bcb5c89dSSowmini Varadhan in = ieee80211_find_node_with_ssid(&ic->ic_scan, 2183bcb5c89dSSowmini Varadhan mlme->im_macaddr, 2184bcb5c89dSSowmini Varadhan ic->ic_des_esslen, 2185bcb5c89dSSowmini Varadhan ic->ic_des_essid); 2186bcb5c89dSSowmini Varadhan } else { 2187bcb5c89dSSowmini Varadhan /* 2188bcb5c89dSSowmini Varadhan * Normal case; just match bssid. 2189bcb5c89dSSowmini Varadhan */ 2190bcb5c89dSSowmini Varadhan in = ieee80211_find_node(&ic->ic_scan, 2191bcb5c89dSSowmini Varadhan mlme->im_macaddr); 2192bcb5c89dSSowmini Varadhan } 2193bcb5c89dSSowmini Varadhan if (in == NULL) { 2194bcb5c89dSSowmini Varadhan ieee80211_err("wifi_cfg_setmlme: " 2195bcb5c89dSSowmini Varadhan "no matched node\n"); 2196bcb5c89dSSowmini Varadhan err = EINVAL; 2197bcb5c89dSSowmini Varadhan break; 2198bcb5c89dSSowmini Varadhan } 2199bcb5c89dSSowmini Varadhan IEEE80211_UNLOCK(ic); 2200bcb5c89dSSowmini Varadhan ieee80211_sta_join(ic, in); 2201bcb5c89dSSowmini Varadhan IEEE80211_LOCK(ic); 2202bcb5c89dSSowmini Varadhan break; 2203bcb5c89dSSowmini Varadhan default: 2204bcb5c89dSSowmini Varadhan err = EINVAL; 2205bcb5c89dSSowmini Varadhan break; 2206bcb5c89dSSowmini Varadhan } 2207bcb5c89dSSowmini Varadhan 2208bcb5c89dSSowmini Varadhan return (err); 2209bcb5c89dSSowmini Varadhan } 2210bcb5c89dSSowmini Varadhan 2211bcb5c89dSSowmini Varadhan /* 2212bcb5c89dSSowmini Varadhan * MAC_PROP_WL_WPA_KEY 2213bcb5c89dSSowmini Varadhan */ 2214bcb5c89dSSowmini Varadhan static int 2215bcb5c89dSSowmini Varadhan wl_set_wpakey(struct ieee80211com *ic, const void *wldp_buf) 2216bcb5c89dSSowmini Varadhan { 2217bcb5c89dSSowmini Varadhan int err = 0; 2218bcb5c89dSSowmini Varadhan uint16_t kid; 2219bcb5c89dSSowmini Varadhan struct ieee80211_node *in; 2220bcb5c89dSSowmini Varadhan struct ieee80211_key *wk; 2221b510adaeSfei feng - Sun Microsystems - Beijing China wl_key_t ik; 2222b510adaeSfei feng - Sun Microsystems - Beijing China 2223b510adaeSfei feng - Sun Microsystems - Beijing China bcopy(wldp_buf, &ik, sizeof (wl_key_t)); 2224bcb5c89dSSowmini Varadhan 2225bcb5c89dSSowmini Varadhan ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_set_wpakey: " 2226b510adaeSfei feng - Sun Microsystems - Beijing China "idx=%d\n", ik.ik_keyix); 2227bcb5c89dSSowmini Varadhan 2228bcb5c89dSSowmini Varadhan /* 2229bcb5c89dSSowmini Varadhan * cipher support is verified by ieee80211_crypt_newkey 2230b510adaeSfei feng - Sun Microsystems - Beijing China * this also checks ik.ik_keylen > sizeof(wk->wk_key) 2231bcb5c89dSSowmini Varadhan */ 2232b510adaeSfei feng - Sun Microsystems - Beijing China if (ik.ik_keylen > sizeof (ik.ik_keydata)) { 2233bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_wpakey: key is too long\n"); 2234bcb5c89dSSowmini Varadhan err = EINVAL; 2235bcb5c89dSSowmini Varadhan return (err); 2236bcb5c89dSSowmini Varadhan } 2237b510adaeSfei feng - Sun Microsystems - Beijing China kid = ik.ik_keyix; 2238bcb5c89dSSowmini Varadhan if (kid == IEEE80211_KEYIX_NONE || kid >= IEEE80211_WEP_NKID) { 2239bcb5c89dSSowmini Varadhan ieee80211_err("wl_set_wpakey: incorrect keyix\n"); 2240bcb5c89dSSowmini Varadhan err = EINVAL; 2241bcb5c89dSSowmini Varadhan return (err); 2242bcb5c89dSSowmini Varadhan } else { 2243bcb5c89dSSowmini Varadhan wk = &ic->ic_nw_keys[kid]; 2244bcb5c89dSSowmini Varadhan /* 2245bcb5c89dSSowmini Varadhan * Globle slots start off w/o any assigned key index. 2246bcb5c89dSSowmini Varadhan * Force one here for consistency with WEPKEY. 2247bcb5c89dSSowmini Varadhan */ 2248bcb5c89dSSowmini Varadhan if (wk->wk_keyix == IEEE80211_KEYIX_NONE) 2249bcb5c89dSSowmini Varadhan wk->wk_keyix = kid; 2250bcb5c89dSSowmini Varadhan in = NULL; 2251bcb5c89dSSowmini Varadhan } 2252bcb5c89dSSowmini Varadhan 2253bcb5c89dSSowmini Varadhan KEY_UPDATE_BEGIN(ic); 2254b510adaeSfei feng - Sun Microsystems - Beijing China if (ieee80211_crypto_newkey(ic, ik.ik_type, 2255b510adaeSfei feng - Sun Microsystems - Beijing China ik.ik_flags, wk)) { 2256b510adaeSfei feng - Sun Microsystems - Beijing China wk->wk_keylen = ik.ik_keylen; 2257bcb5c89dSSowmini Varadhan /* MIC presence is implied by cipher type */ 2258bcb5c89dSSowmini Varadhan if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) 2259bcb5c89dSSowmini Varadhan wk->wk_keylen = IEEE80211_KEYBUF_SIZE; 2260b510adaeSfei feng - Sun Microsystems - Beijing China wk->wk_keyrsc = ik.ik_keyrsc; 2261bcb5c89dSSowmini Varadhan wk->wk_keytsc = 0; 2262b510adaeSfei feng - Sun Microsystems - Beijing China wk->wk_flags |= ik.ik_flags & 2263bcb5c89dSSowmini Varadhan (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); 2264bcb5c89dSSowmini Varadhan (void) memset(wk->wk_key, 0, sizeof (wk->wk_key)); 2265b510adaeSfei feng - Sun Microsystems - Beijing China (void) memcpy(wk->wk_key, ik.ik_keydata, 2266b510adaeSfei feng - Sun Microsystems - Beijing China ik.ik_keylen); 2267bcb5c89dSSowmini Varadhan if (!ieee80211_crypto_setkey(ic, wk, 2268b510adaeSfei feng - Sun Microsystems - Beijing China in != NULL ? in->in_macaddr : ik.ik_macaddr)) { 2269bcb5c89dSSowmini Varadhan err = EIO; 2270b510adaeSfei feng - Sun Microsystems - Beijing China } else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) { 2271bcb5c89dSSowmini Varadhan ic->ic_def_txkey = kid; 2272bcb5c89dSSowmini Varadhan ieee80211_mac_update(ic); 2273bcb5c89dSSowmini Varadhan } 2274bcb5c89dSSowmini Varadhan } else { 2275bcb5c89dSSowmini Varadhan err = EIO; 2276bcb5c89dSSowmini Varadhan } 2277bcb5c89dSSowmini Varadhan KEY_UPDATE_END(ic); 2278bcb5c89dSSowmini Varadhan 2279bcb5c89dSSowmini Varadhan return (err); 2280bcb5c89dSSowmini Varadhan } 2281bcb5c89dSSowmini Varadhan 2282bcb5c89dSSowmini Varadhan /* 2283bcb5c89dSSowmini Varadhan * MAC_PROP_WL_SUP_RATE 2284bcb5c89dSSowmini Varadhan */ 2285bcb5c89dSSowmini Varadhan static void 2286bcb5c89dSSowmini Varadhan wl_get_suprates(struct ieee80211com *ic, void *wldp_buf) 2287bcb5c89dSSowmini Varadhan { 2288bcb5c89dSSowmini Varadhan int i, j, k, l; 2289bcb5c89dSSowmini Varadhan uint8_t srates; 2290bcb5c89dSSowmini Varadhan uint8_t *drates; 2291bcb5c89dSSowmini Varadhan wl_rates_t *wl_rates; 2292bcb5c89dSSowmini Varadhan const struct ieee80211_rateset *srs; 2293bcb5c89dSSowmini Varadhan 2294bcb5c89dSSowmini Varadhan wl_rates = (wl_rates_t *)wldp_buf; 2295bcb5c89dSSowmini Varadhan 2296bcb5c89dSSowmini Varadhan wl_rates->wl_rates_num = 0; 2297bcb5c89dSSowmini Varadhan drates = (uint8_t *)wl_rates->wl_rates_rates; 2298bcb5c89dSSowmini Varadhan for (i = 0; i < IEEE80211_MODE_MAX; i++) { 2299bcb5c89dSSowmini Varadhan srs = &ic->ic_sup_rates[i]; 2300bcb5c89dSSowmini Varadhan if (srs->ir_nrates == 0) 2301bcb5c89dSSowmini Varadhan continue; 2302bcb5c89dSSowmini Varadhan for (j = 0; j < srs->ir_nrates; j++) { 2303bcb5c89dSSowmini Varadhan srates = IEEE80211_RV(srs->ir_rates[j]); 2304bcb5c89dSSowmini Varadhan /* sort & skip duplicated rates */ 2305bcb5c89dSSowmini Varadhan for (k = 0; k < wl_rates->wl_rates_num; k++) { 2306bcb5c89dSSowmini Varadhan if (srates <= drates[k]) 2307bcb5c89dSSowmini Varadhan break; 2308bcb5c89dSSowmini Varadhan } 2309bcb5c89dSSowmini Varadhan if (srates == drates[k]) 2310bcb5c89dSSowmini Varadhan /* skip duplicated rates */ 2311bcb5c89dSSowmini Varadhan continue; 2312bcb5c89dSSowmini Varadhan /* sort */ 2313bcb5c89dSSowmini Varadhan for (l = wl_rates->wl_rates_num; l > k; l--) 2314bcb5c89dSSowmini Varadhan drates[l] = drates[l-1]; 2315bcb5c89dSSowmini Varadhan drates[k] = srates; 2316bcb5c89dSSowmini Varadhan wl_rates->wl_rates_num++; 2317bcb5c89dSSowmini Varadhan } 2318bcb5c89dSSowmini Varadhan } 2319bcb5c89dSSowmini Varadhan 2320bcb5c89dSSowmini Varadhan } 2321bcb5c89dSSowmini Varadhan 2322bcb5c89dSSowmini Varadhan /* 2323127ac1c2Sfei feng - Sun Microsystems - Beijing China * MAC_PROP_WL_CREATE_IBSS 2324127ac1c2Sfei feng - Sun Microsystems - Beijing China */ 2325127ac1c2Sfei feng - Sun Microsystems - Beijing China static int 2326127ac1c2Sfei feng - Sun Microsystems - Beijing China wl_set_createibss(struct ieee80211com *ic, const void *wldp_buf) 2327127ac1c2Sfei feng - Sun Microsystems - Beijing China { 2328127ac1c2Sfei feng - Sun Microsystems - Beijing China wl_create_ibss_t *iw_ibss = (wl_create_ibss_t *)wldp_buf; 2329127ac1c2Sfei feng - Sun Microsystems - Beijing China int err = 0; 2330127ac1c2Sfei feng - Sun Microsystems - Beijing China 2331127ac1c2Sfei feng - Sun Microsystems - Beijing China ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_ibss: " 2332127ac1c2Sfei feng - Sun Microsystems - Beijing China "set createibss=%u\n", *iw_ibss); 2333127ac1c2Sfei feng - Sun Microsystems - Beijing China 2334127ac1c2Sfei feng - Sun Microsystems - Beijing China if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) { 2335127ac1c2Sfei feng - Sun Microsystems - Beijing China err = ENOTSUP; 2336127ac1c2Sfei feng - Sun Microsystems - Beijing China return (err); 2337127ac1c2Sfei feng - Sun Microsystems - Beijing China } 2338127ac1c2Sfei feng - Sun Microsystems - Beijing China if (*iw_ibss) { 2339127ac1c2Sfei feng - Sun Microsystems - Beijing China if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { 2340127ac1c2Sfei feng - Sun Microsystems - Beijing China ic->ic_flags |= IEEE80211_F_IBSSON; 2341127ac1c2Sfei feng - Sun Microsystems - Beijing China ic->ic_opmode = IEEE80211_M_IBSS; 2342127ac1c2Sfei feng - Sun Microsystems - Beijing China /* 2343127ac1c2Sfei feng - Sun Microsystems - Beijing China * Yech, slot time may change depending on the 2344127ac1c2Sfei feng - Sun Microsystems - Beijing China * operating mode so reset it to be sure 2345127ac1c2Sfei feng - Sun Microsystems - Beijing China * everything is setup appropriately. 2346127ac1c2Sfei feng - Sun Microsystems - Beijing China */ 2347127ac1c2Sfei feng - Sun Microsystems - Beijing China ieee80211_reset_erp(ic); 2348127ac1c2Sfei feng - Sun Microsystems - Beijing China err = ENETRESET; 2349127ac1c2Sfei feng - Sun Microsystems - Beijing China } 2350127ac1c2Sfei feng - Sun Microsystems - Beijing China } else { 2351127ac1c2Sfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_IBSSON) { 2352127ac1c2Sfei feng - Sun Microsystems - Beijing China ic->ic_flags &= ~IEEE80211_F_IBSSON; 2353127ac1c2Sfei feng - Sun Microsystems - Beijing China err = ENETRESET; 2354127ac1c2Sfei feng - Sun Microsystems - Beijing China } 2355127ac1c2Sfei feng - Sun Microsystems - Beijing China } 2356127ac1c2Sfei feng - Sun Microsystems - Beijing China 2357127ac1c2Sfei feng - Sun Microsystems - Beijing China return (err); 2358127ac1c2Sfei feng - Sun Microsystems - Beijing China } 2359127ac1c2Sfei feng - Sun Microsystems - Beijing China 2360127ac1c2Sfei feng - Sun Microsystems - Beijing China static void 2361127ac1c2Sfei feng - Sun Microsystems - Beijing China wl_get_createibss(struct ieee80211com *ic, void *wldp_buf) 2362127ac1c2Sfei feng - Sun Microsystems - Beijing China { 2363127ac1c2Sfei feng - Sun Microsystems - Beijing China wl_create_ibss_t *ow_ibss = (wl_create_ibss_t *)wldp_buf; 2364127ac1c2Sfei feng - Sun Microsystems - Beijing China 2365127ac1c2Sfei feng - Sun Microsystems - Beijing China *ow_ibss = (ic->ic_flags & IEEE80211_F_IBSSON)? 1 : 0; 2366127ac1c2Sfei feng - Sun Microsystems - Beijing China } 2367127ac1c2Sfei feng - Sun Microsystems - Beijing China 2368127ac1c2Sfei feng - Sun Microsystems - Beijing China /* 2369bcb5c89dSSowmini Varadhan * Typically invoked by drivers in response to request for 2370bcb5c89dSSowmini Varadhan * information or to change settings from the userland. 2371bcb5c89dSSowmini Varadhan * 2372bcb5c89dSSowmini Varadhan * Return value should be checked by WiFI drivers. Return 0 2373bcb5c89dSSowmini Varadhan * on success. Otherwise, return non-zero value to indicate 2374bcb5c89dSSowmini Varadhan * the error. Driver should operate as below when the return 2375bcb5c89dSSowmini Varadhan * error is: 2376bcb5c89dSSowmini Varadhan * ENETRESET Reset wireless network and re-start to join a 2377bcb5c89dSSowmini Varadhan * WLAN, ENETRESET is returned when a configuration 2378bcb5c89dSSowmini Varadhan * parameter has been changed. 2379bcb5c89dSSowmini Varadhan * When acknowledge a M_IOCTL message, this error 2380bcb5c89dSSowmini Varadhan * is ignored 2381bcb5c89dSSowmini Varadhan */ 2382bcb5c89dSSowmini Varadhan /* ARGSUSED */ 2383bcb5c89dSSowmini Varadhan int 2384bcb5c89dSSowmini Varadhan ieee80211_setprop(void *ic_arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2385bcb5c89dSSowmini Varadhan uint_t wldp_length, const void *wldp_buf) 2386bcb5c89dSSowmini Varadhan { 2387bcb5c89dSSowmini Varadhan int err = 0; 2388bcb5c89dSSowmini Varadhan struct ieee80211com *ic = ic_arg; 2389bcb5c89dSSowmini Varadhan 2390bcb5c89dSSowmini Varadhan ASSERT(ic != NULL); 2391bcb5c89dSSowmini Varadhan IEEE80211_LOCK(ic); 2392bcb5c89dSSowmini Varadhan 2393bcb5c89dSSowmini Varadhan switch (wldp_pr_num) { 2394bcb5c89dSSowmini Varadhan /* mac_prop_id */ 2395bcb5c89dSSowmini Varadhan case MAC_PROP_WL_ESSID: 2396bcb5c89dSSowmini Varadhan err = wl_set_essid(ic, wldp_buf); 2397bcb5c89dSSowmini Varadhan break; 2398bcb5c89dSSowmini Varadhan case MAC_PROP_WL_BSSID: 2399bcb5c89dSSowmini Varadhan err = wl_set_bssid(ic, wldp_buf); 2400bcb5c89dSSowmini Varadhan break; 2401bcb5c89dSSowmini Varadhan case MAC_PROP_WL_PHY_CONFIG: 2402bcb5c89dSSowmini Varadhan err = wl_set_phy(ic, wldp_buf); 2403bcb5c89dSSowmini Varadhan break; 2404bcb5c89dSSowmini Varadhan case MAC_PROP_WL_KEY_TAB: 2405bcb5c89dSSowmini Varadhan err = wl_set_wepkey(ic, wldp_buf); 2406bcb5c89dSSowmini Varadhan break; 2407bcb5c89dSSowmini Varadhan case MAC_PROP_WL_AUTH_MODE: 2408bcb5c89dSSowmini Varadhan err = wl_set_authmode(ic, wldp_buf); 2409bcb5c89dSSowmini Varadhan break; 2410bcb5c89dSSowmini Varadhan case MAC_PROP_WL_ENCRYPTION: 2411bcb5c89dSSowmini Varadhan err = wl_set_encrypt(ic, wldp_buf); 2412bcb5c89dSSowmini Varadhan break; 2413bcb5c89dSSowmini Varadhan case MAC_PROP_WL_BSSTYPE: 2414bcb5c89dSSowmini Varadhan err = wl_set_bsstype(ic, wldp_buf); 2415bcb5c89dSSowmini Varadhan break; 2416bcb5c89dSSowmini Varadhan case MAC_PROP_WL_DESIRED_RATES: 2417bcb5c89dSSowmini Varadhan err = wl_set_desrates(ic, wldp_buf); 2418bcb5c89dSSowmini Varadhan break; 2419bcb5c89dSSowmini Varadhan case MAC_PROP_WL_WPA: 2420bcb5c89dSSowmini Varadhan err = wl_set_wpa(ic, wldp_buf); 2421bcb5c89dSSowmini Varadhan break; 2422bcb5c89dSSowmini Varadhan case MAC_PROP_WL_KEY: 2423bcb5c89dSSowmini Varadhan err = wl_set_wpakey(ic, wldp_buf); 2424bcb5c89dSSowmini Varadhan break; 2425bcb5c89dSSowmini Varadhan case MAC_PROP_WL_DELKEY: 2426bcb5c89dSSowmini Varadhan err = wl_set_delkey(ic, wldp_buf); 2427bcb5c89dSSowmini Varadhan break; 2428bcb5c89dSSowmini Varadhan case MAC_PROP_WL_SETOPTIE: 2429bcb5c89dSSowmini Varadhan err = wl_set_optie(ic, wldp_buf); 2430bcb5c89dSSowmini Varadhan break; 2431bcb5c89dSSowmini Varadhan case MAC_PROP_WL_MLME: 2432bcb5c89dSSowmini Varadhan err = wl_set_mlme(ic, wldp_buf); 2433bcb5c89dSSowmini Varadhan break; 2434127ac1c2Sfei feng - Sun Microsystems - Beijing China case MAC_PROP_WL_CREATE_IBSS: 2435127ac1c2Sfei feng - Sun Microsystems - Beijing China err = wl_set_createibss(ic, wldp_buf); 2436127ac1c2Sfei feng - Sun Microsystems - Beijing China break; 2437bcb5c89dSSowmini Varadhan case MAC_PROP_WL_LINKSTATUS: 2438bcb5c89dSSowmini Varadhan case MAC_PROP_WL_ESS_LIST: 2439bcb5c89dSSowmini Varadhan case MAC_PROP_WL_SUPPORTED_RATES: 2440bcb5c89dSSowmini Varadhan case MAC_PROP_WL_RSSI: 2441bcb5c89dSSowmini Varadhan case MAC_PROP_WL_CAPABILITY: 2442bcb5c89dSSowmini Varadhan case MAC_PROP_WL_SCANRESULTS: 2443bcb5c89dSSowmini Varadhan ieee80211_err("ieee80211_setprop: opmode err\n"); 2444bcb5c89dSSowmini Varadhan err = EINVAL; 2445bcb5c89dSSowmini Varadhan break; 2446bcb5c89dSSowmini Varadhan default: 2447bcb5c89dSSowmini Varadhan ieee80211_err("ieee80211_setprop: opmode not support\n"); 2448bcb5c89dSSowmini Varadhan err = ENOTSUP; 2449bcb5c89dSSowmini Varadhan break; 2450bcb5c89dSSowmini Varadhan } 2451bcb5c89dSSowmini Varadhan 2452bcb5c89dSSowmini Varadhan IEEE80211_UNLOCK(ic); 2453bcb5c89dSSowmini Varadhan 2454bcb5c89dSSowmini Varadhan return (err); 2455bcb5c89dSSowmini Varadhan } 2456bcb5c89dSSowmini Varadhan 2457bcb5c89dSSowmini Varadhan /* ARGSUSED */ 2458bcb5c89dSSowmini Varadhan int 2459bcb5c89dSSowmini Varadhan ieee80211_getprop(void *ic_arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2460*0dc2366fSVenugopal Iyer uint_t wldp_length, void *wldp_buf) 2461bcb5c89dSSowmini Varadhan { 2462bcb5c89dSSowmini Varadhan int err = 0; 2463bcb5c89dSSowmini Varadhan struct ieee80211com *ic = ic_arg; 2464bcb5c89dSSowmini Varadhan 2465bcb5c89dSSowmini Varadhan ASSERT(ic != NULL); 2466bcb5c89dSSowmini Varadhan IEEE80211_LOCK(ic); 2467bcb5c89dSSowmini Varadhan 2468bcb5c89dSSowmini Varadhan switch (wldp_pr_num) { 2469bcb5c89dSSowmini Varadhan /* mac_prop_id */ 2470bcb5c89dSSowmini Varadhan case MAC_PROP_WL_ESSID: 2471bcb5c89dSSowmini Varadhan wl_get_essid(ic, wldp_buf); 2472bcb5c89dSSowmini Varadhan break; 2473bcb5c89dSSowmini Varadhan case MAC_PROP_WL_BSSID: 2474bcb5c89dSSowmini Varadhan wl_get_bssid(ic, wldp_buf); 2475bcb5c89dSSowmini Varadhan break; 2476bcb5c89dSSowmini Varadhan case MAC_PROP_WL_PHY_CONFIG: 2477bcb5c89dSSowmini Varadhan err = wl_get_phy(ic, wldp_buf); 2478bcb5c89dSSowmini Varadhan break; 2479bcb5c89dSSowmini Varadhan case MAC_PROP_WL_AUTH_MODE: 2480bcb5c89dSSowmini Varadhan wl_get_authmode(ic, wldp_buf); 2481bcb5c89dSSowmini Varadhan break; 2482bcb5c89dSSowmini Varadhan case MAC_PROP_WL_ENCRYPTION: 2483bcb5c89dSSowmini Varadhan wl_get_encrypt(ic, wldp_buf); 2484bcb5c89dSSowmini Varadhan break; 2485bcb5c89dSSowmini Varadhan case MAC_PROP_WL_BSSTYPE: 2486bcb5c89dSSowmini Varadhan wl_get_bsstype(ic, wldp_buf); 2487bcb5c89dSSowmini Varadhan break; 2488bcb5c89dSSowmini Varadhan case MAC_PROP_WL_DESIRED_RATES: 2489bcb5c89dSSowmini Varadhan wl_get_desrates(ic, wldp_buf); 2490bcb5c89dSSowmini Varadhan break; 2491bcb5c89dSSowmini Varadhan case MAC_PROP_WL_LINKSTATUS: 2492bcb5c89dSSowmini Varadhan wl_get_linkstatus(ic, wldp_buf); 2493bcb5c89dSSowmini Varadhan break; 2494bcb5c89dSSowmini Varadhan case MAC_PROP_WL_ESS_LIST: 2495bcb5c89dSSowmini Varadhan wl_get_esslist(ic, wldp_buf); 2496bcb5c89dSSowmini Varadhan break; 2497bcb5c89dSSowmini Varadhan case MAC_PROP_WL_SUPPORTED_RATES: 2498bcb5c89dSSowmini Varadhan wl_get_suprates(ic, wldp_buf); 2499bcb5c89dSSowmini Varadhan break; 2500bcb5c89dSSowmini Varadhan case MAC_PROP_WL_RSSI: 2501bcb5c89dSSowmini Varadhan wl_get_rssi(ic, wldp_buf); 2502bcb5c89dSSowmini Varadhan break; 2503bcb5c89dSSowmini Varadhan case MAC_PROP_WL_CAPABILITY: 2504bcb5c89dSSowmini Varadhan wl_get_capability(ic, wldp_buf); 2505bcb5c89dSSowmini Varadhan break; 2506bcb5c89dSSowmini Varadhan case MAC_PROP_WL_WPA: 2507bcb5c89dSSowmini Varadhan wl_get_wpa(ic, wldp_buf); 2508bcb5c89dSSowmini Varadhan break; 2509bcb5c89dSSowmini Varadhan case MAC_PROP_WL_SCANRESULTS: 2510bcb5c89dSSowmini Varadhan wl_get_scanresults(ic, wldp_buf); 2511bcb5c89dSSowmini Varadhan break; 2512127ac1c2Sfei feng - Sun Microsystems - Beijing China case MAC_PROP_WL_CREATE_IBSS: 2513127ac1c2Sfei feng - Sun Microsystems - Beijing China wl_get_createibss(ic, wldp_buf); 2514127ac1c2Sfei feng - Sun Microsystems - Beijing China break; 2515bcb5c89dSSowmini Varadhan case MAC_PROP_WL_KEY_TAB: 2516bcb5c89dSSowmini Varadhan case MAC_PROP_WL_KEY: 2517bcb5c89dSSowmini Varadhan case MAC_PROP_WL_DELKEY: 2518bcb5c89dSSowmini Varadhan case MAC_PROP_WL_SETOPTIE: 2519bcb5c89dSSowmini Varadhan case MAC_PROP_WL_MLME: 2520bcb5c89dSSowmini Varadhan ieee80211_err("ieee80211_setprop: opmode err\n"); 2521bcb5c89dSSowmini Varadhan err = EINVAL; 2522bcb5c89dSSowmini Varadhan break; 2523bcb5c89dSSowmini Varadhan default: 2524bcb5c89dSSowmini Varadhan ieee80211_err("ieee80211_setprop: opmode not support\n"); 2525bcb5c89dSSowmini Varadhan err = ENOTSUP; 2526bcb5c89dSSowmini Varadhan break; 2527bcb5c89dSSowmini Varadhan } 2528bcb5c89dSSowmini Varadhan 2529bcb5c89dSSowmini Varadhan IEEE80211_UNLOCK(ic); 2530bcb5c89dSSowmini Varadhan 2531bcb5c89dSSowmini Varadhan return (err); 2532bcb5c89dSSowmini Varadhan } 2533*0dc2366fSVenugopal Iyer 2534*0dc2366fSVenugopal Iyer void ieee80211_propinfo(void *ic_arg, const char *pr_name, 2535*0dc2366fSVenugopal Iyer mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t prh) 2536*0dc2366fSVenugopal Iyer { 2537*0dc2366fSVenugopal Iyer _NOTE(ARGUNUSED(pr_name, ic_arg)); 2538*0dc2366fSVenugopal Iyer 2539*0dc2366fSVenugopal Iyer /* 2540*0dc2366fSVenugopal Iyer * By default permissions are read/write unless specified 2541*0dc2366fSVenugopal Iyer * otherwise by the driver. 2542*0dc2366fSVenugopal Iyer */ 2543*0dc2366fSVenugopal Iyer 2544*0dc2366fSVenugopal Iyer switch (wldp_pr_num) { 2545*0dc2366fSVenugopal Iyer case MAC_PROP_WL_LINKSTATUS: 2546*0dc2366fSVenugopal Iyer case MAC_PROP_WL_ESS_LIST: 2547*0dc2366fSVenugopal Iyer case MAC_PROP_WL_SUPPORTED_RATES: 2548*0dc2366fSVenugopal Iyer case MAC_PROP_WL_RSSI: 2549*0dc2366fSVenugopal Iyer case MAC_PROP_WL_CAPABILITY: 2550*0dc2366fSVenugopal Iyer case MAC_PROP_WL_SCANRESULTS: 2551*0dc2366fSVenugopal Iyer case MAC_PROP_WL_CREATE_IBSS: 2552*0dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2553*0dc2366fSVenugopal Iyer } 2554*0dc2366fSVenugopal Iyer } 2555