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