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