1 /******************************************************************************
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 The full GNU General Public License is included in this distribution in the
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
31 ******************************************************************************/
32 #include <linux/wireless.h>
33 #include <linux/version.h>
34 #include <linux/kmod.h>
35 #include <linux/slab.h>
36 #include <linux/module.h>
38 #include "ieee80211.h"
40 static const char *ieee80211_modes[] = {
41 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
48 struct modes_unit ieee80211_modes[] = {
57 #define iwe_stream_add_event_rsl iwe_stream_add_event
59 #define MAX_CUSTOM_LEN 64
60 static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
61 char *start, char *stop,
62 struct ieee80211_network *network,
63 struct iw_request_info *info)
65 char custom[MAX_CUSTOM_LEN];
66 char proto_name[IFNAMSIZ];
67 char *pname = proto_name;
72 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
74 /* First entry *MUST* be the AP MAC address */
76 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
77 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
78 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
79 /* Remaining entries will be displayed in the order we provide them */
82 iwe.cmd = SIOCGIWESSID;
84 // if (network->flags & NETWORK_EMPTY_ESSID) {
85 if (network->ssid_len == 0) {
86 iwe.u.data.length = sizeof("<hidden>");
87 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
89 iwe.u.data.length = min(network->ssid_len, (u8)32);
90 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
92 /* Add the protocol name */
93 iwe.cmd = SIOCGIWNAME;
94 for(i=0; i<(sizeof(ieee80211_modes)/sizeof(ieee80211_modes[0])); i++) {
95 if(network->mode&(1<<i)) {
96 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
97 pname +=ieee80211_modes[i].mode_size;
101 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
102 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
104 iwe.cmd = SIOCGIWMODE;
105 if (network->capability &
106 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
107 if (network->capability & WLAN_CAPABILITY_BSS)
108 iwe.u.mode = IW_MODE_MASTER;
110 iwe.u.mode = IW_MODE_ADHOC;
111 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
114 /* Add frequency/channel */
115 iwe.cmd = SIOCGIWFREQ;
116 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
118 iwe.u.freq.m = network->channel;
121 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
122 /* Add encryption capability */
123 iwe.cmd = SIOCGIWENCODE;
124 if (network->capability & WLAN_CAPABILITY_PRIVACY)
125 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
127 iwe.u.data.flags = IW_ENCODE_DISABLED;
128 iwe.u.data.length = 0;
129 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
130 /* Add basic and extended rates */
133 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
134 for (i = 0, j = 0; i < network->rates_len; ) {
135 if (j < network->rates_ex_len &&
136 ((network->rates_ex[j] & 0x7F) <
137 (network->rates[i] & 0x7F)))
138 rate = network->rates_ex[j++] & 0x7F;
140 rate = network->rates[i++] & 0x7F;
143 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
144 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
146 for (; j < network->rates_ex_len; j++) {
147 rate = network->rates_ex[j] & 0x7F;
148 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
149 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
154 if (network->mode >= IEEE_N_24G)//add N rate here;
156 PHT_CAPABILITY_ELE ht_cap = NULL;
157 bool is40M = false, isShortGI = false;
159 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
160 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
162 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
163 is40M = (ht_cap->ChlWidth)?1:0;
164 isShortGI = (ht_cap->ChlWidth)?
165 ((ht_cap->ShortGI40Mhz)?1:0):
166 ((ht_cap->ShortGI20Mhz)?1:0);
168 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
169 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
173 iwe.cmd = SIOCGIWRATE;
174 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
175 iwe.u.bitrate.value = max_rate * 500000;
176 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
178 iwe.cmd = IWEVCUSTOM;
179 iwe.u.data.length = p - custom;
180 if (iwe.u.data.length)
181 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
182 /* Add quality statistics */
183 /* TODO: Fix these values... */
185 iwe.u.qual.qual = network->stats.signal;
186 iwe.u.qual.level = network->stats.rssi;
187 iwe.u.qual.noise = network->stats.noise;
188 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
189 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
190 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
191 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
192 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
193 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
194 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
195 iwe.u.qual.updated = 7;
196 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
197 iwe.cmd = IWEVCUSTOM;
200 iwe.u.data.length = p - custom;
201 if (iwe.u.data.length)
202 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
203 #if (WIRELESS_EXT < 18)
204 if (ieee->wpa_enabled && network->wpa_ie_len){
205 char buf[MAX_WPA_IE_LEN * 2 + 30];
206 // printk("WPA IE\n");
208 p += sprintf(p, "wpa_ie=");
209 for (i = 0; i < network->wpa_ie_len; i++) {
210 p += sprintf(p, "%02x", network->wpa_ie[i]);
213 memset(&iwe, 0, sizeof(iwe));
214 iwe.cmd = IWEVCUSTOM;
215 iwe.u.data.length = strlen(buf);
216 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
219 if (ieee->wpa_enabled && network->rsn_ie_len){
220 char buf[MAX_WPA_IE_LEN * 2 + 30];
223 p += sprintf(p, "rsn_ie=");
224 for (i = 0; i < network->rsn_ie_len; i++) {
225 p += sprintf(p, "%02x", network->rsn_ie[i]);
228 memset(&iwe, 0, sizeof(iwe));
229 iwe.cmd = IWEVCUSTOM;
230 iwe.u.data.length = strlen(buf);
231 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
234 memset(&iwe, 0, sizeof(iwe));
235 if (network->wpa_ie_len)
237 char buf[MAX_WPA_IE_LEN];
238 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
240 iwe.u.data.length = network->wpa_ie_len;
241 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
243 memset(&iwe, 0, sizeof(iwe));
244 if (network->rsn_ie_len)
246 char buf[MAX_WPA_IE_LEN];
247 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
249 iwe.u.data.length = network->rsn_ie_len;
250 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
255 /* Add EXTRA: Age to display seconds since last beacon/probe response
256 * for given network. */
257 iwe.cmd = IWEVCUSTOM;
259 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
260 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
261 iwe.u.data.length = p - custom;
262 if (iwe.u.data.length)
263 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
268 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
269 struct iw_request_info *info,
270 union iwreq_data *wrqu, char *extra)
272 struct ieee80211_network *network;
276 // char *stop = ev + IW_SCAN_MAX_DATA;
277 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
278 //char *stop = ev + IW_SCAN_MAX_DATA;
281 IEEE80211_DEBUG_WX("Getting scan\n");
283 spin_lock_irqsave(&ieee->lock, flags);
285 list_for_each_entry(network, &ieee->network_list, list) {
292 if (ieee->scan_age == 0 ||
293 time_after(network->last_scanned + ieee->scan_age, jiffies))
294 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
296 IEEE80211_DEBUG_SCAN(
297 "Not showing network '%s ("
298 "%pM)' due to age (%lums).\n",
299 escape_essid(network->ssid,
302 (jiffies - network->last_scanned) / (HZ / 100));
305 spin_unlock_irqrestore(&ieee->lock, flags);
307 wrqu->data.length = ev - extra;
308 wrqu->data.flags = 0;
310 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
315 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
316 struct iw_request_info *info,
317 union iwreq_data *wrqu, char *keybuf)
319 struct iw_point *erq = &(wrqu->encoding);
320 struct net_device *dev = ieee->dev;
321 struct ieee80211_security sec = {
324 int i, key, key_provided, len;
325 struct ieee80211_crypt_data **crypt;
327 IEEE80211_DEBUG_WX("SET_ENCODE\n");
329 key = erq->flags & IW_ENCODE_INDEX;
337 key = ieee->tx_keyidx;
340 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
341 "provided" : "default");
342 crypt = &ieee->crypt[key];
344 if (erq->flags & IW_ENCODE_DISABLED) {
345 if (key_provided && *crypt) {
346 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
348 ieee80211_crypt_delayed_deinit(ieee, crypt);
350 IEEE80211_DEBUG_WX("Disabling encryption.\n");
352 /* Check all the keys to see if any are still configured,
353 * and if no key index was provided, de-init them all */
354 for (i = 0; i < WEP_KEYS; i++) {
355 if (ieee->crypt[i] != NULL) {
358 ieee80211_crypt_delayed_deinit(
359 ieee, &ieee->crypt[i]);
365 sec.level = SEC_LEVEL_0;
366 sec.flags |= SEC_ENABLED | SEC_LEVEL;
375 sec.flags |= SEC_ENABLED;
377 if (*crypt != NULL && (*crypt)->ops != NULL &&
378 strcmp((*crypt)->ops->name, "WEP") != 0) {
379 /* changing to use WEP; deinit previously used algorithm
381 ieee80211_crypt_delayed_deinit(ieee, crypt);
384 if (*crypt == NULL) {
385 struct ieee80211_crypt_data *new_crypt;
387 /* take WEP into use */
388 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
390 if (new_crypt == NULL)
392 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
394 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
396 new_crypt->priv = new_crypt->ops->init(key);
398 if (!new_crypt->ops || !new_crypt->priv) {
402 printk(KERN_WARNING "%s: could not initialize WEP: "
403 "load module ieee80211_crypt_wep\n",
410 /* If a new key was provided, set it up */
411 if (erq->length > 0) {
412 len = erq->length <= 5 ? 5 : 13;
413 memcpy(sec.keys[key], keybuf, erq->length);
414 if (len > erq->length)
415 memset(sec.keys[key] + erq->length, 0,
417 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
418 key, escape_essid(sec.keys[key], len),
420 sec.key_sizes[key] = len;
421 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
423 sec.flags |= (1 << key);
424 /* This ensures a key will be activated if no key is
426 if (key == sec.active_key)
427 sec.flags |= SEC_ACTIVE_KEY;
428 ieee->tx_keyidx = key;
431 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
432 NULL, (*crypt)->priv);
434 /* Set a default key of all 0 */
435 printk("Setting key %d to all zero.\n",
438 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
440 memset(sec.keys[key], 0, 13);
441 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
443 sec.key_sizes[key] = 13;
444 sec.flags |= (1 << key);
447 /* No key data - just set the default TX key index */
450 "Setting key %d to default Tx key.\n", key);
451 ieee->tx_keyidx = key;
452 sec.active_key = key;
453 sec.flags |= SEC_ACTIVE_KEY;
458 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
459 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
460 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
461 sec.flags |= SEC_AUTH_MODE;
462 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
463 "OPEN" : "SHARED KEY");
465 /* For now we just support WEP, so only set that security level...
466 * TODO: When WPA is added this is one place that needs to change */
467 sec.flags |= SEC_LEVEL;
468 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
470 if (ieee->set_security)
471 ieee->set_security(dev, &sec);
473 /* Do not reset port if card is in Managed mode since resetting will
474 * generate new IEEE 802.11 authentication which may end up in looping
475 * with IEEE 802.1X. If your hardware requires a reset after WEP
476 * configuration (for example... Prism2), implement the reset_port in
477 * the callbacks structures used to initialize the 802.11 stack. */
478 if (ieee->reset_on_keychange &&
479 ieee->iw_mode != IW_MODE_INFRA &&
480 ieee->reset_port && ieee->reset_port(dev)) {
481 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
487 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
488 struct iw_request_info *info,
489 union iwreq_data *wrqu, char *keybuf)
491 struct iw_point *erq = &(wrqu->encoding);
493 struct ieee80211_crypt_data *crypt;
495 IEEE80211_DEBUG_WX("GET_ENCODE\n");
497 if(ieee->iw_mode == IW_MODE_MONITOR)
500 key = erq->flags & IW_ENCODE_INDEX;
506 key = ieee->tx_keyidx;
508 crypt = ieee->crypt[key];
509 erq->flags = key + 1;
511 if (crypt == NULL || crypt->ops == NULL) {
513 erq->flags |= IW_ENCODE_DISABLED;
517 if (strcmp(crypt->ops->name, "WEP") != 0) {
518 /* only WEP is supported with wireless extensions, so just
519 * report that encryption is used */
521 erq->flags |= IW_ENCODE_ENABLED;
525 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
526 erq->length = (len >= 0 ? len : 0);
528 erq->flags |= IW_ENCODE_ENABLED;
531 erq->flags |= IW_ENCODE_OPEN;
533 erq->flags |= IW_ENCODE_RESTRICTED;
537 #if (WIRELESS_EXT >= 18)
538 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
539 struct iw_request_info *info,
540 union iwreq_data *wrqu, char *extra)
543 struct net_device *dev = ieee->dev;
544 struct iw_point *encoding = &wrqu->encoding;
545 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
549 struct ieee80211_crypto_ops *ops;
550 struct ieee80211_crypt_data **crypt;
552 struct ieee80211_security sec = {
555 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
556 idx = encoding->flags & IW_ENCODE_INDEX;
558 if (idx < 1 || idx > WEP_KEYS)
562 idx = ieee->tx_keyidx;
564 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
566 crypt = &ieee->crypt[idx];
570 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
571 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
572 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
574 if (ieee->iw_mode == IW_MODE_INFRA)
576 crypt = &ieee->crypt[idx];
582 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
583 if ((encoding->flags & IW_ENCODE_DISABLED) ||
584 ext->alg == IW_ENCODE_ALG_NONE) {
586 ieee80211_crypt_delayed_deinit(ieee, crypt);
588 for (i = 0; i < WEP_KEYS; i++)
590 if (ieee->crypt[i] != NULL)
597 sec.level = SEC_LEVEL_0;
598 sec.flags |= SEC_LEVEL;
600 //printk("disabled: flag:%x\n", encoding->flags);
607 if (group_key ? !ieee->host_mc_decrypt :
608 !(ieee->host_encrypt || ieee->host_decrypt ||
609 ieee->host_encrypt_msdu))
610 goto skip_host_crypt;
613 case IW_ENCODE_ALG_WEP:
616 case IW_ENCODE_ALG_TKIP:
619 case IW_ENCODE_ALG_CCMP:
623 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
624 dev->name, ext->alg);
628 printk("alg name:%s\n",alg);
630 ops = ieee80211_get_crypto_ops(alg);
632 ops = ieee80211_get_crypto_ops(alg);
634 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
635 dev->name, ext->alg);
636 printk("========>unknown crypto alg %d\n", ext->alg);
641 if (*crypt == NULL || (*crypt)->ops != ops) {
642 struct ieee80211_crypt_data *new_crypt;
644 ieee80211_crypt_delayed_deinit(ieee, crypt);
646 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
647 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
649 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
650 memset(new_crypt,0,sizeof(*new_crypt));
652 if (new_crypt == NULL) {
656 new_crypt->ops = ops;
658 new_crypt->priv = new_crypt->ops->init(idx);
659 if (new_crypt->priv == NULL) {
668 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
669 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
670 (*crypt)->priv) < 0) {
671 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
672 printk("key setting failed\n");
678 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
679 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
680 ieee->tx_keyidx = idx;
681 sec.active_key = idx;
682 sec.flags |= SEC_ACTIVE_KEY;
685 if (ext->alg != IW_ENCODE_ALG_NONE) {
686 //memcpy(sec.keys[idx], ext->key, ext->key_len);
687 sec.key_sizes[idx] = ext->key_len;
688 sec.flags |= (1 << idx);
689 if (ext->alg == IW_ENCODE_ALG_WEP) {
690 // sec.encode_alg[idx] = SEC_ALG_WEP;
691 sec.flags |= SEC_LEVEL;
692 sec.level = SEC_LEVEL_1;
693 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
694 // sec.encode_alg[idx] = SEC_ALG_TKIP;
695 sec.flags |= SEC_LEVEL;
696 sec.level = SEC_LEVEL_2;
697 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
698 // sec.encode_alg[idx] = SEC_ALG_CCMP;
699 sec.flags |= SEC_LEVEL;
700 sec.level = SEC_LEVEL_3;
702 /* Don't set sec level for group keys. */
704 sec.flags &= ~SEC_LEVEL;
708 if (ieee->set_security)
709 ieee->set_security(ieee->dev, &sec);
711 if (ieee->reset_on_keychange &&
712 ieee->iw_mode != IW_MODE_INFRA &&
713 ieee->reset_port && ieee->reset_port(dev)) {
714 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
720 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
721 struct iw_request_info *info,
722 union iwreq_data *wrqu, char *extra)
724 struct iw_point *encoding = &wrqu->encoding;
725 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
726 struct ieee80211_crypt_data *crypt;
727 int idx, max_key_len;
729 max_key_len = encoding->length - sizeof(*ext);
733 idx = encoding->flags & IW_ENCODE_INDEX;
735 if (idx < 1 || idx > WEP_KEYS)
739 idx = ieee->tx_keyidx;
741 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
742 ext->alg != IW_ENCODE_ALG_WEP)
743 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
746 crypt = ieee->crypt[idx];
747 encoding->flags = idx + 1;
748 memset(ext, 0, sizeof(*ext));
750 if (crypt == NULL || crypt->ops == NULL ) {
751 ext->alg = IW_ENCODE_ALG_NONE;
753 encoding->flags |= IW_ENCODE_DISABLED;
755 if (strcmp(crypt->ops->name, "WEP") == 0 )
756 ext->alg = IW_ENCODE_ALG_WEP;
757 else if (strcmp(crypt->ops->name, "TKIP"))
758 ext->alg = IW_ENCODE_ALG_TKIP;
759 else if (strcmp(crypt->ops->name, "CCMP"))
760 ext->alg = IW_ENCODE_ALG_CCMP;
763 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
764 encoding->flags |= IW_ENCODE_ENABLED;
766 (ext->alg == IW_ENCODE_ALG_TKIP ||
767 ext->alg == IW_ENCODE_ALG_CCMP))
768 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
775 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
776 struct iw_request_info *info,
777 union iwreq_data *wrqu, char *extra)
779 struct iw_mlme *mlme = (struct iw_mlme *) extra;
782 case IW_MLME_DISASSOC:
783 ieee80211_disassociate(ieee);
791 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
792 struct iw_request_info *info,
793 struct iw_param *data, char *extra)
795 switch (data->flags & IW_AUTH_INDEX) {
796 case IW_AUTH_WPA_VERSION:
797 /*need to support wpa2 here*/
798 //printk("wpa version:%x\n", data->value);
800 case IW_AUTH_CIPHER_PAIRWISE:
801 case IW_AUTH_CIPHER_GROUP:
802 case IW_AUTH_KEY_MGMT:
804 * * Host AP driver does not use these parameters and allows
805 * * wpa_supplicant to control them internally.
808 case IW_AUTH_TKIP_COUNTERMEASURES:
809 ieee->tkip_countermeasures = data->value;
811 case IW_AUTH_DROP_UNENCRYPTED:
812 ieee->drop_unencrypted = data->value;
815 case IW_AUTH_80211_AUTH_ALG:
816 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
817 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
818 if(data->value & IW_AUTH_ALG_SHARED_KEY){
822 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
826 else if(data->value & IW_AUTH_ALG_LEAP){
829 //printk("hahahaa:LEAP\n");
833 //printk("open_wep:%d\n", ieee->open_wep);
837 case IW_AUTH_WPA_ENABLED:
838 ieee->wpa_enabled = (data->value)?1:0;
839 //printk("enable wpa:%d\n", ieee->wpa_enabled);
843 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
844 ieee->ieee802_1x = data->value;
846 case IW_AUTH_PRIVACY_INVOKED:
847 ieee->privacy_invoked = data->value;
856 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
860 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
862 // printk("return error out, len:%d\n", len);
871 printk("len:%zu, ie:%d\n", len, ie[1]);
874 buf = kmemdup(ie, len, GFP_KERNEL);
879 ieee->wpa_ie_len = len;
885 ieee->wpa_ie_len = 0;