02faaf3980e7a252f8df034541c7a5a4a2e6f6db
[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
162 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
163 ht_cap = (struct ht_capab_ele *)
164 &network->bssht.bdHTCapBuf[4];
165 else
166 ht_cap = (struct ht_capab_ele *)
167 &network->bssht.bdHTCapBuf[0];
168 is40M = (ht_cap->ChlWidth) ? 1 : 0;
169 isShortGI = (ht_cap->ChlWidth) ?
170 ((ht_cap->ShortGI40Mhz) ? 1 : 0) :
171 ((ht_cap->ShortGI20Mhz) ? 1 : 0);
172
173 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS,
174 MCS_FILTER_ALL);
175 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
176 if (rate > max_rate)
177 max_rate = rate;
178 }
179 iwe.cmd = SIOCGIWRATE;
180 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
181 iwe.u.bitrate.value = max_rate * 500000;
182 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
183 IW_EV_PARAM_LEN);
184 iwe.cmd = IWEVCUSTOM;
185 iwe.u.data.length = p - custom;
186 if (iwe.u.data.length)
187 start = iwe_stream_add_point_rsl(info, start, stop,
188 &iwe, custom);
189 /* Add quality statistics */
190 /* TODO: Fix these values... */
191 iwe.cmd = IWEVQUAL;
192 iwe.u.qual.qual = network->stats.signal;
193 iwe.u.qual.level = network->stats.rssi;
194 iwe.u.qual.noise = network->stats.noise;
195 iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
196 if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
197 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
198 if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
199 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
200 if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
201 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
202 iwe.u.qual.updated = 7;
203 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
204 IW_EV_QUAL_LEN);
205
206 iwe.cmd = IWEVCUSTOM;
207 p = custom;
208 iwe.u.data.length = p - custom;
209 if (iwe.u.data.length)
210 start = iwe_stream_add_point_rsl(info, start, stop,
211 &iwe, custom);
212
213 memset(&iwe, 0, sizeof(iwe));
214 if (network->wpa_ie_len) {
215 char buf[MAX_WPA_IE_LEN];
216
217 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
218 iwe.cmd = IWEVGENIE;
219 iwe.u.data.length = network->wpa_ie_len;
220 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
221 }
222 memset(&iwe, 0, sizeof(iwe));
223 if (network->rsn_ie_len) {
224 char buf[MAX_WPA_IE_LEN];
225
226 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
227 iwe.cmd = IWEVGENIE;
228 iwe.u.data.length = network->rsn_ie_len;
229 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
230 }
231
232 /* add info for WZC */
233 memset(&iwe, 0, sizeof(iwe));
234 if (network->wzc_ie_len) {
235 char buf[MAX_WZC_IE_LEN];
236
237 memcpy(buf, network->wzc_ie, network->wzc_ie_len);
238 iwe.cmd = IWEVGENIE;
239 iwe.u.data.length = network->wzc_ie_len;
240 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
241 }
242
243 /* Add EXTRA: Age to display seconds since last beacon/probe response
244 * for given network. */
245 iwe.cmd = IWEVCUSTOM;
246 p = custom;
247 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
248 " Last beacon: %lums ago",
249 (jiffies - network->last_scanned) / (HZ / 100));
250 iwe.u.data.length = p - custom;
251 if (iwe.u.data.length)
252 start = iwe_stream_add_point_rsl(info, start, stop,
253 &iwe, custom);
254
255 return start;
256 }
257
258 int rtllib_wx_get_scan(struct rtllib_device *ieee,
259 struct iw_request_info *info,
260 union iwreq_data *wrqu, char *extra)
261 {
262 struct rtllib_network *network;
263 unsigned long flags;
264
265 char *ev = extra;
266 char *stop = ev + wrqu->data.length;
267 int i = 0;
268 int err = 0;
269
270 RTLLIB_DEBUG_WX("Getting scan\n");
271 down(&ieee->wx_sem);
272 spin_lock_irqsave(&ieee->lock, flags);
273
274 list_for_each_entry(network, &ieee->network_list, list) {
275 i++;
276 if ((stop - ev) < 200) {
277 err = -E2BIG;
278 break;
279 }
280 if (ieee->scan_age == 0 ||
281 time_after(network->last_scanned + ieee->scan_age, jiffies))
282 ev = rtl819x_translate_scan(ieee, ev, stop, network,
283 info);
284 else
285 RTLLIB_DEBUG_SCAN("Not showing network '%s ("
286 " %pM)' due to age (%lums).\n",
287 escape_essid(network->ssid,
288 network->ssid_len),
289 network->bssid,
290 (jiffies - network->last_scanned) / (HZ / 100));
291 }
292
293 spin_unlock_irqrestore(&ieee->lock, flags);
294 up(&ieee->wx_sem);
295 wrqu->data.length = ev - extra;
296 wrqu->data.flags = 0;
297
298 RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i);
299
300 return err;
301 }
302 EXPORT_SYMBOL(rtllib_wx_get_scan);
303
304 int rtllib_wx_set_encode(struct rtllib_device *ieee,
305 struct iw_request_info *info,
306 union iwreq_data *wrqu, char *keybuf)
307 {
308 struct iw_point *erq = &(wrqu->encoding);
309 struct net_device *dev = ieee->dev;
310 struct rtllib_security sec = {
311 .flags = 0
312 };
313 int i, key, key_provided, len;
314 struct lib80211_crypt_data **crypt;
315
316 RTLLIB_DEBUG_WX("SET_ENCODE\n");
317
318 key = erq->flags & IW_ENCODE_INDEX;
319 if (key) {
320 if (key > NUM_WEP_KEYS)
321 return -EINVAL;
322 key--;
323 key_provided = 1;
324 } else {
325 key_provided = 0;
326 key = ieee->crypt_info.tx_keyidx;
327 }
328
329 RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
330 "provided" : "default");
331 crypt = &ieee->crypt_info.crypt[key];
332 if (erq->flags & IW_ENCODE_DISABLED) {
333 if (key_provided && *crypt) {
334 RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
335 key);
336 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
337 } else
338 RTLLIB_DEBUG_WX("Disabling encryption.\n");
339
340 /* Check all the keys to see if any are still configured,
341 * and if no key index was provided, de-init them all */
342 for (i = 0; i < NUM_WEP_KEYS; i++) {
343 if (ieee->crypt_info.crypt[i] != NULL) {
344 if (key_provided)
345 break;
346 lib80211_crypt_delayed_deinit(&ieee->crypt_info,
347 &ieee->crypt_info.crypt[i]);
348 }
349 }
350
351 if (i == NUM_WEP_KEYS) {
352 sec.enabled = 0;
353 sec.level = SEC_LEVEL_0;
354 sec.flags |= SEC_ENABLED | SEC_LEVEL;
355 }
356
357 goto done;
358 }
359
360
361
362 sec.enabled = 1;
363 sec.flags |= SEC_ENABLED;
364
365 if (*crypt != NULL && (*crypt)->ops != NULL &&
366 strcmp((*crypt)->ops->name, "R-WEP") != 0) {
367 /* changing to use WEP; deinit previously used algorithm
368 * on this key */
369 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
370 }
371
372 if (*crypt == NULL) {
373 struct lib80211_crypt_data *new_crypt;
374
375 /* take WEP into use */
376 new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
377 GFP_KERNEL);
378 if (new_crypt == NULL)
379 return -ENOMEM;
380 new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
381 if (!new_crypt->ops) {
382 request_module("rtllib_crypt_wep");
383 new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
384 }
385
386 if (new_crypt->ops)
387 new_crypt->priv = new_crypt->ops->init(key);
388
389 if (!new_crypt->ops || !new_crypt->priv) {
390 kfree(new_crypt);
391 new_crypt = NULL;
392
393 netdev_warn(dev, "%s: could not initialize WEP: "
394 "load module rtllib_crypt_wep\n",
395 dev->name);
396 return -EOPNOTSUPP;
397 }
398 *crypt = new_crypt;
399 }
400
401 /* If a new key was provided, set it up */
402 if (erq->length > 0) {
403 len = erq->length <= 5 ? 5 : 13;
404 memcpy(sec.keys[key], keybuf, erq->length);
405 if (len > erq->length)
406 memset(sec.keys[key] + erq->length, 0,
407 len - erq->length);
408 RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
409 key, escape_essid(sec.keys[key], len),
410 erq->length, len);
411 sec.key_sizes[key] = len;
412 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
413 (*crypt)->priv);
414 sec.flags |= (1 << key);
415 /* This ensures a key will be activated if no key is
416 * explicitly set */
417 if (key == sec.active_key)
418 sec.flags |= SEC_ACTIVE_KEY;
419 ieee->crypt_info.tx_keyidx = key;
420
421 } else {
422 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
423 NULL, (*crypt)->priv);
424 if (len == 0) {
425 /* Set a default key of all 0 */
426 netdev_info(ieee->dev, "Setting key %d to all zero.\n",
427 key);
428
429 RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
430 key);
431 memset(sec.keys[key], 0, 13);
432 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
433 (*crypt)->priv);
434 sec.key_sizes[key] = 13;
435 sec.flags |= (1 << key);
436 }
437
438 /* No key data - just set the default TX key index */
439 if (key_provided) {
440 RTLLIB_DEBUG_WX(
441 "Setting key %d to default Tx key.\n", key);
442 ieee->crypt_info.tx_keyidx = key;
443 sec.active_key = key;
444 sec.flags |= SEC_ACTIVE_KEY;
445 }
446 }
447 done:
448 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
449 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
450 WLAN_AUTH_SHARED_KEY;
451 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
452 sec.flags |= SEC_AUTH_MODE;
453 RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
454 "OPEN" : "SHARED KEY");
455
456 /* For now we just support WEP, so only set that security level...
457 * TODO: When WPA is added this is one place that needs to change */
458 sec.flags |= SEC_LEVEL;
459 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
460
461 if (ieee->set_security)
462 ieee->set_security(dev, &sec);
463
464 /* Do not reset port if card is in Managed mode since resetting will
465 * generate new IEEE 802.11 authentication which may end up in looping
466 * with IEEE 802.1X. If your hardware requires a reset after WEP
467 * configuration (for example... Prism2), implement the reset_port in
468 * the callbacks structures used to initialize the 802.11 stack. */
469 if (ieee->reset_on_keychange &&
470 ieee->iw_mode != IW_MODE_INFRA &&
471 ieee->reset_port && ieee->reset_port(dev)) {
472 netdev_dbg(dev, "%s: reset_port failed\n", dev->name);
473 return -EINVAL;
474 }
475 return 0;
476 }
477 EXPORT_SYMBOL(rtllib_wx_set_encode);
478
479 int rtllib_wx_get_encode(struct rtllib_device *ieee,
480 struct iw_request_info *info,
481 union iwreq_data *wrqu, char *keybuf)
482 {
483 struct iw_point *erq = &(wrqu->encoding);
484 int len, key;
485 struct lib80211_crypt_data *crypt;
486
487 RTLLIB_DEBUG_WX("GET_ENCODE\n");
488
489 if (ieee->iw_mode == IW_MODE_MONITOR)
490 return -1;
491
492 key = erq->flags & IW_ENCODE_INDEX;
493 if (key) {
494 if (key > NUM_WEP_KEYS)
495 return -EINVAL;
496 key--;
497 } else {
498 key = ieee->crypt_info.tx_keyidx;
499 }
500 crypt = ieee->crypt_info.crypt[key];
501
502 erq->flags = key + 1;
503
504 if (crypt == NULL || crypt->ops == NULL) {
505 erq->length = 0;
506 erq->flags |= IW_ENCODE_DISABLED;
507 return 0;
508 }
509 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
510 erq->length = (len >= 0 ? 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 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
595 dev->name, ext->alg);
596 ret = -EINVAL;
597 goto done;
598 }
599 netdev_info(dev, "alg name:%s\n", alg);
600
601 ops = lib80211_get_crypto_ops(alg);
602 if (ops == NULL) {
603 char tempbuf[100];
604
605 memset(tempbuf, 0x00, 100);
606 sprintf(tempbuf, "%s", module);
607 request_module("%s", tempbuf);
608 ops = lib80211_get_crypto_ops(alg);
609 }
610 if (ops == NULL) {
611 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
612 dev->name, ext->alg);
613 netdev_info(dev, "========>unknown crypto alg %d\n", ext->alg);
614 ret = -EINVAL;
615 goto done;
616 }
617
618 if (*crypt == NULL || (*crypt)->ops != ops) {
619 struct lib80211_crypt_data *new_crypt;
620
621 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
622
623 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
624 if (new_crypt == NULL) {
625 ret = -ENOMEM;
626 goto done;
627 }
628 new_crypt->ops = ops;
629 if (new_crypt->ops)
630 new_crypt->priv = new_crypt->ops->init(idx);
631
632 if (new_crypt->priv == NULL) {
633 kfree(new_crypt);
634 ret = -EINVAL;
635 goto done;
636 }
637 *crypt = new_crypt;
638
639 }
640
641 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
642 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
643 (*crypt)->priv) < 0) {
644 RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
645 netdev_info(dev, "key setting failed\n");
646 ret = -EINVAL;
647 goto done;
648 }
649 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
650 ieee->crypt_info.tx_keyidx = idx;
651 sec.active_key = idx;
652 sec.flags |= SEC_ACTIVE_KEY;
653 }
654 if (ext->alg != IW_ENCODE_ALG_NONE) {
655 sec.key_sizes[idx] = ext->key_len;
656 sec.flags |= (1 << idx);
657 if (ext->alg == IW_ENCODE_ALG_WEP) {
658 sec.flags |= SEC_LEVEL;
659 sec.level = SEC_LEVEL_1;
660 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
661 sec.flags |= SEC_LEVEL;
662 sec.level = SEC_LEVEL_2;
663 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
664 sec.flags |= SEC_LEVEL;
665 sec.level = SEC_LEVEL_3;
666 }
667 /* Don't set sec level for group keys. */
668 if (group_key)
669 sec.flags &= ~SEC_LEVEL;
670 }
671 done:
672 if (ieee->set_security)
673 ieee->set_security(ieee->dev, &sec);
674
675 if (ieee->reset_on_keychange &&
676 ieee->iw_mode != IW_MODE_INFRA &&
677 ieee->reset_port && ieee->reset_port(dev)) {
678 RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
679 return -EINVAL;
680 }
681 return ret;
682 }
683 EXPORT_SYMBOL(rtllib_wx_set_encode_ext);
684
685 int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
686 struct iw_request_info *info,
687 union iwreq_data *wrqu, char *extra)
688 {
689 struct iw_point *encoding = &wrqu->encoding;
690 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
691 struct lib80211_crypt_data *crypt;
692 int idx, max_key_len;
693
694 max_key_len = encoding->length - sizeof(*ext);
695 if (max_key_len < 0)
696 return -EINVAL;
697
698 idx = encoding->flags & IW_ENCODE_INDEX;
699 if (idx) {
700 if (idx < 1 || idx > NUM_WEP_KEYS)
701 return -EINVAL;
702 idx--;
703 } else {
704 idx = ieee->crypt_info.tx_keyidx;
705 }
706 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
707 (ext->alg != IW_ENCODE_ALG_WEP))
708 if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA))
709 return -EINVAL;
710
711 crypt = ieee->crypt_info.crypt[idx];
712
713 encoding->flags = idx + 1;
714 memset(ext, 0, sizeof(*ext));
715
716 if (crypt == NULL || crypt->ops == NULL) {
717 ext->alg = IW_ENCODE_ALG_NONE;
718 ext->key_len = 0;
719 encoding->flags |= IW_ENCODE_DISABLED;
720 } else {
721 if (strcmp(crypt->ops->name, "R-WEP") == 0)
722 ext->alg = IW_ENCODE_ALG_WEP;
723 else if (strcmp(crypt->ops->name, "R-TKIP"))
724 ext->alg = IW_ENCODE_ALG_TKIP;
725 else if (strcmp(crypt->ops->name, "R-CCMP"))
726 ext->alg = IW_ENCODE_ALG_CCMP;
727 else
728 return -EINVAL;
729 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN,
730 NULL, crypt->priv);
731 encoding->flags |= IW_ENCODE_ENABLED;
732 if (ext->key_len &&
733 (ext->alg == IW_ENCODE_ALG_TKIP ||
734 ext->alg == IW_ENCODE_ALG_CCMP))
735 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
736
737 }
738
739 return 0;
740 }
741
742 int rtllib_wx_set_mlme(struct rtllib_device *ieee,
743 struct iw_request_info *info,
744 union iwreq_data *wrqu, char *extra)
745 {
746 u8 i = 0;
747 bool deauth = false;
748 struct iw_mlme *mlme = (struct iw_mlme *) extra;
749
750 if (ieee->state != RTLLIB_LINKED)
751 return -ENOLINK;
752
753 down(&ieee->wx_sem);
754
755 switch (mlme->cmd) {
756 case IW_MLME_DEAUTH:
757 deauth = true;
758 /* leave break out intentionly */
759
760 case IW_MLME_DISASSOC:
761 if (deauth)
762 netdev_info(ieee->dev, "disauth packet !\n");
763 else
764 netdev_info(ieee->dev, "dis associate packet!\n");
765
766 ieee->cannot_notify = true;
767
768 SendDisassociation(ieee, deauth, mlme->reason_code);
769 rtllib_disassociate(ieee);
770
771 ieee->wap_set = 0;
772 for (i = 0; i < 6; i++)
773 ieee->current_network.bssid[i] = 0x55;
774
775 ieee->ssid_set = 0;
776 ieee->current_network.ssid[0] = '\0';
777 ieee->current_network.ssid_len = 0;
778 break;
779 default:
780 up(&ieee->wx_sem);
781 return -EOPNOTSUPP;
782 }
783
784 up(&ieee->wx_sem);
785
786 return 0;
787 }
788 EXPORT_SYMBOL(rtllib_wx_set_mlme);
789
790 int rtllib_wx_set_auth(struct rtllib_device *ieee,
791 struct iw_request_info *info,
792 struct iw_param *data, char *extra)
793 {
794 switch (data->flags & IW_AUTH_INDEX) {
795 case IW_AUTH_WPA_VERSION:
796 break;
797 case IW_AUTH_CIPHER_PAIRWISE:
798 case IW_AUTH_CIPHER_GROUP:
799 case IW_AUTH_KEY_MGMT:
800 /*
801 * Host AP driver does not use these parameters and allows
802 * wpa_supplicant to control them internally.
803 */
804 break;
805 case IW_AUTH_TKIP_COUNTERMEASURES:
806 ieee->tkip_countermeasures = data->value;
807 break;
808 case IW_AUTH_DROP_UNENCRYPTED:
809 ieee->drop_unencrypted = data->value;
810 break;
811
812 case IW_AUTH_80211_AUTH_ALG:
813 if (data->value & IW_AUTH_ALG_SHARED_KEY) {
814 ieee->open_wep = 0;
815 ieee->auth_mode = 1;
816 } else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
817 ieee->open_wep = 1;
818 ieee->auth_mode = 0;
819 } else if (data->value & IW_AUTH_ALG_LEAP) {
820 ieee->open_wep = 1;
821 ieee->auth_mode = 2;
822 } else
823 return -EINVAL;
824 break;
825
826 case IW_AUTH_WPA_ENABLED:
827 ieee->wpa_enabled = (data->value) ? 1 : 0;
828 break;
829
830 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
831 ieee->ieee802_1x = data->value;
832 break;
833 case IW_AUTH_PRIVACY_INVOKED:
834 ieee->privacy_invoked = data->value;
835 break;
836 default:
837 return -EOPNOTSUPP;
838 }
839 return 0;
840 }
841 EXPORT_SYMBOL(rtllib_wx_set_auth);
842
843 int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
844 {
845 u8 *buf;
846 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
847
848 if (len > MAX_WPA_IE_LEN || (len && ie == NULL))
849 return -EINVAL;
850
851 if (len) {
852 eid = ie[0];
853 if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2],
854 wps_oui, 4))) {
855
856 ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) :
857 (MAX_WZC_IE_LEN);
858 buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL);
859 if (buf == NULL)
860 return -ENOMEM;
861 ieee->wps_ie = buf;
862 return 0;
863 }
864 }
865 ieee->wps_ie_len = 0;
866 kfree(ieee->wps_ie);
867 ieee->wps_ie = NULL;
868 if (len) {
869 if (len != ie[1]+2)
870 return -EINVAL;
871 buf = kmemdup(ie, len, GFP_KERNEL);
872 if (buf == NULL)
873 return -ENOMEM;
874 kfree(ieee->wpa_ie);
875 ieee->wpa_ie = buf;
876 ieee->wpa_ie_len = len;
877 } else {
878 kfree(ieee->wpa_ie);
879 ieee->wpa_ie = NULL;
880 ieee->wpa_ie_len = 0;
881 }
882 return 0;
883 }
884 EXPORT_SYMBOL(rtllib_wx_set_gen_ie);
This page took 0.061247 seconds and 4 git commands to generate.