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