linux/drivers/staging/vt6655/wpactl.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
   3 * All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along
  16 * with this program; if not, write to the Free Software Foundation, Inc.,
  17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18 *
  19 *
  20 * File: wpactl.c
  21 *
  22 * Purpose: handle wpa supplicant ioctl input/out functions
  23 *
  24 * Author: Lyndon Chen
  25 *
  26 * Date: Oct. 20, 2003
  27 *
  28 * Functions:
  29 *
  30 * Revision History:
  31 *
  32 */
  33
  34#include "wpactl.h"
  35#include "key.h"
  36#include "mac.h"
  37#include "device.h"
  38#include "wmgr.h"
  39#include "iocmd.h"
  40#include "iowpa.h"
  41#include "rf.h"
  42
  43/*---------------------  Static Definitions -------------------------*/
  44
  45#define VIAWGET_WPA_MAX_BUF_SIZE 1024
  46
  47static const int frequency_list[] = {
  48        2412, 2417, 2422, 2427, 2432, 2437, 2442,
  49        2447, 2452, 2457, 2462, 2467, 2472, 2484
  50};
  51/*---------------------  Static Classes  ----------------------------*/
  52
  53/*---------------------  Static Variables  --------------------------*/
  54//static int          msglevel                =MSG_LEVEL_DEBUG;
  55static int msglevel = MSG_LEVEL_INFO;
  56
  57/*---------------------  Static Functions  --------------------------*/
  58
  59/*---------------------  Export Variables  --------------------------*/
  60static void wpadev_setup(struct net_device *dev)
  61{
  62        dev->type               = ARPHRD_IEEE80211;
  63        dev->hard_header_len    = ETH_HLEN;
  64        dev->mtu                = 2048;
  65        dev->addr_len           = ETH_ALEN;
  66        dev->tx_queue_len       = 1000;
  67
  68        memset(dev->broadcast, 0xFF, ETH_ALEN);
  69
  70        dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
  71}
  72
  73/*
  74 * Description:
  75 *      register netdev for wpa supplicant daemon
  76 *
  77 * Parameters:
  78 *  In:
  79 *      pDevice             -
  80 *      enable              -
  81 *  Out:
  82 *
  83 * Return Value:
  84 *
  85 */
  86
  87static int wpa_init_wpadev(PSDevice pDevice)
  88{
  89        PSDevice wpadev_priv;
  90        struct net_device *dev = pDevice->dev;
  91        int ret = 0;
  92
  93        pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", wpadev_setup);
  94        if (pDevice->wpadev == NULL)
  95                return -ENOMEM;
  96
  97        wpadev_priv = netdev_priv(pDevice->wpadev);
  98        *wpadev_priv = *pDevice;
  99        memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, ETH_ALEN);
 100        pDevice->wpadev->base_addr = dev->base_addr;
 101        pDevice->wpadev->irq = dev->irq;
 102        pDevice->wpadev->mem_start = dev->mem_start;
 103        pDevice->wpadev->mem_end = dev->mem_end;
 104        ret = register_netdev(pDevice->wpadev);
 105        if (ret) {
 106                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n",
 107                        dev->name);
 108                free_netdev(pDevice->wpadev);
 109                return -1;
 110        }
 111
 112        if (pDevice->skb == NULL) {
 113                pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
 114                if (pDevice->skb == NULL)
 115                        return -ENOMEM;
 116        }
 117
 118        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n",
 119                dev->name, pDevice->wpadev->name);
 120
 121        return 0;
 122}
 123
 124/*
 125 * Description:
 126 *      unregister net_device (wpadev)
 127 *
 128 * Parameters:
 129 *  In:
 130 *      pDevice             -
 131 *  Out:
 132 *
 133 * Return Value:
 134 *
 135 */
 136
 137static int wpa_release_wpadev(PSDevice pDevice)
 138{
 139        if (pDevice->skb) {
 140                dev_kfree_skb(pDevice->skb);
 141                pDevice->skb = NULL;
 142        }
 143
 144        if (pDevice->wpadev) {
 145                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
 146                        pDevice->dev->name, pDevice->wpadev->name);
 147                unregister_netdev(pDevice->wpadev);
 148                free_netdev(pDevice->wpadev);
 149                pDevice->wpadev = NULL;
 150        }
 151
 152        return 0;
 153}
 154
 155/*
 156 * Description:
 157 *      Set enable/disable dev for wpa supplicant daemon
 158 *
 159 * Parameters:
 160 *  In:
 161 *      pDevice             -
 162 *      val                 -
 163 *  Out:
 164 *
 165 * Return Value:
 166 *
 167 */
 168
 169int wpa_set_wpadev(PSDevice pDevice, int val)
 170{
 171        if (val)
 172                return wpa_init_wpadev(pDevice);
 173        else
 174                return wpa_release_wpadev(pDevice);
 175}
 176
 177/*
 178 * Description:
 179 *      Set WPA algorithm & keys
 180 *
 181 * Parameters:
 182 *  In:
 183 *      pDevice -
 184 *      param -
 185 *  Out:
 186 *
 187 * Return Value:
 188 *
 189 */
 190
 191int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel)
 192{
 193        struct viawget_wpa_param *param = ctx;
 194        PSMgmtObject pMgmt = pDevice->pMgmt;
 195        unsigned long dwKeyIndex = 0;
 196        unsigned char abyKey[MAX_KEY_LEN];
 197        unsigned char abySeq[MAX_KEY_LEN];
 198        QWORD   KeyRSC;
 199//    NDIS_802_11_KEY_RSC KeyRSC;
 200        unsigned char byKeyDecMode = KEY_CTL_WEP;
 201        int ret = 0;
 202        int uu, ii;
 203
 204        if (param->u.wpa_key.alg_name > WPA_ALG_CCMP ||
 205            param->u.wpa_key.key_len >= MAX_KEY_LEN ||
 206            param->u.wpa_key.seq_len >= MAX_KEY_LEN)
 207                return -EINVAL;
 208
 209        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name);
 210        if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
 211                pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 212                pDevice->bEncryptionEnable = false;
 213                pDevice->byKeyIndex = 0;
 214                pDevice->bTransmitKey = false;
 215                KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset);
 216                for (uu = 0; uu < MAX_KEY_TABLE; uu++) {
 217                        MACvDisableKeyEntry(pDevice->PortOffset, uu);
 218                }
 219                return ret;
 220        }
 221
 222        //spin_unlock_irq(&pDevice->lock);
 223        if (param->u.wpa_key.key && fcpfkernel) {
 224                memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
 225        } else {
 226                spin_unlock_irq(&pDevice->lock);
 227                if (param->u.wpa_key.key &&
 228                    copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)) {
 229                        spin_lock_irq(&pDevice->lock);
 230                        return -EINVAL;
 231                }
 232                spin_lock_irq(&pDevice->lock);
 233        }
 234
 235        dwKeyIndex = (unsigned long)(param->u.wpa_key.key_index);
 236
 237        if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
 238                if (dwKeyIndex > 3) {
 239                        return -EINVAL;
 240                } else {
 241                        if (param->u.wpa_key.set_tx) {
 242                                pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
 243                                pDevice->bTransmitKey = true;
 244                                dwKeyIndex |= (1 << 31);
 245                        }
 246                        KeybSetDefaultKey(&(pDevice->sKey),
 247                                          dwKeyIndex & ~(BIT30 | USE_KEYRSC),
 248                                          param->u.wpa_key.key_len,
 249                                          NULL,
 250                                          abyKey,
 251                                          KEY_CTL_WEP,
 252                                          pDevice->PortOffset,
 253                                          pDevice->byLocalID);
 254
 255                }
 256                pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 257                pDevice->bEncryptionEnable = true;
 258                return ret;
 259        }
 260
 261        //spin_unlock_irq(&pDevice->lock);
 262        if (param->u.wpa_key.seq && fcpfkernel) {
 263                memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
 264        } else {
 265                spin_unlock_irq(&pDevice->lock);
 266                if (param->u.wpa_key.seq &&
 267                    copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)) {
 268                        spin_lock_irq(&pDevice->lock);
 269                        return -EINVAL;
 270                }
 271                spin_lock_irq(&pDevice->lock);
 272        }
 273
 274        if (param->u.wpa_key.seq_len > 0) {
 275                for (ii = 0; ii < param->u.wpa_key.seq_len; ii++) {
 276                        if (ii < 4)
 277                                LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8));
 278                        else
 279                                HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8));
 280                        //KeyRSC |= (abySeq[ii] << (ii * 8));
 281                }
 282                dwKeyIndex |= 1 << 29;
 283        }
 284
 285        if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) {
 286                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return  dwKeyIndex > 3\n");
 287                return -EINVAL;
 288        }
 289
 290        if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
 291                pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
 292        }
 293
 294        if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
 295                pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
 296        }
 297
 298        if (param->u.wpa_key.set_tx)
 299                dwKeyIndex |= (1 << 31);
 300
 301        if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
 302                byKeyDecMode = KEY_CTL_CCMP;
 303        else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
 304                byKeyDecMode = KEY_CTL_TKIP;
 305        else
 306                byKeyDecMode = KEY_CTL_WEP;
 307
 308        // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled
 309        if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
 310                if (param->u.wpa_key.key_len == MAX_KEY_LEN)
 311                        byKeyDecMode = KEY_CTL_TKIP;
 312                else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
 313                        byKeyDecMode = KEY_CTL_WEP;
 314                else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
 315                        byKeyDecMode = KEY_CTL_WEP;
 316        } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
 317                if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
 318                        byKeyDecMode = KEY_CTL_WEP;
 319                else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
 320                        byKeyDecMode = KEY_CTL_WEP;
 321        }
 322
 323        // Check TKIP key length
 324        if ((byKeyDecMode == KEY_CTL_TKIP) &&
 325            (param->u.wpa_key.key_len != MAX_KEY_LEN)) {
 326                // TKIP Key must be 256 bits
 327                //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n"));
 328                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n");
 329                return -EINVAL;
 330        }
 331        // Check AES key length
 332        if ((byKeyDecMode == KEY_CTL_CCMP) &&
 333            (param->u.wpa_key.key_len != AES_KEY_LEN)) {
 334                // AES Key must be 128 bits
 335                //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n"));
 336                return -EINVAL;
 337        }
 338
 339        // spin_lock_irq(&pDevice->lock);
 340        if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) {
 341                // If is_broadcast_ether_addr, set the key as every key entry's group key.
 342                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
 343
 344                if ((KeybSetAllGroupKey(&(pDevice->sKey),
 345                                        dwKeyIndex,
 346                                        param->u.wpa_key.key_len,
 347                                        (PQWORD) &(KeyRSC),
 348                                        (unsigned char *)abyKey,
 349                                        byKeyDecMode,
 350                                        pDevice->PortOffset,
 351                                        pDevice->byLocalID) == true) &&
 352                    (KeybSetDefaultKey(&(pDevice->sKey),
 353                                       dwKeyIndex,
 354                                       param->u.wpa_key.key_len,
 355                                       (PQWORD) &(KeyRSC),
 356                                       (unsigned char *)abyKey,
 357                                       byKeyDecMode,
 358                                       pDevice->PortOffset,
 359                                       pDevice->byLocalID) == true)) {
 360                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
 361
 362                } else {
 363                        //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n"));
 364                        // spin_unlock_irq(&pDevice->lock);
 365                        return -EINVAL;
 366                }
 367
 368        } else {
 369                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
 370                // BSSID not 0xffffffffffff
 371                // Pairwise Key can't be WEP
 372                if (byKeyDecMode == KEY_CTL_WEP) {
 373                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n");
 374                        //spin_unlock_irq(&pDevice->lock);
 375                        return -EINVAL;
 376                }
 377
 378                dwKeyIndex |= (1 << 30); // set pairwise key
 379                if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
 380                        //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n"));
 381                        //spin_unlock_irq(&pDevice->lock);
 382                        return -EINVAL;
 383                }
 384                if (KeybSetKey(&(pDevice->sKey),
 385                               &param->addr[0],
 386                               dwKeyIndex,
 387                               param->u.wpa_key.key_len,
 388                               (PQWORD) &(KeyRSC),
 389                               (unsigned char *)abyKey,
 390                               byKeyDecMode,
 391                               pDevice->PortOffset,
 392                               pDevice->byLocalID) == true) {
 393                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
 394
 395                } else {
 396                        // Key Table Full
 397                        if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
 398                                //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
 399                                //spin_unlock_irq(&pDevice->lock);
 400                                return -EINVAL;
 401
 402                        } else {
 403                                // Save Key and configure just before associate/reassociate to BSSID
 404                                // we do not implement now
 405                                //spin_unlock_irq(&pDevice->lock);
 406                                return -EINVAL;
 407                        }
 408                }
 409        } // BSSID not 0xffffffffffff
 410        if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
 411                pDevice->byKeyIndex = (unsigned char)param->u.wpa_key.key_index;
 412                pDevice->bTransmitKey = true;
 413        }
 414        pDevice->bEncryptionEnable = true;
 415        //spin_unlock_irq(&pDevice->lock);
 416
 417/*
 418  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
 419  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0],
 420  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1],
 421  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2],
 422  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3],
 423  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4]
 424);
 425*/
 426
 427        return ret;
 428}
 429
 430/*
 431 * Description:
 432 *      enable wpa auth & mode
 433 *
 434 * Parameters:
 435 *  In:
 436 *      pDevice   -
 437 *      param     -
 438 *  Out:
 439 *
 440 * Return Value:
 441 *
 442 */
 443
 444static int wpa_set_wpa(PSDevice pDevice,
 445                       struct viawget_wpa_param *param)
 446{
 447        PSMgmtObject    pMgmt = pDevice->pMgmt;
 448        int ret = 0;
 449
 450        pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
 451        pMgmt->bShareKeyAlgorithm = false;
 452
 453        return ret;
 454}
 455
 456/*
 457 * Description:
 458 *      set disassociate
 459 *
 460 * Parameters:
 461 *  In:
 462 *      pDevice   -
 463 *      param     -
 464 *  Out:
 465 *
 466 * Return Value:
 467 *
 468 */
 469
 470static int wpa_set_disassociate(PSDevice pDevice,
 471                                struct viawget_wpa_param *param)
 472{
 473        PSMgmtObject    pMgmt = pDevice->pMgmt;
 474        int ret = 0;
 475
 476        spin_lock_irq(&pDevice->lock);
 477        if (pDevice->bLinkPass) {
 478                if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6))
 479                        bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
 480        }
 481        spin_unlock_irq(&pDevice->lock);
 482
 483        return ret;
 484}
 485
 486/*
 487 * Description:
 488 *      enable scan process
 489 *
 490 * Parameters:
 491 *  In:
 492 *      pDevice   -
 493 *      param     -
 494 *  Out:
 495 *
 496 * Return Value:
 497 *
 498 */
 499
 500static int wpa_set_scan(PSDevice pDevice,
 501                        struct viawget_wpa_param *param)
 502{
 503        int ret = 0;
 504
 505        spin_lock_irq(&pDevice->lock);
 506        BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
 507        bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 508        spin_unlock_irq(&pDevice->lock);
 509
 510        return ret;
 511}
 512
 513/*
 514 * Description:
 515 *      get bssid
 516 *
 517 * Parameters:
 518 *  In:
 519 *      pDevice   -
 520 *      param     -
 521 *  Out:
 522 *
 523 * Return Value:
 524 *
 525 */
 526
 527static int wpa_get_bssid(PSDevice pDevice,
 528                         struct viawget_wpa_param *param)
 529{
 530        PSMgmtObject        pMgmt = pDevice->pMgmt;
 531        int ret = 0;
 532
 533        memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6);
 534
 535        return ret;
 536}
 537
 538/*
 539 * Description:
 540 *      get bssid
 541 *
 542 * Parameters:
 543 *  In:
 544 *      pDevice   -
 545 *      param     -
 546 *  Out:
 547 *
 548 * Return Value:
 549 *
 550 */
 551
 552static int wpa_get_ssid(PSDevice pDevice,
 553                        struct viawget_wpa_param *param)
 554{
 555        PSMgmtObject        pMgmt = pDevice->pMgmt;
 556        PWLAN_IE_SSID       pItemSSID;
 557        int ret = 0;
 558
 559        pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
 560
 561        memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len);
 562        param->u.wpa_associate.ssid_len = pItemSSID->len;
 563
 564        return ret;
 565}
 566
 567/*
 568 * Description:
 569 *      get scan results
 570 *
 571 * Parameters:
 572 *  In:
 573 *      pDevice   -
 574 *      param     -
 575 *  Out:
 576 *
 577 * Return Value:
 578 *
 579 */
 580
 581static int wpa_get_scan(PSDevice pDevice,
 582                        struct viawget_wpa_param *param)
 583{
 584        struct viawget_scan_result *scan_buf;
 585        PSMgmtObject    pMgmt = pDevice->pMgmt;
 586        PWLAN_IE_SSID   pItemSSID;
 587        PKnownBSS pBSS;
 588        unsigned char *pBuf;
 589        int ret = 0;
 590        u16 count = 0;
 591        u16 ii, jj;
 592#if 1
 593
 594        unsigned char *ptempBSS;
 595
 596        ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC);
 597
 598        if (ptempBSS == NULL) {
 599                printk("bubble sort kmalloc memory fail@@@\n");
 600
 601                ret = -ENOMEM;
 602
 603                return ret;
 604
 605        }
 606
 607        for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 608                for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) {
 609                        if ((pMgmt->sBSSList[jj].bActive != true) ||
 610
 611                            ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI) && (pMgmt->sBSSList[jj + 1].bActive != false))) {
 612                                memcpy(ptempBSS, &pMgmt->sBSSList[jj], sizeof(KnownBSS));
 613
 614                                memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1], sizeof(KnownBSS));
 615
 616                                memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS));
 617
 618                        }
 619
 620                }
 621
 622        }
 623
 624        kfree(ptempBSS);
 625#endif
 626
 627//******mike:bubble sort by stronger RSSI*****//
 628
 629        count = 0;
 630        pBSS = &(pMgmt->sBSSList[0]);
 631        for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 632                pBSS = &(pMgmt->sBSSList[ii]);
 633                if (!pBSS->bActive)
 634                        continue;
 635                count++;
 636        }
 637
 638        pBuf = kcalloc(count, sizeof(struct viawget_scan_result), (int)GFP_ATOMIC);
 639
 640        if (pBuf == NULL) {
 641                ret = -ENOMEM;
 642                return ret;
 643        }
 644        scan_buf = (struct viawget_scan_result *)pBuf;
 645        pBSS = &(pMgmt->sBSSList[0]);
 646        for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) {
 647                pBSS = &(pMgmt->sBSSList[ii]);
 648                if (pBSS->bActive) {
 649                        if (jj >= count)
 650                                break;
 651                        memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN);
 652                        pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
 653                        memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len);
 654                        scan_buf->ssid_len = pItemSSID->len;
 655                        scan_buf->freq = frequency_list[pBSS->uChannel-1];
 656                        scan_buf->caps = pBSS->wCapInfo;
 657                        //scan_buf->caps = pBSS->wCapInfo;
 658                        //scan_buf->qual =
 659                        //scan_buf->noise =
 660                        //scan_buf->level =
 661                        //scan_buf->maxrate =
 662                        if (pBSS->wWPALen != 0) {
 663                                scan_buf->wpa_ie_len = pBSS->wWPALen;
 664                                memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen);
 665                        }
 666                        if (pBSS->wRSNLen != 0) {
 667                                scan_buf->rsn_ie_len = pBSS->wRSNLen;
 668                                memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen);
 669                        }
 670                        scan_buf = (struct viawget_scan_result *)((unsigned char *)scan_buf + sizeof(struct viawget_scan_result));
 671                        jj++;
 672                }
 673        }
 674
 675        if (jj < count)
 676                count = jj;
 677
 678        if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) {
 679                ret = -EFAULT;
 680        }
 681        param->u.scan_results.scan_count = count;
 682        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count)
 683
 684                kfree(pBuf);
 685        return ret;
 686}
 687
 688/*
 689 * Description:
 690 *      set associate with AP
 691 *
 692 * Parameters:
 693 *  In:
 694 *      pDevice   -
 695 *      param     -
 696 *  Out:
 697 *
 698 * Return Value:
 699 *
 700 */
 701
 702static int wpa_set_associate(PSDevice pDevice,
 703                             struct viawget_wpa_param *param)
 704{
 705        PSMgmtObject    pMgmt = pDevice->pMgmt;
 706        PWLAN_IE_SSID   pItemSSID;
 707        unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 708        unsigned char abyWPAIE[64];
 709        int ret = 0;
 710        bool bWepEnabled = false;
 711
 712        // set key type & algorithm
 713        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite);
 714        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite);
 715        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite);
 716        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg);
 717        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode);
 718        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
 719
 720        if (param->u.wpa_associate.wpa_ie_len) {
 721                if (!param->u.wpa_associate.wpa_ie)
 722                        return -EINVAL;
 723                if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
 724                        return -EINVAL;
 725                if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
 726                        return -EFAULT;
 727        }
 728
 729        if (param->u.wpa_associate.mode == 1)
 730                pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
 731        else
 732                pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
 733        // set ssid
 734        memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
 735        pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
 736        pItemSSID->byElementID = WLAN_EID_SSID;
 737        pItemSSID->len = param->u.wpa_associate.ssid_len;
 738        memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len);
 739        // set bssid
 740        if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0)
 741                memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6);
 742        else {
 743                bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID);
 744        }
 745
 746        if (param->u.wpa_associate.wpa_ie_len == 0) {
 747                if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY)
 748                        pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
 749                else
 750                        pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
 751        } else if (abyWPAIE[0] == RSN_INFO_ELEM) {
 752                if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
 753                        pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
 754                else
 755                        pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
 756        } else {
 757                if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE)
 758                        pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
 759                else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
 760                        pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
 761                else
 762                        pMgmt->eAuthenMode = WMAC_AUTH_WPA;
 763        }
 764
 765        switch (param->u.wpa_associate.pairwise_suite) {
 766        case CIPHER_CCMP:
 767                pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
 768                break;
 769        case CIPHER_TKIP:
 770                pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
 771                break;
 772        case CIPHER_WEP40:
 773        case CIPHER_WEP104:
 774                pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 775                bWepEnabled = true;
 776                break;
 777        case CIPHER_NONE:
 778                if (param->u.wpa_associate.group_suite == CIPHER_CCMP)
 779                        pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
 780                else
 781                        pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
 782                break;
 783        default:
 784                pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 785        }
 786
 787//DavidWang add for WPA_supplicant support open/share mode
 788
 789        if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) {
 790                pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 791                //pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
 792                pMgmt->bShareKeyAlgorithm = true;
 793        } else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) {
 794                if (!bWepEnabled)  pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 795                else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 796                //pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
 797                //pMgmt->bShareKeyAlgorithm = false; //20080717-06,<Modify> by chester//Fix Open mode, WEP encryption
 798        }
 799//mike save old encryption status
 800        pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus;
 801
 802        if (pDevice->eEncryptionStatus !=  Ndis802_11EncryptionDisabled)
 803                pDevice->bEncryptionEnable = true;
 804        else
 805                pDevice->bEncryptionEnable = false;
 806        if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) ||
 807              ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled == true))))  //DavidWang  //20080717-06,<Modify> by chester//Not to initial WEP
 808                KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
 809        spin_lock_irq(&pDevice->lock);
 810        pDevice->bLinkPass = false;
 811        memset(pMgmt->abyCurrBSSID, 0, 6);
 812        pMgmt->eCurrState = WMAC_STATE_IDLE;
 813        netif_stop_queue(pDevice->dev);
 814        //20080701-02,<Add> by Mike Liu
 815/*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/
 816        {
 817                PKnownBSS       pCurr = NULL;
 818                pCurr = BSSpSearchBSSList(pDevice,
 819                                          pMgmt->abyDesireBSSID,
 820                                          pMgmt->abyDesireSSID,
 821                                          pMgmt->eConfigPHYMode
 822);
 823
 824                if (pCurr == NULL) {
 825                        printk("wpa_set_associate---->hidden mode site survey before associate.......\n");
 826                        bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
 827                }
 828        }
 829/****************************************************************/
 830        bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
 831        spin_unlock_irq(&pDevice->lock);
 832
 833        return ret;
 834}
 835
 836/*
 837 * Description:
 838 *      wpa_ioctl main function supported for wpa supplicant
 839 *
 840 * Parameters:
 841 *  In:
 842 *      pDevice   -
 843 *      iw_point  -
 844 *  Out:
 845 *
 846 * Return Value:
 847 *
 848 */
 849
 850int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
 851{
 852        struct viawget_wpa_param *param;
 853        int ret = 0;
 854        int wpa_ioctl = 0;
 855
 856        if (p->length < sizeof(struct viawget_wpa_param) ||
 857            p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer)
 858                return -EINVAL;
 859
 860        param = kmalloc((int)p->length, (int)GFP_KERNEL);
 861        if (param == NULL)
 862                return -ENOMEM;
 863
 864        if (copy_from_user(param, p->pointer, p->length)) {
 865                ret = -EFAULT;
 866                goto out;
 867        }
 868
 869        switch (param->cmd) {
 870        case VIAWGET_SET_WPA:
 871                ret = wpa_set_wpa(pDevice, param);
 872                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n");
 873                break;
 874
 875        case VIAWGET_SET_KEY:
 876                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n");
 877                spin_lock_irq(&pDevice->lock);
 878                ret = wpa_set_keys(pDevice, param, false);
 879                spin_unlock_irq(&pDevice->lock);
 880                break;
 881
 882        case VIAWGET_SET_SCAN:
 883                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n");
 884                ret = wpa_set_scan(pDevice, param);
 885                break;
 886
 887        case VIAWGET_GET_SCAN:
 888                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n");
 889                ret = wpa_get_scan(pDevice, param);
 890                wpa_ioctl = 1;
 891                break;
 892
 893        case VIAWGET_GET_SSID:
 894                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n");
 895                ret = wpa_get_ssid(pDevice, param);
 896                wpa_ioctl = 1;
 897                break;
 898
 899        case VIAWGET_GET_BSSID:
 900                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n");
 901                ret = wpa_get_bssid(pDevice, param);
 902                wpa_ioctl = 1;
 903                break;
 904
 905        case VIAWGET_SET_ASSOCIATE:
 906                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n");
 907                ret = wpa_set_associate(pDevice, param);
 908                break;
 909
 910        case VIAWGET_SET_DISASSOCIATE:
 911                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n");
 912                ret = wpa_set_disassociate(pDevice, param);
 913                break;
 914
 915        case VIAWGET_SET_DROP_UNENCRYPT:
 916                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n");
 917                break;
 918
 919        case VIAWGET_SET_DEAUTHENTICATE:
 920                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n");
 921                break;
 922
 923        default:
 924                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n",
 925                        param->cmd);
 926                return -EOPNOTSUPP;
 927                break;
 928        }
 929
 930        if ((ret == 0) && wpa_ioctl) {
 931                if (copy_to_user(p->pointer, param, p->length)) {
 932                        ret = -EFAULT;
 933                        goto out;
 934                }
 935        }
 936
 937out:
 938        kfree(param);
 939
 940        return ret;
 941}
 942