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