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