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