Staging: rtl8192u: remove dead code
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rtl8192u / ieee80211 / ieee80211_wx.c
blobd397f1d68eb7640668ad05591f0d1908d0d4e957
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/module.h>
37 #include "ieee80211.h"
38 struct modes_unit {
39 char *mode_string;
40 int mode_size;
42 struct modes_unit ieee80211_modes[] = {
43 {"a",1},
44 {"b",1},
45 {"g",1},
46 {"?",1},
47 {"N-24G",5},
48 {"N-5G",4},
51 #define iwe_stream_add_event_rsl iwe_stream_add_event
53 #define MAX_CUSTOM_LEN 64
54 static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
55 char *start, char *stop,
56 struct ieee80211_network *network,
57 struct iw_request_info *info)
59 char custom[MAX_CUSTOM_LEN];
60 char proto_name[IFNAMSIZ];
61 char *pname = proto_name;
62 char *p;
63 struct iw_event iwe;
64 int i, j;
65 u16 max_rate, rate;
66 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
68 /* First entry *MUST* be the AP MAC address */
69 iwe.cmd = SIOCGIWAP;
70 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
71 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
72 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
73 /* Remaining entries will be displayed in the order we provide them */
75 /* Add the ESSID */
76 iwe.cmd = SIOCGIWESSID;
77 iwe.u.data.flags = 1;
78 // if (network->flags & NETWORK_EMPTY_ESSID) {
79 if (network->ssid_len == 0) {
80 iwe.u.data.length = sizeof("<hidden>");
81 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
82 } else {
83 iwe.u.data.length = min(network->ssid_len, (u8)32);
84 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
86 /* Add the protocol name */
87 iwe.cmd = SIOCGIWNAME;
88 for(i=0; i<(sizeof(ieee80211_modes)/sizeof(ieee80211_modes[0])); i++) {
89 if(network->mode&(1<<i)) {
90 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
91 pname +=ieee80211_modes[i].mode_size;
94 *pname = '\0';
95 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
96 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
97 /* Add mode */
98 iwe.cmd = SIOCGIWMODE;
99 if (network->capability &
100 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
101 if (network->capability & WLAN_CAPABILITY_BSS)
102 iwe.u.mode = IW_MODE_MASTER;
103 else
104 iwe.u.mode = IW_MODE_ADHOC;
105 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
108 /* Add frequency/channel */
109 iwe.cmd = SIOCGIWFREQ;
110 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
111 iwe.u.freq.e = 3; */
112 iwe.u.freq.m = network->channel;
113 iwe.u.freq.e = 0;
114 iwe.u.freq.i = 0;
115 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
116 /* Add encryption capability */
117 iwe.cmd = SIOCGIWENCODE;
118 if (network->capability & WLAN_CAPABILITY_PRIVACY)
119 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
120 else
121 iwe.u.data.flags = IW_ENCODE_DISABLED;
122 iwe.u.data.length = 0;
123 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
124 /* Add basic and extended rates */
125 max_rate = 0;
126 p = custom;
127 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
128 for (i = 0, j = 0; i < network->rates_len; ) {
129 if (j < network->rates_ex_len &&
130 ((network->rates_ex[j] & 0x7F) <
131 (network->rates[i] & 0x7F)))
132 rate = network->rates_ex[j++] & 0x7F;
133 else
134 rate = network->rates[i++] & 0x7F;
135 if (rate > max_rate)
136 max_rate = rate;
137 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
138 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
140 for (; j < network->rates_ex_len; j++) {
141 rate = network->rates_ex[j] & 0x7F;
142 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
143 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
144 if (rate > max_rate)
145 max_rate = rate;
148 if (network->mode >= IEEE_N_24G)//add N rate here;
150 PHT_CAPABILITY_ELE ht_cap = NULL;
151 bool is40M = false, isShortGI = false;
152 u8 max_mcs = 0;
153 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
154 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
155 else
156 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
157 is40M = (ht_cap->ChlWidth)?1:0;
158 isShortGI = (ht_cap->ChlWidth)?
159 ((ht_cap->ShortGI40Mhz)?1:0):
160 ((ht_cap->ShortGI20Mhz)?1:0);
162 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
163 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
164 if (rate > max_rate)
165 max_rate = rate;
167 iwe.cmd = SIOCGIWRATE;
168 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
169 iwe.u.bitrate.value = max_rate * 500000;
170 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
171 IW_EV_PARAM_LEN);
172 iwe.cmd = IWEVCUSTOM;
173 iwe.u.data.length = p - custom;
174 if (iwe.u.data.length)
175 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
176 /* Add quality statistics */
177 /* TODO: Fix these values... */
178 iwe.cmd = IWEVQUAL;
179 iwe.u.qual.qual = network->stats.signal;
180 iwe.u.qual.level = network->stats.rssi;
181 iwe.u.qual.noise = network->stats.noise;
182 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
183 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
184 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
185 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
186 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
187 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
188 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
189 iwe.u.qual.updated = 7;
190 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
191 iwe.cmd = IWEVCUSTOM;
192 p = custom;
194 iwe.u.data.length = p - custom;
195 if (iwe.u.data.length)
196 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
197 #if (WIRELESS_EXT < 18)
198 if (ieee->wpa_enabled && network->wpa_ie_len){
199 char buf[MAX_WPA_IE_LEN * 2 + 30];
200 // printk("WPA IE\n");
201 u8 *p = buf;
202 p += sprintf(p, "wpa_ie=");
203 for (i = 0; i < network->wpa_ie_len; i++) {
204 p += sprintf(p, "%02x", network->wpa_ie[i]);
207 memset(&iwe, 0, sizeof(iwe));
208 iwe.cmd = IWEVCUSTOM;
209 iwe.u.data.length = strlen(buf);
210 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
213 if (ieee->wpa_enabled && network->rsn_ie_len){
214 char buf[MAX_WPA_IE_LEN * 2 + 30];
216 u8 *p = buf;
217 p += sprintf(p, "rsn_ie=");
218 for (i = 0; i < network->rsn_ie_len; i++) {
219 p += sprintf(p, "%02x", network->rsn_ie[i]);
222 memset(&iwe, 0, sizeof(iwe));
223 iwe.cmd = IWEVCUSTOM;
224 iwe.u.data.length = strlen(buf);
225 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
227 #else
228 memset(&iwe, 0, sizeof(iwe));
229 if (network->wpa_ie_len)
231 char buf[MAX_WPA_IE_LEN];
232 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
233 iwe.cmd = IWEVGENIE;
234 iwe.u.data.length = network->wpa_ie_len;
235 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
237 memset(&iwe, 0, sizeof(iwe));
238 if (network->rsn_ie_len)
240 char buf[MAX_WPA_IE_LEN];
241 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
242 iwe.cmd = IWEVGENIE;
243 iwe.u.data.length = network->rsn_ie_len;
244 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
246 #endif
249 /* Add EXTRA: Age to display seconds since last beacon/probe response
250 * for given network. */
251 iwe.cmd = IWEVCUSTOM;
252 p = custom;
253 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
254 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
255 iwe.u.data.length = p - custom;
256 if (iwe.u.data.length)
257 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
259 return start;
262 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
263 struct iw_request_info *info,
264 union iwreq_data *wrqu, char *extra)
266 struct ieee80211_network *network;
267 unsigned long flags;
269 char *ev = extra;
270 // char *stop = ev + IW_SCAN_MAX_DATA;
271 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
272 //char *stop = ev + IW_SCAN_MAX_DATA;
273 int i = 0;
274 int err = 0;
275 IEEE80211_DEBUG_WX("Getting scan\n");
276 down(&ieee->wx_sem);
277 spin_lock_irqsave(&ieee->lock, flags);
279 list_for_each_entry(network, &ieee->network_list, list) {
280 i++;
281 if((stop-ev)<200)
283 err = -E2BIG;
284 break;
286 if (ieee->scan_age == 0 ||
287 time_after(network->last_scanned + ieee->scan_age, jiffies))
288 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
289 else
290 IEEE80211_DEBUG_SCAN(
291 "Not showing network '%s ("
292 MAC_FMT ")' due to age (%lums).\n",
293 escape_essid(network->ssid,
294 network->ssid_len),
295 MAC_ARG(network->bssid),
296 (jiffies - network->last_scanned) / (HZ / 100));
299 spin_unlock_irqrestore(&ieee->lock, flags);
300 up(&ieee->wx_sem);
301 wrqu->data.length = ev - extra;
302 wrqu->data.flags = 0;
304 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
306 return err;
309 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
310 struct iw_request_info *info,
311 union iwreq_data *wrqu, char *keybuf)
313 struct iw_point *erq = &(wrqu->encoding);
314 struct net_device *dev = ieee->dev;
315 struct ieee80211_security sec = {
316 .flags = 0
318 int i, key, key_provided, len;
319 struct ieee80211_crypt_data **crypt;
321 IEEE80211_DEBUG_WX("SET_ENCODE\n");
323 key = erq->flags & IW_ENCODE_INDEX;
324 if (key) {
325 if (key > WEP_KEYS)
326 return -EINVAL;
327 key--;
328 key_provided = 1;
329 } else {
330 key_provided = 0;
331 key = ieee->tx_keyidx;
334 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
335 "provided" : "default");
336 crypt = &ieee->crypt[key];
338 if (erq->flags & IW_ENCODE_DISABLED) {
339 if (key_provided && *crypt) {
340 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
341 key);
342 ieee80211_crypt_delayed_deinit(ieee, crypt);
343 } else
344 IEEE80211_DEBUG_WX("Disabling encryption.\n");
346 /* Check all the keys to see if any are still configured,
347 * and if no key index was provided, de-init them all */
348 for (i = 0; i < WEP_KEYS; i++) {
349 if (ieee->crypt[i] != NULL) {
350 if (key_provided)
351 break;
352 ieee80211_crypt_delayed_deinit(
353 ieee, &ieee->crypt[i]);
357 if (i == WEP_KEYS) {
358 sec.enabled = 0;
359 sec.level = SEC_LEVEL_0;
360 sec.flags |= SEC_ENABLED | SEC_LEVEL;
363 goto done;
368 sec.enabled = 1;
369 sec.flags |= SEC_ENABLED;
371 if (*crypt != NULL && (*crypt)->ops != NULL &&
372 strcmp((*crypt)->ops->name, "WEP") != 0) {
373 /* changing to use WEP; deinit previously used algorithm
374 * on this key */
375 ieee80211_crypt_delayed_deinit(ieee, crypt);
378 if (*crypt == NULL) {
379 struct ieee80211_crypt_data *new_crypt;
381 /* take WEP into use */
382 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
383 GFP_KERNEL);
384 if (new_crypt == NULL)
385 return -ENOMEM;
386 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
387 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
388 if (!new_crypt->ops) {
389 request_module("ieee80211_crypt_wep");
390 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
392 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
393 new_crypt->priv = new_crypt->ops->init(key);
395 if (!new_crypt->ops || !new_crypt->priv) {
396 kfree(new_crypt);
397 new_crypt = NULL;
399 printk(KERN_WARNING "%s: could not initialize WEP: "
400 "load module ieee80211_crypt_wep\n",
401 dev->name);
402 return -EOPNOTSUPP;
404 *crypt = new_crypt;
407 /* If a new key was provided, set it up */
408 if (erq->length > 0) {
409 len = erq->length <= 5 ? 5 : 13;
410 memcpy(sec.keys[key], keybuf, erq->length);
411 if (len > erq->length)
412 memset(sec.keys[key] + erq->length, 0,
413 len - erq->length);
414 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
415 key, escape_essid(sec.keys[key], len),
416 erq->length, len);
417 sec.key_sizes[key] = len;
418 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
419 (*crypt)->priv);
420 sec.flags |= (1 << key);
421 /* This ensures a key will be activated if no key is
422 * explicitely set */
423 if (key == sec.active_key)
424 sec.flags |= SEC_ACTIVE_KEY;
425 ieee->tx_keyidx = key;
427 } else {
428 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
429 NULL, (*crypt)->priv);
430 if (len == 0) {
431 /* Set a default key of all 0 */
432 printk("Setting key %d to all zero.\n",
433 key);
435 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
436 key);
437 memset(sec.keys[key], 0, 13);
438 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
439 (*crypt)->priv);
440 sec.key_sizes[key] = 13;
441 sec.flags |= (1 << key);
444 /* No key data - just set the default TX key index */
445 if (key_provided) {
446 IEEE80211_DEBUG_WX(
447 "Setting key %d to default Tx key.\n", key);
448 ieee->tx_keyidx = key;
449 sec.active_key = key;
450 sec.flags |= SEC_ACTIVE_KEY;
454 done:
455 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
456 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
457 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
458 sec.flags |= SEC_AUTH_MODE;
459 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
460 "OPEN" : "SHARED KEY");
462 /* For now we just support WEP, so only set that security level...
463 * TODO: When WPA is added this is one place that needs to change */
464 sec.flags |= SEC_LEVEL;
465 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
467 if (ieee->set_security)
468 ieee->set_security(dev, &sec);
470 /* Do not reset port if card is in Managed mode since resetting will
471 * generate new IEEE 802.11 authentication which may end up in looping
472 * with IEEE 802.1X. If your hardware requires a reset after WEP
473 * configuration (for example... Prism2), implement the reset_port in
474 * the callbacks structures used to initialize the 802.11 stack. */
475 if (ieee->reset_on_keychange &&
476 ieee->iw_mode != IW_MODE_INFRA &&
477 ieee->reset_port && ieee->reset_port(dev)) {
478 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
479 return -EINVAL;
481 return 0;
484 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
485 struct iw_request_info *info,
486 union iwreq_data *wrqu, char *keybuf)
488 struct iw_point *erq = &(wrqu->encoding);
489 int len, key;
490 struct ieee80211_crypt_data *crypt;
492 IEEE80211_DEBUG_WX("GET_ENCODE\n");
494 if(ieee->iw_mode == IW_MODE_MONITOR)
495 return -1;
497 key = erq->flags & IW_ENCODE_INDEX;
498 if (key) {
499 if (key > WEP_KEYS)
500 return -EINVAL;
501 key--;
502 } else
503 key = ieee->tx_keyidx;
505 crypt = ieee->crypt[key];
506 erq->flags = key + 1;
508 if (crypt == NULL || crypt->ops == NULL) {
509 erq->length = 0;
510 erq->flags |= IW_ENCODE_DISABLED;
511 return 0;
513 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
514 erq->length = (len >= 0 ? len : 0);
516 erq->flags |= IW_ENCODE_ENABLED;
518 if (ieee->open_wep)
519 erq->flags |= IW_ENCODE_OPEN;
520 else
521 erq->flags |= IW_ENCODE_RESTRICTED;
523 return 0;
525 #if (WIRELESS_EXT >= 18)
526 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
527 struct iw_request_info *info,
528 union iwreq_data *wrqu, char *extra)
530 int ret = 0;
531 struct net_device *dev = ieee->dev;
532 struct iw_point *encoding = &wrqu->encoding;
533 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
534 int i, idx;
535 int group_key = 0;
536 const char *alg, *module;
537 struct ieee80211_crypto_ops *ops;
538 struct ieee80211_crypt_data **crypt;
540 struct ieee80211_security sec = {
541 .flags = 0,
543 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
544 idx = encoding->flags & IW_ENCODE_INDEX;
545 if (idx) {
546 if (idx < 1 || idx > WEP_KEYS)
547 return -EINVAL;
548 idx--;
549 } else
550 idx = ieee->tx_keyidx;
552 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
554 crypt = &ieee->crypt[idx];
556 group_key = 1;
557 } else {
558 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
559 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
560 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
561 return -EINVAL;
562 if (ieee->iw_mode == IW_MODE_INFRA)
564 crypt = &ieee->crypt[idx];
566 else
567 return -EINVAL;
570 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
571 if ((encoding->flags & IW_ENCODE_DISABLED) ||
572 ext->alg == IW_ENCODE_ALG_NONE) {
573 if (*crypt)
574 ieee80211_crypt_delayed_deinit(ieee, crypt);
576 for (i = 0; i < WEP_KEYS; i++)
578 if (ieee->crypt[i] != NULL)
580 break;
582 if (i == WEP_KEYS) {
583 sec.enabled = 0;
584 // sec.encrypt = 0;
585 sec.level = SEC_LEVEL_0;
586 sec.flags |= SEC_LEVEL;
588 //printk("disabled: flag:%x\n", encoding->flags);
589 goto done;
592 sec.enabled = 1;
593 // sec.encrypt = 1;
594 switch (ext->alg) {
595 case IW_ENCODE_ALG_WEP:
596 alg = "WEP";
597 module = "ieee80211_crypt_wep";
598 break;
599 case IW_ENCODE_ALG_TKIP:
600 alg = "TKIP";
601 module = "ieee80211_crypt_tkip";
602 break;
603 case IW_ENCODE_ALG_CCMP:
604 alg = "CCMP";
605 module = "ieee80211_crypt_ccmp";
606 break;
607 default:
608 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
609 dev->name, ext->alg);
610 ret = -EINVAL;
611 goto done;
613 printk("alg name:%s\n",alg);
615 ops = ieee80211_get_crypto_ops(alg);
616 if (ops == NULL) {
617 request_module(module);
618 ops = ieee80211_get_crypto_ops(alg);
620 if (ops == NULL) {
621 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
622 dev->name, ext->alg);
623 printk("========>unknown crypto alg %d\n", ext->alg);
624 ret = -EINVAL;
625 goto done;
628 if (*crypt == NULL || (*crypt)->ops != ops) {
629 struct ieee80211_crypt_data *new_crypt;
631 ieee80211_crypt_delayed_deinit(ieee, crypt);
633 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
634 if (new_crypt == NULL) {
635 ret = -ENOMEM;
636 goto done;
638 new_crypt->ops = ops;
639 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
640 new_crypt->priv = new_crypt->ops->init(idx);
641 if (new_crypt->priv == NULL) {
642 kfree(new_crypt);
643 ret = -EINVAL;
644 goto done;
646 *crypt = new_crypt;
650 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
651 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
652 (*crypt)->priv) < 0) {
653 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
654 printk("key setting failed\n");
655 ret = -EINVAL;
656 goto done;
658 //skip_host_crypt:
659 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
660 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
661 ieee->tx_keyidx = idx;
662 sec.active_key = idx;
663 sec.flags |= SEC_ACTIVE_KEY;
666 if (ext->alg != IW_ENCODE_ALG_NONE) {
667 //memcpy(sec.keys[idx], ext->key, ext->key_len);
668 sec.key_sizes[idx] = ext->key_len;
669 sec.flags |= (1 << idx);
670 if (ext->alg == IW_ENCODE_ALG_WEP) {
671 // sec.encode_alg[idx] = SEC_ALG_WEP;
672 sec.flags |= SEC_LEVEL;
673 sec.level = SEC_LEVEL_1;
674 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
675 // sec.encode_alg[idx] = SEC_ALG_TKIP;
676 sec.flags |= SEC_LEVEL;
677 sec.level = SEC_LEVEL_2;
678 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
679 // sec.encode_alg[idx] = SEC_ALG_CCMP;
680 sec.flags |= SEC_LEVEL;
681 sec.level = SEC_LEVEL_3;
683 /* Don't set sec level for group keys. */
684 if (group_key)
685 sec.flags &= ~SEC_LEVEL;
687 done:
688 if (ieee->set_security)
689 ieee->set_security(ieee->dev, &sec);
691 if (ieee->reset_on_keychange &&
692 ieee->iw_mode != IW_MODE_INFRA &&
693 ieee->reset_port && ieee->reset_port(dev)) {
694 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
695 return -EINVAL;
697 return ret;
700 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
701 struct iw_request_info *info,
702 union iwreq_data *wrqu, char *extra)
704 struct iw_point *encoding = &wrqu->encoding;
705 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
706 struct ieee80211_crypt_data *crypt;
707 int idx, max_key_len;
709 max_key_len = encoding->length - sizeof(*ext);
710 if (max_key_len < 0)
711 return -EINVAL;
713 idx = encoding->flags & IW_ENCODE_INDEX;
714 if (idx) {
715 if (idx < 1 || idx > WEP_KEYS)
716 return -EINVAL;
717 idx--;
718 } else
719 idx = ieee->tx_keyidx;
721 if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
722 ext->alg != IW_ENCODE_ALG_WEP)
723 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
724 return -EINVAL;
726 crypt = ieee->crypt[idx];
727 encoding->flags = idx + 1;
728 memset(ext, 0, sizeof(*ext));
730 if (crypt == NULL || crypt->ops == NULL ) {
731 ext->alg = IW_ENCODE_ALG_NONE;
732 ext->key_len = 0;
733 encoding->flags |= IW_ENCODE_DISABLED;
734 } else {
735 if (strcmp(crypt->ops->name, "WEP") == 0 )
736 ext->alg = IW_ENCODE_ALG_WEP;
737 else if (strcmp(crypt->ops->name, "TKIP"))
738 ext->alg = IW_ENCODE_ALG_TKIP;
739 else if (strcmp(crypt->ops->name, "CCMP"))
740 ext->alg = IW_ENCODE_ALG_CCMP;
741 else
742 return -EINVAL;
743 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
744 encoding->flags |= IW_ENCODE_ENABLED;
745 if (ext->key_len &&
746 (ext->alg == IW_ENCODE_ALG_TKIP ||
747 ext->alg == IW_ENCODE_ALG_CCMP))
748 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
752 return 0;
755 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
756 struct iw_request_info *info,
757 union iwreq_data *wrqu, char *extra)
759 struct iw_mlme *mlme = (struct iw_mlme *) extra;
760 switch (mlme->cmd) {
761 case IW_MLME_DEAUTH:
762 case IW_MLME_DISASSOC:
763 ieee80211_disassociate(ieee);
764 break;
765 default:
766 return -EOPNOTSUPP;
768 return 0;
771 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
772 struct iw_request_info *info,
773 struct iw_param *data, char *extra)
775 switch (data->flags & IW_AUTH_INDEX) {
776 case IW_AUTH_WPA_VERSION:
777 /*need to support wpa2 here*/
778 //printk("wpa version:%x\n", data->value);
779 break;
780 case IW_AUTH_CIPHER_PAIRWISE:
781 case IW_AUTH_CIPHER_GROUP:
782 case IW_AUTH_KEY_MGMT:
784 * * Host AP driver does not use these parameters and allows
785 * * wpa_supplicant to control them internally.
786 * */
787 break;
788 case IW_AUTH_TKIP_COUNTERMEASURES:
789 ieee->tkip_countermeasures = data->value;
790 break;
791 case IW_AUTH_DROP_UNENCRYPTED:
792 ieee->drop_unencrypted = data->value;
793 break;
795 case IW_AUTH_80211_AUTH_ALG:
796 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
797 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
798 if(data->value & IW_AUTH_ALG_SHARED_KEY){
799 ieee->open_wep = 0;
800 ieee->auth_mode = 1;
802 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
803 ieee->open_wep = 1;
804 ieee->auth_mode = 0;
806 else if(data->value & IW_AUTH_ALG_LEAP){
807 ieee->open_wep = 1;
808 ieee->auth_mode = 2;
809 //printk("hahahaa:LEAP\n");
811 else
812 return -EINVAL;
813 //printk("open_wep:%d\n", ieee->open_wep);
814 break;
816 case IW_AUTH_WPA_ENABLED:
817 ieee->wpa_enabled = (data->value)?1:0;
818 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
819 break;
821 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
822 ieee->ieee802_1x = data->value;
823 break;
824 case IW_AUTH_PRIVACY_INVOKED:
825 ieee->privacy_invoked = data->value;
826 break;
827 default:
828 return -EOPNOTSUPP;
830 return 0;
832 #endif
833 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
835 u8 *buf;
837 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
839 // printk("return error out, len:%d\n", len);
840 return -EINVAL;
844 if (len)
846 if (len != ie[1]+2)
848 printk("len:%d, ie:%d\n", len, ie[1]);
849 return -EINVAL;
851 buf = kmalloc(len, GFP_KERNEL);
852 if (buf == NULL)
853 return -ENOMEM;
854 memcpy(buf, ie, len);
855 kfree(ieee->wpa_ie);
856 ieee->wpa_ie = buf;
857 ieee->wpa_ie_len = len;
859 else{
860 if (ieee->wpa_ie)
861 kfree(ieee->wpa_ie);
862 ieee->wpa_ie = NULL;
863 ieee->wpa_ie_len = 0;
865 return 0;
869 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
870 #if (WIRELESS_EXT >= 18)
871 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
872 EXPORT_SYMBOL(ieee80211_wx_set_auth);
873 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
874 EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
875 #endif
876 EXPORT_SYMBOL(ieee80211_wx_get_scan);
877 EXPORT_SYMBOL(ieee80211_wx_set_encode);
878 EXPORT_SYMBOL(ieee80211_wx_get_encode);