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