include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / rtl8192u / ieee80211 / ieee80211_wx.c
1 /******************************************************************************
2
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
4
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>
10
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.
14
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.
19
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.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
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
30
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>
37
38 #include "ieee80211.h"
39 struct modes_unit {
40 char *mode_string;
41 int mode_size;
42 };
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},
50 };
51
52 #define iwe_stream_add_event_rsl iwe_stream_add_event
53
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)
59 {
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};
68
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 */
75
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);
86 }
87 /* Add the protocol name */
88 iwe.cmd = SIOCGIWNAME;
89 for(i=0; i<(sizeof(ieee80211_modes)/sizeof(ieee80211_modes[0])); 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;
93 }
94 }
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);
107 }
108
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" : "");
140 }
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;
147 }
148
149 if (network->mode >= IEEE_N_24G)//add N rate here;
150 {
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);
162
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;
167 }
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;
194
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]);
206 }
207
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);
212 }
213
214 if (ieee->wpa_enabled && network->rsn_ie_len){
215 char buf[MAX_WPA_IE_LEN * 2 + 30];
216
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]);
221 }
222
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);
227 }
228 #else
229 memset(&iwe, 0, sizeof(iwe));
230 if (network->wpa_ie_len)
231 {
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);
237 }
238 memset(&iwe, 0, sizeof(iwe));
239 if (network->rsn_ie_len)
240 {
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);
246 }
247 #endif
248
249
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);
259
260 return start;
261 }
262
263 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
264 struct iw_request_info *info,
265 union iwreq_data *wrqu, char *extra)
266 {
267 struct ieee80211_network *network;
268 unsigned long flags;
269
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);
279
280 list_for_each_entry(network, &ieee->network_list, list) {
281 i++;
282 if((stop-ev)<200)
283 {
284 err = -E2BIG;
285 break;
286 }
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));
298 }
299
300 spin_unlock_irqrestore(&ieee->lock, flags);
301 up(&ieee->wx_sem);
302 wrqu->data.length = ev - extra;
303 wrqu->data.flags = 0;
304
305 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
306
307 return err;
308 }
309
310 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
311 struct iw_request_info *info,
312 union iwreq_data *wrqu, char *keybuf)
313 {
314 struct iw_point *erq = &(wrqu->encoding);
315 struct net_device *dev = ieee->dev;
316 struct ieee80211_security sec = {
317 .flags = 0
318 };
319 int i, key, key_provided, len;
320 struct ieee80211_crypt_data **crypt;
321
322 IEEE80211_DEBUG_WX("SET_ENCODE\n");
323
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;
333 }
334
335 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
336 "provided" : "default");
337 crypt = &ieee->crypt[key];
338
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");
346
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]);
355 }
356 }
357
358 if (i == WEP_KEYS) {
359 sec.enabled = 0;
360 sec.level = SEC_LEVEL_0;
361 sec.flags |= SEC_ENABLED | SEC_LEVEL;
362 }
363
364 goto done;
365 }
366
367
368
369 sec.enabled = 1;
370 sec.flags |= SEC_ENABLED;
371
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);
377 }
378
379 if (*crypt == NULL) {
380 struct ieee80211_crypt_data *new_crypt;
381
382 /* take WEP into use */
383 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
384 GFP_KERNEL);
385 if (new_crypt == NULL)
386 return -ENOMEM;
387 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
388 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
389 if (!new_crypt->ops) {
390 request_module("ieee80211_crypt_wep");
391 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
392 }
393 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
394 new_crypt->priv = new_crypt->ops->init(key);
395
396 if (!new_crypt->ops || !new_crypt->priv) {
397 kfree(new_crypt);
398 new_crypt = NULL;
399
400 printk(KERN_WARNING "%s: could not initialize WEP: "
401 "load module ieee80211_crypt_wep\n",
402 dev->name);
403 return -EOPNOTSUPP;
404 }
405 *crypt = new_crypt;
406 }
407
408 /* If a new key was provided, set it up */
409 if (erq->length > 0) {
410 len = erq->length <= 5 ? 5 : 13;
411 memcpy(sec.keys[key], keybuf, erq->length);
412 if (len > erq->length)
413 memset(sec.keys[key] + erq->length, 0,
414 len - erq->length);
415 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
416 key, escape_essid(sec.keys[key], len),
417 erq->length, len);
418 sec.key_sizes[key] = len;
419 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
420 (*crypt)->priv);
421 sec.flags |= (1 << key);
422 /* This ensures a key will be activated if no key is
423 * explicitely set */
424 if (key == sec.active_key)
425 sec.flags |= SEC_ACTIVE_KEY;
426 ieee->tx_keyidx = key;
427
428 } else {
429 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
430 NULL, (*crypt)->priv);
431 if (len == 0) {
432 /* Set a default key of all 0 */
433 printk("Setting key %d to all zero.\n",
434 key);
435
436 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
437 key);
438 memset(sec.keys[key], 0, 13);
439 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
440 (*crypt)->priv);
441 sec.key_sizes[key] = 13;
442 sec.flags |= (1 << key);
443 }
444
445 /* No key data - just set the default TX key index */
446 if (key_provided) {
447 IEEE80211_DEBUG_WX(
448 "Setting key %d to default Tx key.\n", key);
449 ieee->tx_keyidx = key;
450 sec.active_key = key;
451 sec.flags |= SEC_ACTIVE_KEY;
452 }
453 }
454
455 done:
456 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
457 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
458 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
459 sec.flags |= SEC_AUTH_MODE;
460 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
461 "OPEN" : "SHARED KEY");
462
463 /* For now we just support WEP, so only set that security level...
464 * TODO: When WPA is added this is one place that needs to change */
465 sec.flags |= SEC_LEVEL;
466 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
467
468 if (ieee->set_security)
469 ieee->set_security(dev, &sec);
470
471 /* Do not reset port if card is in Managed mode since resetting will
472 * generate new IEEE 802.11 authentication which may end up in looping
473 * with IEEE 802.1X. If your hardware requires a reset after WEP
474 * configuration (for example... Prism2), implement the reset_port in
475 * the callbacks structures used to initialize the 802.11 stack. */
476 if (ieee->reset_on_keychange &&
477 ieee->iw_mode != IW_MODE_INFRA &&
478 ieee->reset_port && ieee->reset_port(dev)) {
479 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
480 return -EINVAL;
481 }
482 return 0;
483 }
484
485 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
486 struct iw_request_info *info,
487 union iwreq_data *wrqu, char *keybuf)
488 {
489 struct iw_point *erq = &(wrqu->encoding);
490 int len, key;
491 struct ieee80211_crypt_data *crypt;
492
493 IEEE80211_DEBUG_WX("GET_ENCODE\n");
494
495 if(ieee->iw_mode == IW_MODE_MONITOR)
496 return -1;
497
498 key = erq->flags & IW_ENCODE_INDEX;
499 if (key) {
500 if (key > WEP_KEYS)
501 return -EINVAL;
502 key--;
503 } else
504 key = ieee->tx_keyidx;
505
506 crypt = ieee->crypt[key];
507 erq->flags = key + 1;
508
509 if (crypt == NULL || crypt->ops == NULL) {
510 erq->length = 0;
511 erq->flags |= IW_ENCODE_DISABLED;
512 return 0;
513 }
514 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
515 erq->length = (len >= 0 ? len : 0);
516
517 erq->flags |= IW_ENCODE_ENABLED;
518
519 if (ieee->open_wep)
520 erq->flags |= IW_ENCODE_OPEN;
521 else
522 erq->flags |= IW_ENCODE_RESTRICTED;
523
524 return 0;
525 }
526 #if (WIRELESS_EXT >= 18)
527 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
528 struct iw_request_info *info,
529 union iwreq_data *wrqu, char *extra)
530 {
531 int ret = 0;
532 struct net_device *dev = ieee->dev;
533 struct iw_point *encoding = &wrqu->encoding;
534 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
535 int i, idx;
536 int group_key = 0;
537 const char *alg, *module;
538 struct ieee80211_crypto_ops *ops;
539 struct ieee80211_crypt_data **crypt;
540
541 struct ieee80211_security sec = {
542 .flags = 0,
543 };
544 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
545 idx = encoding->flags & IW_ENCODE_INDEX;
546 if (idx) {
547 if (idx < 1 || idx > WEP_KEYS)
548 return -EINVAL;
549 idx--;
550 } else
551 idx = ieee->tx_keyidx;
552
553 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
554
555 crypt = &ieee->crypt[idx];
556
557 group_key = 1;
558 } else {
559 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
560 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
561 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
562 return -EINVAL;
563 if (ieee->iw_mode == IW_MODE_INFRA)
564
565 crypt = &ieee->crypt[idx];
566
567 else
568 return -EINVAL;
569 }
570
571 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
572 if ((encoding->flags & IW_ENCODE_DISABLED) ||
573 ext->alg == IW_ENCODE_ALG_NONE) {
574 if (*crypt)
575 ieee80211_crypt_delayed_deinit(ieee, crypt);
576
577 for (i = 0; i < WEP_KEYS; i++)
578
579 if (ieee->crypt[i] != NULL)
580
581 break;
582
583 if (i == WEP_KEYS) {
584 sec.enabled = 0;
585 // sec.encrypt = 0;
586 sec.level = SEC_LEVEL_0;
587 sec.flags |= SEC_LEVEL;
588 }
589 //printk("disabled: flag:%x\n", encoding->flags);
590 goto done;
591 }
592
593 sec.enabled = 1;
594 // sec.encrypt = 1;
595 switch (ext->alg) {
596 case IW_ENCODE_ALG_WEP:
597 alg = "WEP";
598 module = "ieee80211_crypt_wep";
599 break;
600 case IW_ENCODE_ALG_TKIP:
601 alg = "TKIP";
602 module = "ieee80211_crypt_tkip";
603 break;
604 case IW_ENCODE_ALG_CCMP:
605 alg = "CCMP";
606 module = "ieee80211_crypt_ccmp";
607 break;
608 default:
609 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
610 dev->name, ext->alg);
611 ret = -EINVAL;
612 goto done;
613 }
614 printk("alg name:%s\n",alg);
615
616 ops = ieee80211_get_crypto_ops(alg);
617 if (ops == NULL) {
618 request_module(module);
619 ops = ieee80211_get_crypto_ops(alg);
620 }
621 if (ops == NULL) {
622 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
623 dev->name, ext->alg);
624 printk("========>unknown crypto alg %d\n", ext->alg);
625 ret = -EINVAL;
626 goto done;
627 }
628
629 if (*crypt == NULL || (*crypt)->ops != ops) {
630 struct ieee80211_crypt_data *new_crypt;
631
632 ieee80211_crypt_delayed_deinit(ieee, crypt);
633
634 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
635 if (new_crypt == NULL) {
636 ret = -ENOMEM;
637 goto done;
638 }
639 new_crypt->ops = ops;
640 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
641 new_crypt->priv = new_crypt->ops->init(idx);
642 if (new_crypt->priv == NULL) {
643 kfree(new_crypt);
644 ret = -EINVAL;
645 goto done;
646 }
647 *crypt = new_crypt;
648
649 }
650
651 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
652 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
653 (*crypt)->priv) < 0) {
654 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
655 printk("key setting failed\n");
656 ret = -EINVAL;
657 goto done;
658 }
659 //skip_host_crypt:
660 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
661 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
662 ieee->tx_keyidx = idx;
663 sec.active_key = idx;
664 sec.flags |= SEC_ACTIVE_KEY;
665 }
666
667 if (ext->alg != IW_ENCODE_ALG_NONE) {
668 //memcpy(sec.keys[idx], ext->key, ext->key_len);
669 sec.key_sizes[idx] = ext->key_len;
670 sec.flags |= (1 << idx);
671 if (ext->alg == IW_ENCODE_ALG_WEP) {
672 // sec.encode_alg[idx] = SEC_ALG_WEP;
673 sec.flags |= SEC_LEVEL;
674 sec.level = SEC_LEVEL_1;
675 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
676 // sec.encode_alg[idx] = SEC_ALG_TKIP;
677 sec.flags |= SEC_LEVEL;
678 sec.level = SEC_LEVEL_2;
679 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
680 // sec.encode_alg[idx] = SEC_ALG_CCMP;
681 sec.flags |= SEC_LEVEL;
682 sec.level = SEC_LEVEL_3;
683 }
684 /* Don't set sec level for group keys. */
685 if (group_key)
686 sec.flags &= ~SEC_LEVEL;
687 }
688 done:
689 if (ieee->set_security)
690 ieee->set_security(ieee->dev, &sec);
691
692 if (ieee->reset_on_keychange &&
693 ieee->iw_mode != IW_MODE_INFRA &&
694 ieee->reset_port && ieee->reset_port(dev)) {
695 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
696 return -EINVAL;
697 }
698 return ret;
699 }
700
701 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
702 struct iw_request_info *info,
703 union iwreq_data *wrqu, char *extra)
704 {
705 struct iw_point *encoding = &wrqu->encoding;
706 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
707 struct ieee80211_crypt_data *crypt;
708 int idx, max_key_len;
709
710 max_key_len = encoding->length - sizeof(*ext);
711 if (max_key_len < 0)
712 return -EINVAL;
713
714 idx = encoding->flags & IW_ENCODE_INDEX;
715 if (idx) {
716 if (idx < 1 || idx > WEP_KEYS)
717 return -EINVAL;
718 idx--;
719 } else
720 idx = ieee->tx_keyidx;
721
722 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
723 ext->alg != IW_ENCODE_ALG_WEP)
724 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
725 return -EINVAL;
726
727 crypt = ieee->crypt[idx];
728 encoding->flags = idx + 1;
729 memset(ext, 0, sizeof(*ext));
730
731 if (crypt == NULL || crypt->ops == NULL ) {
732 ext->alg = IW_ENCODE_ALG_NONE;
733 ext->key_len = 0;
734 encoding->flags |= IW_ENCODE_DISABLED;
735 } else {
736 if (strcmp(crypt->ops->name, "WEP") == 0 )
737 ext->alg = IW_ENCODE_ALG_WEP;
738 else if (strcmp(crypt->ops->name, "TKIP"))
739 ext->alg = IW_ENCODE_ALG_TKIP;
740 else if (strcmp(crypt->ops->name, "CCMP"))
741 ext->alg = IW_ENCODE_ALG_CCMP;
742 else
743 return -EINVAL;
744 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
745 encoding->flags |= IW_ENCODE_ENABLED;
746 if (ext->key_len &&
747 (ext->alg == IW_ENCODE_ALG_TKIP ||
748 ext->alg == IW_ENCODE_ALG_CCMP))
749 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
750
751 }
752
753 return 0;
754 }
755
756 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
757 struct iw_request_info *info,
758 union iwreq_data *wrqu, char *extra)
759 {
760 struct iw_mlme *mlme = (struct iw_mlme *) extra;
761 switch (mlme->cmd) {
762 case IW_MLME_DEAUTH:
763 case IW_MLME_DISASSOC:
764 ieee80211_disassociate(ieee);
765 break;
766 default:
767 return -EOPNOTSUPP;
768 }
769 return 0;
770 }
771
772 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
773 struct iw_request_info *info,
774 struct iw_param *data, char *extra)
775 {
776 switch (data->flags & IW_AUTH_INDEX) {
777 case IW_AUTH_WPA_VERSION:
778 /*need to support wpa2 here*/
779 //printk("wpa version:%x\n", data->value);
780 break;
781 case IW_AUTH_CIPHER_PAIRWISE:
782 case IW_AUTH_CIPHER_GROUP:
783 case IW_AUTH_KEY_MGMT:
784 /*
785 * * Host AP driver does not use these parameters and allows
786 * * wpa_supplicant to control them internally.
787 * */
788 break;
789 case IW_AUTH_TKIP_COUNTERMEASURES:
790 ieee->tkip_countermeasures = data->value;
791 break;
792 case IW_AUTH_DROP_UNENCRYPTED:
793 ieee->drop_unencrypted = data->value;
794 break;
795
796 case IW_AUTH_80211_AUTH_ALG:
797 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
798 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
799 if(data->value & IW_AUTH_ALG_SHARED_KEY){
800 ieee->open_wep = 0;
801 ieee->auth_mode = 1;
802 }
803 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
804 ieee->open_wep = 1;
805 ieee->auth_mode = 0;
806 }
807 else if(data->value & IW_AUTH_ALG_LEAP){
808 ieee->open_wep = 1;
809 ieee->auth_mode = 2;
810 //printk("hahahaa:LEAP\n");
811 }
812 else
813 return -EINVAL;
814 //printk("open_wep:%d\n", ieee->open_wep);
815 break;
816
817 case IW_AUTH_WPA_ENABLED:
818 ieee->wpa_enabled = (data->value)?1:0;
819 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
820 break;
821
822 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
823 ieee->ieee802_1x = data->value;
824 break;
825 case IW_AUTH_PRIVACY_INVOKED:
826 ieee->privacy_invoked = data->value;
827 break;
828 default:
829 return -EOPNOTSUPP;
830 }
831 return 0;
832 }
833 #endif
834 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
835 {
836 u8 *buf;
837
838 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
839 {
840 // printk("return error out, len:%d\n", len);
841 return -EINVAL;
842 }
843
844
845 if (len)
846 {
847 if (len != ie[1]+2)
848 {
849 printk("len:%zu, ie:%d\n", len, ie[1]);
850 return -EINVAL;
851 }
852 buf = kmalloc(len, GFP_KERNEL);
853 if (buf == NULL)
854 return -ENOMEM;
855 memcpy(buf, ie, len);
856 kfree(ieee->wpa_ie);
857 ieee->wpa_ie = buf;
858 ieee->wpa_ie_len = len;
859 }
860 else{
861 if (ieee->wpa_ie)
862 kfree(ieee->wpa_ie);
863 ieee->wpa_ie = NULL;
864 ieee->wpa_ie_len = 0;
865 }
866 return 0;
867
868 }
869
870 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
871 #if (WIRELESS_EXT >= 18)
872 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
873 EXPORT_SYMBOL(ieee80211_wx_set_auth);
874 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
875 EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
876 #endif
877 EXPORT_SYMBOL(ieee80211_wx_get_scan);
878 EXPORT_SYMBOL(ieee80211_wx_set_encode);
879 EXPORT_SYMBOL(ieee80211_wx_get_encode);