linux/drivers/staging/rtl8723bs/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
   8#include <linux/etherdevice.h>
   9#include <drv_types.h>
  10#include <rtw_debug.h>
  11#include <rtw_mp.h>
  12#include <hal_btcoex.h>
  13#include <linux/jiffies.h>
  14#include <linux/kernel.h>
  15
  16#define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV+30)
  17
  18#define SCAN_ITEM_SIZE 768
  19#define MAX_CUSTOM_LEN 64
  20#define RATE_COUNT 4
  21
  22/*  combo scan */
  23#define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
  24#define WEXT_CSCAN_HEADER_SIZE          12
  25#define WEXT_CSCAN_SSID_SECTION         'S'
  26#define WEXT_CSCAN_CHANNEL_SECTION      'C'
  27#define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
  28#define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
  29#define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
  30#define WEXT_CSCAN_TYPE_SECTION         'T'
  31
  32static int wpa_set_auth_algs(struct net_device *dev, u32 value)
  33{
  34        struct adapter *padapter = rtw_netdev_priv(dev);
  35        int ret = 0;
  36
  37        if ((value & IW_AUTH_ALG_SHARED_KEY) && (value & IW_AUTH_ALG_OPEN_SYSTEM)) {
  38                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
  39                padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
  40                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
  41        } else if (value & IW_AUTH_ALG_SHARED_KEY)      {
  42                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
  43
  44                padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
  45                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
  46        } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
  47                /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
  48                if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
  49                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
  50                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
  51                }
  52        } else {
  53                ret = -EINVAL;
  54        }
  55
  56        return ret;
  57
  58}
  59
  60static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
  61{
  62        int ret = 0;
  63        u32 wep_key_idx, wep_key_len, wep_total_len;
  64        struct ndis_802_11_wep   *pwep = NULL;
  65        struct adapter *padapter = rtw_netdev_priv(dev);
  66        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  67        struct security_priv *psecuritypriv = &padapter->securitypriv;
  68
  69        param->u.crypt.err = 0;
  70        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
  71
  72        if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
  73                ret =  -EINVAL;
  74                goto exit;
  75        }
  76
  77        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
  78            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
  79            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
  80                if (param->u.crypt.idx >= WEP_KEYS ||
  81                    param->u.crypt.idx >= BIP_MAX_KEYID) {
  82                        ret = -EINVAL;
  83                        goto exit;
  84                }
  85        } else {
  86                {
  87                        ret = -EINVAL;
  88                        goto exit;
  89                }
  90        }
  91
  92        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
  93
  94                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
  95                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
  96                padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
  97
  98                wep_key_idx = param->u.crypt.idx;
  99                wep_key_len = param->u.crypt.key_len;
 100
 101                if (wep_key_idx > WEP_KEYS)
 102                        return -EINVAL;
 103
 104                if (wep_key_len > 0) {
 105                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
 106                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
 107                        pwep = kzalloc(wep_total_len, GFP_KERNEL);
 108                        if (!pwep) {
 109                                ret = -ENOMEM;
 110                                goto exit;
 111                        }
 112
 113                        pwep->key_length = wep_key_len;
 114                        pwep->length = wep_total_len;
 115
 116                        if (wep_key_len == 13) {
 117                                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
 118                                padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
 119                        }
 120                } else {
 121                        ret = -EINVAL;
 122                        goto exit;
 123                }
 124
 125                pwep->key_index = wep_key_idx;
 126                pwep->key_index |= 0x80000000;
 127
 128                memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
 129
 130                if (param->u.crypt.set_tx) {
 131                        if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
 132                                ret = -EOPNOTSUPP;
 133                } else {
 134                        /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
 135                        /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to fw/cam */
 136
 137                        if (wep_key_idx >= WEP_KEYS) {
 138                                ret = -EOPNOTSUPP;
 139                                goto exit;
 140                        }
 141
 142                        memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
 143                        psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
 144                        rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
 145                }
 146
 147                goto exit;
 148        }
 149
 150        if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
 151                struct sta_info *psta, *pbcmc_sta;
 152                struct sta_priv *pstapriv = &padapter->stapriv;
 153
 154                if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
 155                        psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
 156                        if (psta == NULL) {
 157                                /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
 158                        } else {
 159                                /* Jeff: don't disable ieee8021x_blocked while clearing key */
 160                                if (strcmp(param->u.crypt.alg, "none") != 0)
 161                                        psta->ieee8021x_blocked = false;
 162
 163                                if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
 164                                                (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
 165                                        psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
 166                                }
 167
 168                                if (param->u.crypt.set_tx == 1) { /* pairwise key */
 169                                        memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 170
 171                                        if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
 172                                                /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
 173                                                memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
 174                                                memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
 175
 176                                                padapter->securitypriv.busetkipkey = false;
 177                                                /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
 178                                        }
 179
 180                                        rtw_setstakey_cmd(padapter, psta, true, true);
 181                                } else { /* group key */
 182                                        if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
 183                                                memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 184                                                /* only TKIP group key need to install this */
 185                                                if (param->u.crypt.key_len > 16) {
 186                                                        memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
 187                                                        memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
 188                                                }
 189                                                padapter->securitypriv.binstallGrpkey = true;
 190
 191                                                padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
 192
 193                                                rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
 194                                        } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
 195                                                /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
 196                                                /* save the IGTK key, length 16 bytes */
 197                                                memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 198                                                /*printk("IGTK key below:\n");
 199                                                for (no = 0;no<16;no++)
 200                                                        printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
 201                                                printk("\n");*/
 202                                                padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
 203                                                padapter->securitypriv.binstallBIPkey = true;
 204                                        }
 205                                }
 206                        }
 207
 208                        pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
 209                        if (pbcmc_sta == NULL) {
 210                                /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
 211                        } else {
 212                                /* Jeff: don't disable ieee8021x_blocked while clearing key */
 213                                if (strcmp(param->u.crypt.alg, "none") != 0)
 214                                        pbcmc_sta->ieee8021x_blocked = false;
 215
 216                                if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
 217                                                (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
 218                                        pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
 219                                }
 220                        }
 221                } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 222                        /* adhoc mode */
 223                }
 224        }
 225
 226exit:
 227
 228        kfree(pwep);
 229        return ret;
 230}
 231
 232static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
 233{
 234        u8 *buf = NULL;
 235        int group_cipher = 0, pairwise_cipher = 0;
 236        int ret = 0;
 237        u8 null_addr[] = {0, 0, 0, 0, 0, 0};
 238
 239        if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
 240                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
 241                if (pie == NULL)
 242                        return ret;
 243                else
 244                        return -EINVAL;
 245        }
 246
 247        if (ielen) {
 248                buf = rtw_zmalloc(ielen);
 249                if (buf == NULL) {
 250                        ret =  -ENOMEM;
 251                        goto exit;
 252                }
 253
 254                memcpy(buf, pie, ielen);
 255
 256                if (ielen < RSN_HEADER_LEN) {
 257                        ret  = -1;
 258                        goto exit;
 259                }
 260
 261                if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
 262                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 263                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
 264                        memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
 265                }
 266
 267                if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
 268                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 269                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
 270                        memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
 271                }
 272
 273                if (group_cipher == 0)
 274                        group_cipher = WPA_CIPHER_NONE;
 275                if (pairwise_cipher == 0)
 276                        pairwise_cipher = WPA_CIPHER_NONE;
 277
 278                switch (group_cipher) {
 279                case WPA_CIPHER_NONE:
 280                        padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
 281                        padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
 282                        break;
 283                case WPA_CIPHER_WEP40:
 284                        padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
 285                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 286                        break;
 287                case WPA_CIPHER_TKIP:
 288                        padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
 289                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
 290                        break;
 291                case WPA_CIPHER_CCMP:
 292                        padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
 293                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
 294                        break;
 295                case WPA_CIPHER_WEP104:
 296                        padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
 297                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 298                        break;
 299                }
 300
 301                switch (pairwise_cipher) {
 302                case WPA_CIPHER_NONE:
 303                        padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
 304                        padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
 305                        break;
 306                case WPA_CIPHER_WEP40:
 307                        padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
 308                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 309                        break;
 310                case WPA_CIPHER_TKIP:
 311                        padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
 312                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
 313                        break;
 314                case WPA_CIPHER_CCMP:
 315                        padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
 316                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
 317                        break;
 318                case WPA_CIPHER_WEP104:
 319                        padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
 320                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 321                        break;
 322                }
 323
 324                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
 325                {/* set wps_ie */
 326                        u16 cnt = 0;
 327                        u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
 328
 329                        while (cnt < ielen) {
 330                                eid = buf[cnt];
 331
 332                                if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
 333                                        padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < MAX_WPS_IE_LEN) ? (buf[cnt+1]+2):MAX_WPS_IE_LEN;
 334
 335                                        memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
 336
 337                                        set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
 338
 339                                        cnt += buf[cnt+1]+2;
 340
 341                                        break;
 342                                } else {
 343                                        cnt += buf[cnt+1]+2; /* goto next */
 344                                }
 345                        }
 346                }
 347        }
 348
 349        /* TKIP and AES disallow multicast packets until installing group key */
 350        if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ ||
 351                padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ ||
 352                padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
 353                /* WPS open need to enable multicast */
 354                /*  check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
 355                rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
 356
 357exit:
 358
 359        kfree(buf);
 360
 361        return ret;
 362}
 363
 364static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
 365{
 366        uint ret = 0;
 367        struct adapter *padapter = rtw_netdev_priv(dev);
 368
 369        switch (name) {
 370        case IEEE_PARAM_WPA_ENABLED:
 371
 372                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
 373
 374                /* ret = ieee80211_wpa_enable(ieee, value); */
 375
 376                switch ((value)&0xff) {
 377                case 1: /* WPA */
 378                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
 379                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
 380                        break;
 381                case 2: /* WPA2 */
 382                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
 383                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
 384                        break;
 385                }
 386
 387                break;
 388
 389        case IEEE_PARAM_TKIP_COUNTERMEASURES:
 390                /* ieee->tkip_countermeasures =value; */
 391                break;
 392
 393        case IEEE_PARAM_DROP_UNENCRYPTED:
 394        {
 395                /* HACK:
 396                 *
 397                 * wpa_supplicant calls set_wpa_enabled when the driver
 398                 * is loaded and unloaded, regardless of if WPA is being
 399                 * used.  No other calls are made which can be used to
 400                 * determine if encryption will be used or not prior to
 401                 * association being expected.  If encryption is not being
 402                 * used, drop_unencrypted is set to false, else true -- we
 403                 * can use this to determine if the CAP_PRIVACY_ON bit should
 404                 * be set.
 405                 */
 406                break;
 407
 408        }
 409        case IEEE_PARAM_PRIVACY_INVOKED:
 410
 411                /* ieee->privacy_invoked =value; */
 412
 413                break;
 414
 415        case IEEE_PARAM_AUTH_ALGS:
 416
 417                ret = wpa_set_auth_algs(dev, value);
 418
 419                break;
 420
 421        case IEEE_PARAM_IEEE_802_1X:
 422
 423                /* ieee->ieee802_1x =value; */
 424
 425                break;
 426
 427        case IEEE_PARAM_WPAX_SELECT:
 428
 429                /*  added for WPA2 mixed mode */
 430                /*
 431                spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
 432                ieee->wpax_type_set = 1;
 433                ieee->wpax_type_notify = value;
 434                spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
 435                */
 436
 437                break;
 438
 439        default:
 440
 441
 442
 443                ret = -EOPNOTSUPP;
 444
 445
 446                break;
 447
 448        }
 449
 450        return ret;
 451
 452}
 453
 454static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
 455{
 456        int ret = 0;
 457        struct adapter *padapter = rtw_netdev_priv(dev);
 458
 459        switch (command) {
 460        case IEEE_MLME_STA_DEAUTH:
 461
 462                if (!rtw_set_802_11_disassociate(padapter))
 463                        ret = -1;
 464
 465                break;
 466
 467        case IEEE_MLME_STA_DISASSOC:
 468
 469                if (!rtw_set_802_11_disassociate(padapter))
 470                        ret = -1;
 471
 472                break;
 473
 474        default:
 475                ret = -EOPNOTSUPP;
 476                break;
 477        }
 478
 479        return ret;
 480
 481}
 482
 483static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
 484{
 485        struct ieee_param *param;
 486        uint ret = 0;
 487
 488        /* down(&ieee->wx_sem); */
 489
 490        if (!p->pointer || p->length != sizeof(struct ieee_param))
 491                return -EINVAL;
 492
 493        param = rtw_malloc(p->length);
 494        if (param == NULL)
 495                return -ENOMEM;
 496
 497        if (copy_from_user(param, p->pointer, p->length)) {
 498                kfree(param);
 499                return -EFAULT;
 500        }
 501
 502        switch (param->cmd) {
 503
 504        case IEEE_CMD_SET_WPA_PARAM:
 505                ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
 506                break;
 507
 508        case IEEE_CMD_SET_WPA_IE:
 509                /* ret = wpa_set_wpa_ie(dev, param, p->length); */
 510                ret =  rtw_set_wpa_ie(rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
 511                break;
 512
 513        case IEEE_CMD_SET_ENCRYPTION:
 514                ret = wpa_set_encryption(dev, param, p->length);
 515                break;
 516
 517        case IEEE_CMD_MLME:
 518                ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
 519                break;
 520
 521        default:
 522                ret = -EOPNOTSUPP;
 523                break;
 524
 525        }
 526
 527        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
 528                ret = -EFAULT;
 529
 530        kfree(param);
 531
 532        /* up(&ieee->wx_sem); */
 533        return ret;
 534}
 535
 536static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
 537{
 538        int ret = 0;
 539        u32 wep_key_idx, wep_key_len, wep_total_len;
 540        struct ndis_802_11_wep   *pwep = NULL;
 541        struct sta_info *psta = NULL, *pbcmc_sta = NULL;
 542        struct adapter *padapter = rtw_netdev_priv(dev);
 543        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 544        struct security_priv *psecuritypriv = &(padapter->securitypriv);
 545        struct sta_priv *pstapriv = &padapter->stapriv;
 546        char *txkey = padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey;
 547        char *rxkey = padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey;
 548        char *grpkey = psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey;
 549
 550        param->u.crypt.err = 0;
 551        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
 552
 553        /* sizeof(struct ieee_param) = 64 bytes; */
 554        /* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
 555        if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
 556                ret =  -EINVAL;
 557                goto exit;
 558        }
 559
 560        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 561            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 562            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 563                if (param->u.crypt.idx >= WEP_KEYS) {
 564                        ret = -EINVAL;
 565                        goto exit;
 566                }
 567        } else {
 568                psta = rtw_get_stainfo(pstapriv, param->sta_addr);
 569                if (!psta)
 570                        /* ret = -EINVAL; */
 571                        goto exit;
 572        }
 573
 574        if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
 575                /* todo:clear default encryption keys */
 576
 577                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
 578                psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
 579                psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
 580                psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
 581
 582                goto exit;
 583        }
 584
 585
 586        if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
 587                wep_key_idx = param->u.crypt.idx;
 588                wep_key_len = param->u.crypt.key_len;
 589
 590                if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
 591                        ret = -EINVAL;
 592                        goto exit;
 593                }
 594
 595
 596                if (wep_key_len > 0) {
 597                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
 598                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
 599                        pwep = kzalloc(wep_total_len, GFP_KERNEL);
 600                        if (!pwep)
 601                                goto exit;
 602
 603                        pwep->key_length = wep_key_len;
 604                        pwep->length = wep_total_len;
 605
 606                }
 607
 608                pwep->key_index = wep_key_idx;
 609
 610                memcpy(pwep->key_material,  param->u.crypt.key, pwep->key_length);
 611
 612                if (param->u.crypt.set_tx) {
 613                        psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
 614                        psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
 615                        psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
 616                        psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
 617
 618                        if (pwep->key_length == 13) {
 619                                psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
 620                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
 621                        }
 622
 623
 624                        psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
 625
 626                        memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
 627
 628                        psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
 629
 630                        rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 1);
 631                } else {
 632                        /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
 633                        /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */
 634
 635                        memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
 636
 637                        psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
 638
 639                        rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 0);
 640                }
 641
 642                goto exit;
 643
 644        }
 645
 646
 647        if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
 648                if (param->u.crypt.set_tx == 1) {
 649                        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 650                                memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 651
 652                                psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
 653                                if (param->u.crypt.key_len == 13)
 654                                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
 655
 656                        } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
 657                                psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
 658
 659                                memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 660
 661                                /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
 662                                /* set mic key */
 663                                memcpy(txkey, &(param->u.crypt.key[16]), 8);
 664                                memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
 665
 666                                psecuritypriv->busetkipkey = true;
 667
 668                        }
 669                        else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
 670                                psecuritypriv->dot118021XGrpPrivacy = _AES_;
 671
 672                                memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 673                        } else {
 674                                psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
 675                        }
 676
 677                        psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
 678
 679                        psecuritypriv->binstallGrpkey = true;
 680
 681                        psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
 682
 683                        rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
 684
 685                        pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
 686                        if (pbcmc_sta) {
 687                                pbcmc_sta->ieee8021x_blocked = false;
 688                                pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
 689                        }
 690                }
 691
 692                goto exit;
 693
 694        }
 695
 696        if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
 697                if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
 698                        if (param->u.crypt.set_tx == 1) {
 699                                memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 700
 701                                if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 702                                        psta->dot118021XPrivacy = _WEP40_;
 703                                        if (param->u.crypt.key_len == 13)
 704                                                psta->dot118021XPrivacy = _WEP104_;
 705                                } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
 706                                        psta->dot118021XPrivacy = _TKIP_;
 707
 708                                        /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
 709                                        /* set mic key */
 710                                        memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
 711                                        memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
 712
 713                                        psecuritypriv->busetkipkey = true;
 714
 715                                } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
 716
 717                                        psta->dot118021XPrivacy = _AES_;
 718                                } else {
 719                                        psta->dot118021XPrivacy = _NO_PRIVACY_;
 720                                }
 721
 722                                rtw_ap_set_pairwise_key(padapter, psta);
 723
 724                                psta->ieee8021x_blocked = false;
 725
 726                        } else { /* group key??? */
 727                                if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 728                                        memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 729
 730                                        psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
 731                                        if (param->u.crypt.key_len == 13)
 732                                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
 733                                } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
 734                                        psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
 735
 736                                        memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 737
 738                                        /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
 739                                        /* set mic key */
 740                                        memcpy(txkey, &(param->u.crypt.key[16]), 8);
 741                                        memcpy(rxkey, &(param->u.crypt.key[24]), 8);
 742
 743                                        psecuritypriv->busetkipkey = true;
 744
 745                                } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
 746                                        psecuritypriv->dot118021XGrpPrivacy = _AES_;
 747
 748                                        memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
 749                                } else {
 750                                        psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
 751                                }
 752
 753                                psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
 754
 755                                psecuritypriv->binstallGrpkey = true;
 756
 757                                psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
 758
 759                                rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
 760
 761                                pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
 762                                if (pbcmc_sta) {
 763                                        pbcmc_sta->ieee8021x_blocked = false;
 764                                        pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
 765                                }
 766                        }
 767                }
 768        }
 769
 770exit:
 771        kfree(pwep);
 772
 773        return ret;
 774
 775}
 776
 777static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
 778{
 779        int ret = 0;
 780        struct adapter *padapter = rtw_netdev_priv(dev);
 781        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 782        struct sta_priv *pstapriv = &padapter->stapriv;
 783        unsigned char *pbuf = param->u.bcn_ie.buf;
 784
 785        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
 786                return -EINVAL;
 787
 788        memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
 789
 790        if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
 791                pstapriv->max_num_sta = NUM_STA;
 792
 793
 794        if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
 795                ret = 0;
 796        else
 797                ret = -EINVAL;
 798
 799
 800        return ret;
 801
 802}
 803
 804static void rtw_hostapd_sta_flush(struct net_device *dev)
 805{
 806        /* _irqL irqL; */
 807        /* struct list_head     *phead, *plist; */
 808        /* struct sta_info *psta = NULL; */
 809        struct adapter *padapter = rtw_netdev_priv(dev);
 810        /* struct sta_priv *pstapriv = &padapter->stapriv; */
 811
 812        flush_all_cam_entry(padapter);  /* clear CAM */
 813
 814        rtw_sta_flush(padapter);
 815}
 816
 817static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
 818{
 819        int ret = 0;
 820        struct sta_info *psta = NULL;
 821        struct adapter *padapter = rtw_netdev_priv(dev);
 822        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 823        struct sta_priv *pstapriv = &padapter->stapriv;
 824
 825        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
 826                return -EINVAL;
 827
 828        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 829            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 830            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 831                return -EINVAL;
 832        }
 833
 834/*
 835        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
 836        if (psta)
 837        {
 838                spin_lock_bh(&(pstapriv->sta_hash_lock));
 839                rtw_free_stainfo(padapter,  psta);
 840                spin_unlock_bh(&(pstapriv->sta_hash_lock));
 841
 842                psta = NULL;
 843        }
 844*/
 845        /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
 846        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
 847        if (psta) {
 848                int flags = param->u.add_sta.flags;
 849
 850                psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
 851
 852                memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
 853
 854
 855                /* check wmm cap. */
 856                if (WLAN_STA_WME&flags)
 857                        psta->qos_option = 1;
 858                else
 859                        psta->qos_option = 0;
 860
 861                if (pmlmepriv->qospriv.qos_option == 0)
 862                        psta->qos_option = 0;
 863
 864                /* chec 802.11n ht cap. */
 865                if (WLAN_STA_HT&flags) {
 866                        psta->htpriv.ht_option = true;
 867                        psta->qos_option = 1;
 868                        memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct ieee80211_ht_cap));
 869                } else {
 870                        psta->htpriv.ht_option = false;
 871                }
 872
 873                if (pmlmepriv->htpriv.ht_option == false)
 874                        psta->htpriv.ht_option = false;
 875
 876                update_sta_info_apmode(padapter, psta);
 877
 878
 879        } else {
 880                ret = -ENOMEM;
 881        }
 882
 883        return ret;
 884
 885}
 886
 887static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
 888{
 889        int ret = 0;
 890        struct sta_info *psta = NULL;
 891        struct adapter *padapter = rtw_netdev_priv(dev);
 892        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 893        struct sta_priv *pstapriv = &padapter->stapriv;
 894
 895        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
 896                return -EINVAL;
 897
 898        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 899            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 900            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 901                return -EINVAL;
 902        }
 903
 904        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
 905        if (psta) {
 906                u8 updated = false;
 907
 908                spin_lock_bh(&pstapriv->asoc_list_lock);
 909                if (list_empty(&psta->asoc_list) == false) {
 910                        list_del_init(&psta->asoc_list);
 911                        pstapriv->asoc_list_cnt--;
 912                        updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
 913
 914                }
 915                spin_unlock_bh(&pstapriv->asoc_list_lock);
 916
 917                associated_clients_update(padapter, updated);
 918
 919                psta = NULL;
 920
 921        }
 922
 923        return ret;
 924
 925}
 926
 927static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
 928{
 929        int ret = 0;
 930        struct sta_info *psta = NULL;
 931        struct adapter *padapter = rtw_netdev_priv(dev);
 932        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 933        struct sta_priv *pstapriv = &padapter->stapriv;
 934        struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
 935        struct sta_data *psta_data = (struct sta_data *)param_ex->data;
 936
 937        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
 938                return -EINVAL;
 939
 940        if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
 941            param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
 942            param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
 943                return -EINVAL;
 944        }
 945
 946        psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
 947        if (psta) {
 948                psta_data->aid = (u16)psta->aid;
 949                psta_data->capability = psta->capability;
 950                psta_data->flags = psta->flags;
 951
 952/*
 953                nonerp_set : BIT(0)
 954                no_short_slot_time_set : BIT(1)
 955                no_short_preamble_set : BIT(2)
 956                no_ht_gf_set : BIT(3)
 957                no_ht_set : BIT(4)
 958                ht_20mhz_set : BIT(5)
 959*/
 960
 961                psta_data->sta_set = ((psta->nonerp_set) |
 962                                                         (psta->no_short_slot_time_set << 1) |
 963                                                         (psta->no_short_preamble_set << 2) |
 964                                                         (psta->no_ht_gf_set << 3) |
 965                                                         (psta->no_ht_set << 4) |
 966                                                         (psta->ht_20mhz_set << 5));
 967
 968                psta_data->tx_supp_rates_len =  psta->bssratelen;
 969                memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
 970                memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
 971                psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
 972                psta_data->rx_bytes = psta->sta_stats.rx_bytes;
 973                psta_data->rx_drops = psta->sta_stats.rx_drops;
 974
 975                psta_data->tx_pkts = psta->sta_stats.tx_pkts;
 976                psta_data->tx_bytes = psta->sta_stats.tx_bytes;
 977                psta_data->tx_drops = psta->sta_stats.tx_drops;
 978
 979
 980        } else {
 981                ret = -1;
 982        }
 983
 984        return ret;
 985
 986}
 987
 988static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
 989{
 990        int ret = 0;
 991        struct sta_info *psta = NULL;
 992        struct adapter *padapter = rtw_netdev_priv(dev);
 993        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 994        struct sta_priv *pstapriv = &padapter->stapriv;
 995
 996        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
 997                return -EINVAL;
 998
 999        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1000            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1001            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1002                return -EINVAL;
1003        }
1004
1005        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
1006        if (psta) {
1007                if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC)) {
1008                        int wpa_ie_len;
1009                        int copy_len;
1010
1011                        wpa_ie_len = psta->wpa_ie[1];
1012
1013                        copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
1014
1015                        param->u.wpa_ie.len = copy_len;
1016
1017                        memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
1018                }
1019        } else {
1020                ret = -1;
1021        }
1022
1023        return ret;
1024
1025}
1026
1027static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
1028{
1029        int ret = 0;
1030        unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
1031        struct adapter *padapter = rtw_netdev_priv(dev);
1032        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1033        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1034        int ie_len;
1035
1036        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1037                return -EINVAL;
1038
1039        ie_len = len-12-2;/*  12 = param header, 2:no packed */
1040
1041
1042        kfree(pmlmepriv->wps_beacon_ie);
1043        pmlmepriv->wps_beacon_ie = NULL;
1044
1045        if (ie_len > 0) {
1046                pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
1047                pmlmepriv->wps_beacon_ie_len = ie_len;
1048                if (!pmlmepriv->wps_beacon_ie)
1049                        return -EINVAL;
1050
1051                memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
1052
1053                update_beacon(padapter, WLAN_EID_VENDOR_SPECIFIC, wps_oui, true);
1054
1055                pmlmeext->bstart_bss = true;
1056        }
1057
1058
1059        return ret;
1060
1061}
1062
1063static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
1064{
1065        int ret = 0;
1066        struct adapter *padapter = rtw_netdev_priv(dev);
1067        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1068        int ie_len;
1069
1070        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1071                return -EINVAL;
1072
1073        ie_len = len-12-2;/*  12 = param header, 2:no packed */
1074
1075
1076        kfree(pmlmepriv->wps_probe_resp_ie);
1077        pmlmepriv->wps_probe_resp_ie = NULL;
1078
1079        if (ie_len > 0) {
1080                pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
1081                pmlmepriv->wps_probe_resp_ie_len = ie_len;
1082                if (!pmlmepriv->wps_probe_resp_ie)
1083                        return -EINVAL;
1084
1085                memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
1086        }
1087
1088
1089        return ret;
1090
1091}
1092
1093static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
1094{
1095        int ret = 0;
1096        struct adapter *padapter = rtw_netdev_priv(dev);
1097        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1098        int ie_len;
1099
1100        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1101                return -EINVAL;
1102
1103        ie_len = len-12-2;/*  12 = param header, 2:no packed */
1104
1105
1106        kfree(pmlmepriv->wps_assoc_resp_ie);
1107        pmlmepriv->wps_assoc_resp_ie = NULL;
1108
1109        if (ie_len > 0) {
1110                pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
1111                pmlmepriv->wps_assoc_resp_ie_len = ie_len;
1112                if (!pmlmepriv->wps_assoc_resp_ie)
1113                        return -EINVAL;
1114
1115                memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
1116        }
1117
1118
1119        return ret;
1120
1121}
1122
1123static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
1124{
1125        int ret = 0;
1126        struct adapter *adapter = rtw_netdev_priv(dev);
1127        struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
1128        struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
1129        struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
1130        int ie_len;
1131        u8 *ssid_ie;
1132        char ssid[NDIS_802_11_LENGTH_SSID + 1];
1133        signed int ssid_len;
1134        u8 ignore_broadcast_ssid;
1135
1136        if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true)
1137                return -EPERM;
1138
1139        if (param->u.bcn_ie.reserved[0] != 0xea)
1140                return -EINVAL;
1141
1142        mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
1143
1144        ie_len = len-12-2;/*  12 = param header, 2:no packed */
1145        ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
1146
1147        if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
1148                struct wlan_bssid_ex *pbss_network = &mlmepriv->cur_network.network;
1149                struct wlan_bssid_ex *pbss_network_ext = &mlmeinfo->network;
1150
1151                memcpy(ssid, ssid_ie+2, ssid_len);
1152                ssid[ssid_len] = 0x0;
1153
1154                memcpy(pbss_network->ssid.ssid, (void *)ssid, ssid_len);
1155                pbss_network->ssid.ssid_length = ssid_len;
1156                memcpy(pbss_network_ext->ssid.ssid, (void *)ssid, ssid_len);
1157                pbss_network_ext->ssid.ssid_length = ssid_len;
1158        }
1159
1160        return ret;
1161}
1162
1163static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
1164{
1165        struct adapter *padapter = rtw_netdev_priv(dev);
1166        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1167
1168        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1169                return -EINVAL;
1170
1171        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1172            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1173            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1174                return -EINVAL;
1175        }
1176
1177        rtw_acl_remove_sta(padapter, param->sta_addr);
1178        return 0;
1179
1180}
1181
1182static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
1183{
1184        struct adapter *padapter = rtw_netdev_priv(dev);
1185        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1186
1187        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1188                return -EINVAL;
1189
1190        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
1191            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
1192            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
1193                return -EINVAL;
1194        }
1195
1196        return rtw_acl_add_sta(padapter, param->sta_addr);
1197
1198}
1199
1200static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
1201{
1202        int ret = 0;
1203        struct adapter *padapter = rtw_netdev_priv(dev);
1204        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1205
1206        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
1207                return -EINVAL;
1208
1209        rtw_set_macaddr_acl(padapter, param->u.mlme.command);
1210
1211        return ret;
1212}
1213
1214static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
1215{
1216        struct ieee_param *param;
1217        int ret = 0;
1218        struct adapter *padapter = rtw_netdev_priv(dev);
1219
1220        /*
1221        * this function is expect to call in master mode, which allows no power saving
1222        * so, we just check hw_init_completed
1223        */
1224
1225        if (!padapter->hw_init_completed)
1226                return -EPERM;
1227
1228        if (!p->pointer || p->length != sizeof(*param))
1229                return -EINVAL;
1230
1231        param = rtw_malloc(p->length);
1232        if (param == NULL)
1233                return -ENOMEM;
1234
1235        if (copy_from_user(param, p->pointer, p->length)) {
1236                kfree(param);
1237                return -EFAULT;
1238        }
1239
1240        switch (param->cmd) {
1241        case RTL871X_HOSTAPD_FLUSH:
1242
1243                rtw_hostapd_sta_flush(dev);
1244
1245                break;
1246
1247        case RTL871X_HOSTAPD_ADD_STA:
1248
1249                ret = rtw_add_sta(dev, param);
1250
1251                break;
1252
1253        case RTL871X_HOSTAPD_REMOVE_STA:
1254
1255                ret = rtw_del_sta(dev, param);
1256
1257                break;
1258
1259        case RTL871X_HOSTAPD_SET_BEACON:
1260
1261                ret = rtw_set_beacon(dev, param, p->length);
1262
1263                break;
1264
1265        case RTL871X_SET_ENCRYPTION:
1266
1267                ret = rtw_set_encryption(dev, param, p->length);
1268
1269                break;
1270
1271        case RTL871X_HOSTAPD_GET_WPAIE_STA:
1272
1273                ret = rtw_get_sta_wpaie(dev, param);
1274
1275                break;
1276
1277        case RTL871X_HOSTAPD_SET_WPS_BEACON:
1278
1279                ret = rtw_set_wps_beacon(dev, param, p->length);
1280
1281                break;
1282
1283        case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
1284
1285                ret = rtw_set_wps_probe_resp(dev, param, p->length);
1286
1287                break;
1288
1289        case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
1290
1291                ret = rtw_set_wps_assoc_resp(dev, param, p->length);
1292
1293                break;
1294
1295        case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
1296
1297                ret = rtw_set_hidden_ssid(dev, param, p->length);
1298
1299                break;
1300
1301        case RTL871X_HOSTAPD_GET_INFO_STA:
1302
1303                ret = rtw_ioctl_get_sta_data(dev, param, p->length);
1304
1305                break;
1306
1307        case RTL871X_HOSTAPD_SET_MACADDR_ACL:
1308
1309                ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
1310
1311                break;
1312
1313        case RTL871X_HOSTAPD_ACL_ADD_STA:
1314
1315                ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
1316
1317                break;
1318
1319        case RTL871X_HOSTAPD_ACL_REMOVE_STA:
1320
1321                ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
1322
1323                break;
1324
1325        default:
1326                ret = -EOPNOTSUPP;
1327                break;
1328
1329        }
1330
1331        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
1332                ret = -EFAULT;
1333
1334        kfree(param);
1335        return ret;
1336}
1337
1338/*  copy from net/wireless/wext.c end */
1339
1340int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1341{
1342        struct iwreq *wrq = (struct iwreq *)rq;
1343        int ret = 0;
1344
1345        switch (cmd) {
1346        case RTL_IOCTL_WPA_SUPPLICANT:
1347                ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
1348                break;
1349        case RTL_IOCTL_HOSTAPD:
1350                ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
1351                break;
1352        default:
1353                ret = -EOPNOTSUPP;
1354                break;
1355        }
1356
1357        return ret;
1358}
1359