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