Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.4 919 lines 24 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 * 20 * File: wpactl.c 21 * 22 * Purpose: handle wpa supplicant ioctl input/out functions 23 * 24 * Author: Lyndon Chen 25 * 26 * Date: July 28, 2006 27 * 28 * Functions: 29 * 30 * Revision History: 31 * 32 */ 33 34#include "wpactl.h" 35#include "key.h" 36#include "mac.h" 37#include "device.h" 38#include "wmgr.h" 39#include "iocmd.h" 40#include "iowpa.h" 41#include "control.h" 42#include "rndis.h" 43#include "rf.h" 44 45/*--------------------- Static Definitions -------------------------*/ 46 47#define VIAWGET_WPA_MAX_BUF_SIZE 1024 48 49static const int frequency_list[] = { 50 2412, 2417, 2422, 2427, 2432, 2437, 2442, 51 2447, 2452, 2457, 2462, 2467, 2472, 2484 52}; 53 54/*--------------------- Static Classes ----------------------------*/ 55 56/*--------------------- Static Variables --------------------------*/ 57static int msglevel = MSG_LEVEL_INFO; 58 59/*--------------------- Static Functions --------------------------*/ 60 61/*--------------------- Export Variables --------------------------*/ 62static void wpadev_setup(struct net_device *dev) 63{ 64 dev->type = ARPHRD_IEEE80211; 65 dev->hard_header_len = ETH_HLEN; 66 dev->mtu = 2048; 67 dev->addr_len = ETH_ALEN; 68 dev->tx_queue_len = 1000; 69 70 memset(dev->broadcast, 0xFF, ETH_ALEN); 71 72 dev->flags = IFF_BROADCAST | IFF_MULTICAST; 73} 74 75/* 76 * Description: 77 * register netdev for wpa supplicant deamon 78 * 79 * Parameters: 80 * In: 81 * pDevice - 82 * enable - 83 * Out: 84 * 85 * Return Value: 86 * 87 */ 88static int wpa_init_wpadev(PSDevice pDevice) 89{ 90 PSDevice wpadev_priv; 91 struct net_device *dev = pDevice->dev; 92 int ret = 0; 93 94 pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", wpadev_setup); 95 if (pDevice->wpadev == NULL) 96 return -ENOMEM; 97 98 wpadev_priv = netdev_priv(pDevice->wpadev); 99 *wpadev_priv = *pDevice; 100 memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, ETH_ALEN); 101 pDevice->wpadev->base_addr = dev->base_addr; 102 pDevice->wpadev->irq = dev->irq; 103 pDevice->wpadev->mem_start = dev->mem_start; 104 pDevice->wpadev->mem_end = dev->mem_end; 105 ret = register_netdev(pDevice->wpadev); 106 if (ret) { 107 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n", 108 dev->name); 109 free_netdev(pDevice->wpadev); 110 return -1; 111 } 112 113 if (pDevice->skb == NULL) { 114 pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); 115 if (pDevice->skb == NULL) 116 return -ENOMEM; 117 } 118 119 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n", 120 dev->name, pDevice->wpadev->name); 121 122 return 0; 123} 124 125/* 126 * Description: 127 * unregister net_device (wpadev) 128 * 129 * Parameters: 130 * In: 131 * pDevice - 132 * Out: 133 * 134 * Return Value: 135 * 136 */ 137static int wpa_release_wpadev(PSDevice pDevice) 138{ 139 if (pDevice->skb) { 140 dev_kfree_skb(pDevice->skb); 141 pDevice->skb = NULL; 142 } 143 144 if (pDevice->wpadev) { 145 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", 146 pDevice->dev->name, pDevice->wpadev->name); 147 unregister_netdev(pDevice->wpadev); 148 free_netdev(pDevice->wpadev); 149 pDevice->wpadev = NULL; 150 } 151 152 return 0; 153} 154 155/* 156 * Description: 157 * Set enable/disable dev for wpa supplicant deamon 158 * 159 * Parameters: 160 * In: 161 * pDevice - 162 * val - 163 * Out: 164 * 165 * Return Value: 166 * 167 */ 168int wpa_set_wpadev(PSDevice pDevice, int val) 169{ 170 if (val) 171 return wpa_init_wpadev(pDevice); 172 return wpa_release_wpadev(pDevice); 173} 174 175/* 176 * Description: 177 * Set WPA algorithm & keys 178 * 179 * Parameters: 180 * In: 181 * pDevice - 182 * param - 183 * Out: 184 * 185 * Return Value: 186 * 187 */ 188 int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL fcpfkernel) 189{ 190 struct viawget_wpa_param *param = ctx; 191 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 192 DWORD dwKeyIndex = 0; 193 BYTE abyKey[MAX_KEY_LEN]; 194 BYTE abySeq[MAX_KEY_LEN]; 195 QWORD KeyRSC; 196 BYTE byKeyDecMode = KEY_CTL_WEP; 197 int ret = 0; 198 int uu; 199 int ii; 200 201 if (param->u.wpa_key.alg_name > WPA_ALG_CCMP) 202 return -EINVAL; 203 204 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", 205 param->u.wpa_key.alg_name); 206 if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { 207 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; 208 pDevice->bEncryptionEnable = FALSE; 209 pDevice->byKeyIndex = 0; 210 pDevice->bTransmitKey = FALSE; 211 for (uu=0; uu<MAX_KEY_TABLE; uu++) { 212 MACvDisableKeyEntry(pDevice, uu); 213 } 214 return ret; 215 } 216 217 if (param->u.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey)) 218 return -EINVAL; 219 220 spin_unlock_irq(&pDevice->lock); 221 if (param->u.wpa_key.key && fcpfkernel) { 222 memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); 223 } else { 224 if (param->u.wpa_key.key && 225 copy_from_user(&abyKey[0], param->u.wpa_key.key, 226 param->u.wpa_key.key_len)) { 227 spin_lock_irq(&pDevice->lock); 228 return -EINVAL; 229 } 230 } 231 spin_lock_irq(&pDevice->lock); 232 233 dwKeyIndex = (DWORD)(param->u.wpa_key.key_index); 234 235 if (param->u.wpa_key.alg_name == WPA_ALG_WEP) { 236 if (dwKeyIndex > 3) { 237 return -EINVAL; 238 } else { 239 if (param->u.wpa_key.set_tx) { 240 pDevice->byKeyIndex = (BYTE)dwKeyIndex; 241 pDevice->bTransmitKey = TRUE; 242 dwKeyIndex |= (1 << 31); 243 } 244 KeybSetDefaultKey( pDevice, 245 &(pDevice->sKey), 246 dwKeyIndex & ~(BIT30 | USE_KEYRSC), 247 param->u.wpa_key.key_len, 248 NULL, 249 abyKey, 250 KEY_CTL_WEP 251 ); 252 253 } 254 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; 255 pDevice->bEncryptionEnable = TRUE; 256 return ret; 257 } 258 259 260 if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq)) 261 return -EINVAL; 262 263 spin_unlock_irq(&pDevice->lock); 264 if (param->u.wpa_key.seq && fcpfkernel) { 265 memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); 266 } else { 267 if (param->u.wpa_key.seq && 268 copy_from_user(&abySeq[0], param->u.wpa_key.seq, 269 param->u.wpa_key.seq_len)) { 270 spin_lock_irq(&pDevice->lock); 271 return -EINVAL; 272 } 273 } 274 spin_lock_irq(&pDevice->lock); 275 276 if (param->u.wpa_key.seq_len > 0) { 277 for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) { 278 if (ii < 4) 279 LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8)); 280 else 281 HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8)); 282 } 283 dwKeyIndex |= 1 << 29; 284 } 285 286 if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { 287 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); 288 return -EINVAL; 289 } 290 291 if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) { 292 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; 293 } 294 295 if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) { 296 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; 297 } 298 299 if (param->u.wpa_key.set_tx) 300 dwKeyIndex |= (1 << 31); 301 302 303 if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) 304 byKeyDecMode = KEY_CTL_CCMP; 305 else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) 306 byKeyDecMode = KEY_CTL_TKIP; 307 else 308 byKeyDecMode = KEY_CTL_WEP; 309 310 // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled 311 if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { 312 if (param->u.wpa_key.key_len == MAX_KEY_LEN) 313 byKeyDecMode = KEY_CTL_TKIP; 314 else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) 315 byKeyDecMode = KEY_CTL_WEP; 316 else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) 317 byKeyDecMode = KEY_CTL_WEP; 318 } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { 319 if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) 320 byKeyDecMode = KEY_CTL_WEP; 321 else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) 322 byKeyDecMode = KEY_CTL_WEP; 323 } 324 325 // Check TKIP key length 326 if ((byKeyDecMode == KEY_CTL_TKIP) && 327 (param->u.wpa_key.key_len != MAX_KEY_LEN)) { 328 // TKIP Key must be 256 bits 329 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n"); 330 return -EINVAL; 331 } 332 // Check AES key length 333 if ((byKeyDecMode == KEY_CTL_CCMP) && 334 (param->u.wpa_key.key_len != AES_KEY_LEN)) { 335 // AES Key must be 128 bits 336 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n"); 337 return -EINVAL; 338 } 339 340 if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) { 341 /* if broadcast, set the key as every key entry's group key */ 342 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); 343 344 if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex, 345 param->u.wpa_key.key_len, 346 (PQWORD) &(KeyRSC), 347 (PBYTE)abyKey, 348 byKeyDecMode 349 ) == TRUE) && 350 (KeybSetDefaultKey(pDevice, 351 &(pDevice->sKey), 352 dwKeyIndex, 353 param->u.wpa_key.key_len, 354 (PQWORD) &(KeyRSC), 355 (PBYTE)abyKey, 356 byKeyDecMode 357 ) == TRUE) ) { 358 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); 359 } else { 360 return -EINVAL; 361 } 362 } else { 363 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); 364 // BSSID not 0xffffffffffff 365 // Pairwise Key can't be WEP 366 if (byKeyDecMode == KEY_CTL_WEP) { 367 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); 368 return -EINVAL; 369 } 370 dwKeyIndex |= (1 << 30); // set pairwise key 371 if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { 372 //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n")); 373 return -EINVAL; 374 } 375 if (KeybSetKey(pDevice, &(pDevice->sKey), &param->addr[0], 376 dwKeyIndex, param->u.wpa_key.key_len, 377 (PQWORD) &(KeyRSC), (PBYTE)abyKey, byKeyDecMode 378 ) == TRUE) { 379 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); 380 } else { 381 // Key Table Full 382 if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) { 383 //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); 384 return -EINVAL; 385 } else { 386 // Save Key and configure just before associate/reassociate to BSSID 387 // we do not implement now 388 return -EINVAL; 389 } 390 } 391 } // BSSID not 0xffffffffffff 392 if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { 393 pDevice->byKeyIndex = (BYTE)param->u.wpa_key.key_index; 394 pDevice->bTransmitKey = TRUE; 395 } 396 pDevice->bEncryptionEnable = TRUE; 397 398 return ret; 399} 400 401 402/* 403 * Description: 404 * enable wpa auth & mode 405 * 406 * Parameters: 407 * In: 408 * pDevice - 409 * param - 410 * Out: 411 * 412 * Return Value: 413 * 414 */ 415static int wpa_set_wpa(PSDevice pDevice, struct viawget_wpa_param *param) 416{ 417 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 418 int ret = 0; 419 420 pMgmt->eAuthenMode = WMAC_AUTH_OPEN; 421 pMgmt->bShareKeyAlgorithm = FALSE; 422 423 return ret; 424} 425 426 /* 427 * Description: 428 * set disassociate 429 * 430 * Parameters: 431 * In: 432 * pDevice - 433 * param - 434 * Out: 435 * 436 * Return Value: 437 * 438 */ 439static int wpa_set_disassociate(PSDevice pDevice, struct viawget_wpa_param *param) 440{ 441 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 442 int ret = 0; 443 444 spin_lock_irq(&pDevice->lock); 445 if (pDevice->bLinkPass) { 446 if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6)) 447 bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL); 448 } 449 spin_unlock_irq(&pDevice->lock); 450 451 return ret; 452} 453 454/* 455 * Description: 456 * enable scan process 457 * 458 * Parameters: 459 * In: 460 * pDevice - 461 * param - 462 * Out: 463 * 464 * Return Value: 465 * 466 */ 467static int wpa_set_scan(PSDevice pDevice, struct viawget_wpa_param *param) 468{ 469 int ret = 0; 470 471/**set ap_scan=1&&scan_ssid=1 under hidden ssid mode**/ 472 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 473 PWLAN_IE_SSID pItemSSID; 474 printk("wpa_set_scan-->desired [ssid=%s,ssid_len=%d]\n", 475 param->u.scan_req.ssid,param->u.scan_req.ssid_len); 476// Set the SSID 477 memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); 478 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; 479 pItemSSID->byElementID = WLAN_EID_SSID; 480 memcpy(pItemSSID->abySSID, param->u.scan_req.ssid, param->u.scan_req.ssid_len); 481 pItemSSID->len = param->u.scan_req.ssid_len; 482 483 spin_lock_irq(&pDevice->lock); 484 BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass); 485 bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, 486 pMgmt->abyDesireSSID); 487 spin_unlock_irq(&pDevice->lock); 488 489 return ret; 490} 491 492/* 493 * Description: 494 * get bssid 495 * 496 * Parameters: 497 * In: 498 * pDevice - 499 * param - 500 * Out: 501 * 502 * Return Value: 503 * 504 */ 505static int wpa_get_bssid(PSDevice pDevice, struct viawget_wpa_param *param) 506{ 507 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 508 int ret = 0; 509 memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID, 6); 510 511 return ret; 512} 513 514/* 515 * Description: 516 * get bssid 517 * 518 * Parameters: 519 * In: 520 * pDevice - 521 * param - 522 * Out: 523 * 524 * Return Value: 525 * 526 */ 527static int wpa_get_ssid(PSDevice pDevice, struct viawget_wpa_param *param) 528{ 529 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 530 PWLAN_IE_SSID pItemSSID; 531 int ret = 0; 532 533 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; 534 535 memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID, pItemSSID->len); 536 param->u.wpa_associate.ssid_len = pItemSSID->len; 537 538 return ret; 539} 540 541/* 542 * Description: 543 * get scan results 544 * 545 * Parameters: 546 * In: 547 * pDevice - 548 * param - 549 * Out: 550 * 551 * Return Value: 552 * 553 */ 554static int wpa_get_scan(PSDevice pDevice, struct viawget_wpa_param *param) 555{ 556 struct viawget_scan_result *scan_buf; 557 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 558 PWLAN_IE_SSID pItemSSID; 559 PKnownBSS pBSS; 560 PBYTE pBuf; 561 int ret = 0; 562 u16 count = 0; 563 u16 ii; 564 u16 jj; 565 long ldBm; //James //add 566 567//******mike:bubble sort by stronger RSSI*****// 568 PBYTE ptempBSS; 569 570 ptempBSS = kmalloc(sizeof(KnownBSS), GFP_ATOMIC); 571 572 if (ptempBSS == NULL) { 573 printk("bubble sort kmalloc memory fail@@@\n"); 574 ret = -ENOMEM; 575 return ret; 576 } 577 578 for (ii = 0; ii < MAX_BSS_NUM; ii++) { 579 for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) { 580 if ((pMgmt->sBSSList[jj].bActive != TRUE) 581 || ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI) 582 && (pMgmt->sBSSList[jj + 1].bActive != FALSE))) { 583 memcpy(ptempBSS,&pMgmt->sBSSList[jj], sizeof(KnownBSS)); 584 memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1], 585 sizeof(KnownBSS)); 586 memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS)); 587 } 588 } 589 } 590 kfree(ptempBSS); 591 592 count = 0; 593 pBSS = &(pMgmt->sBSSList[0]); 594 for (ii = 0; ii < MAX_BSS_NUM; ii++) { 595 pBSS = &(pMgmt->sBSSList[ii]); 596 if (!pBSS->bActive) 597 continue; 598 count++; 599 } 600 601 pBuf = kcalloc(count, sizeof(struct viawget_scan_result), GFP_ATOMIC); 602 603 if (pBuf == NULL) { 604 ret = -ENOMEM; 605 return ret; 606 } 607 scan_buf = (struct viawget_scan_result *)pBuf; 608 pBSS = &(pMgmt->sBSSList[0]); 609 for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) { 610 pBSS = &(pMgmt->sBSSList[ii]); 611 if (pBSS->bActive) { 612 if (jj >= count) 613 break; 614 memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN); 615 pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; 616 memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len); 617 scan_buf->ssid_len = pItemSSID->len; 618 scan_buf->freq = frequency_list[pBSS->uChannel-1]; 619 scan_buf->caps = pBSS->wCapInfo; // DavidWang for sharemode 620 621 RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm); 622 if (-ldBm < 50) 623 scan_buf->qual = 100; 624 else if (-ldBm > 90) 625 scan_buf->qual = 0; 626 else 627 scan_buf->qual=(40-(-ldBm-50))*100/40; 628 629 //James 630 //scan_buf->caps = pBSS->wCapInfo; 631 //scan_buf->qual = 632 scan_buf->noise = 0; 633 scan_buf->level = ldBm; 634 635 //scan_buf->maxrate = 636 if (pBSS->wWPALen != 0) { 637 scan_buf->wpa_ie_len = pBSS->wWPALen; 638 memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen); 639 } 640 if (pBSS->wRSNLen != 0) { 641 scan_buf->rsn_ie_len = pBSS->wRSNLen; 642 memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen); 643 } 644 scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result)); 645 jj ++; 646 } 647 } 648 649 if (jj < count) 650 count = jj; 651 652 if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) 653 ret = -EFAULT; 654 655 param->u.scan_results.scan_count = count; 656 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count); 657 658 kfree(pBuf); 659 return ret; 660} 661 662/* 663 * Description: 664 * set associate with AP 665 * 666 * Parameters: 667 * In: 668 * pDevice - 669 * param - 670 * Out: 671 * 672 * Return Value: 673 * 674 */ 675static int wpa_set_associate(PSDevice pDevice, struct viawget_wpa_param *param) 676{ 677 PSMgmtObject pMgmt = &pDevice->sMgmtObj; 678 PWLAN_IE_SSID pItemSSID; 679 BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 680 BYTE abyWPAIE[64]; 681 int ret = 0; 682 BOOL bwepEnabled=FALSE; 683 684 // set key type & algorithm 685 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite); 686 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite); 687 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite); 688 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg); 689 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode); 690 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); 691 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming dBm = %d\n", param->u.wpa_associate.roam_dbm); // Davidwang 692 693 if (param->u.wpa_associate.wpa_ie) { 694 if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE)) 695 return -EINVAL; 696 697 if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, 698 param->u.wpa_associate.wpa_ie_len)) 699 return -EFAULT; 700 } 701 702 if (param->u.wpa_associate.mode == 1) 703 pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; 704 else 705 pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; 706 707 // set bssid 708 if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0) 709 memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6); 710 // set ssid 711 memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); 712 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; 713 pItemSSID->byElementID = WLAN_EID_SSID; 714 pItemSSID->len = param->u.wpa_associate.ssid_len; 715 memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len); 716 717 if (param->u.wpa_associate.wpa_ie_len == 0) { 718 if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY) 719 pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; 720 else 721 pMgmt->eAuthenMode = WMAC_AUTH_OPEN; 722 } else if (abyWPAIE[0] == RSN_INFO_ELEM) { 723 if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) 724 pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; 725 else 726 pMgmt->eAuthenMode = WMAC_AUTH_WPA2; 727 } else { 728 if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE) 729 pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; 730 else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) 731 pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; 732 else 733 pMgmt->eAuthenMode = WMAC_AUTH_WPA; 734 } 735 736 switch (param->u.wpa_associate.pairwise_suite) { 737 case CIPHER_CCMP: 738 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; 739 break; 740 case CIPHER_TKIP: 741 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; 742 break; 743 case CIPHER_WEP40: 744 case CIPHER_WEP104: 745 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; 746 bwepEnabled = TRUE; 747 break; 748 case CIPHER_NONE: 749 if (param->u.wpa_associate.group_suite == CIPHER_CCMP) 750 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; 751 else 752 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; 753 break; 754 default: 755 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; 756 } 757 758 pMgmt->Roam_dbm = param->u.wpa_associate.roam_dbm; 759 if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { // @wep-sharekey 760 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; 761 pMgmt->bShareKeyAlgorithm = TRUE; 762 } else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) { 763 if(bwepEnabled==TRUE) { //@open-wep 764 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; 765 } else { 766 // @only open 767 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; 768 } 769 } 770 // mike save old encryption status 771 pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus; 772 773 if (pDevice->eEncryptionStatus != Ndis802_11EncryptionDisabled) 774 pDevice->bEncryptionEnable = TRUE; 775 else 776 pDevice->bEncryptionEnable = FALSE; 777 778 if ((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) || 779 ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bwepEnabled==TRUE))) { 780 // mike re-comment:open-wep && sharekey-wep needn't do initial key!! 781 } else { 782 KeyvInitTable(pDevice,&pDevice->sKey); 783 } 784 785 spin_lock_irq(&pDevice->lock); 786 pDevice->bLinkPass = FALSE; 787 ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); 788 memset(pMgmt->abyCurrBSSID, 0, 6); 789 pMgmt->eCurrState = WMAC_STATE_IDLE; 790 netif_stop_queue(pDevice->dev); 791 792/******* search if ap_scan=2, which is associating request in hidden ssid mode ****/ 793 { 794 PKnownBSS pCurr = NULL; 795 pCurr = BSSpSearchBSSList(pDevice, 796 pMgmt->abyDesireBSSID, 797 pMgmt->abyDesireSSID, 798 pDevice->eConfigPHYMode 799 ); 800 801 if (pCurr == NULL){ 802 printk("wpa_set_associate---->hidden mode site survey before associate.......\n"); 803 bScheduleCommand((void *)pDevice, 804 WLAN_CMD_BSSID_SCAN, 805 pMgmt->abyDesireSSID); 806 } 807 } 808/****************************************************************/ 809 810 bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); 811 spin_unlock_irq(&pDevice->lock); 812 813 return ret; 814} 815 816/* 817 * Description: 818 * wpa_ioctl main function supported for wpa supplicant 819 * 820 * Parameters: 821 * In: 822 * pDevice - 823 * iw_point - 824 * Out: 825 * 826 * Return Value: 827 * 828 */ 829int wpa_ioctl(PSDevice pDevice, struct iw_point *p) 830{ 831 struct viawget_wpa_param *param; 832 int ret = 0; 833 int wpa_ioctl = 0; 834 835 if (p->length < sizeof(struct viawget_wpa_param) || 836 p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer) 837 return -EINVAL; 838 839 param = kmalloc((int)p->length, GFP_KERNEL); 840 if (param == NULL) 841 return -ENOMEM; 842 843 if (copy_from_user(param, p->pointer, p->length)) { 844 ret = -EFAULT; 845 goto out; 846 } 847 848 switch (param->cmd) { 849 case VIAWGET_SET_WPA: 850 ret = wpa_set_wpa(pDevice, param); 851 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n"); 852 break; 853 854 case VIAWGET_SET_KEY: 855 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n"); 856 spin_lock_irq(&pDevice->lock); 857 ret = wpa_set_keys(pDevice, param, FALSE); 858 spin_unlock_irq(&pDevice->lock); 859 break; 860 861 case VIAWGET_SET_SCAN: 862 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n"); 863 ret = wpa_set_scan(pDevice, param); 864 break; 865 866 case VIAWGET_GET_SCAN: 867 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n"); 868 ret = wpa_get_scan(pDevice, param); 869 wpa_ioctl = 1; 870 break; 871 872 case VIAWGET_GET_SSID: 873 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n"); 874 ret = wpa_get_ssid(pDevice, param); 875 wpa_ioctl = 1; 876 break; 877 878 case VIAWGET_GET_BSSID: 879 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n"); 880 ret = wpa_get_bssid(pDevice, param); 881 wpa_ioctl = 1; 882 break; 883 884 case VIAWGET_SET_ASSOCIATE: 885 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n"); 886 ret = wpa_set_associate(pDevice, param); 887 break; 888 889 case VIAWGET_SET_DISASSOCIATE: 890 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n"); 891 ret = wpa_set_disassociate(pDevice, param); 892 break; 893 894 case VIAWGET_SET_DROP_UNENCRYPT: 895 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n"); 896 break; 897 898 case VIAWGET_SET_DEAUTHENTICATE: 899 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n"); 900 break; 901 902 default: 903 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n", 904 param->cmd); 905 kfree(param); 906 return -EOPNOTSUPP; 907 } 908 909 if ((ret == 0) && wpa_ioctl) { 910 if (copy_to_user(p->pointer, param, p->length)) { 911 ret = -EFAULT; 912 goto out; 913 } 914 } 915 916out: 917 kfree(param); 918 return ret; 919}