linux/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 *
  19 ******************************************************************************/
  20#define _IOCTL_LINUX_C_
  21
  22#include <osdep_service.h>
  23#include <drv_types.h>
  24#include <wlan_bssdef.h>
  25#include <rtw_debug.h>
  26#include <wifi.h>
  27#include <rtw_mlme.h>
  28#include <rtw_mlme_ext.h>
  29#include <rtw_ioctl.h>
  30#include <rtw_ioctl_set.h>
  31#include <rtl8188e_hal.h>
  32
  33#include <rtw_iol.h>
  34#include <linux/vmalloc.h>
  35#include "osdep_intf.h"
  36
  37#define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV + 30)
  38
  39#define SCAN_ITEM_SIZE 768
  40#define MAX_CUSTOM_LEN 64
  41#define RATE_COUNT 4
  42
  43/*  combo scan */
  44#define WEXT_CSCAN_AMOUNT 9
  45#define WEXT_CSCAN_BUF_LEN              360
  46#define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
  47#define WEXT_CSCAN_HEADER_SIZE          12
  48#define WEXT_CSCAN_SSID_SECTION         'S'
  49#define WEXT_CSCAN_CHANNEL_SECTION      'C'
  50#define WEXT_CSCAN_NPROBE_SECTION       'N'
  51#define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
  52#define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
  53#define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
  54#define WEXT_CSCAN_TYPE_SECTION         'T'
  55
  56static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
  57        6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
  58        48000000, 54000000};
  59
  60static const char * const iw_operation_mode[] = {
  61        "Auto", "Ad-Hoc", "Managed",  "Master", "Repeater",
  62        "Secondary", "Monitor"
  63};
  64
  65void indicate_wx_scan_complete_event(struct adapter *padapter)
  66{
  67        union iwreq_data wrqu;
  68
  69        memset(&wrqu, 0, sizeof(union iwreq_data));
  70        wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
  71}
  72
  73void rtw_indicate_wx_assoc_event(struct adapter *padapter)
  74{
  75        union iwreq_data wrqu;
  76        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
  77
  78        memset(&wrqu, 0, sizeof(union iwreq_data));
  79
  80        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  81
  82        memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
  83
  84        DBG_88E_LEVEL(_drv_always_, "assoc success\n");
  85        wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
  86}
  87
  88void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
  89{
  90        union iwreq_data wrqu;
  91
  92        memset(&wrqu, 0, sizeof(union iwreq_data));
  93
  94        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  95        memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
  96
  97        DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
  98        wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
  99}
 100
 101static char *translate_scan(struct adapter *padapter,
 102                            struct iw_request_info *info,
 103                            struct wlan_network *pnetwork,
 104                            char *start, char *stop)
 105{
 106        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 107        struct iw_event iwe;
 108        u16 cap;
 109        __le16 le_tmp;
 110        u32 ht_ielen = 0;
 111        char custom[MAX_CUSTOM_LEN];
 112        char *p;
 113        u16 max_rate = 0, rate, ht_cap = false;
 114        u32 i = 0;
 115        u8 bw_40MHz = 0, short_GI = 0;
 116        u16 mcs_rate = 0;
 117        u8 ss, sq;
 118
 119        /*  AP MAC address  */
 120        iwe.cmd = SIOCGIWAP;
 121        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 122
 123        memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
 124        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
 125
 126        /* Add the ESSID */
 127        iwe.cmd = SIOCGIWESSID;
 128        iwe.u.data.flags = 1;
 129        iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32);
 130        start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
 131
 132        /* parsing HT_CAP_IE */
 133        p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
 134
 135        if (p && ht_ielen > 0) {
 136                struct rtw_ieee80211_ht_cap *pht_capie;
 137                ht_cap = true;
 138                pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
 139                memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
 140                bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
 141                short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
 142        }
 143
 144        /* Add the protocol name */
 145        iwe.cmd = SIOCGIWNAME;
 146        if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
 147                if (ht_cap)
 148                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
 149                else
 150                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
 151        } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
 152                if (ht_cap)
 153                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
 154                else
 155                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
 156        } else {
 157                if (pnetwork->network.Configuration.DSConfig > 14) {
 158                        if (ht_cap)
 159                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
 160                        else
 161                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
 162                } else {
 163                        if (ht_cap)
 164                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
 165                        else
 166                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
 167                }
 168        }
 169
 170        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
 171
 172          /* Add mode */
 173        iwe.cmd = SIOCGIWMODE;
 174        memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
 175
 176        cap = le16_to_cpu(le_tmp);
 177
 178        if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
 179                if (cap & WLAN_CAPABILITY_BSS)
 180                        iwe.u.mode = IW_MODE_MASTER;
 181                else
 182                        iwe.u.mode = IW_MODE_ADHOC;
 183
 184                start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
 185        }
 186
 187        if (pnetwork->network.Configuration.DSConfig < 1)
 188                pnetwork->network.Configuration.DSConfig = 1;
 189
 190         /* Add frequency/channel */
 191        iwe.cmd = SIOCGIWFREQ;
 192        iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
 193        iwe.u.freq.e = 1;
 194        iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
 195        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
 196
 197        /* Add encryption capability */
 198        iwe.cmd = SIOCGIWENCODE;
 199        if (cap & WLAN_CAPABILITY_PRIVACY)
 200                iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 201        else
 202                iwe.u.data.flags = IW_ENCODE_DISABLED;
 203        iwe.u.data.length = 0;
 204        start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
 205
 206        /*Add basic and extended rates */
 207        max_rate = 0;
 208        p = custom;
 209        p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
 210        while (pnetwork->network.SupportedRates[i] != 0) {
 211                rate = pnetwork->network.SupportedRates[i]&0x7F;
 212                if (rate > max_rate)
 213                        max_rate = rate;
 214                p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
 215                              "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
 216                i++;
 217        }
 218
 219        if (ht_cap) {
 220                if (mcs_rate&0x8000)/* MCS15 */
 221                        max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
 222                else if (mcs_rate&0x0080)/* MCS7 */
 223                        ;
 224                else/* default MCS7 */
 225                        max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
 226
 227                max_rate = max_rate*2;/* Mbps/2; */
 228        }
 229
 230        iwe.cmd = SIOCGIWRATE;
 231        iwe.u.bitrate.fixed = 0;
 232        iwe.u.bitrate.disabled = 0;
 233        iwe.u.bitrate.value = max_rate * 500000;
 234        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
 235
 236        /* parsing WPA/WPA2 IE */
 237        {
 238                u8 buf[MAX_WPA_IE_LEN];
 239                u8 wpa_ie[255], rsn_ie[255];
 240                u16 wpa_len = 0, rsn_len = 0;
 241                u8 *p;
 242
 243                rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
 244                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid));
 245                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
 246
 247                if (wpa_len > 0) {
 248                        p = buf;
 249                        memset(buf, 0, MAX_WPA_IE_LEN);
 250                        p += sprintf(p, "wpa_ie=");
 251                        for (i = 0; i < wpa_len; i++)
 252                                p += sprintf(p, "%02x", wpa_ie[i]);
 253
 254                        memset(&iwe, 0, sizeof(iwe));
 255                        iwe.cmd = IWEVCUSTOM;
 256                        iwe.u.data.length = strlen(buf);
 257                        start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 258
 259                        memset(&iwe, 0, sizeof(iwe));
 260                        iwe.cmd = IWEVGENIE;
 261                        iwe.u.data.length = wpa_len;
 262                        start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
 263                }
 264                if (rsn_len > 0) {
 265                        p = buf;
 266                        memset(buf, 0, MAX_WPA_IE_LEN);
 267                        p += sprintf(p, "rsn_ie=");
 268                        for (i = 0; i < rsn_len; i++)
 269                                p += sprintf(p, "%02x", rsn_ie[i]);
 270                        memset(&iwe, 0, sizeof(iwe));
 271                        iwe.cmd = IWEVCUSTOM;
 272                        iwe.u.data.length = strlen(buf);
 273                        start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 274
 275                        memset(&iwe, 0, sizeof(iwe));
 276                        iwe.cmd = IWEVGENIE;
 277                        iwe.u.data.length = rsn_len;
 278                        start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
 279                }
 280        }
 281
 282        {/* parsing WPS IE */
 283                uint cnt = 0, total_ielen;
 284                u8 *wpsie_ptr = NULL;
 285                uint wps_ielen = 0;
 286
 287                u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
 288                total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
 289
 290                while (cnt < total_ielen) {
 291                        if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
 292                                wpsie_ptr = &ie_ptr[cnt];
 293                                iwe.cmd = IWEVGENIE;
 294                                iwe.u.data.length = (u16)wps_ielen;
 295                                start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
 296                        }
 297                        cnt += ie_ptr[cnt+1]+2; /* goto next */
 298                }
 299        }
 300
 301        /* Add quality statistics */
 302        iwe.cmd = IWEVQUAL;
 303        iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
 304
 305        if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
 306            is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
 307                ss = padapter->recvpriv.signal_strength;
 308                sq = padapter->recvpriv.signal_qual;
 309        } else {
 310                ss = pnetwork->network.PhyInfo.SignalStrength;
 311                sq = pnetwork->network.PhyInfo.SignalQuality;
 312        }
 313
 314        iwe.u.qual.level = (u8)ss;
 315        iwe.u.qual.qual = (u8)sq;   /*  signal quality */
 316        iwe.u.qual.noise = 0; /*  noise level */
 317        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
 318        return start;
 319}
 320
 321static int wpa_set_auth_algs(struct net_device *dev, u32 value)
 322{
 323        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 324        int ret = 0;
 325
 326        if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
 327                DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
 328                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 329                padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
 330                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
 331        } else if (value & AUTH_ALG_SHARED_KEY) {
 332                DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY  [value:0x%x]\n", value);
 333                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 334
 335                padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
 336                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
 337        } else if (value & AUTH_ALG_OPEN_SYSTEM) {
 338                DBG_88E("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
 339                if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
 340                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
 341                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
 342                }
 343        } else if (value & AUTH_ALG_LEAP) {
 344                DBG_88E("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
 345        } else {
 346                DBG_88E("wpa_set_auth_algs, error!\n");
 347                ret = -EINVAL;
 348        }
 349        return ret;
 350}
 351
 352static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
 353{
 354        int ret = 0;
 355        u32 wep_key_idx, wep_key_len, wep_total_len;
 356        struct ndis_802_11_wep   *pwep = NULL;
 357        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 358        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
 359        struct security_priv *psecuritypriv = &padapter->securitypriv;
 360
 361        param->u.crypt.err = 0;
 362        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
 363
 364        if (param_len < (u32) ((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
 365                ret =  -EINVAL;
 366                goto exit;
 367        }
 368
 369        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 370            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 371            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 372                if (param->u.crypt.idx >= WEP_KEYS) {
 373                        ret = -EINVAL;
 374                        goto exit;
 375                }
 376        } else {
 377                ret = -EINVAL;
 378                goto exit;
 379        }
 380
 381        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 382                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
 383                DBG_88E("wpa_set_encryption, crypt.alg = WEP\n");
 384
 385                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 386                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
 387                padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
 388
 389                wep_key_idx = param->u.crypt.idx;
 390                wep_key_len = param->u.crypt.key_len;
 391
 392                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
 393                DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx);
 394
 395                if (wep_key_idx > WEP_KEYS)
 396                        return -EINVAL;
 397
 398                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
 399
 400                if (wep_key_len > 0) {
 401                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
 402                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
 403                        pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
 404                        if (pwep == NULL) {
 405                                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
 406                                goto exit;
 407                        }
 408                        memset(pwep, 0, wep_total_len);
 409                        pwep->KeyLength = wep_key_len;
 410                        pwep->Length = wep_total_len;
 411                        if (wep_key_len == 13) {
 412                                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
 413                                padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
 414                        }
 415                } else {
 416                        ret = -EINVAL;
 417                        goto exit;
 418                }
 419                pwep->KeyIndex = wep_key_idx;
 420                pwep->KeyIndex |= 0x80000000;
 421                memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
 422                if (param->u.crypt.set_tx) {
 423                        DBG_88E("wep, set_tx = 1\n");
 424                        if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
 425                                ret = -EOPNOTSUPP;
 426                } else {
 427                        DBG_88E("wep, set_tx = 0\n");
 428                        if (wep_key_idx >= WEP_KEYS) {
 429                                ret = -EOPNOTSUPP;
 430                                goto exit;
 431                        }
 432                      memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
 433                        psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
 434                        rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
 435                }
 436                goto exit;
 437        }
 438
 439        if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
 440                struct sta_info *psta, *pbcmc_sta;
 441                struct sta_priv *pstapriv = &padapter->stapriv;
 442
 443                if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */
 444                        psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
 445                        if (psta == NULL) {
 446                                ;
 447                        } else {
 448                                if (strcmp(param->u.crypt.alg, "none") != 0)
 449                                        psta->ieee8021x_blocked = false;
 450
 451                                if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
 452                                    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
 453                                        psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
 454
 455                                if (param->u.crypt.set_tx == 1) { /* pairwise key */
 456                                        memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 457
 458                                        if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
 459                                                memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
 460                                                memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
 461                                                padapter->securitypriv.busetkipkey = false;
 462                                        }
 463
 464                                        DBG_88E(" ~~~~set sta key:unicastkey\n");
 465
 466                                        rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
 467                                } else { /* group key */
 468                                        memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 469                                        memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
 470                                        memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
 471                                        padapter->securitypriv.binstallGrpkey = true;
 472                                        DBG_88E(" ~~~~set sta key:groupkey\n");
 473
 474                                        padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
 475
 476                                        rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
 477                                }
 478                        }
 479                        pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
 480                        if (pbcmc_sta == NULL) {
 481                                ;
 482                        } else {
 483                                /* Jeff: don't disable ieee8021x_blocked while clearing key */
 484                                if (strcmp(param->u.crypt.alg, "none") != 0)
 485                                        pbcmc_sta->ieee8021x_blocked = false;
 486
 487                                if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
 488                                    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
 489                                        pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
 490                        }
 491                }
 492        }
 493
 494exit:
 495
 496        kfree(pwep);
 497        return ret;
 498}
 499
 500static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
 501{
 502        u8 *buf = NULL;
 503        int group_cipher = 0, pairwise_cipher = 0;
 504        int ret = 0;
 505
 506        if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
 507                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
 508                if (pie == NULL)
 509                        return ret;
 510                else
 511                        return -EINVAL;
 512        }
 513
 514        if (ielen) {
 515                buf = kzalloc(ielen, GFP_KERNEL);
 516                if (buf == NULL) {
 517                        ret =  -ENOMEM;
 518                        goto exit;
 519                }
 520
 521                memcpy(buf, pie, ielen);
 522
 523                /* dump */
 524                {
 525                        int i;
 526                        DBG_88E("\n wpa_ie(length:%d):\n", ielen);
 527                        for (i = 0; i < ielen; i += 8)
 528                                DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
 529                }
 530
 531                if (ielen < RSN_HEADER_LEN) {
 532                        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
 533                        ret  = -1;
 534                        goto exit;
 535                }
 536
 537                if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
 538                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 539                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
 540                        memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
 541                }
 542
 543                if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
 544                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 545                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
 546                        memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
 547                }
 548
 549                switch (group_cipher) {
 550                case WPA_CIPHER_NONE:
 551                        padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
 552                        padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
 553                        break;
 554                case WPA_CIPHER_WEP40:
 555                        padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
 556                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 557                        break;
 558                case WPA_CIPHER_TKIP:
 559                        padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
 560                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
 561                        break;
 562                case WPA_CIPHER_CCMP:
 563                        padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
 564                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
 565                        break;
 566                case WPA_CIPHER_WEP104:
 567                        padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
 568                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 569                        break;
 570                }
 571
 572                switch (pairwise_cipher) {
 573                case WPA_CIPHER_NONE:
 574                        padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
 575                        padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
 576                        break;
 577                case WPA_CIPHER_WEP40:
 578                        padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
 579                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 580                        break;
 581                case WPA_CIPHER_TKIP:
 582                        padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
 583                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
 584                        break;
 585                case WPA_CIPHER_CCMP:
 586                        padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
 587                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
 588                        break;
 589                case WPA_CIPHER_WEP104:
 590                        padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
 591                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 592                        break;
 593                }
 594
 595                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
 596                {/* set wps_ie */
 597                        u16 cnt = 0;
 598                        u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
 599
 600                        while (cnt < ielen) {
 601                                eid = buf[cnt];
 602                                if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
 603                                        DBG_88E("SET WPS_IE\n");
 604
 605                                        padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2) : (MAX_WPA_IE_LEN<<2);
 606
 607                                        memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
 608
 609                                        set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
 610                                        cnt += buf[cnt+1]+2;
 611                                        break;
 612                                } else {
 613                                        cnt += buf[cnt+1]+2; /* goto next */
 614                                }
 615                        }
 616                }
 617        }
 618
 619        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
 620                 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
 621                 pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
 622exit:
 623        kfree(buf);
 624        return ret;
 625}
 626
 627typedef unsigned char   NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
 628
 629static int rtw_wx_get_name(struct net_device *dev,
 630                             struct iw_request_info *info,
 631                             union iwreq_data *wrqu, char *extra)
 632{
 633        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 634        u32 ht_ielen = 0;
 635        char *p;
 636        u8 ht_cap = false;
 637        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
 638        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
 639        NDIS_802_11_RATES_EX *prates = NULL;
 640
 641        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
 642
 643        if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
 644                /* parsing HT_CAP_IE */
 645                p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
 646                if (p && ht_ielen > 0)
 647                        ht_cap = true;
 648
 649                prates = &pcur_bss->SupportedRates;
 650
 651                if (rtw_is_cckratesonly_included((u8 *)prates) == true) {
 652                        if (ht_cap)
 653                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
 654                        else
 655                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
 656                } else if ((rtw_is_cckrates_included((u8 *)prates)) == true) {
 657                        if (ht_cap)
 658                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
 659                        else
 660                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
 661                } else {
 662                        if (pcur_bss->Configuration.DSConfig > 14) {
 663                                if (ht_cap)
 664                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
 665                                else
 666                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
 667                        } else {
 668                                if (ht_cap)
 669                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
 670                                else
 671                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
 672                        }
 673                }
 674        } else {
 675                snprintf(wrqu->name, IFNAMSIZ, "unassociated");
 676        }
 677        return 0;
 678}
 679
 680static int rtw_wx_set_freq(struct net_device *dev,
 681                             struct iw_request_info *info,
 682                             union iwreq_data *wrqu, char *extra)
 683{
 684        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
 685        return 0;
 686}
 687
 688static int rtw_wx_get_freq(struct net_device *dev,
 689                             struct iw_request_info *info,
 690                             union iwreq_data *wrqu, char *extra)
 691{
 692        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 693        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
 694        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
 695
 696        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 697                /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
 698                wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
 699                wrqu->freq.e = 1;
 700                wrqu->freq.i = pcur_bss->Configuration.DSConfig;
 701        } else {
 702                wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
 703                wrqu->freq.e = 1;
 704                wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
 705        }
 706
 707        return 0;
 708}
 709
 710static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
 711                             union iwreq_data *wrqu, char *b)
 712{
 713        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 714        enum ndis_802_11_network_infra networkType;
 715        int ret = 0;
 716
 717        if (_FAIL == rtw_pwr_wakeup(padapter)) {
 718                ret = -EPERM;
 719                goto exit;
 720        }
 721
 722        if (!padapter->hw_init_completed) {
 723                ret = -EPERM;
 724                goto exit;
 725        }
 726
 727        switch (wrqu->mode) {
 728        case IW_MODE_AUTO:
 729                networkType = Ndis802_11AutoUnknown;
 730                DBG_88E("set_mode = IW_MODE_AUTO\n");
 731                break;
 732        case IW_MODE_ADHOC:
 733                networkType = Ndis802_11IBSS;
 734                DBG_88E("set_mode = IW_MODE_ADHOC\n");
 735                break;
 736        case IW_MODE_MASTER:
 737                networkType = Ndis802_11APMode;
 738                DBG_88E("set_mode = IW_MODE_MASTER\n");
 739                break;
 740        case IW_MODE_INFRA:
 741                networkType = Ndis802_11Infrastructure;
 742                DBG_88E("set_mode = IW_MODE_INFRA\n");
 743                break;
 744        default:
 745                ret = -EINVAL;
 746                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode]));
 747                goto exit;
 748        }
 749        if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
 750                ret = -EPERM;
 751                goto exit;
 752        }
 753        rtw_setopmode_cmd(padapter, networkType);
 754exit:
 755        return ret;
 756}
 757
 758static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
 759                             union iwreq_data *wrqu, char *b)
 760{
 761        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 762        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
 763
 764        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
 765
 766        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 767                wrqu->mode = IW_MODE_INFRA;
 768        else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
 769                  (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
 770                wrqu->mode = IW_MODE_ADHOC;
 771        else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 772                wrqu->mode = IW_MODE_MASTER;
 773        else
 774                wrqu->mode = IW_MODE_AUTO;
 775
 776        return 0;
 777}
 778
 779static int rtw_wx_set_pmkid(struct net_device *dev,
 780                            struct iw_request_info *a,
 781                            union iwreq_data *wrqu, char *extra)
 782{
 783        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 784        u8   j, blInserted = false;
 785        int  ret = false;
 786        struct security_priv *psecuritypriv = &padapter->securitypriv;
 787        struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
 788        u8     strZeroMacAddress[ETH_ALEN] = {0x00};
 789        u8     strIssueBssid[ETH_ALEN] = {0x00};
 790
 791        memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
 792        if (pPMK->cmd == IW_PMKSA_ADD) {
 793                DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
 794                if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
 795                        return ret;
 796                else
 797                        ret = true;
 798                blInserted = false;
 799
 800                /* overwrite PMKID */
 801                for (j = 0; j < NUM_PMKID_CACHE; j++) {
 802                        if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
 803                                /*  BSSID is matched, the same AP => rewrite with new PMKID. */
 804                                DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
 805                                memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
 806                                psecuritypriv->PMKIDList[j].bUsed = true;
 807                                psecuritypriv->PMKIDIndex = j+1;
 808                                blInserted = true;
 809                                break;
 810                        }
 811                }
 812
 813                if (!blInserted) {
 814                        /*  Find a new entry */
 815                        DBG_88E("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
 816                                psecuritypriv->PMKIDIndex);
 817
 818                        memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
 819                        memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
 820
 821                        psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
 822                        psecuritypriv->PMKIDIndex++;
 823                        if (psecuritypriv->PMKIDIndex == 16)
 824                                psecuritypriv->PMKIDIndex = 0;
 825                }
 826        } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
 827                DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
 828                ret = true;
 829                for (j = 0; j < NUM_PMKID_CACHE; j++) {
 830                        if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
 831                                /*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
 832                                memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
 833                                psecuritypriv->PMKIDList[j].bUsed = false;
 834                                break;
 835                        }
 836               }
 837        } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
 838                DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
 839                memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
 840                psecuritypriv->PMKIDIndex = 0;
 841                ret = true;
 842        }
 843        return ret;
 844}
 845
 846static int rtw_wx_get_sens(struct net_device *dev,
 847                             struct iw_request_info *info,
 848                             union iwreq_data *wrqu, char *extra)
 849{
 850        wrqu->sens.value = 0;
 851        wrqu->sens.fixed = 0;   /* no auto select */
 852        wrqu->sens.disabled = 1;
 853        return 0;
 854}
 855
 856static int rtw_wx_get_range(struct net_device *dev,
 857                                struct iw_request_info *info,
 858                                union iwreq_data *wrqu, char *extra)
 859{
 860        struct iw_range *range = (struct iw_range *)extra;
 861        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 862        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 863
 864        u16 val;
 865        int i;
 866
 867        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
 868
 869        wrqu->data.length = sizeof(*range);
 870        memset(range, 0, sizeof(*range));
 871
 872        /* Let's try to keep this struct in the same order as in
 873         * linux/include/wireless.h
 874         */
 875
 876        /* TODO: See what values we can set, and remove the ones we can't
 877         * set, or fill them with some default data.
 878         */
 879
 880        /* ~5 Mb/s real (802.11b) */
 881        range->throughput = 5 * 1000 * 1000;
 882
 883        /* signal level threshold range */
 884
 885        /* percent values between 0 and 100. */
 886        range->max_qual.qual = 100;
 887        range->max_qual.level = 100;
 888        range->max_qual.noise = 100;
 889        range->max_qual.updated = 7; /* Updated all three */
 890
 891        range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
 892        /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
 893        range->avg_qual.level = 178; /* -78 dBm */
 894        range->avg_qual.noise = 0;
 895        range->avg_qual.updated = 7; /* Updated all three */
 896
 897        range->num_bitrates = RATE_COUNT;
 898
 899        for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
 900                range->bitrate[i] = rtw_rates[i];
 901
 902        range->min_frag = MIN_FRAG_THRESHOLD;
 903        range->max_frag = MAX_FRAG_THRESHOLD;
 904
 905        range->pm_capa = 0;
 906
 907        range->we_version_compiled = WIRELESS_EXT;
 908        range->we_version_source = 16;
 909
 910        for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
 911                /*  Include only legal frequencies for some countries */
 912                if (pmlmeext->channel_set[i].ChannelNum != 0) {
 913                        range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
 914                        range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
 915                        range->freq[val].e = 1;
 916                        val++;
 917                }
 918
 919                if (val == IW_MAX_FREQUENCIES)
 920                        break;
 921        }
 922
 923        range->num_channels = val;
 924        range->num_frequency = val;
 925
 926/*  The following code will proivde the security capability to network manager. */
 927/*  If the driver doesn't provide this capability to network manager, */
 928/*  the WPA/WPA2 routers can't be chosen in the network manager. */
 929
 930/*
 931#define IW_SCAN_CAPA_NONE               0x00
 932#define IW_SCAN_CAPA_ESSID              0x01
 933#define IW_SCAN_CAPA_BSSID              0x02
 934#define IW_SCAN_CAPA_CHANNEL            0x04
 935#define IW_SCAN_CAPA_MODE               0x08
 936#define IW_SCAN_CAPA_RATE               0x10
 937#define IW_SCAN_CAPA_TYPE               0x20
 938#define IW_SCAN_CAPA_TIME               0x40
 939*/
 940
 941        range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
 942                          IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
 943
 944        range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
 945                           IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
 946                           IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
 947        return 0;
 948}
 949
 950/* set bssid flow */
 951/* s1. rtw_set_802_11_infrastructure_mode() */
 952/* s2. rtw_set_802_11_authentication_mode() */
 953/* s3. set_802_11_encryption_mode() */
 954/* s4. rtw_set_802_11_bssid() */
 955static int rtw_wx_set_wap(struct net_device *dev,
 956                         struct iw_request_info *info,
 957                         union iwreq_data *awrq,
 958                         char *extra)
 959{
 960        uint ret = 0;
 961        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 962        struct sockaddr *temp = (struct sockaddr *)awrq;
 963        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
 964        struct list_head *phead;
 965        u8 *dst_bssid, *src_bssid;
 966        struct __queue *queue   = &(pmlmepriv->scanned_queue);
 967        struct  wlan_network    *pnetwork = NULL;
 968        enum ndis_802_11_auth_mode      authmode;
 969
 970        if (_FAIL == rtw_pwr_wakeup(padapter)) {
 971                ret = -1;
 972                goto exit;
 973        }
 974
 975        if (!padapter->bup) {
 976                ret = -1;
 977                goto exit;
 978        }
 979
 980        if (temp->sa_family != ARPHRD_ETHER) {
 981                ret = -EINVAL;
 982                goto exit;
 983        }
 984
 985        authmode = padapter->securitypriv.ndisauthtype;
 986        spin_lock_bh(&queue->lock);
 987        phead = get_list_head(queue);
 988        pmlmepriv->pscanned = phead->next;
 989
 990        while (phead != pmlmepriv->pscanned) {
 991                pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
 992
 993                pmlmepriv->pscanned = pmlmepriv->pscanned->next;
 994
 995                dst_bssid = pnetwork->network.MacAddress;
 996
 997                src_bssid = temp->sa_data;
 998
 999                if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
1000                        if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1001                                ret = -1;
1002                                spin_unlock_bh(&queue->lock);
1003                                goto exit;
1004                        }
1005
1006                                break;
1007                }
1008        }
1009        spin_unlock_bh(&queue->lock);
1010
1011        rtw_set_802_11_authentication_mode(padapter, authmode);
1012        /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1013        if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
1014                ret = -1;
1015                goto exit;
1016        }
1017
1018exit:
1019
1020        return ret;
1021}
1022
1023static int rtw_wx_get_wap(struct net_device *dev,
1024                            struct iw_request_info *info,
1025                            union iwreq_data *wrqu, char *extra)
1026{
1027        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1028        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1029        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1030
1031        wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1032
1033        memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1034
1035        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
1036
1037        if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
1038            ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
1039            ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true))
1040                memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1041        else
1042                memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1043        return 0;
1044}
1045
1046static int rtw_wx_set_mlme(struct net_device *dev,
1047                             struct iw_request_info *info,
1048                             union iwreq_data *wrqu, char *extra)
1049{
1050        int ret = 0;
1051        u16 reason;
1052        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1053        struct iw_mlme *mlme = (struct iw_mlme *)extra;
1054
1055        if (mlme == NULL)
1056                return -1;
1057
1058        DBG_88E("%s\n", __func__);
1059
1060        reason = mlme->reason_code;
1061
1062        DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
1063
1064        switch (mlme->cmd) {
1065        case IW_MLME_DEAUTH:
1066                if (!rtw_set_802_11_disassociate(padapter))
1067                        ret = -1;
1068                break;
1069        case IW_MLME_DISASSOC:
1070                if (!rtw_set_802_11_disassociate(padapter))
1071                        ret = -1;
1072                break;
1073        default:
1074                return -EOPNOTSUPP;
1075        }
1076        return ret;
1077}
1078
1079static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1080                             union iwreq_data *wrqu, char *extra)
1081{
1082        u8 _status = false;
1083        int ret = 0;
1084        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1085        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1086        struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1087        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
1088
1089        if (padapter->registrypriv.mp_mode == 1) {
1090                if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
1091                        ret = -1;
1092                        goto exit;
1093                }
1094        }
1095        if (_FAIL == rtw_pwr_wakeup(padapter)) {
1096                ret = -1;
1097                goto exit;
1098        }
1099
1100        if (padapter->bDriverStopped) {
1101                DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped);
1102                ret = -1;
1103                goto exit;
1104        }
1105
1106        if (!padapter->bup) {
1107                ret = -1;
1108                goto exit;
1109        }
1110
1111        if (!padapter->hw_init_completed) {
1112                ret = -1;
1113                goto exit;
1114        }
1115
1116        /*  When Busy Traffic, driver do not site survey. So driver return success. */
1117        /*  wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1118        /*  modify by thomas 2011-02-22. */
1119        if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
1120                indicate_wx_scan_complete_event(padapter);
1121                goto exit;
1122        }
1123
1124        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1125                indicate_wx_scan_complete_event(padapter);
1126                goto exit;
1127        }
1128
1129/*      For the DMP WiFi Display project, the driver won't to scan because */
1130/*      the pmlmepriv->scan_interval is always equal to 3. */
1131/*      So, the wpa_supplicant won't find out the WPS SoftAP. */
1132
1133        memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
1134
1135        if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1136                struct iw_scan_req *req = (struct iw_scan_req *)extra;
1137
1138                if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1139                        int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1140
1141                        memcpy(ssid[0].Ssid, req->essid, len);
1142                        ssid[0].SsidLength = len;
1143
1144                        DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
1145
1146                        spin_lock_bh(&pmlmepriv->lock);
1147
1148                        _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1149
1150                        spin_unlock_bh(&pmlmepriv->lock);
1151                } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
1152                        DBG_88E("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
1153                }
1154        } else {
1155                if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
1156                    !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1157                        int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
1158                        char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1159                        char section;
1160                        char sec_len;
1161                        int ssid_index = 0;
1162
1163                        while (len >= 1) {
1164                                section = *(pos++);
1165                                len -= 1;
1166
1167                                switch (section) {
1168                                case WEXT_CSCAN_SSID_SECTION:
1169                                        if (len < 1) {
1170                                                len = 0;
1171                                                break;
1172                                        }
1173                                        sec_len = *(pos++); len -= 1;
1174                                        if (sec_len > 0 && sec_len <= len) {
1175                                                ssid[ssid_index].SsidLength = sec_len;
1176                                                memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
1177                                                ssid_index++;
1178                                        }
1179                                        pos += sec_len;
1180                                        len -= sec_len;
1181                                        break;
1182                                case WEXT_CSCAN_TYPE_SECTION:
1183                                case WEXT_CSCAN_CHANNEL_SECTION:
1184                                        pos += 1;
1185                                        len -= 1;
1186                                        break;
1187                                case WEXT_CSCAN_PASV_DWELL_SECTION:
1188                                case WEXT_CSCAN_HOME_DWELL_SECTION:
1189                                case WEXT_CSCAN_ACTV_DWELL_SECTION:
1190                                        pos += 2;
1191                                        len -= 2;
1192                                        break;
1193                                default:
1194                                        len = 0; /*  stop parsing */
1195                                }
1196                        }
1197
1198                        /* it has still some scan parameter to parse, we only do this now... */
1199                        _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1200                } else {
1201                        _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1202                }
1203        }
1204
1205        if (!_status)
1206                ret = -1;
1207
1208exit:
1209
1210        return ret;
1211}
1212
1213static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1214                             union iwreq_data *wrqu, char *extra)
1215{
1216        struct list_head *plist, *phead;
1217        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1218        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1219        struct __queue *queue   = &(pmlmepriv->scanned_queue);
1220        struct  wlan_network    *pnetwork = NULL;
1221        char *ev = extra;
1222        char *stop = ev + wrqu->data.length;
1223        u32 ret = 0;
1224        u32 cnt = 0;
1225        u32 wait_for_surveydone;
1226        int wait_status;
1227        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
1228        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1229
1230        if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
1231                ret = -EINVAL;
1232                goto exit;
1233        }
1234
1235        wait_for_surveydone = 100;
1236
1237        wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1238
1239        while (check_fwstate(pmlmepriv, wait_status)) {
1240                msleep(30);
1241                cnt++;
1242                if (cnt > wait_for_surveydone)
1243                        break;
1244        }
1245
1246        spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1247
1248        phead = get_list_head(queue);
1249        plist = phead->next;
1250
1251        while (phead != plist) {
1252                if ((stop - ev) < SCAN_ITEM_SIZE) {
1253                        ret = -E2BIG;
1254                        break;
1255                }
1256
1257                pnetwork = container_of(plist, struct wlan_network, list);
1258
1259                /* report network only if the current channel set contains the channel to which this network belongs */
1260                if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
1261                        ev = translate_scan(padapter, a, pnetwork, ev, stop);
1262
1263                plist = plist->next;
1264        }
1265
1266        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1267
1268        wrqu->data.length = ev-extra;
1269        wrqu->data.flags = 0;
1270
1271exit:
1272        return ret;
1273}
1274
1275/* set ssid flow */
1276/* s1. rtw_set_802_11_infrastructure_mode() */
1277/* s2. set_802_11_authenticaion_mode() */
1278/* s3. set_802_11_encryption_mode() */
1279/* s4. rtw_set_802_11_ssid() */
1280static int rtw_wx_set_essid(struct net_device *dev,
1281                              struct iw_request_info *a,
1282                              union iwreq_data *wrqu, char *extra)
1283{
1284        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1285        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1286        struct __queue *queue = &pmlmepriv->scanned_queue;
1287        struct list_head *phead;
1288        struct wlan_network *pnetwork = NULL;
1289        enum ndis_802_11_auth_mode authmode;
1290        struct ndis_802_11_ssid ndis_ssid;
1291        u8 *dst_ssid, *src_ssid;
1292
1293        uint ret = 0, len;
1294
1295
1296        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1297                 ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1298        if (_FAIL == rtw_pwr_wakeup(padapter)) {
1299                ret = -1;
1300                goto exit;
1301        }
1302
1303        if (!padapter->bup) {
1304                ret = -1;
1305                goto exit;
1306        }
1307
1308        if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1309                ret = -E2BIG;
1310                goto exit;
1311        }
1312
1313        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1314                ret = -1;
1315                goto exit;
1316        }
1317
1318        authmode = padapter->securitypriv.ndisauthtype;
1319        DBG_88E("=>%s\n", __func__);
1320        if (wrqu->essid.flags && wrqu->essid.length) {
1321                len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1322
1323                if (wrqu->essid.length != 33)
1324                        DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1325
1326                memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1327                ndis_ssid.SsidLength = len;
1328                memcpy(ndis_ssid.Ssid, extra, len);
1329                src_ssid = ndis_ssid.Ssid;
1330
1331                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
1332                spin_lock_bh(&queue->lock);
1333               phead = get_list_head(queue);
1334              pmlmepriv->pscanned = phead->next;
1335
1336                while (phead != pmlmepriv->pscanned) {
1337                        pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1338
1339                        pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1340
1341                        dst_ssid = pnetwork->network.Ssid.Ssid;
1342
1343                        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1344                                 ("rtw_wx_set_essid: dst_ssid =%s\n",
1345                                  pnetwork->network.Ssid.Ssid));
1346
1347                        if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
1348                            (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
1349                                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1350                                         ("rtw_wx_set_essid: find match, set infra mode\n"));
1351
1352                                if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
1353                                        if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1354                                                continue;
1355                                }
1356
1357                                if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1358                                        ret = -1;
1359                                        spin_unlock_bh(&queue->lock);
1360                                        goto exit;
1361                                }
1362
1363                                break;
1364                        }
1365                }
1366                spin_unlock_bh(&queue->lock);
1367                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1368                         ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1369                rtw_set_802_11_authentication_mode(padapter, authmode);
1370                if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1371                        ret = -1;
1372                        goto exit;
1373                }
1374        }
1375
1376exit:
1377
1378        DBG_88E("<=%s, ret %d\n", __func__, ret);
1379
1380
1381        return ret;
1382}
1383
1384static int rtw_wx_get_essid(struct net_device *dev,
1385                              struct iw_request_info *a,
1386                              union iwreq_data *wrqu, char *extra)
1387{
1388        u32 len, ret = 0;
1389        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1390        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1391        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1392
1393        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
1394
1395
1396        if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
1397            (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
1398                len = pcur_bss->Ssid.SsidLength;
1399
1400                wrqu->essid.length = len;
1401
1402                memcpy(extra, pcur_bss->Ssid.Ssid, len);
1403
1404                wrqu->essid.flags = 1;
1405        } else {
1406                ret = -1;
1407                goto exit;
1408        }
1409
1410exit:
1411
1412
1413        return ret;
1414}
1415
1416static int rtw_wx_set_rate(struct net_device *dev,
1417                              struct iw_request_info *a,
1418                              union iwreq_data *wrqu, char *extra)
1419{
1420        int i, ret = 0;
1421        u8 datarates[NumRates];
1422        u32     target_rate = wrqu->bitrate.value;
1423        u32     fixed = wrqu->bitrate.fixed;
1424        u32     ratevalue = 0;
1425         u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1426
1427
1428        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
1429        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1430
1431        if (target_rate == -1) {
1432                ratevalue = 11;
1433                goto set_rate;
1434        }
1435        target_rate = target_rate/100000;
1436
1437        switch (target_rate) {
1438        case 10:
1439                ratevalue = 0;
1440                break;
1441        case 20:
1442                ratevalue = 1;
1443                break;
1444        case 55:
1445                ratevalue = 2;
1446                break;
1447        case 60:
1448                ratevalue = 3;
1449                break;
1450        case 90:
1451                ratevalue = 4;
1452                break;
1453        case 110:
1454                ratevalue = 5;
1455                break;
1456        case 120:
1457                ratevalue = 6;
1458                break;
1459        case 180:
1460                ratevalue = 7;
1461                break;
1462        case 240:
1463                ratevalue = 8;
1464                break;
1465        case 360:
1466                ratevalue = 9;
1467                break;
1468        case 480:
1469                ratevalue = 10;
1470                break;
1471        case 540:
1472                ratevalue = 11;
1473                break;
1474        default:
1475                ratevalue = 11;
1476                break;
1477        }
1478
1479set_rate:
1480
1481        for (i = 0; i < NumRates; i++) {
1482                if (ratevalue == mpdatarate[i]) {
1483                        datarates[i] = mpdatarate[i];
1484                        if (fixed == 0)
1485                                break;
1486                } else {
1487                        datarates[i] = 0xff;
1488                }
1489
1490                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1491        }
1492
1493        return ret;
1494}
1495
1496static int rtw_wx_get_rate(struct net_device *dev,
1497                             struct iw_request_info *info,
1498                             union iwreq_data *wrqu, char *extra)
1499{
1500        u16 max_rate = 0;
1501
1502        max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1503
1504        if (max_rate == 0)
1505                return -EPERM;
1506
1507        wrqu->bitrate.fixed = 0;        /* no auto select */
1508        wrqu->bitrate.value = max_rate * 100000;
1509
1510        return 0;
1511}
1512
1513static int rtw_wx_set_rts(struct net_device *dev,
1514                             struct iw_request_info *info,
1515                             union iwreq_data *wrqu, char *extra)
1516{
1517        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1518
1519
1520        if (wrqu->rts.disabled) {
1521                padapter->registrypriv.rts_thresh = 2347;
1522        } else {
1523                if (wrqu->rts.value < 0 ||
1524                    wrqu->rts.value > 2347)
1525                        return -EINVAL;
1526
1527                padapter->registrypriv.rts_thresh = wrqu->rts.value;
1528        }
1529
1530        DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1531
1532
1533        return 0;
1534}
1535
1536static int rtw_wx_get_rts(struct net_device *dev,
1537                             struct iw_request_info *info,
1538                             union iwreq_data *wrqu, char *extra)
1539{
1540        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1541
1542
1543        DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1544
1545        wrqu->rts.value = padapter->registrypriv.rts_thresh;
1546        wrqu->rts.fixed = 0;    /* no auto select */
1547        /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1548
1549
1550        return 0;
1551}
1552
1553static int rtw_wx_set_frag(struct net_device *dev,
1554                             struct iw_request_info *info,
1555                             union iwreq_data *wrqu, char *extra)
1556{
1557        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1558
1559
1560        if (wrqu->frag.disabled) {
1561                padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1562        } else {
1563                if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1564                    wrqu->frag.value > MAX_FRAG_THRESHOLD)
1565                        return -EINVAL;
1566
1567                padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1568        }
1569
1570        DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1571
1572
1573        return 0;
1574}
1575
1576static int rtw_wx_get_frag(struct net_device *dev,
1577                             struct iw_request_info *info,
1578                             union iwreq_data *wrqu, char *extra)
1579{
1580        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1581
1582
1583        DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1584
1585        wrqu->frag.value = padapter->xmitpriv.frag_len;
1586        wrqu->frag.fixed = 0;   /* no auto select */
1587
1588
1589        return 0;
1590}
1591
1592static int rtw_wx_get_retry(struct net_device *dev,
1593                             struct iw_request_info *info,
1594                             union iwreq_data *wrqu, char *extra)
1595{
1596        wrqu->retry.value = 7;
1597        wrqu->retry.fixed = 0;  /* no auto select */
1598        wrqu->retry.disabled = 1;
1599
1600        return 0;
1601}
1602
1603static int rtw_wx_set_enc(struct net_device *dev,
1604                            struct iw_request_info *info,
1605                            union iwreq_data *wrqu, char *keybuf)
1606{
1607        u32 key, ret = 0;
1608        u32 keyindex_provided;
1609        struct ndis_802_11_wep   wep;
1610        enum ndis_802_11_auth_mode authmode;
1611
1612        struct iw_point *erq = &(wrqu->encoding);
1613        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1614        struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1615        DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
1616
1617        memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1618
1619        key = erq->flags & IW_ENCODE_INDEX;
1620
1621
1622        if (erq->flags & IW_ENCODE_DISABLED) {
1623                DBG_88E("EncryptionDisabled\n");
1624                padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1625                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1626                padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1627                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1628                authmode = Ndis802_11AuthModeOpen;
1629                padapter->securitypriv.ndisauthtype = authmode;
1630
1631                goto exit;
1632        }
1633
1634        if (key) {
1635                if (key > WEP_KEYS)
1636                        return -EINVAL;
1637                key--;
1638                keyindex_provided = 1;
1639        } else {
1640                keyindex_provided = 0;
1641                key = padapter->securitypriv.dot11PrivacyKeyIndex;
1642                DBG_88E("rtw_wx_set_enc, key =%d\n", key);
1643        }
1644
1645        /* set authentication mode */
1646        if (erq->flags & IW_ENCODE_OPEN) {
1647                DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
1648                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1649                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1650                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1651                padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1652                authmode = Ndis802_11AuthModeOpen;
1653                padapter->securitypriv.ndisauthtype = authmode;
1654        } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1655                DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
1656                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1657                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1658                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1659                padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1660                authmode = Ndis802_11AuthModeShared;
1661                padapter->securitypriv.ndisauthtype = authmode;
1662        } else {
1663                DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
1664
1665                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1666                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1667                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1668                padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1669                authmode = Ndis802_11AuthModeOpen;
1670                padapter->securitypriv.ndisauthtype = authmode;
1671        }
1672
1673        wep.KeyIndex = key;
1674        if (erq->length > 0) {
1675                wep.KeyLength = erq->length <= 5 ? 5 : 13;
1676
1677                wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
1678        } else {
1679                wep.KeyLength = 0;
1680
1681                if (keyindex_provided == 1) {
1682                        /*  set key_id only, no given KeyMaterial(erq->length == 0). */
1683                        padapter->securitypriv.dot11PrivacyKeyIndex = key;
1684
1685                        DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1686
1687                        switch (padapter->securitypriv.dot11DefKeylen[key]) {
1688                        case 5:
1689                                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1690                                break;
1691                        case 13:
1692                                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1693                                break;
1694                        default:
1695                                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1696                                break;
1697                        }
1698
1699                        goto exit;
1700                }
1701        }
1702
1703        wep.KeyIndex |= 0x80000000;
1704
1705        memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1706
1707        if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
1708                if (rf_on == pwrpriv->rf_pwrstate)
1709                        ret = -EOPNOTSUPP;
1710                goto exit;
1711        }
1712
1713exit:
1714
1715
1716        return ret;
1717}
1718
1719static int rtw_wx_get_enc(struct net_device *dev,
1720                            struct iw_request_info *info,
1721                            union iwreq_data *wrqu, char *keybuf)
1722{
1723        uint key, ret = 0;
1724        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1725        struct iw_point *erq = &(wrqu->encoding);
1726        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
1727
1728
1729        if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1730                if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1731                        erq->length = 0;
1732                        erq->flags |= IW_ENCODE_DISABLED;
1733                        return 0;
1734                }
1735        }
1736
1737        key = erq->flags & IW_ENCODE_INDEX;
1738
1739        if (key) {
1740                if (key > WEP_KEYS)
1741                        return -EINVAL;
1742                key--;
1743        } else {
1744                key = padapter->securitypriv.dot11PrivacyKeyIndex;
1745        }
1746
1747        erq->flags = key + 1;
1748
1749        switch (padapter->securitypriv.ndisencryptstatus) {
1750        case Ndis802_11EncryptionNotSupported:
1751        case Ndis802_11EncryptionDisabled:
1752                erq->length = 0;
1753                erq->flags |= IW_ENCODE_DISABLED;
1754                break;
1755        case Ndis802_11Encryption1Enabled:
1756                erq->length = padapter->securitypriv.dot11DefKeylen[key];
1757                if (erq->length) {
1758                        memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1759
1760                        erq->flags |= IW_ENCODE_ENABLED;
1761
1762                        if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1763                                erq->flags |= IW_ENCODE_OPEN;
1764                        else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1765                                erq->flags |= IW_ENCODE_RESTRICTED;
1766                } else {
1767                        erq->length = 0;
1768                        erq->flags |= IW_ENCODE_DISABLED;
1769                }
1770                break;
1771        case Ndis802_11Encryption2Enabled:
1772        case Ndis802_11Encryption3Enabled:
1773                erq->length = 16;
1774                erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1775                break;
1776        default:
1777                erq->length = 0;
1778                erq->flags |= IW_ENCODE_DISABLED;
1779                break;
1780        }
1781
1782        return ret;
1783}
1784
1785static int rtw_wx_get_power(struct net_device *dev,
1786                             struct iw_request_info *info,
1787                             union iwreq_data *wrqu, char *extra)
1788{
1789        wrqu->power.value = 0;
1790        wrqu->power.fixed = 0;  /* no auto select */
1791        wrqu->power.disabled = 1;
1792
1793        return 0;
1794}
1795
1796static int rtw_wx_set_gen_ie(struct net_device *dev,
1797                             struct iw_request_info *info,
1798                             union iwreq_data *wrqu, char *extra)
1799{
1800        int ret;
1801        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1802
1803        ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1804        return ret;
1805}
1806
1807static int rtw_wx_set_auth(struct net_device *dev,
1808                             struct iw_request_info *info,
1809                             union iwreq_data *wrqu, char *extra)
1810{
1811        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1812        struct iw_param *param = (struct iw_param *)&(wrqu->param);
1813        int ret = 0;
1814
1815        switch (param->flags & IW_AUTH_INDEX) {
1816        case IW_AUTH_WPA_VERSION:
1817                break;
1818        case IW_AUTH_CIPHER_PAIRWISE:
1819
1820                break;
1821        case IW_AUTH_CIPHER_GROUP:
1822
1823                break;
1824        case IW_AUTH_KEY_MGMT:
1825                /*
1826                 *  ??? does not use these parameters
1827                 */
1828                break;
1829        case IW_AUTH_TKIP_COUNTERMEASURES:
1830                if (param->value) {
1831                        /*  wpa_supplicant is enabling the tkip countermeasure. */
1832                        padapter->securitypriv.btkip_countermeasure = true;
1833                } else {
1834                        /*  wpa_supplicant is disabling the tkip countermeasure. */
1835                        padapter->securitypriv.btkip_countermeasure = false;
1836                }
1837                break;
1838        case IW_AUTH_DROP_UNENCRYPTED:
1839                /* HACK:
1840                 *
1841                 * wpa_supplicant calls set_wpa_enabled when the driver
1842                 * is loaded and unloaded, regardless of if WPA is being
1843                 * used.  No other calls are made which can be used to
1844                 * determine if encryption will be used or not prior to
1845                 * association being expected.  If encryption is not being
1846                 * used, drop_unencrypted is set to false, else true -- we
1847                 * can use this to determine if the CAP_PRIVACY_ON bit should
1848                 * be set.
1849                 */
1850
1851                if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
1852                        break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
1853                                        /*  then it needn't reset it; */
1854
1855                if (param->value) {
1856                        padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1857                        padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1858                        padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1859                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1860                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1861                }
1862
1863                break;
1864        case IW_AUTH_80211_AUTH_ALG:
1865                /*
1866                 *  It's the starting point of a link layer connection using wpa_supplicant
1867                */
1868                if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
1869                        LeaveAllPowerSaveMode(padapter);
1870                        rtw_disassoc_cmd(padapter, 500, false);
1871                        DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
1872                        rtw_indicate_disconnect(padapter);
1873                        rtw_free_assoc_resources(padapter, 1);
1874                }
1875                ret = wpa_set_auth_algs(dev, (u32)param->value);
1876                break;
1877        case IW_AUTH_WPA_ENABLED:
1878                break;
1879        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1880                break;
1881        case IW_AUTH_PRIVACY_INVOKED:
1882                break;
1883        default:
1884                return -EOPNOTSUPP;
1885        }
1886
1887        return ret;
1888}
1889
1890static int rtw_wx_set_enc_ext(struct net_device *dev,
1891                             struct iw_request_info *info,
1892                             union iwreq_data *wrqu, char *extra)
1893{
1894        char *alg_name;
1895        u32 param_len;
1896        struct ieee_param *param = NULL;
1897        struct iw_point *pencoding = &wrqu->encoding;
1898        struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1899        int ret = 0;
1900
1901        param_len = sizeof(struct ieee_param) + pext->key_len;
1902        param = (struct ieee_param *)rtw_malloc(param_len);
1903        if (param == NULL)
1904                return -1;
1905
1906        memset(param, 0, param_len);
1907
1908        param->cmd = IEEE_CMD_SET_ENCRYPTION;
1909        memset(param->sta_addr, 0xff, ETH_ALEN);
1910
1911        switch (pext->alg) {
1912        case IW_ENCODE_ALG_NONE:
1913                /* todo: remove key */
1914                /* remove = 1; */
1915                alg_name = "none";
1916                break;
1917        case IW_ENCODE_ALG_WEP:
1918                alg_name = "WEP";
1919                break;
1920        case IW_ENCODE_ALG_TKIP:
1921                alg_name = "TKIP";
1922                break;
1923        case IW_ENCODE_ALG_CCMP:
1924                alg_name = "CCMP";
1925                break;
1926        default:
1927                ret = -1;
1928                goto exit;
1929        }
1930
1931        strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1932
1933        if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1934                param->u.crypt.set_tx = 1;
1935
1936        /* cliW: WEP does not have group key
1937         * just not checking GROUP key setting
1938         */
1939        if ((pext->alg != IW_ENCODE_ALG_WEP) &&
1940            (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
1941                param->u.crypt.set_tx = 0;
1942
1943        param->u.crypt.idx = (pencoding->flags&0x00FF) - 1;
1944
1945        if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1946                memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1947
1948        if (pext->key_len) {
1949                param->u.crypt.key_len = pext->key_len;
1950                memcpy(param->u.crypt.key, pext + 1, pext->key_len);
1951        }
1952
1953        ret =  wpa_set_encryption(dev, param, param_len);
1954
1955exit:
1956        kfree(param);
1957        return ret;
1958}
1959
1960static int rtw_wx_get_nick(struct net_device *dev,
1961                           struct iw_request_info *info,
1962                           union iwreq_data *wrqu, char *extra)
1963{
1964        if (extra) {
1965                wrqu->data.length = 14;
1966                wrqu->data.flags = 1;
1967                memcpy(extra, "<WIFI@REALTEK>", 14);
1968        }
1969
1970        /* dump debug info here */
1971        return 0;
1972}
1973
1974static int dummy(struct net_device *dev, struct iw_request_info *a,
1975                 union iwreq_data *wrqu, char *b)
1976{
1977        return -1;
1978}
1979
1980static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
1981{
1982        uint ret = 0;
1983        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1984
1985        switch (name) {
1986        case IEEE_PARAM_WPA_ENABLED:
1987                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
1988                switch ((value)&0xff) {
1989                case 1: /* WPA */
1990                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
1991                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1992                        break;
1993                case 2: /* WPA2 */
1994                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
1995                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1996                        break;
1997                }
1998                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1999                         ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
2000                break;
2001        case IEEE_PARAM_TKIP_COUNTERMEASURES:
2002                break;
2003        case IEEE_PARAM_DROP_UNENCRYPTED: {
2004                /* HACK:
2005                 *
2006                 * wpa_supplicant calls set_wpa_enabled when the driver
2007                 * is loaded and unloaded, regardless of if WPA is being
2008                 * used.  No other calls are made which can be used to
2009                 * determine if encryption will be used or not prior to
2010                 * association being expected.  If encryption is not being
2011                 * used, drop_unencrypted is set to false, else true -- we
2012                 * can use this to determine if the CAP_PRIVACY_ON bit should
2013                 * be set.
2014                 */
2015
2016                break;
2017        }
2018        case IEEE_PARAM_PRIVACY_INVOKED:
2019                break;
2020
2021        case IEEE_PARAM_AUTH_ALGS:
2022                ret = wpa_set_auth_algs(dev, value);
2023                break;
2024        case IEEE_PARAM_IEEE_802_1X:
2025                break;
2026        case IEEE_PARAM_WPAX_SELECT:
2027                break;
2028        default:
2029                ret = -EOPNOTSUPP;
2030                break;
2031        }
2032        return ret;
2033}
2034
2035static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2036{
2037        int ret = 0;
2038        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2039
2040        switch (command) {
2041        case IEEE_MLME_STA_DEAUTH:
2042                if (!rtw_set_802_11_disassociate(padapter))
2043                        ret = -1;
2044                break;
2045        case IEEE_MLME_STA_DISASSOC:
2046                if (!rtw_set_802_11_disassociate(padapter))
2047                        ret = -1;
2048                break;
2049        default:
2050                ret = -EOPNOTSUPP;
2051                break;
2052        }
2053
2054        return ret;
2055}
2056
2057static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2058{
2059        struct ieee_param *param;
2060        uint ret = 0;
2061
2062        if (p->length < sizeof(struct ieee_param) || !p->pointer) {
2063                ret = -EINVAL;
2064                goto out;
2065        }
2066
2067        param = (struct ieee_param *)rtw_malloc(p->length);
2068        if (param == NULL) {
2069                ret = -ENOMEM;
2070                goto out;
2071        }
2072
2073        if (copy_from_user(param, p->pointer, p->length)) {
2074                kfree(param);
2075                ret = -EFAULT;
2076                goto out;
2077        }
2078
2079        switch (param->cmd) {
2080        case IEEE_CMD_SET_WPA_PARAM:
2081                ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
2082                break;
2083
2084        case IEEE_CMD_SET_WPA_IE:
2085                ret =  rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev),
2086                                      (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
2087                break;
2088
2089        case IEEE_CMD_SET_ENCRYPTION:
2090                ret = wpa_set_encryption(dev, param, p->length);
2091                break;
2092
2093        case IEEE_CMD_MLME:
2094                ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
2095                break;
2096
2097        default:
2098                DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
2099                ret = -EOPNOTSUPP;
2100                break;
2101        }
2102
2103        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2104                ret = -EFAULT;
2105
2106        kfree(param);
2107
2108out:
2109
2110        return ret;
2111}
2112
2113#ifdef CONFIG_88EU_AP_MODE
2114static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
2115{
2116        struct cmd_obj *ph2c;
2117        struct set_stakey_parm  *psetstakey_para;
2118        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2119        u8 res = _SUCCESS;
2120
2121        ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
2122        if (ph2c == NULL) {
2123                res = _FAIL;
2124                goto exit;
2125        }
2126
2127        psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
2128        if (psetstakey_para == NULL) {
2129                kfree(ph2c);
2130                res = _FAIL;
2131                goto exit;
2132        }
2133
2134        init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
2135
2136        psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
2137
2138        memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
2139
2140        memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
2141
2142        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2143
2144exit:
2145
2146        return res;
2147}
2148
2149static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
2150{
2151        u8 keylen;
2152        struct cmd_obj *pcmd;
2153        struct setkey_parm *psetkeyparm;
2154        struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
2155        int res = _SUCCESS;
2156
2157        DBG_88E("%s\n", __func__);
2158
2159        pcmd = kzalloc(sizeof(struct    cmd_obj), GFP_KERNEL);
2160        if (pcmd == NULL) {
2161                res = _FAIL;
2162                goto exit;
2163        }
2164        psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
2165        if (psetkeyparm == NULL) {
2166                kfree(pcmd);
2167                res = _FAIL;
2168                goto exit;
2169        }
2170
2171        memset(psetkeyparm, 0, sizeof(struct setkey_parm));
2172
2173        psetkeyparm->keyid = (u8)keyid;
2174
2175        psetkeyparm->algorithm = alg;
2176
2177        psetkeyparm->set_tx = 1;
2178
2179        switch (alg) {
2180        case _WEP40_:
2181                keylen = 5;
2182                break;
2183        case _WEP104_:
2184                keylen = 13;
2185                break;
2186        case _TKIP_:
2187        case _TKIP_WTMIC_:
2188        case _AES_:
2189        default:
2190                keylen = 16;
2191        }
2192
2193        memcpy(&(psetkeyparm->key[0]), key, keylen);
2194
2195        pcmd->cmdcode = _SetKey_CMD_;
2196        pcmd->parmbuf = (u8 *)psetkeyparm;
2197        pcmd->cmdsz =  (sizeof(struct setkey_parm));
2198        pcmd->rsp = NULL;
2199        pcmd->rspsz = 0;
2200
2201        INIT_LIST_HEAD(&pcmd->list);
2202
2203        res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2204
2205exit:
2206
2207        return res;
2208}
2209
2210static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
2211{
2212        u8 alg;
2213
2214        switch (keylen) {
2215        case 5:
2216                alg = _WEP40_;
2217                break;
2218        case 13:
2219                alg = _WEP104_;
2220                break;
2221        default:
2222                alg = _NO_PRIVACY_;
2223        }
2224
2225        return set_group_key(padapter, key, alg, keyid);
2226}
2227
2228static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
2229{
2230        int ret = 0;
2231        u32 wep_key_idx, wep_key_len, wep_total_len;
2232        struct ndis_802_11_wep   *pwep = NULL;
2233        struct sta_info *psta = NULL, *pbcmc_sta = NULL;
2234        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2235        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
2236        struct security_priv *psecuritypriv = &(padapter->securitypriv);
2237        struct sta_priv *pstapriv = &padapter->stapriv;
2238
2239        DBG_88E("%s\n", __func__);
2240        param->u.crypt.err = 0;
2241        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2242        if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
2243                ret =  -EINVAL;
2244                goto exit;
2245        }
2246        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2247            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2248            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
2249                if (param->u.crypt.idx >= WEP_KEYS) {
2250                        ret = -EINVAL;
2251                        goto exit;
2252                }
2253        } else {
2254                psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2255                if (!psta) {
2256                        DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
2257                        goto exit;
2258                }
2259        }
2260
2261        if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
2262                /* todo:clear default encryption keys */
2263
2264                DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
2265                goto exit;
2266        }
2267        if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
2268                DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
2269                wep_key_idx = param->u.crypt.idx;
2270                wep_key_len = param->u.crypt.key_len;
2271                DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
2272                if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
2273                        ret = -EINVAL;
2274                        goto exit;
2275                }
2276
2277                if (wep_key_len > 0) {
2278                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
2279                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
2280                        pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
2281                        if (pwep == NULL) {
2282                                DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
2283                                goto exit;
2284                        }
2285
2286                        memset(pwep, 0, wep_total_len);
2287
2288                        pwep->KeyLength = wep_key_len;
2289                        pwep->Length = wep_total_len;
2290                }
2291
2292                pwep->KeyIndex = wep_key_idx;
2293
2294                memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
2295
2296                if (param->u.crypt.set_tx) {
2297                        DBG_88E("wep, set_tx = 1\n");
2298
2299                        psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
2300                        psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
2301                        psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2302
2303                        if (pwep->KeyLength == 13) {
2304                                psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
2305                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2306                        }
2307
2308                        psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
2309
2310                        memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
2311
2312                        psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2313
2314                        set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2315                } else {
2316                        DBG_88E("wep, set_tx = 0\n");
2317
2318                        /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
2319                        /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
2320
2321                      memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
2322
2323                        psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
2324
2325                        set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
2326                }
2327
2328                goto exit;
2329        }
2330
2331        if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
2332                if (param->u.crypt.set_tx == 1) {
2333                        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2334                                DBG_88E("%s, set group_key, WEP\n", __func__);
2335
2336                                memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2337                                            param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2338
2339                                psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2340                                if (param->u.crypt.key_len == 13)
2341                                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2342                        } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2343                                DBG_88E("%s, set group_key, TKIP\n", __func__);
2344                                psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2345                                memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2346                                            param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2347                                /* set mic key */
2348                                memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
2349                                memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
2350
2351                                psecuritypriv->busetkipkey = true;
2352                        } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2353                                DBG_88E("%s, set group_key, CCMP\n", __func__);
2354                                psecuritypriv->dot118021XGrpPrivacy = _AES_;
2355                                memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2356                                            param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2357                        } else {
2358                                DBG_88E("%s, set group_key, none\n", __func__);
2359                                psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2360                        }
2361                        psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2362                        psecuritypriv->binstallGrpkey = true;
2363                        psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2364                        set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2365                        pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2366                        if (pbcmc_sta) {
2367                                pbcmc_sta->ieee8021x_blocked = false;
2368                                pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2369                        }
2370                }
2371                goto exit;
2372        }
2373
2374        if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
2375                if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2376                        if (param->u.crypt.set_tx == 1) {
2377                                memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2378
2379                                if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2380                                        DBG_88E("%s, set pairwise key, WEP\n", __func__);
2381
2382                                        psta->dot118021XPrivacy = _WEP40_;
2383                                        if (param->u.crypt.key_len == 13)
2384                                                psta->dot118021XPrivacy = _WEP104_;
2385                                } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2386                                        DBG_88E("%s, set pairwise key, TKIP\n", __func__);
2387
2388                                        psta->dot118021XPrivacy = _TKIP_;
2389
2390                                        /* set mic key */
2391                                        memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
2392                                        memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
2393
2394                                        psecuritypriv->busetkipkey = true;
2395                                } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2396                                        DBG_88E("%s, set pairwise key, CCMP\n", __func__);
2397
2398                                        psta->dot118021XPrivacy = _AES_;
2399                                } else {
2400                                        DBG_88E("%s, set pairwise key, none\n", __func__);
2401
2402                                        psta->dot118021XPrivacy = _NO_PRIVACY_;
2403                                }
2404
2405                                set_pairwise_key(padapter, psta);
2406
2407                                psta->ieee8021x_blocked = false;
2408                        } else { /* group key??? */
2409                                if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2410                                        memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2411                                                    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2412                                        psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2413                                        if (param->u.crypt.key_len == 13)
2414                                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2415                                } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2416                                        psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
2417
2418                                        memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2419                                                    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2420
2421                                        /* set mic key */
2422                                        memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
2423                                        memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
2424
2425                                        psecuritypriv->busetkipkey = true;
2426                                } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2427                                        psecuritypriv->dot118021XGrpPrivacy = _AES_;
2428
2429                                        memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
2430                                                    param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
2431                                } else {
2432                                        psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2433                                }
2434
2435                                psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
2436
2437                                psecuritypriv->binstallGrpkey = true;
2438
2439                                psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
2440
2441                                set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
2442
2443                                pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
2444                                if (pbcmc_sta) {
2445                                        pbcmc_sta->ieee8021x_blocked = false;
2446                                        pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
2447                                }
2448                        }
2449                }
2450        }
2451
2452exit:
2453
2454        kfree(pwep);
2455
2456        return ret;
2457}
2458
2459static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
2460{
2461        int ret = 0;
2462        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2463        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2464        struct sta_priv *pstapriv = &padapter->stapriv;
2465        unsigned char *pbuf = param->u.bcn_ie.buf;
2466
2467        DBG_88E("%s, len =%d\n", __func__, len);
2468
2469        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2470                return -EINVAL;
2471
2472        memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
2473
2474        if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
2475                pstapriv->max_num_sta = NUM_STA;
2476
2477        if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
2478                ret = 0;
2479        else
2480                ret = -EINVAL;
2481
2482        return ret;
2483}
2484
2485static int rtw_hostapd_sta_flush(struct net_device *dev)
2486{
2487        int ret = 0;
2488        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2489
2490        DBG_88E("%s\n", __func__);
2491
2492        flush_all_cam_entry(padapter);  /* clear CAM */
2493
2494        ret = rtw_sta_flush(padapter);
2495
2496        return ret;
2497}
2498
2499static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
2500{
2501        int ret = 0;
2502        struct sta_info *psta = NULL;
2503        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2504        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2505        struct sta_priv *pstapriv = &padapter->stapriv;
2506
2507        DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
2508
2509        if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
2510                return -EINVAL;
2511
2512        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2513            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2514            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2515                return -EINVAL;
2516
2517        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2518        if (psta) {
2519                int flags = param->u.add_sta.flags;
2520
2521                psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
2522
2523                memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
2524
2525                /* check wmm cap. */
2526                if (WLAN_STA_WME&flags)
2527                        psta->qos_option = 1;
2528                else
2529                        psta->qos_option = 0;
2530
2531                if (pmlmepriv->qospriv.qos_option == 0)
2532                        psta->qos_option = 0;
2533
2534                /* chec 802.11n ht cap. */
2535                if (WLAN_STA_HT&flags) {
2536                        psta->htpriv.ht_option = true;
2537                        psta->qos_option = 1;
2538                        memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
2539                } else {
2540                        psta->htpriv.ht_option = false;
2541                }
2542
2543                if (pmlmepriv->htpriv.ht_option == false)
2544                        psta->htpriv.ht_option = false;
2545
2546                update_sta_info_apmode(padapter, psta);
2547        } else {
2548                ret = -ENOMEM;
2549        }
2550
2551        return ret;
2552}
2553
2554static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
2555{
2556        int ret = 0;
2557        struct sta_info *psta = NULL;
2558        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2559        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2560        struct sta_priv *pstapriv = &padapter->stapriv;
2561        int updated = 0;
2562
2563        DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
2564
2565        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2566                return -EINVAL;
2567
2568        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2569            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2570            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2571                return -EINVAL;
2572
2573        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2574        if (psta) {
2575                spin_lock_bh(&pstapriv->asoc_list_lock);
2576                if (!list_empty(&psta->asoc_list)) {
2577                        list_del_init(&psta->asoc_list);
2578                        pstapriv->asoc_list_cnt--;
2579                        updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
2580                }
2581                spin_unlock_bh(&pstapriv->asoc_list_lock);
2582                associated_clients_update(padapter, updated);
2583                psta = NULL;
2584        } else {
2585                DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
2586        }
2587
2588        return ret;
2589}
2590
2591static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
2592{
2593        int ret = 0;
2594        struct sta_info *psta = NULL;
2595        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2596        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2597        struct sta_priv *pstapriv = &padapter->stapriv;
2598        struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
2599        struct sta_data *psta_data = (struct sta_data *)param_ex->data;
2600
2601        DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
2602
2603        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2604                return -EINVAL;
2605
2606        if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
2607            param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
2608            param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
2609                return -EINVAL;
2610
2611        psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
2612        if (psta) {
2613                psta_data->aid = (u16)psta->aid;
2614                psta_data->capability = psta->capability;
2615                psta_data->flags = psta->flags;
2616
2617/*
2618                nonerp_set : BIT(0)
2619                no_short_slot_time_set : BIT(1)
2620                no_short_preamble_set : BIT(2)
2621                no_ht_gf_set : BIT(3)
2622                no_ht_set : BIT(4)
2623                ht_20mhz_set : BIT(5)
2624*/
2625
2626                psta_data->sta_set = ((psta->nonerp_set) |
2627                                      (psta->no_short_slot_time_set << 1) |
2628                                      (psta->no_short_preamble_set << 2) |
2629                                      (psta->no_ht_gf_set << 3) |
2630                                      (psta->no_ht_set << 4) |
2631                                      (psta->ht_20mhz_set << 5));
2632                psta_data->tx_supp_rates_len =  psta->bssratelen;
2633                memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
2634                memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
2635                psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
2636                psta_data->rx_bytes = psta->sta_stats.rx_bytes;
2637                psta_data->rx_drops = psta->sta_stats.rx_drops;
2638                psta_data->tx_pkts = psta->sta_stats.tx_pkts;
2639                psta_data->tx_bytes = psta->sta_stats.tx_bytes;
2640                psta_data->tx_drops = psta->sta_stats.tx_drops;
2641        } else {
2642                ret = -1;
2643        }
2644
2645        return ret;
2646}
2647
2648static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
2649{
2650        int ret = 0;
2651        struct sta_info *psta = NULL;
2652        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2653        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2654        struct sta_priv *pstapriv = &padapter->stapriv;
2655
2656        DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
2657
2658        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
2659                return -EINVAL;
2660
2661        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2662            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2663            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2664                return -EINVAL;
2665
2666        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
2667        if (psta) {
2668                if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
2669                        int wpa_ie_len;
2670                        int copy_len;
2671
2672                        wpa_ie_len = psta->wpa_ie[1];
2673                        copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len+2);
2674                        param->u.wpa_ie.len = copy_len;
2675                        memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
2676                } else {
2677                        DBG_88E("sta's wpa_ie is NONE\n");
2678                }
2679        } else {
2680                ret = -1;
2681        }
2682
2683        return ret;
2684}
2685
2686static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
2687{
2688        int ret = 0;
2689        unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2690        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2691        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2692        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2693        int ie_len;
2694
2695        DBG_88E("%s, len =%d\n", __func__, len);
2696
2697        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2698                return -EINVAL;
2699
2700        ie_len = len-12-2;/*  12 = param header, 2:no packed */
2701
2702        if (pmlmepriv->wps_beacon_ie) {
2703                kfree(pmlmepriv->wps_beacon_ie);
2704                pmlmepriv->wps_beacon_ie = NULL;
2705        }
2706
2707        if (ie_len > 0) {
2708                pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
2709                pmlmepriv->wps_beacon_ie_len = ie_len;
2710                if (pmlmepriv->wps_beacon_ie == NULL) {
2711                        DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2712                        return -EINVAL;
2713                }
2714
2715                memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
2716
2717                update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
2718
2719                pmlmeext->bstart_bss = true;
2720        }
2721
2722        return ret;
2723}
2724
2725static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
2726{
2727        int ret = 0;
2728        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2729        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2730        int ie_len;
2731
2732        DBG_88E("%s, len =%d\n", __func__, len);
2733
2734        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2735                return -EINVAL;
2736
2737        ie_len = len-12-2;/*  12 = param header, 2:no packed */
2738
2739        if (pmlmepriv->wps_probe_resp_ie) {
2740                kfree(pmlmepriv->wps_probe_resp_ie);
2741                pmlmepriv->wps_probe_resp_ie = NULL;
2742        }
2743
2744        if (ie_len > 0) {
2745                pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
2746                pmlmepriv->wps_probe_resp_ie_len = ie_len;
2747                if (pmlmepriv->wps_probe_resp_ie == NULL) {
2748                        DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2749                        return -EINVAL;
2750                }
2751                memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
2752        }
2753
2754        return ret;
2755}
2756
2757static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
2758{
2759        int ret = 0;
2760        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2761        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2762        int ie_len;
2763
2764        DBG_88E("%s, len =%d\n", __func__, len);
2765
2766        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2767                return -EINVAL;
2768
2769        ie_len = len-12-2;/*  12 = param header, 2:no packed */
2770
2771        if (pmlmepriv->wps_assoc_resp_ie) {
2772                kfree(pmlmepriv->wps_assoc_resp_ie);
2773                pmlmepriv->wps_assoc_resp_ie = NULL;
2774        }
2775
2776        if (ie_len > 0) {
2777                pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
2778                pmlmepriv->wps_assoc_resp_ie_len = ie_len;
2779                if (pmlmepriv->wps_assoc_resp_ie == NULL) {
2780                        DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2781                        return -EINVAL;
2782                }
2783
2784                memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
2785        }
2786
2787        return ret;
2788}
2789
2790static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
2791{
2792        int ret = 0;
2793        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2794        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2795        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2796        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2797
2798        u8 value;
2799
2800        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2801                return -EINVAL;
2802
2803        if (param->u.wpa_param.name != 0) /* dummy test... */
2804                DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
2805        value = param->u.wpa_param.value;
2806
2807        /* use the same definition of hostapd's ignore_broadcast_ssid */
2808        if (value != 1 && value != 2)
2809                value = 0;
2810        DBG_88E("%s value(%u)\n", __func__, value);
2811        pmlmeinfo->hidden_ssid_mode = value;
2812        return ret;
2813}
2814
2815static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
2816{
2817        int ret = 0;
2818        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2819        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2820
2821        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2822                return -EINVAL;
2823
2824        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2825            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2826            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2827                return -EINVAL;
2828        ret = rtw_acl_remove_sta(padapter, param->sta_addr);
2829        return ret;
2830}
2831
2832static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
2833{
2834        int ret = 0;
2835        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2836        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2837
2838        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2839                return -EINVAL;
2840
2841        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2842            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2843            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
2844                return -EINVAL;
2845        ret = rtw_acl_add_sta(padapter, param->sta_addr);
2846        return ret;
2847}
2848
2849static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
2850{
2851        int ret = 0;
2852        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2853        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2854
2855        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2856                return -EINVAL;
2857
2858        rtw_set_macaddr_acl(padapter, param->u.mlme.command);
2859
2860        return ret;
2861}
2862
2863static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
2864{
2865        struct ieee_param *param;
2866        int ret = 0;
2867        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2868
2869        /*
2870        * this function is expect to call in master mode, which allows no power saving
2871        * so, we just check hw_init_completed
2872        */
2873
2874        if (!padapter->hw_init_completed) {
2875                ret = -EPERM;
2876                goto out;
2877        }
2878
2879        if (!p->pointer) {
2880                ret = -EINVAL;
2881                goto out;
2882        }
2883
2884        param = (struct ieee_param *)rtw_malloc(p->length);
2885        if (param == NULL) {
2886                ret = -ENOMEM;
2887                goto out;
2888        }
2889
2890        if (copy_from_user(param, p->pointer, p->length)) {
2891                kfree(param);
2892                ret = -EFAULT;
2893                goto out;
2894        }
2895
2896        switch (param->cmd) {
2897        case RTL871X_HOSTAPD_FLUSH:
2898                ret = rtw_hostapd_sta_flush(dev);
2899                break;
2900        case RTL871X_HOSTAPD_ADD_STA:
2901                ret = rtw_add_sta(dev, param);
2902                break;
2903        case RTL871X_HOSTAPD_REMOVE_STA:
2904                ret = rtw_del_sta(dev, param);
2905                break;
2906        case RTL871X_HOSTAPD_SET_BEACON:
2907                ret = rtw_set_beacon(dev, param, p->length);
2908                break;
2909        case RTL871X_SET_ENCRYPTION:
2910                ret = rtw_set_encryption(dev, param, p->length);
2911                break;
2912        case RTL871X_HOSTAPD_GET_WPAIE_STA:
2913                ret = rtw_get_sta_wpaie(dev, param);
2914                break;
2915        case RTL871X_HOSTAPD_SET_WPS_BEACON:
2916                ret = rtw_set_wps_beacon(dev, param, p->length);
2917                break;
2918        case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
2919                ret = rtw_set_wps_probe_resp(dev, param, p->length);
2920                break;
2921        case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
2922                ret = rtw_set_wps_assoc_resp(dev, param, p->length);
2923                break;
2924        case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
2925                ret = rtw_set_hidden_ssid(dev, param, p->length);
2926                break;
2927        case RTL871X_HOSTAPD_GET_INFO_STA:
2928                ret = rtw_ioctl_get_sta_data(dev, param, p->length);
2929                break;
2930        case RTL871X_HOSTAPD_SET_MACADDR_ACL:
2931                ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
2932                break;
2933        case RTL871X_HOSTAPD_ACL_ADD_STA:
2934                ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
2935                break;
2936        case RTL871X_HOSTAPD_ACL_REMOVE_STA:
2937                ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
2938                break;
2939        default:
2940                DBG_88E("Unknown hostapd request: %d\n", param->cmd);
2941                ret = -EOPNOTSUPP;
2942                break;
2943        }
2944
2945        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2946                ret = -EFAULT;
2947        kfree(param);
2948out:
2949        return ret;
2950}
2951#endif
2952
2953#include <rtw_android.h>
2954static int rtw_wx_set_priv(struct net_device *dev,
2955                                struct iw_request_info *info,
2956                                union iwreq_data *awrq,
2957                                char *extra)
2958{
2959        int ret = 0;
2960        int len = 0;
2961        char *ext;
2962        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2963        struct iw_point *dwrq = (struct iw_point *)awrq;
2964
2965        if (dwrq->length == 0)
2966                return -EFAULT;
2967
2968        len = dwrq->length;
2969        ext = vmalloc(len);
2970        if (!ext)
2971                return -ENOMEM;
2972
2973        if (copy_from_user(ext, dwrq->pointer, len)) {
2974                vfree(ext);
2975                return -EFAULT;
2976        }
2977
2978        /* added for wps2.0 @20110524 */
2979        if (dwrq->flags == 0x8766 && len > 8) {
2980                u32 cp_sz;
2981                struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2982                u8 *probereq_wpsie = ext;
2983                int probereq_wpsie_len = len;
2984                u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
2985
2986                if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
2987                    (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
2988                        cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
2989
2990                        pmlmepriv->wps_probe_req_ie_len = 0;
2991                        kfree(pmlmepriv->wps_probe_req_ie);
2992                        pmlmepriv->wps_probe_req_ie = NULL;
2993
2994                        pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
2995                        if (pmlmepriv->wps_probe_req_ie == NULL) {
2996                                pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
2997                                ret =  -EINVAL;
2998                                goto FREE_EXT;
2999                        }
3000                        memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
3001                        pmlmepriv->wps_probe_req_ie_len = cp_sz;
3002                }
3003                goto FREE_EXT;
3004        }
3005
3006        if (len >= WEXT_CSCAN_HEADER_SIZE &&
3007            !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
3008                ret = rtw_wx_set_scan(dev, info, awrq, ext);
3009                goto FREE_EXT;
3010        }
3011
3012FREE_EXT:
3013
3014        vfree(ext);
3015
3016        return ret;
3017}
3018
3019static iw_handler rtw_handlers[] = {
3020        NULL,                                   /* SIOCSIWCOMMIT */
3021        rtw_wx_get_name,                /* SIOCGIWNAME */
3022        dummy,                                  /* SIOCSIWNWID */
3023        dummy,                                  /* SIOCGIWNWID */
3024        rtw_wx_set_freq,                /* SIOCSIWFREQ */
3025        rtw_wx_get_freq,                /* SIOCGIWFREQ */
3026        rtw_wx_set_mode,                /* SIOCSIWMODE */
3027        rtw_wx_get_mode,                /* SIOCGIWMODE */
3028        dummy,                                  /* SIOCSIWSENS */
3029        rtw_wx_get_sens,                /* SIOCGIWSENS */
3030        NULL,                                   /* SIOCSIWRANGE */
3031        rtw_wx_get_range,               /* SIOCGIWRANGE */
3032        rtw_wx_set_priv,                /* SIOCSIWPRIV */
3033        NULL,                                   /* SIOCGIWPRIV */
3034        NULL,                                   /* SIOCSIWSTATS */
3035        NULL,                                   /* SIOCGIWSTATS */
3036        dummy,                                  /* SIOCSIWSPY */
3037        dummy,                                  /* SIOCGIWSPY */
3038        NULL,                                   /* SIOCGIWTHRSPY */
3039        NULL,                                   /* SIOCWIWTHRSPY */
3040        rtw_wx_set_wap,         /* SIOCSIWAP */
3041        rtw_wx_get_wap,         /* SIOCGIWAP */
3042        rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
3043        dummy,                                  /* SIOCGIWAPLIST -- depricated */
3044        rtw_wx_set_scan,                /* SIOCSIWSCAN */
3045        rtw_wx_get_scan,                /* SIOCGIWSCAN */
3046        rtw_wx_set_essid,               /* SIOCSIWESSID */
3047        rtw_wx_get_essid,               /* SIOCGIWESSID */
3048        dummy,                                  /* SIOCSIWNICKN */
3049        rtw_wx_get_nick,                /* SIOCGIWNICKN */
3050        NULL,                                   /* -- hole -- */
3051        NULL,                                   /* -- hole -- */
3052        rtw_wx_set_rate,                /* SIOCSIWRATE */
3053        rtw_wx_get_rate,                /* SIOCGIWRATE */
3054        rtw_wx_set_rts,                 /* SIOCSIWRTS */
3055        rtw_wx_get_rts,                 /* SIOCGIWRTS */
3056        rtw_wx_set_frag,                /* SIOCSIWFRAG */
3057        rtw_wx_get_frag,                /* SIOCGIWFRAG */
3058        dummy,                                  /* SIOCSIWTXPOW */
3059        dummy,                                  /* SIOCGIWTXPOW */
3060        dummy,                                  /* SIOCSIWRETRY */
3061        rtw_wx_get_retry,               /* SIOCGIWRETRY */
3062        rtw_wx_set_enc,                 /* SIOCSIWENCODE */
3063        rtw_wx_get_enc,                 /* SIOCGIWENCODE */
3064        dummy,                                  /* SIOCSIWPOWER */
3065        rtw_wx_get_power,               /* SIOCGIWPOWER */
3066        NULL,                                   /*---hole---*/
3067        NULL,                                   /*---hole---*/
3068        rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
3069        NULL,                                   /* SIOCGWGENIE */
3070        rtw_wx_set_auth,                /* SIOCSIWAUTH */
3071        NULL,                                   /* SIOCGIWAUTH */
3072        rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
3073        NULL,                                   /* SIOCGIWENCODEEXT */
3074        rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
3075        NULL,                                   /*---hole---*/
3076};
3077
3078static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
3079{
3080        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3081        struct iw_statistics *piwstats = &padapter->iwstats;
3082        int tmp_level = 0;
3083        int tmp_qual = 0;
3084        int tmp_noise = 0;
3085
3086        if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3087                piwstats->qual.qual = 0;
3088                piwstats->qual.level = 0;
3089                piwstats->qual.noise = 0;
3090        } else {
3091                tmp_level = padapter->recvpriv.signal_strength;
3092                tmp_qual = padapter->recvpriv.signal_qual;
3093                tmp_noise = padapter->recvpriv.noise;
3094
3095                piwstats->qual.level = tmp_level;
3096                piwstats->qual.qual = tmp_qual;
3097                piwstats->qual.noise = tmp_noise;
3098        }
3099        piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
3100        return &padapter->iwstats;
3101}
3102
3103struct iw_handler_def rtw_handlers_def = {
3104        .standard = rtw_handlers,
3105        .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
3106        .get_wireless_stats = rtw_get_wireless_stats,
3107};
3108
3109#include <rtw_android.h>
3110int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3111{
3112        struct iwreq *wrq = (struct iwreq *)rq;
3113        int ret = 0;
3114
3115        switch (cmd) {
3116        case RTL_IOCTL_WPA_SUPPLICANT:
3117                ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
3118                break;
3119#ifdef CONFIG_88EU_AP_MODE
3120        case RTL_IOCTL_HOSTAPD:
3121                ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
3122                break;
3123#endif /*  CONFIG_88EU_AP_MODE */
3124        case (SIOCDEVPRIVATE+1):
3125                ret = rtw_android_priv_cmd(dev, rq, cmd);
3126                break;
3127        default:
3128                ret = -EOPNOTSUPP;
3129                break;
3130        }
3131        return ret;
3132}
3133