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