Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac802...
[deliverable/linux.git] / drivers / staging / rtl8192e / rtllib_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/kmod.h>
34 #include <linux/module.h>
35
36 #include "rtllib.h"
37 struct modes_unit {
38 char *mode_string;
39 int mode_size;
40 };
41 static struct modes_unit rtllib_modes[] = {
42 {"a", 1},
43 {"b", 1},
44 {"g", 1},
45 {"?", 1},
46 {"N-24G", 5},
47 {"N-5G", 4},
48 };
49
50 #define MAX_CUSTOM_LEN 64
51 static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
52 char *start, char *stop,
53 struct rtllib_network *network,
54 struct iw_request_info *info)
55 {
56 char custom[MAX_CUSTOM_LEN];
57 char proto_name[IFNAMSIZ];
58 char *pname = proto_name;
59 char *p;
60 struct iw_event iwe;
61 int i, j;
62 u16 max_rate, rate;
63 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
64
65 /* First entry *MUST* be the AP MAC address */
66 iwe.cmd = SIOCGIWAP;
67 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
68 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
69 start = iwe_stream_add_event_rsl(info, start, stop,
70 &iwe, IW_EV_ADDR_LEN);
71 /* Remaining entries will be displayed in the order we provide them */
72
73 /* Add the ESSID */
74 iwe.cmd = SIOCGIWESSID;
75 iwe.u.data.flags = 1;
76 if (network->ssid_len > 0) {
77 iwe.u.data.length = min(network->ssid_len, (u8)32);
78 start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
79 network->ssid);
80 } else if (network->hidden_ssid_len == 0) {
81 iwe.u.data.length = sizeof("<hidden>");
82 start = iwe_stream_add_point_rsl(info, start, stop,
83 &iwe, "<hidden>");
84 } else {
85 iwe.u.data.length = min(network->hidden_ssid_len, (u8)32);
86 start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
87 network->hidden_ssid);
88 }
89 /* Add the protocol name */
90 iwe.cmd = SIOCGIWNAME;
91 for (i = 0; i < ARRAY_SIZE(rtllib_modes); i++) {
92 if (network->mode&(1<<i)) {
93 sprintf(pname, rtllib_modes[i].mode_string,
94 rtllib_modes[i].mode_size);
95 pname += rtllib_modes[i].mode_size;
96 }
97 }
98 *pname = '\0';
99 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
100 start = iwe_stream_add_event_rsl(info, start, stop,
101 &iwe, IW_EV_CHAR_LEN);
102 /* Add mode */
103 iwe.cmd = SIOCGIWMODE;
104 if (network->capability &
105 (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
106 if (network->capability & WLAN_CAPABILITY_ESS)
107 iwe.u.mode = IW_MODE_MASTER;
108 else
109 iwe.u.mode = IW_MODE_ADHOC;
110 start = iwe_stream_add_event_rsl(info, start, stop,
111 &iwe, IW_EV_UINT_LEN);
112 }
113
114 /* Add frequency/channel */
115 iwe.cmd = SIOCGIWFREQ;
116 /* iwe.u.freq.m = rtllib_frequency(network->channel, network->mode);
117 iwe.u.freq.e = 3; */
118 iwe.u.freq.m = network->channel;
119 iwe.u.freq.e = 0;
120 iwe.u.freq.i = 0;
121 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
122 IW_EV_FREQ_LEN);
123
124 /* Add encryption capability */
125 iwe.cmd = SIOCGIWENCODE;
126 if (network->capability & WLAN_CAPABILITY_PRIVACY)
127 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
128 else
129 iwe.u.data.flags = IW_ENCODE_DISABLED;
130 iwe.u.data.length = 0;
131 start = iwe_stream_add_point_rsl(info, start, stop,
132 &iwe, network->ssid);
133 /* Add basic and extended rates */
134 max_rate = 0;
135 p = custom;
136 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
137 for (i = 0, j = 0; i < network->rates_len;) {
138 if (j < network->rates_ex_len &&
139 ((network->rates_ex[j] & 0x7F) <
140 (network->rates[i] & 0x7F)))
141 rate = network->rates_ex[j++] & 0x7F;
142 else
143 rate = network->rates[i++] & 0x7F;
144 if (rate > max_rate)
145 max_rate = rate;
146 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
147 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
148 }
149 for (; j < network->rates_ex_len; j++) {
150 rate = network->rates_ex[j] & 0x7F;
151 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
152 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
153 if (rate > max_rate)
154 max_rate = rate;
155 }
156
157 if (network->mode >= IEEE_N_24G) {
158 struct ht_capab_ele *ht_cap = NULL;
159 bool is40M = false, isShortGI = false;
160 u8 max_mcs = 0;
161 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
162 ht_cap = (struct ht_capab_ele *)
163 &network->bssht.bdHTCapBuf[4];
164 else
165 ht_cap = (struct ht_capab_ele *)
166 &network->bssht.bdHTCapBuf[0];
167 is40M = (ht_cap->ChlWidth) ? 1 : 0;
168 isShortGI = (ht_cap->ChlWidth) ?
169 ((ht_cap->ShortGI40Mhz) ? 1 : 0) :
170 ((ht_cap->ShortGI20Mhz) ? 1 : 0);
171
172 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS,
173 MCS_FILTER_ALL);
174 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
175 if (rate > max_rate)
176 max_rate = rate;
177 }
178 iwe.cmd = SIOCGIWRATE;
179 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
180 iwe.u.bitrate.value = max_rate * 500000;
181 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
182 IW_EV_PARAM_LEN);
183 iwe.cmd = IWEVCUSTOM;
184 iwe.u.data.length = p - custom;
185 if (iwe.u.data.length)
186 start = iwe_stream_add_point_rsl(info, start, stop,
187 &iwe, custom);
188 /* Add quality statistics */
189 /* TODO: Fix these values... */
190 iwe.cmd = IWEVQUAL;
191 iwe.u.qual.qual = network->stats.signal;
192 iwe.u.qual.level = network->stats.rssi;
193 iwe.u.qual.noise = network->stats.noise;
194 iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
195 if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
196 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
197 if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
198 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
199 if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
200 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
201 iwe.u.qual.updated = 7;
202 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
203 IW_EV_QUAL_LEN);
204
205 iwe.cmd = IWEVCUSTOM;
206 p = custom;
207 iwe.u.data.length = p - custom;
208 if (iwe.u.data.length)
209 start = iwe_stream_add_point_rsl(info, start, stop,
210 &iwe, custom);
211
212 memset(&iwe, 0, sizeof(iwe));
213 if (network->wpa_ie_len) {
214 char buf[MAX_WPA_IE_LEN];
215 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
216 iwe.cmd = IWEVGENIE;
217 iwe.u.data.length = network->wpa_ie_len;
218 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
219 }
220 memset(&iwe, 0, sizeof(iwe));
221 if (network->rsn_ie_len) {
222 char buf[MAX_WPA_IE_LEN];
223 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
224 iwe.cmd = IWEVGENIE;
225 iwe.u.data.length = network->rsn_ie_len;
226 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
227 }
228
229 /* add info for WZC */
230 memset(&iwe, 0, sizeof(iwe));
231 if (network->wzc_ie_len) {
232 char buf[MAX_WZC_IE_LEN];
233 memcpy(buf, network->wzc_ie, network->wzc_ie_len);
234 iwe.cmd = IWEVGENIE;
235 iwe.u.data.length = network->wzc_ie_len;
236 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
237 }
238
239 /* Add EXTRA: Age to display seconds since last beacon/probe response
240 * for given network. */
241 iwe.cmd = IWEVCUSTOM;
242 p = custom;
243 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
244 " Last beacon: %lums ago",
245 (jiffies - network->last_scanned) / (HZ / 100));
246 iwe.u.data.length = p - custom;
247 if (iwe.u.data.length)
248 start = iwe_stream_add_point_rsl(info, start, stop,
249 &iwe, custom);
250
251 return start;
252 }
253
254 int rtllib_wx_get_scan(struct rtllib_device *ieee,
255 struct iw_request_info *info,
256 union iwreq_data *wrqu, char *extra)
257 {
258 struct rtllib_network *network;
259 unsigned long flags;
260
261 char *ev = extra;
262 char *stop = ev + wrqu->data.length;
263 int i = 0;
264 int err = 0;
265 RTLLIB_DEBUG_WX("Getting scan\n");
266 down(&ieee->wx_sem);
267 spin_lock_irqsave(&ieee->lock, flags);
268
269 list_for_each_entry(network, &ieee->network_list, list) {
270 i++;
271 if ((stop - ev) < 200) {
272 err = -E2BIG;
273 break;
274 }
275 if (ieee->scan_age == 0 ||
276 time_after(network->last_scanned + ieee->scan_age, jiffies))
277 ev = rtl819x_translate_scan(ieee, ev, stop, network,
278 info);
279 else
280 RTLLIB_DEBUG_SCAN("Not showing network '%s ("
281 " %pM)' due to age (%lums).\n",
282 escape_essid(network->ssid,
283 network->ssid_len),
284 network->bssid,
285 (jiffies - network->last_scanned) / (HZ / 100));
286 }
287
288 spin_unlock_irqrestore(&ieee->lock, flags);
289 up(&ieee->wx_sem);
290 wrqu->data.length = ev - extra;
291 wrqu->data.flags = 0;
292
293 RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i);
294
295 return err;
296 }
297 EXPORT_SYMBOL(rtllib_wx_get_scan);
298
299 int rtllib_wx_set_encode(struct rtllib_device *ieee,
300 struct iw_request_info *info,
301 union iwreq_data *wrqu, char *keybuf)
302 {
303 struct iw_point *erq = &(wrqu->encoding);
304 struct net_device *dev = ieee->dev;
305 struct rtllib_security sec = {
306 .flags = 0
307 };
308 int i, key, key_provided, len;
309 struct lib80211_crypt_data **crypt;
310
311 RTLLIB_DEBUG_WX("SET_ENCODE\n");
312
313 key = erq->flags & IW_ENCODE_INDEX;
314 if (key) {
315 if (key > NUM_WEP_KEYS)
316 return -EINVAL;
317 key--;
318 key_provided = 1;
319 } else {
320 key_provided = 0;
321 key = ieee->crypt_info.tx_keyidx;
322 }
323
324 RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
325 "provided" : "default");
326 crypt = &ieee->crypt_info.crypt[key];
327 if (erq->flags & IW_ENCODE_DISABLED) {
328 if (key_provided && *crypt) {
329 RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
330 key);
331 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
332 } else
333 RTLLIB_DEBUG_WX("Disabling encryption.\n");
334
335 /* Check all the keys to see if any are still configured,
336 * and if no key index was provided, de-init them all */
337 for (i = 0; i < NUM_WEP_KEYS; i++) {
338 if (ieee->crypt_info.crypt[i] != NULL) {
339 if (key_provided)
340 break;
341 lib80211_crypt_delayed_deinit(&ieee->crypt_info,
342 &ieee->crypt_info.crypt[i]);
343 }
344 }
345
346 if (i == NUM_WEP_KEYS) {
347 sec.enabled = 0;
348 sec.level = SEC_LEVEL_0;
349 sec.flags |= SEC_ENABLED | SEC_LEVEL;
350 }
351
352 goto done;
353 }
354
355
356
357 sec.enabled = 1;
358 sec.flags |= SEC_ENABLED;
359
360 if (*crypt != NULL && (*crypt)->ops != NULL &&
361 strcmp((*crypt)->ops->name, "R-WEP") != 0) {
362 /* changing to use WEP; deinit previously used algorithm
363 * on this key */
364 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
365 }
366
367 if (*crypt == NULL) {
368 struct lib80211_crypt_data *new_crypt;
369
370 /* take WEP into use */
371 new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
372 GFP_KERNEL);
373 if (new_crypt == NULL)
374 return -ENOMEM;
375 new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
376 if (!new_crypt->ops) {
377 request_module("rtllib_crypt_wep");
378 new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
379 }
380
381 if (new_crypt->ops)
382 new_crypt->priv = new_crypt->ops->init(key);
383
384 if (!new_crypt->ops || !new_crypt->priv) {
385 kfree(new_crypt);
386 new_crypt = NULL;
387
388 printk(KERN_WARNING "%s: could not initialize WEP: "
389 "load module rtllib_crypt_wep\n",
390 dev->name);
391 return -EOPNOTSUPP;
392 }
393 *crypt = new_crypt;
394 }
395
396 /* If a new key was provided, set it up */
397 if (erq->length > 0) {
398 len = erq->length <= 5 ? 5 : 13;
399 memcpy(sec.keys[key], keybuf, erq->length);
400 if (len > erq->length)
401 memset(sec.keys[key] + erq->length, 0,
402 len - erq->length);
403 RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
404 key, escape_essid(sec.keys[key], len),
405 erq->length, len);
406 sec.key_sizes[key] = len;
407 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
408 (*crypt)->priv);
409 sec.flags |= (1 << key);
410 /* This ensures a key will be activated if no key is
411 * explicitly set */
412 if (key == sec.active_key)
413 sec.flags |= SEC_ACTIVE_KEY;
414 ieee->crypt_info.tx_keyidx = key;
415
416 } else {
417 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
418 NULL, (*crypt)->priv);
419 if (len == 0) {
420 /* Set a default key of all 0 */
421 printk(KERN_INFO "Setting key %d to all zero.\n",
422 key);
423
424 RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
425 key);
426 memset(sec.keys[key], 0, 13);
427 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
428 (*crypt)->priv);
429 sec.key_sizes[key] = 13;
430 sec.flags |= (1 << key);
431 }
432
433 /* No key data - just set the default TX key index */
434 if (key_provided) {
435 RTLLIB_DEBUG_WX(
436 "Setting key %d to default Tx key.\n", key);
437 ieee->crypt_info.tx_keyidx = key;
438 sec.active_key = key;
439 sec.flags |= SEC_ACTIVE_KEY;
440 }
441 }
442 done:
443 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
444 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
445 WLAN_AUTH_SHARED_KEY;
446 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
447 sec.flags |= SEC_AUTH_MODE;
448 RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
449 "OPEN" : "SHARED KEY");
450
451 /* For now we just support WEP, so only set that security level...
452 * TODO: When WPA is added this is one place that needs to change */
453 sec.flags |= SEC_LEVEL;
454 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
455
456 if (ieee->set_security)
457 ieee->set_security(dev, &sec);
458
459 /* Do not reset port if card is in Managed mode since resetting will
460 * generate new IEEE 802.11 authentication which may end up in looping
461 * with IEEE 802.1X. If your hardware requires a reset after WEP
462 * configuration (for example... Prism2), implement the reset_port in
463 * the callbacks structures used to initialize the 802.11 stack. */
464 if (ieee->reset_on_keychange &&
465 ieee->iw_mode != IW_MODE_INFRA &&
466 ieee->reset_port && ieee->reset_port(dev)) {
467 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
468 return -EINVAL;
469 }
470 return 0;
471 }
472 EXPORT_SYMBOL(rtllib_wx_set_encode);
473
474 int rtllib_wx_get_encode(struct rtllib_device *ieee,
475 struct iw_request_info *info,
476 union iwreq_data *wrqu, char *keybuf)
477 {
478 struct iw_point *erq = &(wrqu->encoding);
479 int len, key;
480 struct lib80211_crypt_data *crypt;
481
482 RTLLIB_DEBUG_WX("GET_ENCODE\n");
483
484 if (ieee->iw_mode == IW_MODE_MONITOR)
485 return -1;
486
487 key = erq->flags & IW_ENCODE_INDEX;
488 if (key) {
489 if (key > NUM_WEP_KEYS)
490 return -EINVAL;
491 key--;
492 } else {
493 key = ieee->crypt_info.tx_keyidx;
494 }
495 crypt = ieee->crypt_info.crypt[key];
496
497 erq->flags = key + 1;
498
499 if (crypt == NULL || crypt->ops == NULL) {
500 erq->length = 0;
501 erq->flags |= IW_ENCODE_DISABLED;
502 return 0;
503 }
504 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
505 erq->length = (len >= 0 ? len : 0);
506
507 erq->flags |= IW_ENCODE_ENABLED;
508
509 if (ieee->open_wep)
510 erq->flags |= IW_ENCODE_OPEN;
511 else
512 erq->flags |= IW_ENCODE_RESTRICTED;
513
514 return 0;
515 }
516 EXPORT_SYMBOL(rtllib_wx_get_encode);
517
518 int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
519 struct iw_request_info *info,
520 union iwreq_data *wrqu, char *extra)
521 {
522 int ret = 0;
523 struct net_device *dev = ieee->dev;
524 struct iw_point *encoding = &wrqu->encoding;
525 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
526 int i, idx;
527 int group_key = 0;
528 const char *alg, *module;
529 struct lib80211_crypto_ops *ops;
530 struct lib80211_crypt_data **crypt;
531
532 struct rtllib_security sec = {
533 .flags = 0,
534 };
535 idx = encoding->flags & IW_ENCODE_INDEX;
536 if (idx) {
537 if (idx < 1 || idx > NUM_WEP_KEYS)
538 return -EINVAL;
539 idx--;
540 } else{
541 idx = ieee->crypt_info.tx_keyidx;
542 }
543 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
544 crypt = &ieee->crypt_info.crypt[idx];
545 group_key = 1;
546 } else {
547 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
548 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
549 return -EINVAL;
550 if (ieee->iw_mode == IW_MODE_INFRA)
551 crypt = &ieee->crypt_info.crypt[idx];
552 else
553 return -EINVAL;
554 }
555
556 sec.flags |= SEC_ENABLED;
557 if ((encoding->flags & IW_ENCODE_DISABLED) ||
558 ext->alg == IW_ENCODE_ALG_NONE) {
559 if (*crypt)
560 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
561
562 for (i = 0; i < NUM_WEP_KEYS; i++) {
563 if (ieee->crypt_info.crypt[i] != NULL)
564 break;
565 }
566 if (i == NUM_WEP_KEYS) {
567 sec.enabled = 0;
568 sec.level = SEC_LEVEL_0;
569 sec.flags |= SEC_LEVEL;
570 }
571 goto done;
572 }
573
574 sec.enabled = 1;
575 switch (ext->alg) {
576 case IW_ENCODE_ALG_WEP:
577 alg = "R-WEP";
578 module = "rtllib_crypt_wep";
579 break;
580 case IW_ENCODE_ALG_TKIP:
581 alg = "R-TKIP";
582 module = "rtllib_crypt_tkip";
583 break;
584 case IW_ENCODE_ALG_CCMP:
585 alg = "R-CCMP";
586 module = "rtllib_crypt_ccmp";
587 break;
588 default:
589 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
590 dev->name, ext->alg);
591 ret = -EINVAL;
592 goto done;
593 }
594 printk(KERN_INFO "alg name:%s\n", alg);
595
596 ops = lib80211_get_crypto_ops(alg);
597 if (ops == NULL) {
598 char tempbuf[100];
599
600 memset(tempbuf, 0x00, 100);
601 sprintf(tempbuf, "%s", module);
602 request_module("%s", tempbuf);
603 ops = lib80211_get_crypto_ops(alg);
604 }
605 if (ops == NULL) {
606 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
607 dev->name, ext->alg);
608 printk(KERN_INFO "========>unknown crypto alg %d\n", ext->alg);
609 ret = -EINVAL;
610 goto done;
611 }
612
613 if (*crypt == NULL || (*crypt)->ops != ops) {
614 struct lib80211_crypt_data *new_crypt;
615
616 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
617
618 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
619 if (new_crypt == NULL) {
620 ret = -ENOMEM;
621 goto done;
622 }
623 new_crypt->ops = ops;
624 if (new_crypt->ops)
625 new_crypt->priv = new_crypt->ops->init(idx);
626
627 if (new_crypt->priv == NULL) {
628 kfree(new_crypt);
629 ret = -EINVAL;
630 goto done;
631 }
632 *crypt = new_crypt;
633
634 }
635
636 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
637 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
638 (*crypt)->priv) < 0) {
639 RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
640 printk(KERN_INFO "key setting failed\n");
641 ret = -EINVAL;
642 goto done;
643 }
644 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
645 ieee->crypt_info.tx_keyidx = idx;
646 sec.active_key = idx;
647 sec.flags |= SEC_ACTIVE_KEY;
648 }
649 if (ext->alg != IW_ENCODE_ALG_NONE) {
650 sec.key_sizes[idx] = ext->key_len;
651 sec.flags |= (1 << idx);
652 if (ext->alg == IW_ENCODE_ALG_WEP) {
653 sec.flags |= SEC_LEVEL;
654 sec.level = SEC_LEVEL_1;
655 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
656 sec.flags |= SEC_LEVEL;
657 sec.level = SEC_LEVEL_2;
658 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
659 sec.flags |= SEC_LEVEL;
660 sec.level = SEC_LEVEL_3;
661 }
662 /* Don't set sec level for group keys. */
663 if (group_key)
664 sec.flags &= ~SEC_LEVEL;
665 }
666 done:
667 if (ieee->set_security)
668 ieee->set_security(ieee->dev, &sec);
669
670 if (ieee->reset_on_keychange &&
671 ieee->iw_mode != IW_MODE_INFRA &&
672 ieee->reset_port && ieee->reset_port(dev)) {
673 RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
674 return -EINVAL;
675 }
676 return ret;
677 }
678 EXPORT_SYMBOL(rtllib_wx_set_encode_ext);
679
680 int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
681 struct iw_request_info *info,
682 union iwreq_data *wrqu, char *extra)
683 {
684 struct iw_point *encoding = &wrqu->encoding;
685 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
686 struct lib80211_crypt_data *crypt;
687 int idx, max_key_len;
688
689 max_key_len = encoding->length - sizeof(*ext);
690 if (max_key_len < 0)
691 return -EINVAL;
692
693 idx = encoding->flags & IW_ENCODE_INDEX;
694 if (idx) {
695 if (idx < 1 || idx > NUM_WEP_KEYS)
696 return -EINVAL;
697 idx--;
698 } else {
699 idx = ieee->crypt_info.tx_keyidx;
700 }
701 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
702 (ext->alg != IW_ENCODE_ALG_WEP))
703 if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA))
704 return -EINVAL;
705
706 crypt = ieee->crypt_info.crypt[idx];
707
708 encoding->flags = idx + 1;
709 memset(ext, 0, sizeof(*ext));
710
711 if (crypt == NULL || crypt->ops == NULL) {
712 ext->alg = IW_ENCODE_ALG_NONE;
713 ext->key_len = 0;
714 encoding->flags |= IW_ENCODE_DISABLED;
715 } else {
716 if (strcmp(crypt->ops->name, "R-WEP") == 0)
717 ext->alg = IW_ENCODE_ALG_WEP;
718 else if (strcmp(crypt->ops->name, "R-TKIP"))
719 ext->alg = IW_ENCODE_ALG_TKIP;
720 else if (strcmp(crypt->ops->name, "R-CCMP"))
721 ext->alg = IW_ENCODE_ALG_CCMP;
722 else
723 return -EINVAL;
724 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN,
725 NULL, crypt->priv);
726 encoding->flags |= IW_ENCODE_ENABLED;
727 if (ext->key_len &&
728 (ext->alg == IW_ENCODE_ALG_TKIP ||
729 ext->alg == IW_ENCODE_ALG_CCMP))
730 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
731
732 }
733
734 return 0;
735 }
736
737 int rtllib_wx_set_mlme(struct rtllib_device *ieee,
738 struct iw_request_info *info,
739 union iwreq_data *wrqu, char *extra)
740 {
741 u8 i = 0;
742 bool deauth = false;
743 struct iw_mlme *mlme = (struct iw_mlme *) extra;
744
745 if (ieee->state != RTLLIB_LINKED)
746 return -ENOLINK;
747
748 down(&ieee->wx_sem);
749
750 switch (mlme->cmd) {
751 case IW_MLME_DEAUTH:
752 deauth = true;
753 /* leave break out intentionly */
754
755 case IW_MLME_DISASSOC:
756 if (deauth)
757 printk(KERN_INFO "disauth packet !\n");
758 else
759 printk(KERN_INFO "dis associate packet!\n");
760
761 ieee->cannot_notify = true;
762
763 SendDisassociation(ieee, deauth, mlme->reason_code);
764 rtllib_disassociate(ieee);
765
766 ieee->wap_set = 0;
767 for (i = 0; i < 6; i++)
768 ieee->current_network.bssid[i] = 0x55;
769
770 ieee->ssid_set = 0;
771 ieee->current_network.ssid[0] = '\0';
772 ieee->current_network.ssid_len = 0;
773 break;
774 default:
775 up(&ieee->wx_sem);
776 return -EOPNOTSUPP;
777 }
778
779 up(&ieee->wx_sem);
780
781 return 0;
782 }
783 EXPORT_SYMBOL(rtllib_wx_set_mlme);
784
785 int rtllib_wx_set_auth(struct rtllib_device *ieee,
786 struct iw_request_info *info,
787 struct iw_param *data, char *extra)
788 {
789 switch (data->flags & IW_AUTH_INDEX) {
790 case IW_AUTH_WPA_VERSION:
791 break;
792 case IW_AUTH_CIPHER_PAIRWISE:
793 case IW_AUTH_CIPHER_GROUP:
794 case IW_AUTH_KEY_MGMT:
795 /*
796 * Host AP driver does not use these parameters and allows
797 * wpa_supplicant to control them internally.
798 */
799 break;
800 case IW_AUTH_TKIP_COUNTERMEASURES:
801 ieee->tkip_countermeasures = data->value;
802 break;
803 case IW_AUTH_DROP_UNENCRYPTED:
804 ieee->drop_unencrypted = data->value;
805 break;
806
807 case IW_AUTH_80211_AUTH_ALG:
808 if (data->value & IW_AUTH_ALG_SHARED_KEY) {
809 ieee->open_wep = 0;
810 ieee->auth_mode = 1;
811 } else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
812 ieee->open_wep = 1;
813 ieee->auth_mode = 0;
814 } else if (data->value & IW_AUTH_ALG_LEAP) {
815 ieee->open_wep = 1;
816 ieee->auth_mode = 2;
817 } else
818 return -EINVAL;
819 break;
820
821 case IW_AUTH_WPA_ENABLED:
822 ieee->wpa_enabled = (data->value) ? 1 : 0;
823 break;
824
825 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
826 ieee->ieee802_1x = data->value;
827 break;
828 case IW_AUTH_PRIVACY_INVOKED:
829 ieee->privacy_invoked = data->value;
830 break;
831 default:
832 return -EOPNOTSUPP;
833 }
834 return 0;
835 }
836 EXPORT_SYMBOL(rtllib_wx_set_auth);
837
838 int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
839 {
840 u8 *buf;
841 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
842
843 if (len > MAX_WPA_IE_LEN || (len && ie == NULL))
844 return -EINVAL;
845
846 if (len) {
847 eid = ie[0];
848 if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2],
849 wps_oui, 4))) {
850
851 ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) :
852 (MAX_WZC_IE_LEN);
853 buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL);
854 if (buf == NULL)
855 return -ENOMEM;
856 ieee->wps_ie = buf;
857 return 0;
858 }
859 }
860 ieee->wps_ie_len = 0;
861 kfree(ieee->wps_ie);
862 ieee->wps_ie = NULL;
863 if (len) {
864 if (len != ie[1]+2)
865 return -EINVAL;
866 buf = kmemdup(ie, len, GFP_KERNEL);
867 if (buf == NULL)
868 return -ENOMEM;
869 kfree(ieee->wpa_ie);
870 ieee->wpa_ie = buf;
871 ieee->wpa_ie_len = len;
872 } else {
873 kfree(ieee->wpa_ie);
874 ieee->wpa_ie = NULL;
875 ieee->wpa_ie_len = 0;
876 }
877 return 0;
878 }
879 EXPORT_SYMBOL(rtllib_wx_set_gen_ie);
This page took 0.083422 seconds and 6 git commands to generate.