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 / rtl8192su / ieee80211 / ieee80211_wx.c
blobee3a914b494e575cb746d2a02d07c2b987403ebb
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/kmod.h>
34 #include <linux/slab.h>
35 #include <linux/module.h>
37 #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);
75 /* Remaining entries will be displayed in the order we provide them */
77 /* Add the ESSID */
78 iwe.cmd = SIOCGIWESSID;
79 iwe.u.data.flags = 1;
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;
169 iwe.cmd = SIOCGIWRATE;
170 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
171 iwe.u.bitrate.value = max_rate * 500000;
172 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
173 IW_EV_PARAM_LEN);
175 iwe.cmd = IWEVCUSTOM;
176 iwe.u.data.length = p - custom;
177 if (iwe.u.data.length)
178 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
180 /* Add quality statistics */
181 /* TODO: Fix these values... */
182 iwe.cmd = IWEVQUAL;
183 iwe.u.qual.qual = network->stats.signal;
184 iwe.u.qual.level = network->stats.rssi;
185 iwe.u.qual.noise = network->stats.noise;
186 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
187 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
188 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
189 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
190 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
191 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
192 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
193 iwe.u.qual.updated = 7;
194 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
195 iwe.cmd = IWEVCUSTOM;
196 p = custom;
198 iwe.u.data.length = p - custom;
199 if (iwe.u.data.length)
200 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
202 memset(&iwe, 0, sizeof(iwe));
203 if (network->wpa_ie_len)
205 char buf[MAX_WPA_IE_LEN];
206 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
207 iwe.cmd = IWEVGENIE;
208 iwe.u.data.length = network->wpa_ie_len;
209 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
211 memset(&iwe, 0, sizeof(iwe));
212 if (network->rsn_ie_len)
214 char buf[MAX_WPA_IE_LEN];
215 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
216 iwe.cmd = IWEVGENIE;
217 iwe.u.data.length = network->rsn_ie_len;
218 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
221 /* Add EXTRA: Age to display seconds since last beacon/probe response
222 * for given network. */
223 iwe.cmd = IWEVCUSTOM;
224 p = custom;
225 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
226 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
227 iwe.u.data.length = p - custom;
228 if (iwe.u.data.length)
229 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
231 return start;
234 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
235 struct iw_request_info *info,
236 union iwreq_data *wrqu, char *extra)
238 struct ieee80211_network *network;
239 unsigned long flags;
241 char *ev = extra;
242 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
243 int i = 0;
244 int err = 0;
245 IEEE80211_DEBUG_WX("Getting scan\n");
246 down(&ieee->wx_sem);
247 spin_lock_irqsave(&ieee->lock, flags);
249 list_for_each_entry(network, &ieee->network_list, list) {
250 i++;
251 if((stop-ev)<200)
253 err = -E2BIG;
254 break;
256 if (ieee->scan_age == 0 ||
257 time_after(network->last_scanned + ieee->scan_age, jiffies))
258 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
259 else
260 IEEE80211_DEBUG_SCAN(
261 "Not showing network '%s ("
262 "%pM)' due to age (%lums).\n",
263 escape_essid(network->ssid,
264 network->ssid_len),
265 network->bssid,
266 (jiffies - network->last_scanned) / (HZ / 100));
269 spin_unlock_irqrestore(&ieee->lock, flags);
270 up(&ieee->wx_sem);
271 wrqu->data.length = ev - extra;
272 wrqu->data.flags = 0;
274 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
276 return err;
279 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
280 struct iw_request_info *info,
281 union iwreq_data *wrqu, char *keybuf)
283 struct iw_point *erq = &(wrqu->encoding);
284 struct net_device *dev = ieee->dev;
285 struct ieee80211_security sec = {
286 .flags = 0
288 int i, key, key_provided, len;
289 struct ieee80211_crypt_data **crypt;
291 IEEE80211_DEBUG_WX("SET_ENCODE\n");
293 key = erq->flags & IW_ENCODE_INDEX;
294 if (key) {
295 if (key > WEP_KEYS)
296 return -EINVAL;
297 key--;
298 key_provided = 1;
299 } else {
300 key_provided = 0;
301 key = ieee->tx_keyidx;
304 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
305 "provided" : "default");
306 crypt = &ieee->crypt[key];
308 if (erq->flags & IW_ENCODE_DISABLED) {
309 if (key_provided && *crypt) {
310 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
311 key);
312 ieee80211_crypt_delayed_deinit(ieee, crypt);
313 } else
314 IEEE80211_DEBUG_WX("Disabling encryption.\n");
316 /* Check all the keys to see if any are still configured,
317 * and if no key index was provided, de-init them all */
318 for (i = 0; i < WEP_KEYS; i++) {
319 if (ieee->crypt[i] != NULL) {
320 if (key_provided)
321 break;
322 ieee80211_crypt_delayed_deinit(
323 ieee, &ieee->crypt[i]);
327 if (i == WEP_KEYS) {
328 sec.enabled = 0;
329 sec.level = SEC_LEVEL_0;
330 sec.flags |= SEC_ENABLED | SEC_LEVEL;
333 goto done;
338 sec.enabled = 1;
339 sec.flags |= SEC_ENABLED;
341 if (*crypt != NULL && (*crypt)->ops != NULL &&
342 strcmp((*crypt)->ops->name, "WEP") != 0) {
343 /* changing to use WEP; deinit previously used algorithm
344 * on this key */
345 ieee80211_crypt_delayed_deinit(ieee, crypt);
348 if (*crypt == NULL) {
349 struct ieee80211_crypt_data *new_crypt;
351 /* take WEP into use */
352 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
353 GFP_KERNEL);
354 if (new_crypt == NULL)
355 return -ENOMEM;
356 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
357 if (!new_crypt->ops)
358 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
359 if (new_crypt->ops)
360 new_crypt->priv = new_crypt->ops->init(key);
362 if (!new_crypt->ops || !new_crypt->priv) {
363 kfree(new_crypt);
364 new_crypt = NULL;
366 printk(KERN_WARNING "%s: could not initialize WEP: "
367 "load module ieee80211_crypt_wep\n",
368 dev->name);
369 return -EOPNOTSUPP;
371 *crypt = new_crypt;
374 /* If a new key was provided, set it up */
375 if (erq->length > 0) {
376 len = erq->length <= 5 ? 5 : 13;
377 memcpy(sec.keys[key], keybuf, erq->length);
378 if (len > erq->length)
379 memset(sec.keys[key] + erq->length, 0,
380 len - erq->length);
381 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
382 key, escape_essid(sec.keys[key], len),
383 erq->length, len);
384 sec.key_sizes[key] = len;
385 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
386 (*crypt)->priv);
387 sec.flags |= (1 << key);
388 /* This ensures a key will be activated if no key is
389 * explicitely set */
390 if (key == sec.active_key)
391 sec.flags |= SEC_ACTIVE_KEY;
392 ieee->tx_keyidx = key;
394 } else {
395 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
396 NULL, (*crypt)->priv);
397 if (len == 0) {
398 /* Set a default key of all 0 */
399 printk("Setting key %d to all zero.\n",
400 key);
402 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
403 key);
404 memset(sec.keys[key], 0, 13);
405 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
406 (*crypt)->priv);
407 sec.key_sizes[key] = 13;
408 sec.flags |= (1 << key);
411 /* No key data - just set the default TX key index */
412 if (key_provided) {
413 IEEE80211_DEBUG_WX(
414 "Setting key %d to default Tx key.\n", key);
415 ieee->tx_keyidx = key;
416 sec.active_key = key;
417 sec.flags |= SEC_ACTIVE_KEY;
421 done:
422 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
423 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
424 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
425 sec.flags |= SEC_AUTH_MODE;
426 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
427 "OPEN" : "SHARED KEY");
429 /* For now we just support WEP, so only set that security level...
430 * TODO: When WPA is added this is one place that needs to change */
431 sec.flags |= SEC_LEVEL;
432 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
434 if (ieee->set_security)
435 ieee->set_security(dev, &sec);
437 /* Do not reset port if card is in Managed mode since resetting will
438 * generate new IEEE 802.11 authentication which may end up in looping
439 * with IEEE 802.1X. If your hardware requires a reset after WEP
440 * configuration (for example... Prism2), implement the reset_port in
441 * the callbacks structures used to initialize the 802.11 stack. */
442 if (ieee->reset_on_keychange &&
443 ieee->iw_mode != IW_MODE_INFRA &&
444 ieee->reset_port && ieee->reset_port(dev)) {
445 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
446 return -EINVAL;
448 return 0;
451 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
452 struct iw_request_info *info,
453 union iwreq_data *wrqu, char *keybuf)
455 struct iw_point *erq = &(wrqu->encoding);
456 int len, key;
457 struct ieee80211_crypt_data *crypt;
459 IEEE80211_DEBUG_WX("GET_ENCODE\n");
461 if(ieee->iw_mode == IW_MODE_MONITOR)
462 return -1;
464 key = erq->flags & IW_ENCODE_INDEX;
465 if (key) {
466 if (key > WEP_KEYS)
467 return -EINVAL;
468 key--;
469 } else
470 key = ieee->tx_keyidx;
472 crypt = ieee->crypt[key];
473 erq->flags = key + 1;
475 if (crypt == NULL || crypt->ops == NULL) {
476 erq->length = 0;
477 erq->flags |= IW_ENCODE_DISABLED;
478 return 0;
481 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
482 erq->length = (len >= 0 ? len : 0);
484 erq->flags |= IW_ENCODE_ENABLED;
486 if (ieee->open_wep)
487 erq->flags |= IW_ENCODE_OPEN;
488 else
489 erq->flags |= IW_ENCODE_RESTRICTED;
491 return 0;
494 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
495 struct iw_request_info *info,
496 union iwreq_data *wrqu, char *extra)
498 int ret = 0;
499 struct net_device *dev = ieee->dev;
500 struct iw_point *encoding = &wrqu->encoding;
501 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
502 int i, idx;
503 int group_key = 0;
504 const char *alg;
505 struct ieee80211_crypto_ops *ops;
506 struct ieee80211_crypt_data **crypt;
508 struct ieee80211_security sec = {
509 .flags = 0,
511 idx = encoding->flags & IW_ENCODE_INDEX;
512 if (idx) {
513 if (idx < 1 || idx > WEP_KEYS)
514 return -EINVAL;
515 idx--;
516 } else
517 idx = ieee->tx_keyidx;
519 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
521 crypt = &ieee->crypt[idx];
523 group_key = 1;
524 } else {
525 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
526 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
527 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
528 return -EINVAL;
529 if (ieee->iw_mode == IW_MODE_INFRA)
531 crypt = &ieee->crypt[idx];
533 else
534 return -EINVAL;
537 sec.flags |= SEC_ENABLED;
539 if ((encoding->flags & IW_ENCODE_DISABLED) ||
540 ext->alg == IW_ENCODE_ALG_NONE) {
541 if (*crypt)
542 ieee80211_crypt_delayed_deinit(ieee, crypt);
544 for (i = 0; i < WEP_KEYS; i++)
546 if (ieee->crypt[i] != NULL)
548 break;
550 if (i == WEP_KEYS) {
551 sec.enabled = 0;
552 // sec.encrypt = 0;
553 sec.level = SEC_LEVEL_0;
554 sec.flags |= SEC_LEVEL;
556 //printk("disabled: flag:%x\n", encoding->flags);
557 goto done;
560 sec.enabled = 1;
562 switch (ext->alg) {
563 case IW_ENCODE_ALG_WEP:
564 alg = "WEP";
565 break;
566 case IW_ENCODE_ALG_TKIP:
567 alg = "TKIP";
568 break;
569 case IW_ENCODE_ALG_CCMP:
570 alg = "CCMP";
571 break;
572 default:
573 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
574 dev->name, ext->alg);
575 ret = -EINVAL;
576 goto done;
578 IEEE80211_DEBUG_WX("alg name: %s\n", alg);
580 ops = ieee80211_get_crypto_ops(alg);
581 if (ops == NULL)
582 ops = ieee80211_get_crypto_ops(alg);
583 if (ops == NULL) {
584 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
585 dev->name, ext->alg);
586 printk("========>unknown crypto alg %d\n", ext->alg);
587 ret = -EINVAL;
588 goto done;
591 if (*crypt == NULL || (*crypt)->ops != ops) {
592 struct ieee80211_crypt_data *new_crypt;
594 ieee80211_crypt_delayed_deinit(ieee, crypt);
596 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
597 if (new_crypt == NULL) {
598 ret = -ENOMEM;
599 goto done;
601 new_crypt->ops = ops;
602 if (new_crypt->ops)
603 new_crypt->priv = new_crypt->ops->init(idx);
604 if (new_crypt->priv == NULL) {
605 kfree(new_crypt);
606 ret = -EINVAL;
607 goto done;
609 *crypt = new_crypt;
613 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
614 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
615 (*crypt)->priv) < 0) {
616 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
617 printk("key setting failed\n");
618 ret = -EINVAL;
619 goto done;
621 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
622 ieee->tx_keyidx = idx;
623 sec.active_key = idx;
624 sec.flags |= SEC_ACTIVE_KEY;
627 if (ext->alg != IW_ENCODE_ALG_NONE) {
628 sec.key_sizes[idx] = ext->key_len;
629 sec.flags |= (1 << idx);
630 if (ext->alg == IW_ENCODE_ALG_WEP) {
631 sec.flags |= SEC_LEVEL;
632 sec.level = SEC_LEVEL_1;
633 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
634 sec.flags |= SEC_LEVEL;
635 sec.level = SEC_LEVEL_2;
636 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
637 sec.flags |= SEC_LEVEL;
638 sec.level = SEC_LEVEL_3;
640 /* Don't set sec level for group keys. */
641 if (group_key)
642 sec.flags &= ~SEC_LEVEL;
644 done:
645 if (ieee->set_security)
646 ieee->set_security(ieee->dev, &sec);
648 if (ieee->reset_on_keychange &&
649 ieee->iw_mode != IW_MODE_INFRA &&
650 ieee->reset_port && ieee->reset_port(dev)) {
651 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
652 return -EINVAL;
655 return ret;
658 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
659 struct iw_request_info *info,
660 union iwreq_data *wrqu, char *extra)
662 struct iw_mlme *mlme = (struct iw_mlme *) extra;
664 switch (mlme->cmd) {
665 case IW_MLME_DEAUTH:
666 case IW_MLME_DISASSOC:
667 ieee80211_disassociate(ieee);
668 break;
669 default:
670 return -EOPNOTSUPP;
673 return 0;
676 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
677 struct iw_request_info *info,
678 struct iw_param *data, char *extra)
680 switch (data->flags & IW_AUTH_INDEX) {
681 case IW_AUTH_WPA_VERSION:
682 /*need to support wpa2 here*/
683 break;
684 case IW_AUTH_CIPHER_PAIRWISE:
685 case IW_AUTH_CIPHER_GROUP:
686 case IW_AUTH_KEY_MGMT:
688 * * Host AP driver does not use these parameters and allows
689 * * wpa_supplicant to control them internally.
690 * */
691 break;
692 case IW_AUTH_TKIP_COUNTERMEASURES:
693 ieee->tkip_countermeasures = data->value;
694 break;
695 case IW_AUTH_DROP_UNENCRYPTED:
696 ieee->drop_unencrypted = data->value;
697 break;
699 case IW_AUTH_80211_AUTH_ALG:
700 if(data->value & IW_AUTH_ALG_SHARED_KEY){
701 ieee->open_wep = 0;
702 ieee->auth_mode = 1;
704 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
705 ieee->open_wep = 1;
706 ieee->auth_mode = 0;
708 else if(data->value & IW_AUTH_ALG_LEAP){
709 ieee->open_wep = 1;
710 ieee->auth_mode = 2;
712 else
713 return -EINVAL;
714 break;
716 case IW_AUTH_WPA_ENABLED:
717 ieee->wpa_enabled = (data->value)?1:0;
718 break;
719 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
720 ieee->ieee802_1x = data->value;
721 break;
722 case IW_AUTH_PRIVACY_INVOKED:
723 ieee->privacy_invoked = data->value;
724 break;
725 default:
726 return -EOPNOTSUPP;
729 return 0;
732 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
734 u8 *buf;
736 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
738 return -EINVAL;
742 if (len)
744 if (len != ie[1]+2)
746 printk("len: %Zd, ie:%d\n", len, ie[1]);
747 return -EINVAL;
749 buf = kmemdup(ie, len, GFP_KERNEL);
750 if (buf == NULL)
751 return -ENOMEM;
752 kfree(ieee->wpa_ie);
753 ieee->wpa_ie = buf;
754 ieee->wpa_ie_len = len;
756 else{
757 if (ieee->wpa_ie)
758 kfree(ieee->wpa_ie);
759 ieee->wpa_ie = NULL;
760 ieee->wpa_ie_len = 0;
763 return 0;