linux/drivers/staging/vt6655/hostap.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 * File: hostap.c
  20 *
  21 * Purpose: handle hostap deamon ioctl input/out functions
  22 *
  23 * Author: Lyndon Chen
  24 *
  25 * Date: Oct. 20, 2003
  26 *
  27 * Functions:
  28 *
  29 * Revision History:
  30 *
  31 */
  32
  33#include "hostap.h"
  34#include "iocmd.h"
  35#include "mac.h"
  36#include "card.h"
  37#include "baseband.h"
  38#include "wpactl.h"
  39#include "key.h"
  40
  41#define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024
  42#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT0
  43#define HOSTAP_CRYPT_FLAG_PERMANENT BIT1
  44#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
  45#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
  46#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
  47#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
  48#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
  49#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
  50
  51
  52/*---------------------  Static Definitions -------------------------*/
  53
  54/*---------------------  Static Classes  ----------------------------*/
  55
  56/*---------------------  Static Variables  --------------------------*/
  57//static int          msglevel                =MSG_LEVEL_DEBUG;
  58static int          msglevel                =MSG_LEVEL_INFO;
  59
  60/*---------------------  Static Functions  --------------------------*/
  61
  62
  63
  64
  65/*---------------------  Export Variables  --------------------------*/
  66
  67
  68/*
  69 * Description:
  70 *      register net_device (AP) for hostap deamon
  71 *
  72 * Parameters:
  73 *  In:
  74 *      pDevice             -
  75 *      rtnl_locked         -
  76 *  Out:
  77 *
  78 * Return Value:
  79 *
  80 */
  81
  82static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked)
  83{
  84    PSDevice apdev_priv;
  85        struct net_device *dev = pDevice->dev;
  86        int ret;
  87        const struct net_device_ops apdev_netdev_ops = {
  88                .ndo_start_xmit         = pDevice->tx_80211,
  89        };
  90
  91    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name);
  92
  93        pDevice->apdev = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
  94        if (pDevice->apdev == NULL)
  95                return -ENOMEM;
  96        memset(pDevice->apdev, 0, sizeof(struct net_device));
  97
  98    apdev_priv = netdev_priv(pDevice->apdev);
  99    *apdev_priv = *pDevice;
 100        memcpy(pDevice->apdev->dev_addr, dev->dev_addr, ETH_ALEN);
 101
 102        pDevice->apdev->netdev_ops = &apdev_netdev_ops;
 103
 104        pDevice->apdev->type = ARPHRD_IEEE80211;
 105
 106        pDevice->apdev->base_addr = dev->base_addr;
 107        pDevice->apdev->irq = dev->irq;
 108        pDevice->apdev->mem_start = dev->mem_start;
 109        pDevice->apdev->mem_end = dev->mem_end;
 110        sprintf(pDevice->apdev->name, "%sap", dev->name);
 111        if (rtnl_locked)
 112                ret = register_netdevice(pDevice->apdev);
 113        else
 114                ret = register_netdev(pDevice->apdev);
 115        if (ret) {
 116                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(AP) failed!\n",
 117                       dev->name);
 118                return -1;
 119        }
 120
 121    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n",
 122               dev->name, pDevice->apdev->name);
 123
 124    KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
 125
 126        return 0;
 127}
 128
 129/*
 130 * Description:
 131 *      unregister net_device(AP)
 132 *
 133 * Parameters:
 134 *  In:
 135 *      pDevice             -
 136 *      rtnl_locked         -
 137 *  Out:
 138 *
 139 * Return Value:
 140 *
 141 */
 142
 143static int hostap_disable_hostapd(PSDevice pDevice, int rtnl_locked)
 144{
 145
 146    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: disabling hostapd mode\n", pDevice->dev->name);
 147
 148    if (pDevice->apdev && pDevice->apdev->name && pDevice->apdev->name[0]) {
 149                if (rtnl_locked)
 150                        unregister_netdevice(pDevice->apdev);
 151                else
 152                        unregister_netdev(pDevice->apdev);
 153            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
 154                       pDevice->dev->name, pDevice->apdev->name);
 155        }
 156        kfree(pDevice->apdev);
 157        pDevice->apdev = NULL;
 158    pDevice->bEnable8021x = FALSE;
 159    pDevice->bEnableHostWEP = FALSE;
 160    pDevice->bEncryptionEnable = FALSE;
 161
 162//4.2007-0118-03,<Add> by EinsnLiu
 163//execute some clear work
 164pDevice->pMgmt->byCSSPK=KEY_CTL_NONE;
 165pDevice->pMgmt->byCSSGK=KEY_CTL_NONE;
 166KeyvInitTable(&pDevice->sKey,pDevice->PortOffset);
 167
 168        return 0;
 169}
 170
 171
 172/*
 173 * Description:
 174 *      Set enable/disable hostapd mode
 175 *
 176 * Parameters:
 177 *  In:
 178 *      pDevice             -
 179 *      rtnl_locked         -
 180 *  Out:
 181 *
 182 * Return Value:
 183 *
 184 */
 185
 186int hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked)
 187{
 188        if (val < 0 || val > 1)
 189                return -EINVAL;
 190
 191        if (pDevice->bEnableHostapd == val)
 192                return 0;
 193
 194        pDevice->bEnableHostapd = val;
 195
 196        if (val)
 197                return hostap_enable_hostapd(pDevice, rtnl_locked);
 198        else
 199                return hostap_disable_hostapd(pDevice, rtnl_locked);
 200}
 201
 202
 203/*
 204 * Description:
 205 *      remove station function supported for hostap deamon
 206 *
 207 * Parameters:
 208 *  In:
 209 *      pDevice   -
 210 *      param     -
 211 *  Out:
 212 *
 213 * Return Value:
 214 *
 215 */
 216static int hostap_remove_sta(PSDevice pDevice,
 217                                     struct viawget_hostapd_param *param)
 218{
 219        UINT uNodeIndex;
 220
 221
 222    if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, param->sta_addr, &uNodeIndex)) {
 223        BSSvRemoveOneNode(pDevice, uNodeIndex);
 224    }
 225    else {
 226        return -ENOENT;
 227    }
 228        return 0;
 229}
 230
 231/*
 232 * Description:
 233 *      add a station from hostap deamon
 234 *
 235 * Parameters:
 236 *  In:
 237 *      pDevice   -
 238 *      param     -
 239 *  Out:
 240 *
 241 * Return Value:
 242 *
 243 */
 244static int hostap_add_sta(PSDevice pDevice,
 245                                  struct viawget_hostapd_param *param)
 246{
 247    PSMgmtObject    pMgmt = pDevice->pMgmt;
 248        UINT uNodeIndex;
 249
 250
 251    if (!BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
 252        BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex);
 253    }
 254    memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, param->sta_addr, WLAN_ADDR_LEN);
 255    pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
 256    pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = param->u.add_sta.capability;
 257// TODO listenInterval
 258//    pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = 1;
 259    pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = FALSE;
 260    pMgmt->sNodeDBTable[uNodeIndex].bySuppRate = param->u.add_sta.tx_supp_rates;
 261
 262    // set max tx rate
 263    pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
 264           pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
 265    // set max basic rate
 266    pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate = RATE_2M;
 267    // Todo: check sta preamble, if ap can't support, set status code
 268    pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
 269            WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo);
 270
 271    pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)param->u.add_sta.aid;
 272
 273    pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies;
 274
 275    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Add STA AID= %d \n", pMgmt->sNodeDBTable[uNodeIndex].wAID);
 276    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n",
 277               param->sta_addr[0],
 278               param->sta_addr[1],
 279               param->sta_addr[2],
 280               param->sta_addr[3],
 281               param->sta_addr[4],
 282               param->sta_addr[5]
 283              ) ;
 284    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Max Support rate = %d \n",
 285               pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
 286
 287        return 0;
 288}
 289
 290/*
 291 * Description:
 292 *      get station info
 293 *
 294 * Parameters:
 295 *  In:
 296 *      pDevice   -
 297 *      param     -
 298 *  Out:
 299 *
 300 * Return Value:
 301 *
 302 */
 303
 304static int hostap_get_info_sta(PSDevice pDevice,
 305                                       struct viawget_hostapd_param *param)
 306{
 307    PSMgmtObject    pMgmt = pDevice->pMgmt;
 308        UINT uNodeIndex;
 309
 310    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
 311            param->u.get_info_sta.inactive_sec =
 312                (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ;
 313
 314            //param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts;
 315        }
 316        else {
 317            return -ENOENT;
 318        }
 319
 320        return 0;
 321}
 322
 323/*
 324 * Description:
 325 *      reset txexec
 326 *
 327 * Parameters:
 328 *  In:
 329 *      pDevice   -
 330 *      param     -
 331 *  Out:
 332 *      TURE, FALSE
 333 *
 334 * Return Value:
 335 *
 336 */
 337/*
 338static int hostap_reset_txexc_sta(PSDevice pDevice,
 339                                          struct viawget_hostapd_param *param)
 340{
 341    PSMgmtObject    pMgmt = pDevice->pMgmt;
 342        UINT uNodeIndex;
 343
 344    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
 345        pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts = 0;
 346        }
 347        else {
 348            return -ENOENT;
 349        }
 350
 351        return 0;
 352}
 353*/
 354
 355/*
 356 * Description:
 357 *      set station flag
 358 *
 359 * Parameters:
 360 *  In:
 361 *      pDevice   -
 362 *      param     -
 363 *  Out:
 364 *
 365 * Return Value:
 366 *
 367 */
 368static int hostap_set_flags_sta(PSDevice pDevice,
 369                                        struct viawget_hostapd_param *param)
 370{
 371    PSMgmtObject    pMgmt = pDevice->pMgmt;
 372        UINT uNodeIndex;
 373
 374    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
 375                pMgmt->sNodeDBTable[uNodeIndex].dwFlags |= param->u.set_flags_sta.flags_or;
 376                pMgmt->sNodeDBTable[uNodeIndex].dwFlags &= param->u.set_flags_sta.flags_and;
 377                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x \n",
 378                            (UINT)pMgmt->sNodeDBTable[uNodeIndex].dwFlags);
 379        }
 380        else {
 381            return -ENOENT;
 382        }
 383
 384        return 0;
 385}
 386
 387
 388
 389/*
 390 * Description:
 391 *      set generic element (wpa ie)
 392 *
 393 * Parameters:
 394 *  In:
 395 *      pDevice   -
 396 *      param     -
 397 *  Out:
 398 *
 399 * Return Value:
 400 *
 401 */
 402static int hostap_set_generic_element(PSDevice pDevice,
 403                                        struct viawget_hostapd_param *param)
 404{
 405    PSMgmtObject    pMgmt = pDevice->pMgmt;
 406
 407
 408
 409    memcpy( pMgmt->abyWPAIE,
 410            param->u.generic_elem.data,
 411            param->u.generic_elem.len
 412           );
 413
 414    pMgmt->wWPAIELen =  param->u.generic_elem.len;
 415
 416    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->wWPAIELen = %d\n",  pMgmt->wWPAIELen);
 417
 418    // disable wpa
 419    if (pMgmt->wWPAIELen == 0) {
 420        pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
 421                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " No WPAIE, Disable WPA \n");
 422    } else  {
 423        // enable wpa
 424        if ((pMgmt->abyWPAIE[0] == WLAN_EID_RSN_WPA) ||
 425             (pMgmt->abyWPAIE[0] == WLAN_EID_RSN)) {
 426              pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
 427               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set WPAIE enable WPA\n");
 428        } else
 429            return -EINVAL;
 430    }
 431
 432        return 0;
 433}
 434
 435/*
 436 * Description:
 437 *      flush station nodes table.
 438 *
 439 * Parameters:
 440 *  In:
 441 *      pDevice   -
 442 *  Out:
 443 *
 444 * Return Value:
 445 *
 446 */
 447
 448static void hostap_flush_sta(PSDevice pDevice)
 449{
 450    // reserved node index =0 for multicast node.
 451    BSSvClearNodeDBTable(pDevice, 1);
 452    pDevice->uAssocCount = 0;
 453
 454    return;
 455}
 456
 457/*
 458 * Description:
 459 *      set each stations encryption key
 460 *
 461 * Parameters:
 462 *  In:
 463 *      pDevice   -
 464 *      param     -
 465 *  Out:
 466 *
 467 * Return Value:
 468 *
 469 */
 470static int hostap_set_encryption(PSDevice pDevice,
 471                                       struct viawget_hostapd_param *param,
 472                                       int param_len)
 473{
 474    PSMgmtObject    pMgmt = pDevice->pMgmt;
 475    DWORD   dwKeyIndex = 0;
 476    BYTE    abyKey[MAX_KEY_LEN];
 477    BYTE    abySeq[MAX_KEY_LEN];
 478    NDIS_802_11_KEY_RSC   KeyRSC;
 479    BYTE    byKeyDecMode = KEY_CTL_WEP;
 480        int     ret = 0;
 481        int     iNodeIndex = -1;
 482        int     ii;
 483        BOOL    bKeyTableFull = FALSE;
 484        WORD    wKeyCtl = 0;
 485
 486
 487        param->u.crypt.err = 0;
 488/*
 489        if (param_len !=
 490            (int) ((char *) param->u.crypt.key - (char *) param) +
 491            param->u.crypt.key_len)
 492                return -EINVAL;
 493*/
 494
 495        if (param->u.crypt.alg > WPA_ALG_CCMP)
 496                return -EINVAL;
 497
 498
 499        if ((param->u.crypt.idx > 3) || (param->u.crypt.key_len > MAX_KEY_LEN)) {
 500                param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
 501                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n");
 502                return -EINVAL;
 503        }
 504
 505        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 506            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 507            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 508                if (param->u.crypt.idx >= MAX_GROUP_KEY)
 509                        return -EINVAL;
 510        iNodeIndex = 0;
 511
 512        } else {
 513            if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == FALSE) {
 514                param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
 515            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
 516                return -EINVAL;
 517            }
 518        }
 519    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: sta_index %d \n", iNodeIndex);
 520    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: alg %d \n", param->u.crypt.alg);
 521
 522        if (param->u.crypt.alg == WPA_ALG_NONE) {
 523
 524        if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly == TRUE) {
 525            if (KeybRemoveKey(&(pDevice->sKey),
 526                                param->sta_addr,
 527                                pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex,
 528                                pDevice->PortOffset) == FALSE) {
 529                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybRemoveKey fail \n");
 530            }
 531            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE;
 532        }
 533        pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = 0;
 534        pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = 0;
 535        pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = 0;
 536        pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = 0;
 537        pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
 538        pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
 539        pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = 0;
 540        memset(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
 541                0,
 542                MAX_KEY_LEN
 543               );
 544
 545        return ret;
 546        }
 547
 548    memcpy(abyKey, param->u.crypt.key, param->u.crypt.key_len);
 549    // copy to node key tbl
 550    pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = param->u.crypt.idx;
 551    pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = param->u.crypt.key_len;
 552    memcpy(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
 553            param->u.crypt.key,
 554            param->u.crypt.key_len
 555           );
 556
 557    dwKeyIndex = (DWORD)(param->u.crypt.idx);
 558    if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
 559        pDevice->byKeyIndex = (BYTE)dwKeyIndex;
 560        pDevice->bTransmitKey = TRUE;
 561        dwKeyIndex |= (1 << 31);
 562    }
 563
 564        if (param->u.crypt.alg == WPA_ALG_WEP) {
 565
 566        if ((pDevice->bEnable8021x == FALSE) || (iNodeIndex == 0)) {
 567            KeybSetDefaultKey(&(pDevice->sKey),
 568                                dwKeyIndex & ~(BIT30 | USE_KEYRSC),
 569                                param->u.crypt.key_len,
 570                                NULL,
 571                                abyKey,
 572                                KEY_CTL_WEP,
 573                                pDevice->PortOffset,
 574                                pDevice->byLocalID);
 575
 576        } else {
 577            // 8021x enable, individual key
 578            dwKeyIndex |= (1 << 30); // set pairwise key
 579            if (KeybSetKey(&(pDevice->sKey),
 580                           &param->sta_addr[0],
 581                           dwKeyIndex & ~(USE_KEYRSC),
 582                           param->u.crypt.key_len,
 583                           (PQWORD) &(KeyRSC),
 584                           (PBYTE)abyKey,
 585                            KEY_CTL_WEP,
 586                            pDevice->PortOffset,
 587                            pDevice->byLocalID) == TRUE) {
 588
 589                pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE;
 590
 591            } else {
 592                // Key Table Full
 593                pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE;
 594                bKeyTableFull = TRUE;
 595            }
 596        }
 597        pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 598        pDevice->bEncryptionEnable = TRUE;
 599        pMgmt->byCSSPK = KEY_CTL_WEP;
 600        pMgmt->byCSSGK = KEY_CTL_WEP;
 601        pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = KEY_CTL_WEP;
 602        pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
 603        return ret;
 604        }
 605
 606        if (param->u.crypt.seq) {
 607            memcpy(&abySeq, param->u.crypt.seq, 8);
 608                for (ii = 0 ; ii < 8 ; ii++) {
 609                 KeyRSC |= (abySeq[ii] << (ii * 8));
 610                }
 611                dwKeyIndex |= 1 << 29;
 612                pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC;
 613        }
 614
 615        if (param->u.crypt.alg == WPA_ALG_TKIP) {
 616            if (param->u.crypt.key_len != MAX_KEY_LEN)
 617                return -EINVAL;
 618            pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
 619        byKeyDecMode = KEY_CTL_TKIP;
 620        pMgmt->byCSSPK = KEY_CTL_TKIP;
 621        pMgmt->byCSSGK = KEY_CTL_TKIP;
 622        }
 623
 624        if (param->u.crypt.alg == WPA_ALG_CCMP) {
 625            if ((param->u.crypt.key_len != AES_KEY_LEN) ||
 626                (pDevice->byLocalID <= REV_ID_VT3253_A1))
 627                return -EINVAL;
 628        pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
 629        byKeyDecMode = KEY_CTL_CCMP;
 630        pMgmt->byCSSPK = KEY_CTL_CCMP;
 631        pMgmt->byCSSGK = KEY_CTL_CCMP;
 632    }
 633
 634
 635    if (iNodeIndex == 0) {
 636       KeybSetDefaultKey(&(pDevice->sKey),
 637                           dwKeyIndex,
 638                           param->u.crypt.key_len,
 639                           (PQWORD) &(KeyRSC),
 640                           abyKey,
 641                           byKeyDecMode,
 642                           pDevice->PortOffset,
 643                           pDevice->byLocalID);
 644       pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE;
 645
 646    } else {
 647        dwKeyIndex |= (1 << 30); // set pairwise key
 648        if (KeybSetKey(&(pDevice->sKey),
 649                       &param->sta_addr[0],
 650                       dwKeyIndex,
 651                       param->u.crypt.key_len,
 652                       (PQWORD) &(KeyRSC),
 653                       (PBYTE)abyKey,
 654                        byKeyDecMode,
 655                        pDevice->PortOffset,
 656                        pDevice->byLocalID) == TRUE) {
 657
 658            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE;
 659
 660        } else {
 661            // Key Table Full
 662            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE;
 663            bKeyTableFull = TRUE;
 664            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Key Table Full\n");
 665        }
 666
 667    }
 668
 669    if (bKeyTableFull == TRUE) {
 670        wKeyCtl &= 0x7F00;              // clear all key control filed
 671        wKeyCtl |= (byKeyDecMode << 4);
 672        wKeyCtl |= (byKeyDecMode);
 673        wKeyCtl |= 0x0044;              // use group key for all address
 674        wKeyCtl |= 0x4000;              // disable KeyTable[MAX_KEY_TABLE-1] on-fly to genernate rx int
 675        MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID);
 676    }
 677
 678    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set key sta_index= %d \n", iNodeIndex);
 679    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " tx_index=%d len=%d \n", param->u.crypt.idx,
 680               param->u.crypt.key_len );
 681    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
 682               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
 683               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[1],
 684               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[2],
 685               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[3],
 686               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[4]
 687              );
 688
 689        // set wep key
 690    pDevice->bEncryptionEnable = TRUE;
 691    pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = byKeyDecMode;
 692    pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
 693    pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
 694    pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
 695
 696        return ret;
 697}
 698
 699
 700
 701/*
 702 * Description:
 703 *      get each stations encryption key
 704 *
 705 * Parameters:
 706 *  In:
 707 *      pDevice   -
 708 *      param     -
 709 *  Out:
 710 *
 711 * Return Value:
 712 *
 713 */
 714static int hostap_get_encryption(PSDevice pDevice,
 715                                       struct viawget_hostapd_param *param,
 716                                       int param_len)
 717{
 718    PSMgmtObject    pMgmt = pDevice->pMgmt;
 719        int     ret = 0;
 720        int     ii;
 721        int     iNodeIndex =0;
 722
 723
 724        param->u.crypt.err = 0;
 725
 726        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 727            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 728            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 729        iNodeIndex = 0;
 730        } else {
 731            if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == FALSE) {
 732                param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
 733            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
 734                return -EINVAL;
 735            }
 736        }
 737        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: %d\n", iNodeIndex);
 738    memset(param->u.crypt.seq, 0, 8);
 739    for (ii = 0 ; ii < 8 ; ii++) {
 740        param->u.crypt.seq[ii] = (BYTE)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8);
 741    }
 742
 743        return ret;
 744}
 745
 746
 747/*
 748 * Description:
 749 *      hostap_ioctl main function supported for hostap deamon.
 750 *
 751 * Parameters:
 752 *  In:
 753 *      pDevice   -
 754 *      iw_point  -
 755 *  Out:
 756 *
 757 * Return Value:
 758 *
 759 */
 760
 761int hostap_ioctl(PSDevice pDevice, struct iw_point *p)
 762{
 763        struct viawget_hostapd_param *param;
 764        int ret = 0;
 765        int ap_ioctl = 0;
 766
 767        if (p->length < sizeof(struct viawget_hostapd_param) ||
 768            p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
 769                return -EINVAL;
 770
 771        param = (struct viawget_hostapd_param *) kmalloc((int)p->length, (int)GFP_KERNEL);
 772        if (param == NULL)
 773                return -ENOMEM;
 774
 775        if (copy_from_user(param, p->pointer, p->length)) {
 776                ret = -EFAULT;
 777                goto out;
 778        }
 779
 780        switch (param->cmd) {
 781        case VIAWGET_HOSTAPD_SET_ENCRYPTION:
 782            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ENCRYPTION \n");
 783        spin_lock_irq(&pDevice->lock);
 784                ret = hostap_set_encryption(pDevice, param, p->length);
 785        spin_unlock_irq(&pDevice->lock);
 786                break;
 787        case VIAWGET_HOSTAPD_GET_ENCRYPTION:
 788            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_ENCRYPTION \n");
 789        spin_lock_irq(&pDevice->lock);
 790                ret = hostap_get_encryption(pDevice, param, p->length);
 791        spin_unlock_irq(&pDevice->lock);
 792                break;
 793        case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR:
 794            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n");
 795                return -EOPNOTSUPP;
 796                break;
 797        case VIAWGET_HOSTAPD_FLUSH:
 798            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n");
 799        spin_lock_irq(&pDevice->lock);
 800        hostap_flush_sta(pDevice);
 801        spin_unlock_irq(&pDevice->lock);
 802                break;
 803        case VIAWGET_HOSTAPD_ADD_STA:
 804            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_ADD_STA \n");
 805         spin_lock_irq(&pDevice->lock);
 806                 ret = hostap_add_sta(pDevice, param);
 807         spin_unlock_irq(&pDevice->lock);
 808                break;
 809        case VIAWGET_HOSTAPD_REMOVE_STA:
 810            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_REMOVE_STA \n");
 811         spin_lock_irq(&pDevice->lock);
 812                 ret = hostap_remove_sta(pDevice, param);
 813         spin_unlock_irq(&pDevice->lock);
 814                break;
 815        case VIAWGET_HOSTAPD_GET_INFO_STA:
 816            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_INFO_STA \n");
 817                 ret = hostap_get_info_sta(pDevice, param);
 818                 ap_ioctl = 1;
 819                break;
 820/*
 821        case VIAWGET_HOSTAPD_RESET_TXEXC_STA:
 822            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_RESET_TXEXC_STA \n");
 823                 ret = hostap_reset_txexc_sta(pDevice, param);
 824                break;
 825*/
 826        case VIAWGET_HOSTAPD_SET_FLAGS_STA:
 827            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n");
 828                 ret = hostap_set_flags_sta(pDevice, param);
 829                break;
 830
 831        case VIAWGET_HOSTAPD_MLME:
 832            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_MLME \n");
 833            return -EOPNOTSUPP;
 834
 835        case VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT:
 836            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT \n");
 837                ret = hostap_set_generic_element(pDevice, param);
 838                break;
 839
 840        case VIAWGET_HOSTAPD_SCAN_REQ:
 841            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SCAN_REQ \n");
 842            return -EOPNOTSUPP;
 843
 844        case VIAWGET_HOSTAPD_STA_CLEAR_STATS:
 845            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n");
 846            return -EOPNOTSUPP;
 847
 848        default:
 849            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_ioctl: unknown cmd=%d\n",
 850                       (int)param->cmd);
 851                return -EOPNOTSUPP;
 852                break;
 853        }
 854
 855
 856        if ((ret == 0) && ap_ioctl) {
 857                if (copy_to_user(p->pointer, param, p->length)) {
 858                        ret = -EFAULT;
 859                        goto out;
 860                }
 861        }
 862
 863 out:
 864        if (param != NULL)
 865                kfree(param);
 866
 867        return ret;
 868}
 869
 870