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/kmod.h>
34 #include <linux/slab.h>
35 #include <linux/module.h>
36
37 #include "ieee80211.h"
38 struct modes_unit {
39 char *mode_string;
40 int mode_size;
41 };
42 static struct modes_unit ieee80211_modes[] = {
43 {"a", 1},
44 {"b", 1},
45 {"g", 1},
46 {"?", 1},
47 {"N-24G", 5},
48 {"N-5G", 4},
49 };
50
51 #define iwe_stream_add_event_rsl iwe_stream_add_event
52
53 #define MAX_CUSTOM_LEN 64
rtl819x_translate_scan(struct ieee80211_device * ieee,char * start,char * stop,struct ieee80211_network * network,struct iw_request_info * info)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)
58 {
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};
67
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 */
74
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);
85 }
86 /* Add the protocol name */
87 iwe.cmd = SIOCGIWNAME;
88 for(i=0; i<ARRAY_SIZE(ieee80211_modes); 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;
92 }
93 }
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);
106 }
107
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" : "");
139 }
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;
146 }
147
148 if (network->mode >= IEEE_N_24G)//add N rate here;
149 {
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);
161
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;
166 }
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;
193
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
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]);
205 }
206
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);
211 }
212
213 if (ieee->wpa_enabled && network->rsn_ie_len){
214 char buf[MAX_WPA_IE_LEN * 2 + 30];
215
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]);
220 }
221
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);
226 }
227
228
229 /* Add EXTRA: Age to display seconds since last beacon/probe response
230 * for given network. */
231 iwe.cmd = IWEVCUSTOM;
232 p = custom;
233 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
234 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
235 iwe.u.data.length = p - custom;
236 if (iwe.u.data.length)
237 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
238
239 return start;
240 }
241
ieee80211_wx_get_scan(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)242 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
243 struct iw_request_info *info,
244 union iwreq_data *wrqu, char *extra)
245 {
246 struct ieee80211_network *network;
247 unsigned long flags;
248
249 char *ev = extra;
250 // char *stop = ev + IW_SCAN_MAX_DATA;
251 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
252 //char *stop = ev + IW_SCAN_MAX_DATA;
253 int i = 0;
254 int err = 0;
255 IEEE80211_DEBUG_WX("Getting scan\n");
256 mutex_lock(&ieee->wx_mutex);
257 spin_lock_irqsave(&ieee->lock, flags);
258
259 list_for_each_entry(network, &ieee->network_list, list) {
260 i++;
261 if((stop-ev)<200)
262 {
263 err = -E2BIG;
264 break;
265 }
266 if (ieee->scan_age == 0 ||
267 time_after(network->last_scanned + ieee->scan_age, jiffies))
268 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
269 else
270 IEEE80211_DEBUG_SCAN(
271 "Not showing network '%s ("
272 "%pM)' due to age (%lums).\n",
273 escape_essid(network->ssid,
274 network->ssid_len),
275 network->bssid,
276 (jiffies - network->last_scanned) / (HZ / 100));
277 }
278
279 spin_unlock_irqrestore(&ieee->lock, flags);
280 mutex_unlock(&ieee->wx_mutex);
281 wrqu->data.length = ev - extra;
282 wrqu->data.flags = 0;
283
284 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
285
286 return err;
287 }
288 EXPORT_SYMBOL(ieee80211_wx_get_scan);
289
ieee80211_wx_set_encode(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)290 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
291 struct iw_request_info *info,
292 union iwreq_data *wrqu, char *keybuf)
293 {
294 struct iw_point *erq = &(wrqu->encoding);
295 struct net_device *dev = ieee->dev;
296 struct ieee80211_security sec = {
297 .flags = 0
298 };
299 int i, key, key_provided, len;
300 struct ieee80211_crypt_data **crypt;
301
302 IEEE80211_DEBUG_WX("SET_ENCODE\n");
303
304 key = erq->flags & IW_ENCODE_INDEX;
305 if (key) {
306 if (key > WEP_KEYS)
307 return -EINVAL;
308 key--;
309 key_provided = 1;
310 } else {
311 key_provided = 0;
312 key = ieee->tx_keyidx;
313 }
314
315 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
316 "provided" : "default");
317 crypt = &ieee->crypt[key];
318
319 if (erq->flags & IW_ENCODE_DISABLED) {
320 if (key_provided && *crypt) {
321 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
322 key);
323 ieee80211_crypt_delayed_deinit(ieee, crypt);
324 } else
325 IEEE80211_DEBUG_WX("Disabling encryption.\n");
326
327 /* Check all the keys to see if any are still configured,
328 * and if no key index was provided, de-init them all */
329 for (i = 0; i < WEP_KEYS; i++) {
330 if (ieee->crypt[i] != NULL) {
331 if (key_provided)
332 break;
333 ieee80211_crypt_delayed_deinit(
334 ieee, &ieee->crypt[i]);
335 }
336 }
337
338 if (i == WEP_KEYS) {
339 sec.enabled = 0;
340 sec.level = SEC_LEVEL_0;
341 sec.flags |= SEC_ENABLED | SEC_LEVEL;
342 }
343
344 goto done;
345 }
346
347
348
349 sec.enabled = 1;
350 sec.flags |= SEC_ENABLED;
351
352 if (*crypt != NULL && (*crypt)->ops != NULL &&
353 strcmp((*crypt)->ops->name, "WEP") != 0) {
354 /* changing to use WEP; deinit previously used algorithm
355 * on this key */
356 ieee80211_crypt_delayed_deinit(ieee, crypt);
357 }
358
359 if (*crypt == NULL) {
360 struct ieee80211_crypt_data *new_crypt;
361
362 /* take WEP into use */
363 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
364 GFP_KERNEL);
365 if (!new_crypt)
366 return -ENOMEM;
367 new_crypt->ops = try_then_request_module(ieee80211_get_crypto_ops("WEP"),
368 "ieee80211_crypt_wep");
369 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
370 new_crypt->priv = new_crypt->ops->init(key);
371
372 if (!new_crypt->ops || !new_crypt->priv) {
373 kfree(new_crypt);
374 new_crypt = NULL;
375
376 printk(KERN_WARNING "%s: could not initialize WEP: "
377 "load module ieee80211_crypt_wep\n",
378 dev->name);
379 return -EOPNOTSUPP;
380 }
381 *crypt = new_crypt;
382 }
383
384 /* If a new key was provided, set it up */
385 if (erq->length > 0) {
386 len = erq->length <= 5 ? 5 : 13;
387 memcpy(sec.keys[key], keybuf, erq->length);
388 if (len > erq->length)
389 memset(sec.keys[key] + erq->length, 0,
390 len - erq->length);
391 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
392 key, escape_essid(sec.keys[key], len),
393 erq->length, len);
394 sec.key_sizes[key] = len;
395 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
396 (*crypt)->priv);
397 sec.flags |= (1 << key);
398 /* This ensures a key will be activated if no key is
399 * explicitely set */
400 if (key == sec.active_key)
401 sec.flags |= SEC_ACTIVE_KEY;
402 ieee->tx_keyidx = key;
403
404 } else {
405 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
406 NULL, (*crypt)->priv);
407 if (len == 0) {
408 /* Set a default key of all 0 */
409 printk("Setting key %d to all zero.\n",
410 key);
411
412 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
413 key);
414 memset(sec.keys[key], 0, 13);
415 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
416 (*crypt)->priv);
417 sec.key_sizes[key] = 13;
418 sec.flags |= (1 << key);
419 }
420
421 /* No key data - just set the default TX key index */
422 if (key_provided) {
423 IEEE80211_DEBUG_WX(
424 "Setting key %d to default Tx key.\n", key);
425 ieee->tx_keyidx = key;
426 sec.active_key = key;
427 sec.flags |= SEC_ACTIVE_KEY;
428 }
429 }
430
431 done:
432 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
433 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
434 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
435 sec.flags |= SEC_AUTH_MODE;
436 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
437 "OPEN" : "SHARED KEY");
438
439 /* For now we just support WEP, so only set that security level...
440 * TODO: When WPA is added this is one place that needs to change */
441 sec.flags |= SEC_LEVEL;
442 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
443
444 if (ieee->set_security)
445 ieee->set_security(dev, &sec);
446
447 /* Do not reset port if card is in Managed mode since resetting will
448 * generate new IEEE 802.11 authentication which may end up in looping
449 * with IEEE 802.1X. If your hardware requires a reset after WEP
450 * configuration (for example... Prism2), implement the reset_port in
451 * the callbacks structures used to initialize the 802.11 stack. */
452 if (ieee->reset_on_keychange &&
453 ieee->iw_mode != IW_MODE_INFRA &&
454 ieee->reset_port && ieee->reset_port(dev)) {
455 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
456 return -EINVAL;
457 }
458 return 0;
459 }
460 EXPORT_SYMBOL(ieee80211_wx_set_encode);
461
ieee80211_wx_get_encode(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)462 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
463 struct iw_request_info *info,
464 union iwreq_data *wrqu, char *keybuf)
465 {
466 struct iw_point *erq = &(wrqu->encoding);
467 int len, key;
468 struct ieee80211_crypt_data *crypt;
469
470 IEEE80211_DEBUG_WX("GET_ENCODE\n");
471
472 if(ieee->iw_mode == IW_MODE_MONITOR)
473 return -1;
474
475 key = erq->flags & IW_ENCODE_INDEX;
476 if (key) {
477 if (key > WEP_KEYS)
478 return -EINVAL;
479 key--;
480 } else
481 key = ieee->tx_keyidx;
482
483 crypt = ieee->crypt[key];
484 erq->flags = key + 1;
485
486 if (crypt == NULL || crypt->ops == NULL) {
487 erq->length = 0;
488 erq->flags |= IW_ENCODE_DISABLED;
489 return 0;
490 }
491 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
492 erq->length = (len >= 0 ? len : 0);
493
494 erq->flags |= IW_ENCODE_ENABLED;
495
496 if (ieee->open_wep)
497 erq->flags |= IW_ENCODE_OPEN;
498 else
499 erq->flags |= IW_ENCODE_RESTRICTED;
500
501 return 0;
502 }
503 EXPORT_SYMBOL(ieee80211_wx_get_encode);
504
ieee80211_wx_set_encode_ext(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)505 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
506 struct iw_request_info *info,
507 union iwreq_data *wrqu, char *extra)
508 {
509 int ret = 0;
510 struct net_device *dev = ieee->dev;
511 struct iw_point *encoding = &wrqu->encoding;
512 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
513 int i, idx;
514 int group_key = 0;
515 const char *alg, *module;
516 struct ieee80211_crypto_ops *ops;
517 struct ieee80211_crypt_data **crypt;
518
519 struct ieee80211_security sec = {
520 .flags = 0,
521 };
522 idx = encoding->flags & IW_ENCODE_INDEX;
523 if (idx) {
524 if (idx < 1 || idx > WEP_KEYS)
525 return -EINVAL;
526 idx--;
527 } else
528 idx = ieee->tx_keyidx;
529
530 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
531
532 crypt = &ieee->crypt[idx];
533
534 group_key = 1;
535 } else {
536 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
537 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
538 return -EINVAL;
539 if (ieee->iw_mode == IW_MODE_INFRA)
540
541 crypt = &ieee->crypt[idx];
542
543 else
544 return -EINVAL;
545 }
546
547 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
548 if ((encoding->flags & IW_ENCODE_DISABLED) ||
549 ext->alg == IW_ENCODE_ALG_NONE) {
550 if (*crypt)
551 ieee80211_crypt_delayed_deinit(ieee, crypt);
552
553 for (i = 0; i < WEP_KEYS; i++)
554
555 if (ieee->crypt[i] != NULL)
556
557 break;
558
559 if (i == WEP_KEYS) {
560 sec.enabled = 0;
561 // sec.encrypt = 0;
562 sec.level = SEC_LEVEL_0;
563 sec.flags |= SEC_LEVEL;
564 }
565 goto done;
566 }
567
568 sec.enabled = 1;
569 // sec.encrypt = 1;
570 switch (ext->alg) {
571 case IW_ENCODE_ALG_WEP:
572 alg = "WEP";
573 module = "ieee80211_crypt_wep";
574 break;
575 case IW_ENCODE_ALG_TKIP:
576 alg = "TKIP";
577 module = "ieee80211_crypt_tkip";
578 break;
579 case IW_ENCODE_ALG_CCMP:
580 alg = "CCMP";
581 module = "ieee80211_crypt_ccmp";
582 break;
583 default:
584 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
585 dev->name, ext->alg);
586 ret = -EINVAL;
587 goto done;
588 }
589 printk("alg name:%s\n",alg);
590
591 ops = try_then_request_module(ieee80211_get_crypto_ops(alg), module);
592 if (!ops) {
593 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
594 dev->name, ext->alg);
595 printk("========>unknown crypto alg %d\n", ext->alg);
596 ret = -EINVAL;
597 goto done;
598 }
599
600 if (*crypt == NULL || (*crypt)->ops != ops) {
601 struct ieee80211_crypt_data *new_crypt;
602
603 ieee80211_crypt_delayed_deinit(ieee, crypt);
604
605 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
606 if (!new_crypt) {
607 ret = -ENOMEM;
608 goto done;
609 }
610 new_crypt->ops = ops;
611 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
612 new_crypt->priv = new_crypt->ops->init(idx);
613 if (new_crypt->priv == NULL) {
614 kfree(new_crypt);
615 ret = -EINVAL;
616 goto done;
617 }
618 *crypt = new_crypt;
619 }
620
621 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
622 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
623 (*crypt)->priv) < 0) {
624 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
625 printk("key setting failed\n");
626 ret = -EINVAL;
627 goto done;
628 }
629 //skip_host_crypt:
630 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
631 ieee->tx_keyidx = idx;
632 sec.active_key = idx;
633 sec.flags |= SEC_ACTIVE_KEY;
634 }
635
636 if (ext->alg != IW_ENCODE_ALG_NONE) {
637 //memcpy(sec.keys[idx], ext->key, ext->key_len);
638 sec.key_sizes[idx] = ext->key_len;
639 sec.flags |= (1 << idx);
640 if (ext->alg == IW_ENCODE_ALG_WEP) {
641 // sec.encode_alg[idx] = SEC_ALG_WEP;
642 sec.flags |= SEC_LEVEL;
643 sec.level = SEC_LEVEL_1;
644 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
645 // sec.encode_alg[idx] = SEC_ALG_TKIP;
646 sec.flags |= SEC_LEVEL;
647 sec.level = SEC_LEVEL_2;
648 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
649 // sec.encode_alg[idx] = SEC_ALG_CCMP;
650 sec.flags |= SEC_LEVEL;
651 sec.level = SEC_LEVEL_3;
652 }
653 /* Don't set sec level for group keys. */
654 if (group_key)
655 sec.flags &= ~SEC_LEVEL;
656 }
657 done:
658 if (ieee->set_security)
659 ieee->set_security(ieee->dev, &sec);
660
661 if (ieee->reset_on_keychange &&
662 ieee->iw_mode != IW_MODE_INFRA &&
663 ieee->reset_port && ieee->reset_port(dev)) {
664 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
665 return -EINVAL;
666 }
667 return ret;
668 }
669 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
670
ieee80211_wx_get_encode_ext(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)671 int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
672 struct iw_request_info *info,
673 union iwreq_data *wrqu, char *extra)
674 {
675 struct iw_point *encoding = &wrqu->encoding;
676 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
677 struct ieee80211_crypt_data *crypt;
678 int idx, max_key_len;
679
680 max_key_len = encoding->length - sizeof(*ext);
681 if (max_key_len < 0)
682 return -EINVAL;
683
684 idx = encoding->flags & IW_ENCODE_INDEX;
685 if (idx) {
686 if (idx < 1 || idx > WEP_KEYS)
687 return -EINVAL;
688 idx--;
689 } else
690 idx = ieee->tx_keyidx;
691
692 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
693 ext->alg != IW_ENCODE_ALG_WEP)
694 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
695 return -EINVAL;
696
697 crypt = ieee->crypt[idx];
698 encoding->flags = idx + 1;
699 memset(ext, 0, sizeof(*ext));
700
701 if (crypt == NULL || crypt->ops == NULL ) {
702 ext->alg = IW_ENCODE_ALG_NONE;
703 ext->key_len = 0;
704 encoding->flags |= IW_ENCODE_DISABLED;
705 } else {
706 if (strcmp(crypt->ops->name, "WEP") == 0 )
707 ext->alg = IW_ENCODE_ALG_WEP;
708 else if (strcmp(crypt->ops->name, "TKIP"))
709 ext->alg = IW_ENCODE_ALG_TKIP;
710 else if (strcmp(crypt->ops->name, "CCMP"))
711 ext->alg = IW_ENCODE_ALG_CCMP;
712 else
713 return -EINVAL;
714 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
715 encoding->flags |= IW_ENCODE_ENABLED;
716 if (ext->key_len &&
717 (ext->alg == IW_ENCODE_ALG_TKIP ||
718 ext->alg == IW_ENCODE_ALG_CCMP))
719 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
720 }
721
722 return 0;
723 }
724 EXPORT_SYMBOL(ieee80211_wx_get_encode_ext);
725
ieee80211_wx_set_mlme(struct ieee80211_device * ieee,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)726 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
727 struct iw_request_info *info,
728 union iwreq_data *wrqu, char *extra)
729 {
730 struct iw_mlme *mlme = (struct iw_mlme *) extra;
731 switch (mlme->cmd) {
732 case IW_MLME_DEAUTH:
733 case IW_MLME_DISASSOC:
734 ieee80211_disassociate(ieee);
735 break;
736 default:
737 return -EOPNOTSUPP;
738 }
739 return 0;
740 }
741 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
742
ieee80211_wx_set_auth(struct ieee80211_device * ieee,struct iw_request_info * info,struct iw_param * data,char * extra)743 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
744 struct iw_request_info *info,
745 struct iw_param *data, char *extra)
746 {
747 switch (data->flags & IW_AUTH_INDEX) {
748 case IW_AUTH_WPA_VERSION:
749 /*need to support wpa2 here*/
750 break;
751 case IW_AUTH_CIPHER_PAIRWISE:
752 case IW_AUTH_CIPHER_GROUP:
753 case IW_AUTH_KEY_MGMT:
754 /*
755 * * Host AP driver does not use these parameters and allows
756 * * wpa_supplicant to control them internally.
757 * */
758 break;
759 case IW_AUTH_TKIP_COUNTERMEASURES:
760 ieee->tkip_countermeasures = data->value;
761 break;
762 case IW_AUTH_DROP_UNENCRYPTED:
763 ieee->drop_unencrypted = data->value;
764 break;
765
766 case IW_AUTH_80211_AUTH_ALG:
767 //printk("======>%s():data->value is %d\n",__func__,data->value);
768 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
769 if(data->value & IW_AUTH_ALG_SHARED_KEY){
770 ieee->open_wep = 0;
771 ieee->auth_mode = 1;
772 }
773 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
774 ieee->open_wep = 1;
775 ieee->auth_mode = 0;
776 }
777 else if(data->value & IW_AUTH_ALG_LEAP){
778 ieee->open_wep = 1;
779 ieee->auth_mode = 2;
780 }
781 else
782 return -EINVAL;
783 break;
784
785 case IW_AUTH_WPA_ENABLED:
786 ieee->wpa_enabled = (data->value)?1:0;
787 break;
788
789 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
790 ieee->ieee802_1x = data->value;
791 break;
792 case IW_AUTH_PRIVACY_INVOKED:
793 ieee->privacy_invoked = data->value;
794 break;
795 default:
796 return -EOPNOTSUPP;
797 }
798 return 0;
799 }
800 EXPORT_SYMBOL(ieee80211_wx_set_auth);
801
ieee80211_wx_set_gen_ie(struct ieee80211_device * ieee,u8 * ie,size_t len)802 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
803 {
804 u8 *buf;
805
806 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
807 {
808 // printk("return error out, len:%d\n", len);
809 return -EINVAL;
810 }
811
812
813 if (len)
814 {
815 if (len != ie[1]+2)
816 {
817 printk("len:%zu, ie:%d\n", len, ie[1]);
818 return -EINVAL;
819 }
820 buf = kmemdup(ie, len, GFP_KERNEL);
821 if (buf == NULL)
822 return -ENOMEM;
823 kfree(ieee->wpa_ie);
824 ieee->wpa_ie = buf;
825 ieee->wpa_ie_len = len;
826 }
827 else{
828 kfree(ieee->wpa_ie);
829 ieee->wpa_ie = NULL;
830 ieee->wpa_ie_len = 0;
831 }
832 return 0;
833 }
834 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
835