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