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