staging: __FUNCTION__ is gcc-specific, use __func__
[linux-2.6/libata-dev.git] / drivers / staging / rtl8187se / ieee80211 / ieee80211_wx.c
blob6aad61e7804161d60b483b1d487c3e3341cfd83e
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 static const char *ieee80211_modes[] = {
39 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
42 #ifdef FEDORACORE_9
43 #define IN_FEDORACORE_9 1
44 #else
45 #define IN_FEDORACORE_9 0
46 #endif
48 #define MAX_CUSTOM_LEN 64
49 static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
50 char *start, char *stop,
51 struct ieee80211_network *network,
52 struct iw_request_info *info)
54 char custom[MAX_CUSTOM_LEN];
55 char *p;
56 struct iw_event iwe;
57 int i, j;
58 u8 max_rate, rate;
60 /* First entry *MUST* be the AP MAC address */
61 iwe.cmd = SIOCGIWAP;
62 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
63 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
64 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
65 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
66 #else
67 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
68 #endif
70 /* Remaining entries will be displayed in the order we provide them */
72 /* Add the ESSID */
73 iwe.cmd = SIOCGIWESSID;
74 iwe.u.data.flags = 1;
75 //YJ,modified,080903,for hidden ap
76 //if (network->flags & NETWORK_EMPTY_ESSID) {
77 if (network->ssid_len == 0) {
78 //YJ,modified,080903,end
79 iwe.u.data.length = sizeof("<hidden>");
80 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
81 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
82 #else
83 start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
84 #endif
85 } else {
86 iwe.u.data.length = min(network->ssid_len, (u8)32);
87 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
88 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
89 #else
90 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
91 #endif
93 //printk("ESSID: %s\n",network->ssid);
94 /* Add the protocol name */
95 iwe.cmd = SIOCGIWNAME;
96 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
97 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
98 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
99 #else
100 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN);
101 #endif
103 /* Add mode */
104 iwe.cmd = SIOCGIWMODE;
105 if (network->capability &
106 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
107 if (network->capability & WLAN_CAPABILITY_BSS)
108 iwe.u.mode = IW_MODE_MASTER;
109 else
110 iwe.u.mode = IW_MODE_ADHOC;
112 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
113 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
114 #else
115 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
116 #endif
119 /* Add frequency/channel */
120 iwe.cmd = SIOCGIWFREQ;
121 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
122 iwe.u.freq.e = 3; */
123 iwe.u.freq.m = network->channel;
124 iwe.u.freq.e = 0;
125 iwe.u.freq.i = 0;
126 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
127 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
128 #else
129 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
130 #endif
132 /* Add encryption capability */
133 iwe.cmd = SIOCGIWENCODE;
134 if (network->capability & WLAN_CAPABILITY_PRIVACY)
135 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
136 else
137 iwe.u.data.flags = IW_ENCODE_DISABLED;
138 iwe.u.data.length = 0;
139 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
140 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
141 #else
142 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
143 #endif
145 /* Add basic and extended rates */
146 max_rate = 0;
147 p = custom;
148 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
149 for (i = 0, j = 0; i < network->rates_len; ) {
150 if (j < network->rates_ex_len &&
151 ((network->rates_ex[j] & 0x7F) <
152 (network->rates[i] & 0x7F)))
153 rate = network->rates_ex[j++] & 0x7F;
154 else
155 rate = network->rates[i++] & 0x7F;
156 if (rate > max_rate)
157 max_rate = rate;
158 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
159 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
161 for (; j < network->rates_ex_len; j++) {
162 rate = network->rates_ex[j] & 0x7F;
163 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
164 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
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 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
173 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
174 #else
175 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN);
176 #endif
178 iwe.cmd = IWEVCUSTOM;
179 iwe.u.data.length = p - custom;
180 if (iwe.u.data.length)
181 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
182 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
183 #else
184 start = iwe_stream_add_point(start, stop, &iwe, custom);
185 #endif
187 /* Add quality statistics */
188 /* TODO: Fix these values... */
189 if (network->stats.signal == 0 || network->stats.rssi == 0)
190 printk("========>signal:%d, rssi:%d\n", network->stats.signal, network->stats.rssi);
191 iwe.cmd = IWEVQUAL;
192 // printk("SIGNAL: %d,RSSI: %d,NOISE: %d\n",network->stats.signal,network->stats.rssi,network->stats.noise);
193 iwe.u.qual.qual = network->stats.signalstrength;
194 iwe.u.qual.level = network->stats.signal;
195 iwe.u.qual.noise = network->stats.noise;
196 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
197 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
198 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
199 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
200 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
201 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
202 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
203 iwe.u.qual.updated = 7;
204 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
205 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
206 #else
207 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
208 #endif
210 iwe.cmd = IWEVCUSTOM;
211 p = custom;
213 iwe.u.data.length = p - custom;
214 if (iwe.u.data.length)
215 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
216 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
217 #else
218 start = iwe_stream_add_point(start, stop, &iwe, custom);
219 #endif
221 #if 0
222 if (ieee->wpa_enabled && network->wpa_ie_len){
223 char buf[MAX_WPA_IE_LEN * 2 + 30];
224 // printk("WPA IE\n");
225 u8 *p = buf;
226 p += sprintf(p, "wpa_ie=");
227 for (i = 0; i < network->wpa_ie_len; i++) {
228 p += sprintf(p, "%02x", network->wpa_ie[i]);
231 memset(&iwe, 0, sizeof(iwe));
232 iwe.cmd = IWEVCUSTOM;
233 iwe.u.data.length = strlen(buf);
234 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
235 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
236 #else
237 start = iwe_stream_add_point(start, stop, &iwe, buf);
238 #endif
241 if (ieee->wpa_enabled && network->rsn_ie_len){
242 char buf[MAX_WPA_IE_LEN * 2 + 30];
244 u8 *p = buf;
245 p += sprintf(p, "rsn_ie=");
246 for (i = 0; i < network->rsn_ie_len; i++) {
247 p += sprintf(p, "%02x", network->rsn_ie[i]);
251 #else
252 memset(&iwe, 0, sizeof(iwe));
253 if (network->wpa_ie_len) {
254 // printk("wpa_ie_len:%d\n", network->wpa_ie_len);
255 char buf[MAX_WPA_IE_LEN];
256 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
257 iwe.cmd = IWEVGENIE;
258 iwe.u.data.length = network->wpa_ie_len;
259 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
260 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
261 #else
262 start = iwe_stream_add_point(start, stop, &iwe, buf);
263 #endif
266 memset(&iwe, 0, sizeof(iwe));
267 if (network->rsn_ie_len) {
268 // printk("=====>rsn_ie_len:\n", network->rsn_ie_len);
269 #if 0
271 int i;
272 for (i=0; i<network->rsn_ie_len; i++);
273 printk("%2x ", network->rsn_ie[i]);
274 printk("\n");
276 #endif
277 char buf[MAX_WPA_IE_LEN];
278 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
279 iwe.cmd = IWEVGENIE;
280 iwe.u.data.length = network->rsn_ie_len;
281 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
282 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
283 #else
284 start = iwe_stream_add_point(start, stop, &iwe, buf);
285 #endif
288 #endif
290 /* Add EXTRA: Age to display seconds since last beacon/probe response
291 * for given network. */
292 iwe.cmd = IWEVCUSTOM;
293 p = custom;
294 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
295 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
296 iwe.u.data.length = p - custom;
297 if (iwe.u.data.length)
298 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
299 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
300 #else
301 start = iwe_stream_add_point(start, stop, &iwe, custom);
302 #endif
304 return start;
307 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
308 struct iw_request_info *info,
309 union iwreq_data *wrqu, char *extra)
311 struct ieee80211_network *network;
312 unsigned long flags;
313 int err = 0;
314 char *ev = extra;
315 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
316 //char *stop = ev + IW_SCAN_MAX_DATA;
317 int i = 0;
319 IEEE80211_DEBUG_WX("Getting scan\n");
320 down(&ieee->wx_sem);
321 spin_lock_irqsave(&ieee->lock, flags);
323 if(!ieee->bHwRadioOff)
325 list_for_each_entry(network, &ieee->network_list, list) {
326 i++;
328 if((stop-ev)<200)
330 err = -E2BIG;
331 break;
333 if (ieee->scan_age == 0 ||
334 time_after(network->last_scanned + ieee->scan_age, jiffies))
336 ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
338 else
339 IEEE80211_DEBUG_SCAN(
340 "Not showing network '%s ("
341 MAC_FMT ")' due to age (%lums).\n",
342 escape_essid(network->ssid,
343 network->ssid_len),
344 MAC_ARG(network->bssid),
345 (jiffies - network->last_scanned) / (HZ / 100));
348 spin_unlock_irqrestore(&ieee->lock, flags);
349 up(&ieee->wx_sem);
350 wrqu->data.length = ev - extra;
351 wrqu->data.flags = 0;
352 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
354 return err;
357 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
358 struct iw_request_info *info,
359 union iwreq_data *wrqu, char *keybuf)
361 struct iw_point *erq = &(wrqu->encoding);
362 struct net_device *dev = ieee->dev;
363 struct ieee80211_security sec = {
364 .flags = 0
366 int i, key, key_provided, len;
367 struct ieee80211_crypt_data **crypt;
369 IEEE80211_DEBUG_WX("SET_ENCODE\n");
371 key = erq->flags & IW_ENCODE_INDEX;
372 if (key) {
373 if (key > WEP_KEYS)
374 return -EINVAL;
375 key--;
376 key_provided = 1;
377 } else {
378 key_provided = 0;
379 key = ieee->tx_keyidx;
382 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
383 "provided" : "default");
385 crypt = &ieee->crypt[key];
387 if (erq->flags & IW_ENCODE_DISABLED) {
388 if (key_provided && *crypt) {
389 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
390 key);
391 ieee80211_crypt_delayed_deinit(ieee, crypt);
392 } else
393 IEEE80211_DEBUG_WX("Disabling encryption.\n");
395 /* Check all the keys to see if any are still configured,
396 * and if no key index was provided, de-init them all */
397 for (i = 0; i < WEP_KEYS; i++) {
398 if (ieee->crypt[i] != NULL) {
399 if (key_provided)
400 break;
401 ieee80211_crypt_delayed_deinit(
402 ieee, &ieee->crypt[i]);
406 if (i == WEP_KEYS) {
407 sec.enabled = 0;
408 sec.level = SEC_LEVEL_0;
409 sec.flags |= SEC_ENABLED | SEC_LEVEL;
412 goto done;
417 sec.enabled = 1;
418 sec.flags |= SEC_ENABLED;
420 if (*crypt != NULL && (*crypt)->ops != NULL &&
421 strcmp((*crypt)->ops->name, "WEP") != 0) {
422 /* changing to use WEP; deinit previously used algorithm
423 * on this key */
424 ieee80211_crypt_delayed_deinit(ieee, crypt);
427 if (*crypt == NULL) {
428 struct ieee80211_crypt_data *new_crypt;
430 /* take WEP into use */
431 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
432 GFP_KERNEL);
433 if (new_crypt == NULL)
434 return -ENOMEM;
435 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
436 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
437 if (!new_crypt->ops) {
438 request_module("ieee80211_crypt_wep");
439 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
442 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
443 new_crypt->priv = new_crypt->ops->init(key);
445 if (!new_crypt->ops || !new_crypt->priv) {
446 kfree(new_crypt);
447 new_crypt = NULL;
449 printk(KERN_WARNING "%s: could not initialize WEP: "
450 "load module ieee80211_crypt_wep\n",
451 dev->name);
452 return -EOPNOTSUPP;
454 *crypt = new_crypt;
457 /* If a new key was provided, set it up */
458 if (erq->length > 0) {
459 len = erq->length <= 5 ? 5 : 13;
460 memcpy(sec.keys[key], keybuf, erq->length);
461 if (len > erq->length)
462 memset(sec.keys[key] + erq->length, 0,
463 len - erq->length);
464 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
465 key, escape_essid(sec.keys[key], len),
466 erq->length, len);
467 sec.key_sizes[key] = len;
468 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
469 (*crypt)->priv);
470 sec.flags |= (1 << key);
471 /* This ensures a key will be activated if no key is
472 * explicitely set */
473 if (key == sec.active_key)
474 sec.flags |= SEC_ACTIVE_KEY;
475 ieee->tx_keyidx = key;//by wb 080312
476 } else {
477 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
478 NULL, (*crypt)->priv);
479 if (len == 0) {
480 /* Set a default key of all 0 */
481 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
482 key);
483 memset(sec.keys[key], 0, 13);
484 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
485 (*crypt)->priv);
486 sec.key_sizes[key] = 13;
487 sec.flags |= (1 << key);
490 /* No key data - just set the default TX key index */
491 if (key_provided) {
492 IEEE80211_DEBUG_WX(
493 "Setting key %d to default Tx key.\n", key);
494 ieee->tx_keyidx = key;
495 sec.active_key = key;
496 sec.flags |= SEC_ACTIVE_KEY;
500 done:
501 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
502 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
503 sec.flags |= SEC_AUTH_MODE;
504 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
505 "OPEN" : "SHARED KEY");
507 /* For now we just support WEP, so only set that security level...
508 * TODO: When WPA is added this is one place that needs to change */
509 sec.flags |= SEC_LEVEL;
510 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
512 if (ieee->set_security)
513 ieee->set_security(dev, &sec);
515 /* Do not reset port if card is in Managed mode since resetting will
516 * generate new IEEE 802.11 authentication which may end up in looping
517 * with IEEE 802.1X. If your hardware requires a reset after WEP
518 * configuration (for example... Prism2), implement the reset_port in
519 * the callbacks structures used to initialize the 802.11 stack. */
520 if (ieee->reset_on_keychange &&
521 ieee->iw_mode != IW_MODE_INFRA &&
522 ieee->reset_port && ieee->reset_port(dev)) {
523 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
524 return -EINVAL;
526 return 0;
529 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
530 struct iw_request_info *info,
531 union iwreq_data *wrqu, char *keybuf)
533 struct iw_point *erq = &(wrqu->encoding);
534 int len, key;
535 struct ieee80211_crypt_data *crypt;
537 IEEE80211_DEBUG_WX("GET_ENCODE\n");
539 if(ieee->iw_mode == IW_MODE_MONITOR)
540 return -1;
542 key = erq->flags & IW_ENCODE_INDEX;
543 if (key) {
544 if (key > WEP_KEYS)
545 return -EINVAL;
546 key--;
547 } else
548 key = ieee->tx_keyidx;
550 crypt = ieee->crypt[key];
551 erq->flags = key + 1;
553 if (crypt == NULL || crypt->ops == NULL) {
554 erq->length = 0;
555 erq->flags |= IW_ENCODE_DISABLED;
556 return 0;
559 if (strcmp(crypt->ops->name, "WEP") != 0) {
560 /* only WEP is supported with wireless extensions, so just
561 * report that encryption is used */
562 erq->length = 0;
563 erq->flags |= IW_ENCODE_ENABLED;
564 return 0;
567 len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
568 erq->length = (len >= 0 ? len : 0);
570 erq->flags |= IW_ENCODE_ENABLED;
572 if (ieee->open_wep)
573 erq->flags |= IW_ENCODE_OPEN;
574 else
575 erq->flags |= IW_ENCODE_RESTRICTED;
577 return 0;
580 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
581 struct iw_request_info *info,
582 union iwreq_data *wrqu, char *extra)
584 struct net_device *dev = ieee->dev;
585 struct iw_point *encoding = &wrqu->encoding;
586 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
587 int i, idx, ret = 0;
588 int group_key = 0;
589 const char *alg, *module;
590 struct ieee80211_crypto_ops *ops;
591 struct ieee80211_crypt_data **crypt;
593 struct ieee80211_security sec = {
594 .flags = 0,
596 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
597 idx = encoding->flags & IW_ENCODE_INDEX;
598 if (idx) {
599 if (idx < 1 || idx > WEP_KEYS)
600 return -EINVAL;
601 idx--;
602 } else
603 idx = ieee->tx_keyidx;
605 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
606 crypt = &ieee->crypt[idx];
607 group_key = 1;
608 } else {
609 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
610 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
611 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
612 return -EINVAL;
613 if (ieee->iw_mode == IW_MODE_INFRA)
614 crypt = &ieee->crypt[idx];
615 else
616 return -EINVAL;
619 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
620 if ((encoding->flags & IW_ENCODE_DISABLED) ||
621 ext->alg == IW_ENCODE_ALG_NONE) {
622 if (*crypt)
623 ieee80211_crypt_delayed_deinit(ieee, crypt);
625 for (i = 0; i < WEP_KEYS; i++)
626 if (ieee->crypt[i] != NULL)
627 break;
629 if (i == WEP_KEYS) {
630 sec.enabled = 0;
631 // sec.encrypt = 0;
632 sec.level = SEC_LEVEL_0;
633 sec.flags |= SEC_LEVEL;
635 //printk("disabled: flag:%x\n", encoding->flags);
636 goto done;
639 sec.enabled = 1;
640 // sec.encrypt = 1;
641 #if 0
642 if (group_key ? !ieee->host_mc_decrypt :
643 !(ieee->host_encrypt || ieee->host_decrypt ||
644 ieee->host_encrypt_msdu))
645 goto skip_host_crypt;
646 #endif
647 switch (ext->alg) {
648 case IW_ENCODE_ALG_WEP:
649 alg = "WEP";
650 module = "ieee80211_crypt_wep";
651 break;
652 case IW_ENCODE_ALG_TKIP:
653 alg = "TKIP";
654 module = "ieee80211_crypt_tkip";
655 break;
656 case IW_ENCODE_ALG_CCMP:
657 alg = "CCMP";
658 module = "ieee80211_crypt_ccmp";
659 break;
660 default:
661 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
662 dev->name, ext->alg);
663 ret = -EINVAL;
664 goto done;
666 // printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
668 ops = ieee80211_get_crypto_ops(alg);
669 if (ops == NULL) {
670 request_module(module);
671 ops = ieee80211_get_crypto_ops(alg);
673 if (ops == NULL) {
674 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
675 dev->name, ext->alg);
676 printk("========>unknown crypto alg %d\n", ext->alg);
677 ret = -EINVAL;
678 goto done;
681 if (*crypt == NULL || (*crypt)->ops != ops) {
682 struct ieee80211_crypt_data *new_crypt;
684 ieee80211_crypt_delayed_deinit(ieee, crypt);
686 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
687 if (new_crypt == NULL) {
688 ret = -ENOMEM;
689 goto done;
691 new_crypt->ops = ops;
692 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
693 new_crypt->priv = new_crypt->ops->init(idx);
694 if (new_crypt->priv == NULL) {
695 kfree(new_crypt);
696 ret = -EINVAL;
697 goto done;
699 *crypt = new_crypt;
703 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
704 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
705 (*crypt)->priv) < 0) {
706 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
707 printk("key setting failed\n");
708 ret = -EINVAL;
709 goto done;
711 #if 1
712 //skip_host_crypt:
713 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
714 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
715 ieee->tx_keyidx = idx;
716 sec.active_key = idx;
717 sec.flags |= SEC_ACTIVE_KEY;
720 if (ext->alg != IW_ENCODE_ALG_NONE) {
721 memcpy(sec.keys[idx], ext->key, ext->key_len);
722 sec.key_sizes[idx] = ext->key_len;
723 sec.flags |= (1 << idx);
724 if (ext->alg == IW_ENCODE_ALG_WEP) {
725 // sec.encode_alg[idx] = SEC_ALG_WEP;
726 sec.flags |= SEC_LEVEL;
727 sec.level = SEC_LEVEL_1;
728 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
729 // sec.encode_alg[idx] = SEC_ALG_TKIP;
730 sec.flags |= SEC_LEVEL;
731 sec.level = SEC_LEVEL_2;
732 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
733 // sec.encode_alg[idx] = SEC_ALG_CCMP;
734 sec.flags |= SEC_LEVEL;
735 sec.level = SEC_LEVEL_3;
737 /* Don't set sec level for group keys. */
738 if (group_key)
739 sec.flags &= ~SEC_LEVEL;
741 #endif
742 done:
743 if (ieee->set_security)
744 ieee->set_security(ieee->dev, &sec);
746 if (ieee->reset_on_keychange &&
747 ieee->iw_mode != IW_MODE_INFRA &&
748 ieee->reset_port && ieee->reset_port(dev)) {
749 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
750 return -EINVAL;
753 return ret;
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 // printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
761 #if 1
762 switch (mlme->cmd) {
763 case IW_MLME_DEAUTH:
764 case IW_MLME_DISASSOC:
765 // printk("disassoc now\n");
766 ieee80211_disassociate(ieee);
767 break;
768 default:
769 return -EOPNOTSUPP;
771 #endif
772 return 0;
775 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
776 struct iw_request_info *info,
777 struct iw_param *data, char *extra)
780 struct ieee80211_security sec = {
781 .flags = SEC_AUTH_MODE,
784 //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
785 switch (data->flags & IW_AUTH_INDEX) {
786 case IW_AUTH_WPA_VERSION:
787 /*need to support wpa2 here*/
788 //printk("wpa version:%x\n", data->value);
789 break;
790 case IW_AUTH_CIPHER_PAIRWISE:
791 case IW_AUTH_CIPHER_GROUP:
792 case IW_AUTH_KEY_MGMT:
794 * * Host AP driver does not use these parameters and allows
795 * * wpa_supplicant to control them internally.
796 * */
797 break;
798 case IW_AUTH_TKIP_COUNTERMEASURES:
799 ieee->tkip_countermeasures = data->value;
800 break;
801 case IW_AUTH_DROP_UNENCRYPTED:
802 ieee->drop_unencrypted = data->value;
803 break;
805 case IW_AUTH_80211_AUTH_ALG:
806 ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
807 //printk("open_wep:%d\n", ieee->open_wep);
808 break;
810 #if 1
811 case IW_AUTH_WPA_ENABLED:
812 ieee->wpa_enabled = (data->value)?1:0;
813 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
814 break;
816 #endif
817 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
818 ieee->ieee802_1x = data->value;
819 break;
820 case IW_AUTH_PRIVACY_INVOKED:
821 ieee->privacy_invoked = data->value;
822 break;
823 default:
824 return -EOPNOTSUPP;
826 return 0;
829 #if 1
830 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
832 #if 0
833 printk("====>%s()\n", __func__);
835 int i;
836 for (i=0; i<len; i++)
837 printk("%2x ", ie[i]&0xff);
838 printk("\n");
840 #endif
841 u8 *buf = NULL;
843 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
845 printk("return error out, len:%d\n", len);
846 return -EINVAL;
849 if (len)
851 if (len != ie[1]+2){
852 printk("len:%d, ie:%d\n", len, ie[1]);
853 return -EINVAL;
855 buf = kmalloc(len, GFP_KERNEL);
856 if (buf == NULL)
857 return -ENOMEM;
858 memcpy(buf, ie, len);
859 kfree(ieee->wpa_ie);
860 ieee->wpa_ie = buf;
861 ieee->wpa_ie_len = len;
863 else{
864 if (ieee->wpa_ie)
865 kfree(ieee->wpa_ie);
866 ieee->wpa_ie = NULL;
867 ieee->wpa_ie_len = 0;
869 // printk("<=====out %s()\n", __func__);
871 return 0;
874 #endif
876 #if 0
877 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
878 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
879 EXPORT_SYMBOL(ieee80211_wx_set_auth);
880 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
881 EXPORT_SYMBOL(ieee80211_wx_get_scan);
882 EXPORT_SYMBOL(ieee80211_wx_set_encode);
883 EXPORT_SYMBOL(ieee80211_wx_get_encode);
884 #endif