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 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
59 iwe_stream_add_event_rsl(char * stream, /* Stream of events */
60 char * ends, /* End of stream */
61 struct iw_event *iwe, /* Payload */
62 int event_len) /* Real size of payload */
64 /* Check if it's possible */
65 if((stream + event_len) < ends) {
68 memcpy(stream, (char *) iwe, event_len);
74 #define iwe_stream_add_event_rsl iwe_stream_add_event
77 #define MAX_CUSTOM_LEN 64
78 static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
79 char *start, char *stop,
80 struct ieee80211_network *network,
81 struct iw_request_info *info)
83 char custom[MAX_CUSTOM_LEN];
84 char proto_name[IFNAMSIZ];
85 char *pname = proto_name;
90 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
92 /* First entry *MUST* be the AP MAC address */
94 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
95 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
96 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
97 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
99 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_ADDR_LEN);
101 /* Remaining entries will be displayed in the order we provide them */
104 iwe.cmd = SIOCGIWESSID;
105 iwe.u.data.flags = 1;
106 // if (network->flags & NETWORK_EMPTY_ESSID) {
107 if (network->ssid_len == 0) {
108 iwe.u.data.length = sizeof("<hidden>");
109 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
110 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
112 start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
115 iwe.u.data.length = min(network->ssid_len, (u8)32);
116 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
117 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
119 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
122 /* Add the protocol name */
123 iwe.cmd = SIOCGIWNAME;
124 for(i=0; i<(sizeof(ieee80211_modes)/sizeof(ieee80211_modes[0])); i++) {
125 if(network->mode&(1<<i)) {
126 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
127 pname +=ieee80211_modes[i].mode_size;
131 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
132 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
133 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
135 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_CHAR_LEN);
138 iwe.cmd = SIOCGIWMODE;
139 if (network->capability &
140 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
141 if (network->capability & WLAN_CAPABILITY_BSS)
142 iwe.u.mode = IW_MODE_MASTER;
144 iwe.u.mode = IW_MODE_ADHOC;
145 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
146 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
148 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_UINT_LEN);
152 /* Add frequency/channel */
153 iwe.cmd = SIOCGIWFREQ;
154 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
156 iwe.u.freq.m = network->channel;
159 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
160 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
162 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_FREQ_LEN);
164 /* Add encryption capability */
165 iwe.cmd = SIOCGIWENCODE;
166 if (network->capability & WLAN_CAPABILITY_PRIVACY)
167 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
169 iwe.u.data.flags = IW_ENCODE_DISABLED;
170 iwe.u.data.length = 0;
171 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
172 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
174 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
176 /* Add basic and extended rates */
179 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
180 for (i = 0, j = 0; i < network->rates_len; ) {
181 if (j < network->rates_ex_len &&
182 ((network->rates_ex[j] & 0x7F) <
183 (network->rates[i] & 0x7F)))
184 rate = network->rates_ex[j++] & 0x7F;
186 rate = network->rates[i++] & 0x7F;
189 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
190 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
192 for (; j < network->rates_ex_len; j++) {
193 rate = network->rates_ex[j] & 0x7F;
194 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
195 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
200 if (network->mode >= IEEE_N_24G)//add N rate here;
202 PHT_CAPABILITY_ELE ht_cap = NULL;
203 bool is40M = false, isShortGI = false;
205 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
206 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
208 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
209 is40M = (ht_cap->ChlWidth)?1:0;
210 isShortGI = (ht_cap->ChlWidth)?
211 ((ht_cap->ShortGI40Mhz)?1:0):
212 ((ht_cap->ShortGI20Mhz)?1:0);
214 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
215 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
220 printk("max rate:%d ===basic rate:\n", max_rate);
221 for (i=0;i<network->rates_len;i++)
222 printk(" %x", network->rates[i]);
223 printk("\n=======extend rate\n");
224 for (i=0; i<network->rates_ex_len; i++)
225 printk(" %x", network->rates_ex[i]);
228 iwe.cmd = SIOCGIWRATE;
229 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
230 iwe.u.bitrate.value = max_rate * 500000;
231 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
232 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
235 start = iwe_stream_add_event_rsl(start, stop, &iwe,
238 iwe.cmd = IWEVCUSTOM;
239 iwe.u.data.length = p - custom;
240 if (iwe.u.data.length)
241 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
242 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
244 start = iwe_stream_add_point(start, stop, &iwe, custom);
246 /* Add quality statistics */
247 /* TODO: Fix these values... */
249 iwe.u.qual.qual = network->stats.signal;
250 iwe.u.qual.level = network->stats.rssi;
251 iwe.u.qual.noise = network->stats.noise;
252 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
253 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
254 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
255 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
256 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
257 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
258 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
259 iwe.u.qual.updated = 7;
260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
261 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
263 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_QUAL_LEN);
265 iwe.cmd = IWEVCUSTOM;
268 iwe.u.data.length = p - custom;
269 if (iwe.u.data.length)
270 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
271 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
273 start = iwe_stream_add_point(start, stop, &iwe, custom);
275 #if (WIRELESS_EXT < 18)
276 if (ieee->wpa_enabled && network->wpa_ie_len){
277 char buf[MAX_WPA_IE_LEN * 2 + 30];
278 // printk("WPA IE\n");
280 p += sprintf(p, "wpa_ie=");
281 for (i = 0; i < network->wpa_ie_len; i++) {
282 p += sprintf(p, "%02x", network->wpa_ie[i]);
285 memset(&iwe, 0, sizeof(iwe));
286 iwe.cmd = IWEVCUSTOM;
287 iwe.u.data.length = strlen(buf);
288 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
289 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
291 start = iwe_stream_add_point(start, stop, &iwe, buf);
295 if (ieee->wpa_enabled && network->rsn_ie_len){
296 char buf[MAX_WPA_IE_LEN * 2 + 30];
299 p += sprintf(p, "rsn_ie=");
300 for (i = 0; i < network->rsn_ie_len; i++) {
301 p += sprintf(p, "%02x", network->rsn_ie[i]);
304 memset(&iwe, 0, sizeof(iwe));
305 iwe.cmd = IWEVCUSTOM;
306 iwe.u.data.length = strlen(buf);
307 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
308 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
310 start = iwe_stream_add_point(start, stop, &iwe, buf);
314 memset(&iwe, 0, sizeof(iwe));
315 if (network->wpa_ie_len)
317 char buf[MAX_WPA_IE_LEN];
318 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
320 iwe.u.data.length = network->wpa_ie_len;
321 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
322 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
324 start = iwe_stream_add_point(start, stop, &iwe, buf);
327 memset(&iwe, 0, sizeof(iwe));
328 if (network->rsn_ie_len)
330 char buf[MAX_WPA_IE_LEN];
331 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
333 iwe.u.data.length = network->rsn_ie_len;
334 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
335 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
337 start = iwe_stream_add_point(start, stop, &iwe, buf);
343 /* Add EXTRA: Age to display seconds since last beacon/probe response
344 * for given network. */
345 iwe.cmd = IWEVCUSTOM;
347 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
348 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
349 iwe.u.data.length = p - custom;
350 if (iwe.u.data.length)
351 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
352 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
354 start = iwe_stream_add_point(start, stop, &iwe, custom);
360 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
361 struct iw_request_info *info,
362 union iwreq_data *wrqu, char *extra)
364 struct ieee80211_network *network;
368 // char *stop = ev + IW_SCAN_MAX_DATA;
369 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
370 //char *stop = ev + IW_SCAN_MAX_DATA;
373 IEEE80211_DEBUG_WX("Getting scan\n");
375 spin_lock_irqsave(&ieee->lock, flags);
377 list_for_each_entry(network, &ieee->network_list, list) {
384 if (ieee->scan_age == 0 ||
385 time_after(network->last_scanned + ieee->scan_age, jiffies))
386 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
388 IEEE80211_DEBUG_SCAN(
389 "Not showing network '%s ("
390 "%pM)' due to age (%lums).\n",
391 escape_essid(network->ssid,
394 (jiffies - network->last_scanned) / (HZ / 100));
397 spin_unlock_irqrestore(&ieee->lock, flags);
399 wrqu->data.length = ev - extra;
400 wrqu->data.flags = 0;
402 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
407 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
408 struct iw_request_info *info,
409 union iwreq_data *wrqu, char *keybuf)
411 struct iw_point *erq = &(wrqu->encoding);
412 struct net_device *dev = ieee->dev;
413 struct ieee80211_security sec = {
416 int i, key, key_provided, len;
417 struct ieee80211_crypt_data **crypt;
419 IEEE80211_DEBUG_WX("SET_ENCODE\n");
421 key = erq->flags & IW_ENCODE_INDEX;
429 key = ieee->tx_keyidx;
432 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
433 "provided" : "default");
434 crypt = &ieee->crypt[key];
436 if (erq->flags & IW_ENCODE_DISABLED) {
437 if (key_provided && *crypt) {
438 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
440 ieee80211_crypt_delayed_deinit(ieee, crypt);
442 IEEE80211_DEBUG_WX("Disabling encryption.\n");
444 /* Check all the keys to see if any are still configured,
445 * and if no key index was provided, de-init them all */
446 for (i = 0; i < WEP_KEYS; i++) {
447 if (ieee->crypt[i] != NULL) {
450 ieee80211_crypt_delayed_deinit(
451 ieee, &ieee->crypt[i]);
457 sec.level = SEC_LEVEL_0;
458 sec.flags |= SEC_ENABLED | SEC_LEVEL;
467 sec.flags |= SEC_ENABLED;
469 if (*crypt != NULL && (*crypt)->ops != NULL &&
470 strcmp((*crypt)->ops->name, "WEP") != 0) {
471 /* changing to use WEP; deinit previously used algorithm
473 ieee80211_crypt_delayed_deinit(ieee, crypt);
476 if (*crypt == NULL) {
477 struct ieee80211_crypt_data *new_crypt;
479 /* take WEP into use */
480 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
482 if (new_crypt == NULL)
484 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
485 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
487 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
489 new_crypt->priv = new_crypt->ops->init(key);
491 if (!new_crypt->ops || !new_crypt->priv) {
495 printk(KERN_WARNING "%s: could not initialize WEP: "
496 "load module ieee80211_crypt_wep\n",
503 /* If a new key was provided, set it up */
504 if (erq->length > 0) {
505 len = erq->length <= 5 ? 5 : 13;
506 memcpy(sec.keys[key], keybuf, erq->length);
507 if (len > erq->length)
508 memset(sec.keys[key] + erq->length, 0,
510 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
511 key, escape_essid(sec.keys[key], len),
513 sec.key_sizes[key] = len;
514 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
516 sec.flags |= (1 << key);
517 /* This ensures a key will be activated if no key is
519 if (key == sec.active_key)
520 sec.flags |= SEC_ACTIVE_KEY;
521 ieee->tx_keyidx = key;
524 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
525 NULL, (*crypt)->priv);
527 /* Set a default key of all 0 */
528 printk("Setting key %d to all zero.\n",
531 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
533 memset(sec.keys[key], 0, 13);
534 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
536 sec.key_sizes[key] = 13;
537 sec.flags |= (1 << key);
540 /* No key data - just set the default TX key index */
543 "Setting key %d to default Tx key.\n", key);
544 ieee->tx_keyidx = key;
545 sec.active_key = key;
546 sec.flags |= SEC_ACTIVE_KEY;
551 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
552 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
553 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
554 sec.flags |= SEC_AUTH_MODE;
555 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
556 "OPEN" : "SHARED KEY");
558 /* For now we just support WEP, so only set that security level...
559 * TODO: When WPA is added this is one place that needs to change */
560 sec.flags |= SEC_LEVEL;
561 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
563 if (ieee->set_security)
564 ieee->set_security(dev, &sec);
566 /* Do not reset port if card is in Managed mode since resetting will
567 * generate new IEEE 802.11 authentication which may end up in looping
568 * with IEEE 802.1X. If your hardware requires a reset after WEP
569 * configuration (for example... Prism2), implement the reset_port in
570 * the callbacks structures used to initialize the 802.11 stack. */
571 if (ieee->reset_on_keychange &&
572 ieee->iw_mode != IW_MODE_INFRA &&
573 ieee->reset_port && ieee->reset_port(dev)) {
574 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
580 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
581 struct iw_request_info *info,
582 union iwreq_data *wrqu, char *keybuf)
584 struct iw_point *erq = &(wrqu->encoding);
586 struct ieee80211_crypt_data *crypt;
588 IEEE80211_DEBUG_WX("GET_ENCODE\n");
590 if(ieee->iw_mode == IW_MODE_MONITOR)
593 key = erq->flags & IW_ENCODE_INDEX;
599 key = ieee->tx_keyidx;
601 crypt = ieee->crypt[key];
602 erq->flags = key + 1;
604 if (crypt == NULL || crypt->ops == NULL) {
606 erq->flags |= IW_ENCODE_DISABLED;
610 if (strcmp(crypt->ops->name, "WEP") != 0) {
611 /* only WEP is supported with wireless extensions, so just
612 * report that encryption is used */
614 erq->flags |= IW_ENCODE_ENABLED;
618 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
619 erq->length = (len >= 0 ? len : 0);
621 erq->flags |= IW_ENCODE_ENABLED;
624 erq->flags |= IW_ENCODE_OPEN;
626 erq->flags |= IW_ENCODE_RESTRICTED;
630 #if (WIRELESS_EXT >= 18)
631 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
632 struct iw_request_info *info,
633 union iwreq_data *wrqu, char *extra)
636 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
637 struct net_device *dev = ieee->dev;
638 struct iw_point *encoding = &wrqu->encoding;
639 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
643 struct ieee80211_crypto_ops *ops;
644 struct ieee80211_crypt_data **crypt;
646 struct ieee80211_security sec = {
649 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
650 idx = encoding->flags & IW_ENCODE_INDEX;
652 if (idx < 1 || idx > WEP_KEYS)
656 idx = ieee->tx_keyidx;
658 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
660 crypt = &ieee->crypt[idx];
664 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
665 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
666 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
668 if (ieee->iw_mode == IW_MODE_INFRA)
670 crypt = &ieee->crypt[idx];
676 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
677 if ((encoding->flags & IW_ENCODE_DISABLED) ||
678 ext->alg == IW_ENCODE_ALG_NONE) {
680 ieee80211_crypt_delayed_deinit(ieee, crypt);
682 for (i = 0; i < WEP_KEYS; i++)
684 if (ieee->crypt[i] != NULL)
691 sec.level = SEC_LEVEL_0;
692 sec.flags |= SEC_LEVEL;
694 //printk("disabled: flag:%x\n", encoding->flags);
701 if (group_key ? !ieee->host_mc_decrypt :
702 !(ieee->host_encrypt || ieee->host_decrypt ||
703 ieee->host_encrypt_msdu))
704 goto skip_host_crypt;
707 case IW_ENCODE_ALG_WEP:
710 case IW_ENCODE_ALG_TKIP:
713 case IW_ENCODE_ALG_CCMP:
717 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
718 dev->name, ext->alg);
722 printk("alg name:%s\n",alg);
724 ops = ieee80211_get_crypto_ops(alg);
726 ops = ieee80211_get_crypto_ops(alg);
728 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
729 dev->name, ext->alg);
730 printk("========>unknown crypto alg %d\n", ext->alg);
735 if (*crypt == NULL || (*crypt)->ops != ops) {
736 struct ieee80211_crypt_data *new_crypt;
738 ieee80211_crypt_delayed_deinit(ieee, crypt);
740 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
741 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
743 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
744 memset(new_crypt,0,sizeof(*new_crypt));
746 if (new_crypt == NULL) {
750 new_crypt->ops = ops;
752 new_crypt->priv = new_crypt->ops->init(idx);
753 if (new_crypt->priv == NULL) {
762 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
763 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
764 (*crypt)->priv) < 0) {
765 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
766 printk("key setting failed\n");
772 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
773 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
774 ieee->tx_keyidx = idx;
775 sec.active_key = idx;
776 sec.flags |= SEC_ACTIVE_KEY;
779 if (ext->alg != IW_ENCODE_ALG_NONE) {
780 //memcpy(sec.keys[idx], ext->key, ext->key_len);
781 sec.key_sizes[idx] = ext->key_len;
782 sec.flags |= (1 << idx);
783 if (ext->alg == IW_ENCODE_ALG_WEP) {
784 // sec.encode_alg[idx] = SEC_ALG_WEP;
785 sec.flags |= SEC_LEVEL;
786 sec.level = SEC_LEVEL_1;
787 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
788 // sec.encode_alg[idx] = SEC_ALG_TKIP;
789 sec.flags |= SEC_LEVEL;
790 sec.level = SEC_LEVEL_2;
791 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
792 // sec.encode_alg[idx] = SEC_ALG_CCMP;
793 sec.flags |= SEC_LEVEL;
794 sec.level = SEC_LEVEL_3;
796 /* Don't set sec level for group keys. */
798 sec.flags &= ~SEC_LEVEL;
802 if (ieee->set_security)
803 ieee->set_security(ieee->dev, &sec);
805 if (ieee->reset_on_keychange &&
806 ieee->iw_mode != IW_MODE_INFRA &&
807 ieee->reset_port && ieee->reset_port(dev)) {
808 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
815 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
816 struct iw_request_info *info,
817 union iwreq_data *wrqu, char *extra)
819 struct iw_point *encoding = &wrqu->encoding;
820 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
821 struct ieee80211_crypt_data *crypt;
822 int idx, max_key_len;
824 max_key_len = encoding->length - sizeof(*ext);
828 idx = encoding->flags & IW_ENCODE_INDEX;
830 if (idx < 1 || idx > WEP_KEYS)
834 idx = ieee->tx_keyidx;
836 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
837 ext->alg != IW_ENCODE_ALG_WEP)
838 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
841 crypt = ieee->crypt[idx];
842 encoding->flags = idx + 1;
843 memset(ext, 0, sizeof(*ext));
845 if (crypt == NULL || crypt->ops == NULL ) {
846 ext->alg = IW_ENCODE_ALG_NONE;
848 encoding->flags |= IW_ENCODE_DISABLED;
850 if (strcmp(crypt->ops->name, "WEP") == 0 )
851 ext->alg = IW_ENCODE_ALG_WEP;
852 else if (strcmp(crypt->ops->name, "TKIP"))
853 ext->alg = IW_ENCODE_ALG_TKIP;
854 else if (strcmp(crypt->ops->name, "CCMP"))
855 ext->alg = IW_ENCODE_ALG_CCMP;
858 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
859 encoding->flags |= IW_ENCODE_ENABLED;
861 (ext->alg == IW_ENCODE_ALG_TKIP ||
862 ext->alg == IW_ENCODE_ALG_CCMP))
863 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
870 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
871 struct iw_request_info *info,
872 union iwreq_data *wrqu, char *extra)
874 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
875 struct iw_mlme *mlme = (struct iw_mlme *) extra;
878 case IW_MLME_DISASSOC:
879 ieee80211_disassociate(ieee);
888 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
889 struct iw_request_info *info,
890 struct iw_param *data, char *extra)
892 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
893 switch (data->flags & IW_AUTH_INDEX) {
894 case IW_AUTH_WPA_VERSION:
895 /*need to support wpa2 here*/
896 //printk("wpa version:%x\n", data->value);
898 case IW_AUTH_CIPHER_PAIRWISE:
899 case IW_AUTH_CIPHER_GROUP:
900 case IW_AUTH_KEY_MGMT:
902 * * Host AP driver does not use these parameters and allows
903 * * wpa_supplicant to control them internally.
906 case IW_AUTH_TKIP_COUNTERMEASURES:
907 ieee->tkip_countermeasures = data->value;
909 case IW_AUTH_DROP_UNENCRYPTED:
910 ieee->drop_unencrypted = data->value;
913 case IW_AUTH_80211_AUTH_ALG:
914 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
915 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
916 if(data->value & IW_AUTH_ALG_SHARED_KEY){
920 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
924 else if(data->value & IW_AUTH_ALG_LEAP){
927 //printk("hahahaa:LEAP\n");
931 //printk("open_wep:%d\n", ieee->open_wep);
935 case IW_AUTH_WPA_ENABLED:
936 ieee->wpa_enabled = (data->value)?1:0;
937 //printk("enable wpa:%d\n", ieee->wpa_enabled);
941 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
942 ieee->ieee802_1x = data->value;
944 case IW_AUTH_PRIVACY_INVOKED:
945 ieee->privacy_invoked = data->value;
955 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
957 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
959 printk("====>%s()\n", __FUNCTION__);
962 for (i=0; i<len; i++)
963 printk("%2x ", ie[i]&0xff);
969 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
971 // printk("return error out, len:%d\n", len);
980 printk("len:%zu, ie:%d\n", len, ie[1]);
983 buf = kmalloc(len, GFP_KERNEL);
986 memcpy(buf, ie, len);
989 ieee->wpa_ie_len = len;
995 ieee->wpa_ie_len = 0;
1003 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1004 //EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
1005 #if (WIRELESS_EXT >= 18)
1006 //EXPORT_SYMBOL(ieee80211_wx_set_mlme);
1007 //EXPORT_SYMBOL(ieee80211_wx_set_auth);
1008 //EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
1009 //EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
1011 //EXPORT_SYMBOL(ieee80211_wx_get_scan);
1012 //EXPORT_SYMBOL(ieee80211_wx_set_encode);
1013 //EXPORT_SYMBOL(ieee80211_wx_get_encode);
1015 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_gen_ie);
1016 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_mlme);
1017 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_auth);
1018 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_encode_ext);
1019 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_scan);
1020 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_encode);
1021 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_encode);