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/module.h>
37 #include "ieee80211.h"
39 static const char *ieee80211_modes[] = {
40 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
47 struct modes_unit ieee80211_modes[] = {
56 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
58 iwe_stream_add_event_rsl(char * stream, /* Stream of events */
59 char * ends, /* End of stream */
60 struct iw_event *iwe, /* Payload */
61 int event_len) /* Real size of payload */
63 /* Check if it's possible */
64 if((stream + event_len) < ends) {
67 memcpy(stream, (char *) iwe, event_len);
73 #define iwe_stream_add_event_rsl iwe_stream_add_event
76 #define MAX_CUSTOM_LEN 64
77 static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
78 char *start, char *stop,
79 struct ieee80211_network *network,
80 struct iw_request_info *info)
82 char custom[MAX_CUSTOM_LEN];
83 char proto_name[IFNAMSIZ];
84 char *pname = proto_name;
89 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
91 /* First entry *MUST* be the AP MAC address */
93 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
94 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
95 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
96 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
98 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_ADDR_LEN);
100 /* Remaining entries will be displayed in the order we provide them */
103 iwe.cmd = SIOCGIWESSID;
104 iwe.u.data.flags = 1;
105 // if (network->flags & NETWORK_EMPTY_ESSID) {
106 if (network->ssid_len == 0) {
107 iwe.u.data.length = sizeof("<hidden>");
108 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
109 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
111 start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
114 iwe.u.data.length = min(network->ssid_len, (u8)32);
115 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
116 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
118 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
121 /* Add the protocol name */
122 iwe.cmd = SIOCGIWNAME;
123 for(i=0; i<(sizeof(ieee80211_modes)/sizeof(ieee80211_modes[0])); i++) {
124 if(network->mode&(1<<i)) {
125 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
126 pname +=ieee80211_modes[i].mode_size;
130 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
131 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
132 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
134 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_CHAR_LEN);
137 iwe.cmd = SIOCGIWMODE;
138 if (network->capability &
139 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
140 if (network->capability & WLAN_CAPABILITY_BSS)
141 iwe.u.mode = IW_MODE_MASTER;
143 iwe.u.mode = IW_MODE_ADHOC;
144 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
145 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
147 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_UINT_LEN);
151 /* Add frequency/channel */
152 iwe.cmd = SIOCGIWFREQ;
153 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
155 iwe.u.freq.m = network->channel;
158 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
159 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
161 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_FREQ_LEN);
163 /* Add encryption capability */
164 iwe.cmd = SIOCGIWENCODE;
165 if (network->capability & WLAN_CAPABILITY_PRIVACY)
166 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
168 iwe.u.data.flags = IW_ENCODE_DISABLED;
169 iwe.u.data.length = 0;
170 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
171 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
173 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
175 /* Add basic and extended rates */
178 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
179 for (i = 0, j = 0; i < network->rates_len; ) {
180 if (j < network->rates_ex_len &&
181 ((network->rates_ex[j] & 0x7F) <
182 (network->rates[i] & 0x7F)))
183 rate = network->rates_ex[j++] & 0x7F;
185 rate = network->rates[i++] & 0x7F;
188 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
189 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
191 for (; j < network->rates_ex_len; j++) {
192 rate = network->rates_ex[j] & 0x7F;
193 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
194 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
199 if (network->mode >= IEEE_N_24G)//add N rate here;
201 PHT_CAPABILITY_ELE ht_cap = NULL;
202 bool is40M = false, isShortGI = false;
204 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
205 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
207 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
208 is40M = (ht_cap->ChlWidth)?1:0;
209 isShortGI = (ht_cap->ChlWidth)?
210 ((ht_cap->ShortGI40Mhz)?1:0):
211 ((ht_cap->ShortGI20Mhz)?1:0);
213 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
214 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
219 printk("max rate:%d ===basic rate:\n", max_rate);
220 for (i=0;i<network->rates_len;i++)
221 printk(" %x", network->rates[i]);
222 printk("\n=======extend rate\n");
223 for (i=0; i<network->rates_ex_len; i++)
224 printk(" %x", network->rates_ex[i]);
227 iwe.cmd = SIOCGIWRATE;
228 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
229 iwe.u.bitrate.value = max_rate * 500000;
230 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
231 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
234 start = iwe_stream_add_event_rsl(start, stop, &iwe,
237 iwe.cmd = IWEVCUSTOM;
238 iwe.u.data.length = p - custom;
239 if (iwe.u.data.length)
240 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
241 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
243 start = iwe_stream_add_point(start, stop, &iwe, custom);
245 /* Add quality statistics */
246 /* TODO: Fix these values... */
248 iwe.u.qual.qual = network->stats.signal;
249 iwe.u.qual.level = network->stats.rssi;
250 iwe.u.qual.noise = network->stats.noise;
251 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
252 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
253 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
254 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
255 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
256 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
257 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
258 iwe.u.qual.updated = 7;
259 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
260 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
262 start = iwe_stream_add_event_rsl(start, stop, &iwe, IW_EV_QUAL_LEN);
264 iwe.cmd = IWEVCUSTOM;
267 iwe.u.data.length = p - custom;
268 if (iwe.u.data.length)
269 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
270 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
272 start = iwe_stream_add_point(start, stop, &iwe, custom);
274 #if (WIRELESS_EXT < 18)
275 if (ieee->wpa_enabled && network->wpa_ie_len){
276 char buf[MAX_WPA_IE_LEN * 2 + 30];
277 // printk("WPA IE\n");
279 p += sprintf(p, "wpa_ie=");
280 for (i = 0; i < network->wpa_ie_len; i++) {
281 p += sprintf(p, "%02x", network->wpa_ie[i]);
284 memset(&iwe, 0, sizeof(iwe));
285 iwe.cmd = IWEVCUSTOM;
286 iwe.u.data.length = strlen(buf);
287 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
288 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
290 start = iwe_stream_add_point(start, stop, &iwe, buf);
294 if (ieee->wpa_enabled && network->rsn_ie_len){
295 char buf[MAX_WPA_IE_LEN * 2 + 30];
298 p += sprintf(p, "rsn_ie=");
299 for (i = 0; i < network->rsn_ie_len; i++) {
300 p += sprintf(p, "%02x", network->rsn_ie[i]);
303 memset(&iwe, 0, sizeof(iwe));
304 iwe.cmd = IWEVCUSTOM;
305 iwe.u.data.length = strlen(buf);
306 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
307 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
309 start = iwe_stream_add_point(start, stop, &iwe, buf);
313 memset(&iwe, 0, sizeof(iwe));
314 if (network->wpa_ie_len)
316 char buf[MAX_WPA_IE_LEN];
317 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
319 iwe.u.data.length = network->wpa_ie_len;
320 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
321 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
323 start = iwe_stream_add_point(start, stop, &iwe, buf);
326 memset(&iwe, 0, sizeof(iwe));
327 if (network->rsn_ie_len)
329 char buf[MAX_WPA_IE_LEN];
330 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
332 iwe.u.data.length = network->rsn_ie_len;
333 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
334 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
336 start = iwe_stream_add_point(start, stop, &iwe, buf);
342 /* Add EXTRA: Age to display seconds since last beacon/probe response
343 * for given network. */
344 iwe.cmd = IWEVCUSTOM;
346 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
347 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
348 iwe.u.data.length = p - custom;
349 if (iwe.u.data.length)
350 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
351 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
353 start = iwe_stream_add_point(start, stop, &iwe, custom);
359 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
360 struct iw_request_info *info,
361 union iwreq_data *wrqu, char *extra)
363 struct ieee80211_network *network;
367 // char *stop = ev + IW_SCAN_MAX_DATA;
368 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
369 //char *stop = ev + IW_SCAN_MAX_DATA;
372 IEEE80211_DEBUG_WX("Getting scan\n");
374 spin_lock_irqsave(&ieee->lock, flags);
376 list_for_each_entry(network, &ieee->network_list, list) {
383 if (ieee->scan_age == 0 ||
384 time_after(network->last_scanned + ieee->scan_age, jiffies))
385 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
387 IEEE80211_DEBUG_SCAN(
388 "Not showing network '%s ("
389 MAC_FMT ")' due to age (%lums).\n",
390 escape_essid(network->ssid,
392 MAC_ARG(network->bssid),
393 (jiffies - network->last_scanned) / (HZ / 100));
396 spin_unlock_irqrestore(&ieee->lock, flags);
398 wrqu->data.length = ev - extra;
399 wrqu->data.flags = 0;
401 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
406 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
407 struct iw_request_info *info,
408 union iwreq_data *wrqu, char *keybuf)
410 struct iw_point *erq = &(wrqu->encoding);
411 struct net_device *dev = ieee->dev;
412 struct ieee80211_security sec = {
415 int i, key, key_provided, len;
416 struct ieee80211_crypt_data **crypt;
418 IEEE80211_DEBUG_WX("SET_ENCODE\n");
420 key = erq->flags & IW_ENCODE_INDEX;
428 key = ieee->tx_keyidx;
431 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
432 "provided" : "default");
433 crypt = &ieee->crypt[key];
435 if (erq->flags & IW_ENCODE_DISABLED) {
436 if (key_provided && *crypt) {
437 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
439 ieee80211_crypt_delayed_deinit(ieee, crypt);
441 IEEE80211_DEBUG_WX("Disabling encryption.\n");
443 /* Check all the keys to see if any are still configured,
444 * and if no key index was provided, de-init them all */
445 for (i = 0; i < WEP_KEYS; i++) {
446 if (ieee->crypt[i] != NULL) {
449 ieee80211_crypt_delayed_deinit(
450 ieee, &ieee->crypt[i]);
456 sec.level = SEC_LEVEL_0;
457 sec.flags |= SEC_ENABLED | SEC_LEVEL;
466 sec.flags |= SEC_ENABLED;
468 if (*crypt != NULL && (*crypt)->ops != NULL &&
469 strcmp((*crypt)->ops->name, "WEP") != 0) {
470 /* changing to use WEP; deinit previously used algorithm
472 ieee80211_crypt_delayed_deinit(ieee, crypt);
475 if (*crypt == NULL) {
476 struct ieee80211_crypt_data *new_crypt;
478 /* take WEP into use */
479 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
481 if (new_crypt == NULL)
483 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
484 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
486 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
488 new_crypt->priv = new_crypt->ops->init(key);
490 if (!new_crypt->ops || !new_crypt->priv) {
494 printk(KERN_WARNING "%s: could not initialize WEP: "
495 "load module ieee80211_crypt_wep\n",
502 /* If a new key was provided, set it up */
503 if (erq->length > 0) {
504 len = erq->length <= 5 ? 5 : 13;
505 memcpy(sec.keys[key], keybuf, erq->length);
506 if (len > erq->length)
507 memset(sec.keys[key] + erq->length, 0,
509 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
510 key, escape_essid(sec.keys[key], len),
512 sec.key_sizes[key] = len;
513 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
515 sec.flags |= (1 << key);
516 /* This ensures a key will be activated if no key is
518 if (key == sec.active_key)
519 sec.flags |= SEC_ACTIVE_KEY;
520 ieee->tx_keyidx = key;
523 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
524 NULL, (*crypt)->priv);
526 /* Set a default key of all 0 */
527 printk("Setting key %d to all zero.\n",
530 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
532 memset(sec.keys[key], 0, 13);
533 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
535 sec.key_sizes[key] = 13;
536 sec.flags |= (1 << key);
539 /* No key data - just set the default TX key index */
542 "Setting key %d to default Tx key.\n", key);
543 ieee->tx_keyidx = key;
544 sec.active_key = key;
545 sec.flags |= SEC_ACTIVE_KEY;
550 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
551 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
552 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
553 sec.flags |= SEC_AUTH_MODE;
554 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
555 "OPEN" : "SHARED KEY");
557 /* For now we just support WEP, so only set that security level...
558 * TODO: When WPA is added this is one place that needs to change */
559 sec.flags |= SEC_LEVEL;
560 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
562 if (ieee->set_security)
563 ieee->set_security(dev, &sec);
565 /* Do not reset port if card is in Managed mode since resetting will
566 * generate new IEEE 802.11 authentication which may end up in looping
567 * with IEEE 802.1X. If your hardware requires a reset after WEP
568 * configuration (for example... Prism2), implement the reset_port in
569 * the callbacks structures used to initialize the 802.11 stack. */
570 if (ieee->reset_on_keychange &&
571 ieee->iw_mode != IW_MODE_INFRA &&
572 ieee->reset_port && ieee->reset_port(dev)) {
573 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
579 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
580 struct iw_request_info *info,
581 union iwreq_data *wrqu, char *keybuf)
583 struct iw_point *erq = &(wrqu->encoding);
585 struct ieee80211_crypt_data *crypt;
587 IEEE80211_DEBUG_WX("GET_ENCODE\n");
589 if(ieee->iw_mode == IW_MODE_MONITOR)
592 key = erq->flags & IW_ENCODE_INDEX;
598 key = ieee->tx_keyidx;
600 crypt = ieee->crypt[key];
601 erq->flags = key + 1;
603 if (crypt == NULL || crypt->ops == NULL) {
605 erq->flags |= IW_ENCODE_DISABLED;
609 if (strcmp(crypt->ops->name, "WEP") != 0) {
610 /* only WEP is supported with wireless extensions, so just
611 * report that encryption is used */
613 erq->flags |= IW_ENCODE_ENABLED;
617 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
618 erq->length = (len >= 0 ? len : 0);
620 erq->flags |= IW_ENCODE_ENABLED;
623 erq->flags |= IW_ENCODE_OPEN;
625 erq->flags |= IW_ENCODE_RESTRICTED;
629 #if (WIRELESS_EXT >= 18)
630 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
631 struct iw_request_info *info,
632 union iwreq_data *wrqu, char *extra)
635 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
636 struct net_device *dev = ieee->dev;
637 struct iw_point *encoding = &wrqu->encoding;
638 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
642 struct ieee80211_crypto_ops *ops;
643 struct ieee80211_crypt_data **crypt;
645 struct ieee80211_security sec = {
648 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
649 idx = encoding->flags & IW_ENCODE_INDEX;
651 if (idx < 1 || idx > WEP_KEYS)
655 idx = ieee->tx_keyidx;
657 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
659 crypt = &ieee->crypt[idx];
663 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
664 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
665 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
667 if (ieee->iw_mode == IW_MODE_INFRA)
669 crypt = &ieee->crypt[idx];
675 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
676 if ((encoding->flags & IW_ENCODE_DISABLED) ||
677 ext->alg == IW_ENCODE_ALG_NONE) {
679 ieee80211_crypt_delayed_deinit(ieee, crypt);
681 for (i = 0; i < WEP_KEYS; i++)
683 if (ieee->crypt[i] != NULL)
690 sec.level = SEC_LEVEL_0;
691 sec.flags |= SEC_LEVEL;
693 //printk("disabled: flag:%x\n", encoding->flags);
700 if (group_key ? !ieee->host_mc_decrypt :
701 !(ieee->host_encrypt || ieee->host_decrypt ||
702 ieee->host_encrypt_msdu))
703 goto skip_host_crypt;
706 case IW_ENCODE_ALG_WEP:
709 case IW_ENCODE_ALG_TKIP:
712 case IW_ENCODE_ALG_CCMP:
716 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
717 dev->name, ext->alg);
721 printk("alg name:%s\n",alg);
723 ops = ieee80211_get_crypto_ops(alg);
725 ops = ieee80211_get_crypto_ops(alg);
727 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
728 dev->name, ext->alg);
729 printk("========>unknown crypto alg %d\n", ext->alg);
734 if (*crypt == NULL || (*crypt)->ops != ops) {
735 struct ieee80211_crypt_data *new_crypt;
737 ieee80211_crypt_delayed_deinit(ieee, crypt);
739 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
740 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
742 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
743 memset(new_crypt,0,sizeof(*new_crypt));
745 if (new_crypt == NULL) {
749 new_crypt->ops = ops;
751 new_crypt->priv = new_crypt->ops->init(idx);
752 if (new_crypt->priv == NULL) {
761 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
762 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
763 (*crypt)->priv) < 0) {
764 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
765 printk("key setting failed\n");
771 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
772 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
773 ieee->tx_keyidx = idx;
774 sec.active_key = idx;
775 sec.flags |= SEC_ACTIVE_KEY;
778 if (ext->alg != IW_ENCODE_ALG_NONE) {
779 //memcpy(sec.keys[idx], ext->key, ext->key_len);
780 sec.key_sizes[idx] = ext->key_len;
781 sec.flags |= (1 << idx);
782 if (ext->alg == IW_ENCODE_ALG_WEP) {
783 // sec.encode_alg[idx] = SEC_ALG_WEP;
784 sec.flags |= SEC_LEVEL;
785 sec.level = SEC_LEVEL_1;
786 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
787 // sec.encode_alg[idx] = SEC_ALG_TKIP;
788 sec.flags |= SEC_LEVEL;
789 sec.level = SEC_LEVEL_2;
790 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
791 // sec.encode_alg[idx] = SEC_ALG_CCMP;
792 sec.flags |= SEC_LEVEL;
793 sec.level = SEC_LEVEL_3;
795 /* Don't set sec level for group keys. */
797 sec.flags &= ~SEC_LEVEL;
801 if (ieee->set_security)
802 ieee->set_security(ieee->dev, &sec);
804 if (ieee->reset_on_keychange &&
805 ieee->iw_mode != IW_MODE_INFRA &&
806 ieee->reset_port && ieee->reset_port(dev)) {
807 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
814 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
815 struct iw_request_info *info,
816 union iwreq_data *wrqu, char *extra)
818 struct iw_point *encoding = &wrqu->encoding;
819 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
820 struct ieee80211_crypt_data *crypt;
821 int idx, max_key_len;
823 max_key_len = encoding->length - sizeof(*ext);
827 idx = encoding->flags & IW_ENCODE_INDEX;
829 if (idx < 1 || idx > WEP_KEYS)
833 idx = ieee->tx_keyidx;
835 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
836 ext->alg != IW_ENCODE_ALG_WEP)
837 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
840 crypt = ieee->crypt[idx];
841 encoding->flags = idx + 1;
842 memset(ext, 0, sizeof(*ext));
844 if (crypt == NULL || crypt->ops == NULL ) {
845 ext->alg = IW_ENCODE_ALG_NONE;
847 encoding->flags |= IW_ENCODE_DISABLED;
849 if (strcmp(crypt->ops->name, "WEP") == 0 )
850 ext->alg = IW_ENCODE_ALG_WEP;
851 else if (strcmp(crypt->ops->name, "TKIP"))
852 ext->alg = IW_ENCODE_ALG_TKIP;
853 else if (strcmp(crypt->ops->name, "CCMP"))
854 ext->alg = IW_ENCODE_ALG_CCMP;
857 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
858 encoding->flags |= IW_ENCODE_ENABLED;
860 (ext->alg == IW_ENCODE_ALG_TKIP ||
861 ext->alg == IW_ENCODE_ALG_CCMP))
862 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
869 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
870 struct iw_request_info *info,
871 union iwreq_data *wrqu, char *extra)
873 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
874 struct iw_mlme *mlme = (struct iw_mlme *) extra;
877 case IW_MLME_DISASSOC:
878 ieee80211_disassociate(ieee);
887 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
888 struct iw_request_info *info,
889 struct iw_param *data, char *extra)
891 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
892 switch (data->flags & IW_AUTH_INDEX) {
893 case IW_AUTH_WPA_VERSION:
894 /*need to support wpa2 here*/
895 //printk("wpa version:%x\n", data->value);
897 case IW_AUTH_CIPHER_PAIRWISE:
898 case IW_AUTH_CIPHER_GROUP:
899 case IW_AUTH_KEY_MGMT:
901 * * Host AP driver does not use these parameters and allows
902 * * wpa_supplicant to control them internally.
905 case IW_AUTH_TKIP_COUNTERMEASURES:
906 ieee->tkip_countermeasures = data->value;
908 case IW_AUTH_DROP_UNENCRYPTED:
909 ieee->drop_unencrypted = data->value;
912 case IW_AUTH_80211_AUTH_ALG:
913 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
914 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
915 if(data->value & IW_AUTH_ALG_SHARED_KEY){
919 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
923 else if(data->value & IW_AUTH_ALG_LEAP){
926 //printk("hahahaa:LEAP\n");
930 //printk("open_wep:%d\n", ieee->open_wep);
934 case IW_AUTH_WPA_ENABLED:
935 ieee->wpa_enabled = (data->value)?1:0;
936 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
940 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
941 ieee->ieee802_1x = data->value;
943 case IW_AUTH_PRIVACY_INVOKED:
944 ieee->privacy_invoked = data->value;
954 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
956 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
958 printk("====>%s()\n", __FUNCTION__);
961 for (i=0; i<len; i++)
962 printk("%2x ", ie[i]&0xff);
968 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
970 // printk("return error out, len:%d\n", len);
979 printk("len:%zu, ie:%d\n", len, ie[1]);
982 buf = kmalloc(len, GFP_KERNEL);
985 memcpy(buf, ie, len);
988 ieee->wpa_ie_len = len;
994 ieee->wpa_ie_len = 0;
1002 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1003 //EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
1004 #if (WIRELESS_EXT >= 18)
1005 //EXPORT_SYMBOL(ieee80211_wx_set_mlme);
1006 //EXPORT_SYMBOL(ieee80211_wx_set_auth);
1007 //EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
1008 //EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
1010 //EXPORT_SYMBOL(ieee80211_wx_get_scan);
1011 //EXPORT_SYMBOL(ieee80211_wx_set_encode);
1012 //EXPORT_SYMBOL(ieee80211_wx_get_encode);
1014 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_gen_ie);
1015 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_mlme);
1016 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_auth);
1017 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_encode_ext);
1018 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_scan);
1019 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_encode);
1020 //EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_encode);