GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / rtl8192e / ieee80211 / ieee80211_wx.c
blobd06e48842e696b2caab648f576b1262df74e1314
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
8 <jkmaline@cc.hut.fi>
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
18 more details.
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
25 file called LICENSE.
27 Contact Information:
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"
39 struct modes_unit {
40 char *mode_string;
41 int mode_size;
43 struct modes_unit ieee80211_modes[] = {
44 {"a",1},
45 {"b",1},
46 {"g",1},
47 {"?",1},
48 {"N-24G",5},
49 {"N-5G",4},
52 #define iwe_stream_add_event_rsl iwe_stream_add_event
54 #define MAX_CUSTOM_LEN 64
55 static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
56 char *start, char *stop,
57 struct ieee80211_network *network,
58 struct iw_request_info *info)
60 char custom[MAX_CUSTOM_LEN];
61 char proto_name[IFNAMSIZ];
62 char *pname = proto_name;
63 char *p;
64 struct iw_event iwe;
65 int i, j;
66 u16 max_rate, rate;
67 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
69 /* First entry *MUST* be the AP MAC address */
70 iwe.cmd = SIOCGIWAP;
71 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
72 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
73 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
74 /* Remaining entries will be displayed in the order we provide them */
76 /* Add the ESSID */
77 iwe.cmd = SIOCGIWESSID;
78 iwe.u.data.flags = 1;
79 // if (network->flags & NETWORK_EMPTY_ESSID) {
80 if (network->ssid_len == 0) {
81 iwe.u.data.length = sizeof("<hidden>");
82 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
83 } else {
84 iwe.u.data.length = min(network->ssid_len, (u8)32);
85 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
87 /* Add the protocol name */
88 iwe.cmd = SIOCGIWNAME;
89 for(i=0; i<ARRAY_SIZE(ieee80211_modes); i++) {
90 if(network->mode&(1<<i)) {
91 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
92 pname +=ieee80211_modes[i].mode_size;
95 *pname = '\0';
96 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
97 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
98 /* Add mode */
99 iwe.cmd = SIOCGIWMODE;
100 if (network->capability &
101 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
102 if (network->capability & WLAN_CAPABILITY_BSS)
103 iwe.u.mode = IW_MODE_MASTER;
104 else
105 iwe.u.mode = IW_MODE_ADHOC;
106 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
109 /* Add frequency/channel */
110 iwe.cmd = SIOCGIWFREQ;
111 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
112 iwe.u.freq.e = 3; */
113 iwe.u.freq.m = network->channel;
114 iwe.u.freq.e = 0;
115 iwe.u.freq.i = 0;
116 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
117 /* Add encryption capability */
118 iwe.cmd = SIOCGIWENCODE;
119 if (network->capability & WLAN_CAPABILITY_PRIVACY)
120 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
121 else
122 iwe.u.data.flags = IW_ENCODE_DISABLED;
123 iwe.u.data.length = 0;
124 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
125 /* Add basic and extended rates */
126 max_rate = 0;
127 p = custom;
128 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
129 for (i = 0, j = 0; i < network->rates_len; ) {
130 if (j < network->rates_ex_len &&
131 ((network->rates_ex[j] & 0x7F) <
132 (network->rates[i] & 0x7F)))
133 rate = network->rates_ex[j++] & 0x7F;
134 else
135 rate = network->rates[i++] & 0x7F;
136 if (rate > max_rate)
137 max_rate = rate;
138 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
139 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
141 for (; j < network->rates_ex_len; j++) {
142 rate = network->rates_ex[j] & 0x7F;
143 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
144 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
145 if (rate > max_rate)
146 max_rate = rate;
149 if (network->mode >= IEEE_N_24G)//add N rate here;
151 PHT_CAPABILITY_ELE ht_cap = NULL;
152 bool is40M = false, isShortGI = false;
153 u8 max_mcs = 0;
154 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
155 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
156 else
157 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
158 is40M = (ht_cap->ChlWidth)?1:0;
159 isShortGI = (ht_cap->ChlWidth)?
160 ((ht_cap->ShortGI40Mhz)?1:0):
161 ((ht_cap->ShortGI20Mhz)?1:0);
163 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
164 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
165 if (rate > max_rate)
166 max_rate = rate;
168 iwe.cmd = SIOCGIWRATE;
169 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
170 iwe.u.bitrate.value = max_rate * 500000;
171 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
172 IW_EV_PARAM_LEN);
173 iwe.cmd = IWEVCUSTOM;
174 iwe.u.data.length = p - custom;
175 if (iwe.u.data.length)
176 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
177 /* Add quality statistics */
178 /* TODO: Fix these values... */
179 iwe.cmd = IWEVQUAL;
180 iwe.u.qual.qual = network->stats.signal;
181 iwe.u.qual.level = network->stats.rssi;
182 iwe.u.qual.noise = network->stats.noise;
183 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
184 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
185 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
186 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
187 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
188 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
189 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
190 iwe.u.qual.updated = 7;
191 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
192 iwe.cmd = IWEVCUSTOM;
193 p = custom;
195 iwe.u.data.length = p - custom;
196 if (iwe.u.data.length)
197 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
198 #if (WIRELESS_EXT < 18)
199 if (ieee->wpa_enabled && network->wpa_ie_len){
200 char buf[MAX_WPA_IE_LEN * 2 + 30];
201 // printk("WPA IE\n");
202 u8 *p = buf;
203 p += sprintf(p, "wpa_ie=");
204 for (i = 0; i < network->wpa_ie_len; i++) {
205 p += sprintf(p, "%02x", network->wpa_ie[i]);
208 memset(&iwe, 0, sizeof(iwe));
209 iwe.cmd = IWEVCUSTOM;
210 iwe.u.data.length = strlen(buf);
211 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
214 if (ieee->wpa_enabled && network->rsn_ie_len){
215 char buf[MAX_WPA_IE_LEN * 2 + 30];
217 u8 *p = buf;
218 p += sprintf(p, "rsn_ie=");
219 for (i = 0; i < network->rsn_ie_len; i++) {
220 p += sprintf(p, "%02x", network->rsn_ie[i]);
223 memset(&iwe, 0, sizeof(iwe));
224 iwe.cmd = IWEVCUSTOM;
225 iwe.u.data.length = strlen(buf);
226 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
228 #else
229 memset(&iwe, 0, sizeof(iwe));
230 if (network->wpa_ie_len)
232 char buf[MAX_WPA_IE_LEN];
233 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
234 iwe.cmd = IWEVGENIE;
235 iwe.u.data.length = network->wpa_ie_len;
236 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
238 memset(&iwe, 0, sizeof(iwe));
239 if (network->rsn_ie_len)
241 char buf[MAX_WPA_IE_LEN];
242 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
243 iwe.cmd = IWEVGENIE;
244 iwe.u.data.length = network->rsn_ie_len;
245 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
247 #endif
250 /* Add EXTRA: Age to display seconds since last beacon/probe response
251 * for given network. */
252 iwe.cmd = IWEVCUSTOM;
253 p = custom;
254 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
255 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
256 iwe.u.data.length = p - custom;
257 if (iwe.u.data.length)
258 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
260 return start;
263 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
264 struct iw_request_info *info,
265 union iwreq_data *wrqu, char *extra)
267 struct ieee80211_network *network;
268 unsigned long flags;
270 char *ev = extra;
271 // char *stop = ev + IW_SCAN_MAX_DATA;
272 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
273 //char *stop = ev + IW_SCAN_MAX_DATA;
274 int i = 0;
275 int err = 0;
276 IEEE80211_DEBUG_WX("Getting scan\n");
277 down(&ieee->wx_sem);
278 spin_lock_irqsave(&ieee->lock, flags);
280 list_for_each_entry(network, &ieee->network_list, list) {
281 i++;
282 if((stop-ev)<200)
284 err = -E2BIG;
285 break;
287 if (ieee->scan_age == 0 ||
288 time_after(network->last_scanned + ieee->scan_age, jiffies))
289 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
290 else
291 IEEE80211_DEBUG_SCAN(
292 "Not showing network '%s ("
293 "%pM)' due to age (%lums).\n",
294 escape_essid(network->ssid,
295 network->ssid_len),
296 network->bssid,
297 (jiffies - network->last_scanned) / (HZ / 100));
300 spin_unlock_irqrestore(&ieee->lock, flags);
301 up(&ieee->wx_sem);
302 wrqu->data.length = ev - extra;
303 wrqu->data.flags = 0;
305 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
307 return err;
310 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
311 struct iw_request_info *info,
312 union iwreq_data *wrqu, char *keybuf)
314 struct iw_point *erq = &(wrqu->encoding);
315 struct net_device *dev = ieee->dev;
316 struct ieee80211_security sec = {
317 .flags = 0
319 int i, key, key_provided, len;
320 struct ieee80211_crypt_data **crypt;
322 IEEE80211_DEBUG_WX("SET_ENCODE\n");
324 key = erq->flags & IW_ENCODE_INDEX;
325 if (key) {
326 if (key > WEP_KEYS)
327 return -EINVAL;
328 key--;
329 key_provided = 1;
330 } else {
331 key_provided = 0;
332 key = ieee->tx_keyidx;
335 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
336 "provided" : "default");
337 crypt = &ieee->crypt[key];
339 if (erq->flags & IW_ENCODE_DISABLED) {
340 if (key_provided && *crypt) {
341 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
342 key);
343 ieee80211_crypt_delayed_deinit(ieee, crypt);
344 } else
345 IEEE80211_DEBUG_WX("Disabling encryption.\n");
347 /* Check all the keys to see if any are still configured,
348 * and if no key index was provided, de-init them all */
349 for (i = 0; i < WEP_KEYS; i++) {
350 if (ieee->crypt[i] != NULL) {
351 if (key_provided)
352 break;
353 ieee80211_crypt_delayed_deinit(
354 ieee, &ieee->crypt[i]);
358 if (i == WEP_KEYS) {
359 sec.enabled = 0;
360 sec.level = SEC_LEVEL_0;
361 sec.flags |= SEC_ENABLED | SEC_LEVEL;
364 goto done;
369 sec.enabled = 1;
370 sec.flags |= SEC_ENABLED;
372 if (*crypt != NULL && (*crypt)->ops != NULL &&
373 strcmp((*crypt)->ops->name, "WEP") != 0) {
374 /* changing to use WEP; deinit previously used algorithm
375 * on this key */
376 ieee80211_crypt_delayed_deinit(ieee, crypt);
379 if (*crypt == NULL) {
380 struct ieee80211_crypt_data *new_crypt;
382 /* take WEP into use */
383 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
384 GFP_KERNEL);
385 if (new_crypt == NULL)
386 return -ENOMEM;
387 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
388 if (!new_crypt->ops)
389 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
390 if (new_crypt->ops)
391 new_crypt->priv = new_crypt->ops->init(key);
393 if (!new_crypt->ops || !new_crypt->priv) {
394 kfree(new_crypt);
395 new_crypt = NULL;
397 printk(KERN_WARNING "%s: could not initialize WEP: "
398 "load module ieee80211_crypt_wep\n",
399 dev->name);
400 return -EOPNOTSUPP;
402 *crypt = new_crypt;
405 /* If a new key was provided, set it up */
406 if (erq->length > 0) {
407 len = erq->length <= 5 ? 5 : 13;
408 memcpy(sec.keys[key], keybuf, erq->length);
409 if (len > erq->length)
410 memset(sec.keys[key] + erq->length, 0,
411 len - erq->length);
412 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
413 key, escape_essid(sec.keys[key], len),
414 erq->length, len);
415 sec.key_sizes[key] = len;
416 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
417 (*crypt)->priv);
418 sec.flags |= (1 << key);
419 /* This ensures a key will be activated if no key is
420 * explicitely set */
421 if (key == sec.active_key)
422 sec.flags |= SEC_ACTIVE_KEY;
423 ieee->tx_keyidx = key;
425 } else {
426 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
427 NULL, (*crypt)->priv);
428 if (len == 0) {
429 /* Set a default key of all 0 */
430 printk("Setting key %d to all zero.\n",
431 key);
433 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
434 key);
435 memset(sec.keys[key], 0, 13);
436 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
437 (*crypt)->priv);
438 sec.key_sizes[key] = 13;
439 sec.flags |= (1 << key);
442 /* No key data - just set the default TX key index */
443 if (key_provided) {
444 IEEE80211_DEBUG_WX(
445 "Setting key %d to default Tx key.\n", key);
446 ieee->tx_keyidx = key;
447 sec.active_key = key;
448 sec.flags |= SEC_ACTIVE_KEY;
452 done:
453 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
454 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
455 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
456 sec.flags |= SEC_AUTH_MODE;
457 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
458 "OPEN" : "SHARED KEY");
460 /* For now we just support WEP, so only set that security level...
461 * TODO: When WPA is added this is one place that needs to change */
462 sec.flags |= SEC_LEVEL;
463 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
465 if (ieee->set_security)
466 ieee->set_security(dev, &sec);
468 /* Do not reset port if card is in Managed mode since resetting will
469 * generate new IEEE 802.11 authentication which may end up in looping
470 * with IEEE 802.1X. If your hardware requires a reset after WEP
471 * configuration (for example... Prism2), implement the reset_port in
472 * the callbacks structures used to initialize the 802.11 stack. */
473 if (ieee->reset_on_keychange &&
474 ieee->iw_mode != IW_MODE_INFRA &&
475 ieee->reset_port && ieee->reset_port(dev)) {
476 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
477 return -EINVAL;
479 return 0;
482 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
483 struct iw_request_info *info,
484 union iwreq_data *wrqu, char *keybuf)
486 struct iw_point *erq = &(wrqu->encoding);
487 int len, key;
488 struct ieee80211_crypt_data *crypt;
490 IEEE80211_DEBUG_WX("GET_ENCODE\n");
492 if(ieee->iw_mode == IW_MODE_MONITOR)
493 return -1;
495 key = erq->flags & IW_ENCODE_INDEX;
496 if (key) {
497 if (key > WEP_KEYS)
498 return -EINVAL;
499 key--;
500 } else
501 key = ieee->tx_keyidx;
503 crypt = ieee->crypt[key];
504 erq->flags = key + 1;
506 if (crypt == NULL || crypt->ops == NULL) {
507 erq->length = 0;
508 erq->flags |= IW_ENCODE_DISABLED;
509 return 0;
511 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
512 erq->length = (len >= 0 ? len : 0);
514 erq->flags |= IW_ENCODE_ENABLED;
516 if (ieee->open_wep)
517 erq->flags |= IW_ENCODE_OPEN;
518 else
519 erq->flags |= IW_ENCODE_RESTRICTED;
521 return 0;
523 #if (WIRELESS_EXT >= 18)
524 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
525 struct iw_request_info *info,
526 union iwreq_data *wrqu, char *extra)
528 int ret = 0;
529 struct net_device *dev = ieee->dev;
530 struct iw_point *encoding = &wrqu->encoding;
531 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
532 int i, idx;
533 int group_key = 0;
534 const char *alg;
535 struct ieee80211_crypto_ops *ops;
536 struct ieee80211_crypt_data **crypt;
538 struct ieee80211_security sec = {
539 .flags = 0,
541 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
542 idx = encoding->flags & IW_ENCODE_INDEX;
543 if (idx) {
544 if (idx < 1 || idx > WEP_KEYS)
545 return -EINVAL;
546 idx--;
547 } else
548 idx = ieee->tx_keyidx;
550 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
552 crypt = &ieee->crypt[idx];
554 group_key = 1;
555 } else {
556 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
557 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
558 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
559 return -EINVAL;
560 if (ieee->iw_mode == IW_MODE_INFRA)
562 crypt = &ieee->crypt[idx];
564 else
565 return -EINVAL;
568 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
569 if ((encoding->flags & IW_ENCODE_DISABLED) ||
570 ext->alg == IW_ENCODE_ALG_NONE) {
571 if (*crypt)
572 ieee80211_crypt_delayed_deinit(ieee, crypt);
574 for (i = 0; i < WEP_KEYS; i++)
576 if (ieee->crypt[i] != NULL)
578 break;
580 if (i == WEP_KEYS) {
581 sec.enabled = 0;
582 // sec.encrypt = 0;
583 sec.level = SEC_LEVEL_0;
584 sec.flags |= SEC_LEVEL;
586 //printk("disabled: flag:%x\n", encoding->flags);
587 goto done;
590 sec.enabled = 1;
591 // sec.encrypt = 1;
592 switch (ext->alg) {
593 case IW_ENCODE_ALG_WEP:
594 alg = "WEP";
595 break;
596 case IW_ENCODE_ALG_TKIP:
597 alg = "TKIP";
598 break;
599 case IW_ENCODE_ALG_CCMP:
600 alg = "CCMP";
601 break;
602 default:
603 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
604 dev->name, ext->alg);
605 ret = -EINVAL;
606 goto done;
608 printk("alg name:%s\n",alg);
610 ops = ieee80211_get_crypto_ops(alg);
611 if (ops == NULL)
612 ops = ieee80211_get_crypto_ops(alg);
613 if (ops == NULL) {
614 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
615 dev->name, ext->alg);
616 printk("========>unknown crypto alg %d\n", ext->alg);
617 ret = -EINVAL;
618 goto done;
621 if (*crypt == NULL || (*crypt)->ops != ops) {
622 struct ieee80211_crypt_data *new_crypt;
624 ieee80211_crypt_delayed_deinit(ieee, crypt);
626 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
627 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
628 #else
629 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
630 memset(new_crypt,0,sizeof(*new_crypt));
631 #endif
632 if (new_crypt == NULL) {
633 ret = -ENOMEM;
634 goto done;
636 new_crypt->ops = ops;
637 if (new_crypt->ops)
638 new_crypt->priv = new_crypt->ops->init(idx);
639 if (new_crypt->priv == NULL) {
640 kfree(new_crypt);
641 ret = -EINVAL;
642 goto done;
644 *crypt = new_crypt;
648 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
649 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
650 (*crypt)->priv) < 0) {
651 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
652 printk("key setting failed\n");
653 ret = -EINVAL;
654 goto done;
656 //skip_host_crypt:
657 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
658 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
659 ieee->tx_keyidx = idx;
660 sec.active_key = idx;
661 sec.flags |= SEC_ACTIVE_KEY;
664 if (ext->alg != IW_ENCODE_ALG_NONE) {
665 //memcpy(sec.keys[idx], ext->key, ext->key_len);
666 sec.key_sizes[idx] = ext->key_len;
667 sec.flags |= (1 << idx);
668 if (ext->alg == IW_ENCODE_ALG_WEP) {
669 // sec.encode_alg[idx] = SEC_ALG_WEP;
670 sec.flags |= SEC_LEVEL;
671 sec.level = SEC_LEVEL_1;
672 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
673 // sec.encode_alg[idx] = SEC_ALG_TKIP;
674 sec.flags |= SEC_LEVEL;
675 sec.level = SEC_LEVEL_2;
676 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
677 // sec.encode_alg[idx] = SEC_ALG_CCMP;
678 sec.flags |= SEC_LEVEL;
679 sec.level = SEC_LEVEL_3;
681 /* Don't set sec level for group keys. */
682 if (group_key)
683 sec.flags &= ~SEC_LEVEL;
685 done:
686 if (ieee->set_security)
687 ieee->set_security(ieee->dev, &sec);
689 if (ieee->reset_on_keychange &&
690 ieee->iw_mode != IW_MODE_INFRA &&
691 ieee->reset_port && ieee->reset_port(dev)) {
692 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
693 return -EINVAL;
695 return ret;
698 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
699 struct iw_request_info *info,
700 union iwreq_data *wrqu, char *extra)
702 struct iw_point *encoding = &wrqu->encoding;
703 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
704 struct ieee80211_crypt_data *crypt;
705 int idx, max_key_len;
707 max_key_len = encoding->length - sizeof(*ext);
708 if (max_key_len < 0)
709 return -EINVAL;
711 idx = encoding->flags & IW_ENCODE_INDEX;
712 if (idx) {
713 if (idx < 1 || idx > WEP_KEYS)
714 return -EINVAL;
715 idx--;
716 } else
717 idx = ieee->tx_keyidx;
719 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
720 ext->alg != IW_ENCODE_ALG_WEP)
721 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
722 return -EINVAL;
724 crypt = ieee->crypt[idx];
725 encoding->flags = idx + 1;
726 memset(ext, 0, sizeof(*ext));
728 if (crypt == NULL || crypt->ops == NULL ) {
729 ext->alg = IW_ENCODE_ALG_NONE;
730 ext->key_len = 0;
731 encoding->flags |= IW_ENCODE_DISABLED;
732 } else {
733 if (strcmp(crypt->ops->name, "WEP") == 0 )
734 ext->alg = IW_ENCODE_ALG_WEP;
735 else if (strcmp(crypt->ops->name, "TKIP"))
736 ext->alg = IW_ENCODE_ALG_TKIP;
737 else if (strcmp(crypt->ops->name, "CCMP"))
738 ext->alg = IW_ENCODE_ALG_CCMP;
739 else
740 return -EINVAL;
741 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
742 encoding->flags |= IW_ENCODE_ENABLED;
743 if (ext->key_len &&
744 (ext->alg == IW_ENCODE_ALG_TKIP ||
745 ext->alg == IW_ENCODE_ALG_CCMP))
746 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
750 return 0;
753 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
754 struct iw_request_info *info,
755 union iwreq_data *wrqu, char *extra)
757 struct iw_mlme *mlme = (struct iw_mlme *) extra;
758 switch (mlme->cmd) {
759 case IW_MLME_DEAUTH:
760 case IW_MLME_DISASSOC:
761 ieee80211_disassociate(ieee);
762 break;
763 default:
764 return -EOPNOTSUPP;
766 return 0;
769 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
770 struct iw_request_info *info,
771 struct iw_param *data, char *extra)
773 switch (data->flags & IW_AUTH_INDEX) {
774 case IW_AUTH_WPA_VERSION:
775 /*need to support wpa2 here*/
776 //printk("wpa version:%x\n", data->value);
777 break;
778 case IW_AUTH_CIPHER_PAIRWISE:
779 case IW_AUTH_CIPHER_GROUP:
780 case IW_AUTH_KEY_MGMT:
782 * * Host AP driver does not use these parameters and allows
783 * * wpa_supplicant to control them internally.
784 * */
785 break;
786 case IW_AUTH_TKIP_COUNTERMEASURES:
787 ieee->tkip_countermeasures = data->value;
788 break;
789 case IW_AUTH_DROP_UNENCRYPTED:
790 ieee->drop_unencrypted = data->value;
791 break;
793 case IW_AUTH_80211_AUTH_ALG:
794 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
795 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
796 if(data->value & IW_AUTH_ALG_SHARED_KEY){
797 ieee->open_wep = 0;
798 ieee->auth_mode = 1;
800 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
801 ieee->open_wep = 1;
802 ieee->auth_mode = 0;
804 else if(data->value & IW_AUTH_ALG_LEAP){
805 ieee->open_wep = 1;
806 ieee->auth_mode = 2;
807 //printk("hahahaa:LEAP\n");
809 else
810 return -EINVAL;
811 //printk("open_wep:%d\n", ieee->open_wep);
812 break;
814 case IW_AUTH_WPA_ENABLED:
815 ieee->wpa_enabled = (data->value)?1:0;
816 //printk("enable wpa:%d\n", ieee->wpa_enabled);
817 break;
818 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
819 ieee->ieee802_1x = data->value;
820 break;
821 case IW_AUTH_PRIVACY_INVOKED:
822 ieee->privacy_invoked = data->value;
823 break;
824 default:
825 return -EOPNOTSUPP;
827 return 0;
829 #endif
830 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
832 u8 *buf;
834 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
836 // printk("return error out, len:%d\n", len);
837 return -EINVAL;
841 if (len)
843 if (len != ie[1]+2)
845 printk("len:%zu, ie:%d\n", len, ie[1]);
846 return -EINVAL;
848 buf = kmemdup(ie, len, GFP_KERNEL);
849 if (buf == NULL)
850 return -ENOMEM;
851 kfree(ieee->wpa_ie);
852 ieee->wpa_ie = buf;
853 ieee->wpa_ie_len = len;
855 else{
856 if (ieee->wpa_ie)
857 kfree(ieee->wpa_ie);
858 ieee->wpa_ie = NULL;
859 ieee->wpa_ie_len = 0;
861 return 0;