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