Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.14 825 lines 22 kB view raw
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}