1 /******************************************************************************
2
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31 ******************************************************************************/
32 #include <linux/wireless.h>
33 #include <linux/version.h>
34 #include <linux/kmod.h>
35 #include <linux/module.h>
36
37 #include "ieee80211.h"
38 static const char *ieee80211_modes[] = {
39 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
40 };
41
42 #ifdef FEDORACORE_9
43 #define IN_FEDORACORE_9 1
44 #else
45 #define IN_FEDORACORE_9 0
46 #endif
47
48 #define MAX_CUSTOM_LEN 64
49 static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
50 char *start, char *stop,
51 struct ieee80211_network *network,
52 struct iw_request_info *info)
53 {
54 char custom[MAX_CUSTOM_LEN];
55 char *p;
56 struct iw_event iwe;
57 int i, j;
58 u8 max_rate, rate;
59
60 /* First entry *MUST* be the AP MAC address */
61 iwe.cmd = SIOCGIWAP;
62 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
63 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
64 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
65 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
66 #else
67 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
68 #endif
69
70 /* Remaining entries will be displayed in the order we provide them */
71
72 /* Add the ESSID */
73 iwe.cmd = SIOCGIWESSID;
74 iwe.u.data.flags = 1;
75 //YJ,modified,080903,for hidden ap
76 //if (network->flags & NETWORK_EMPTY_ESSID) {
77 if (network->ssid_len == 0) {
78 //YJ,modified,080903,end
79 iwe.u.data.length = sizeof("<hidden>");
80 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
81 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
82 #else
83 start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
84 #endif
85 } else {
86 iwe.u.data.length = min(network->ssid_len, (u8)32);
87 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
88 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
89 #else
90 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
91 #endif
92 }
93 //printk("ESSID: %s\n",network->ssid);
94 /* Add the protocol name */
95 iwe.cmd = SIOCGIWNAME;
96 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
97 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
98 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
99 #else
100 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN);
101 #endif
102
103 /* Add mode */
104 iwe.cmd = SIOCGIWMODE;
105 if (network->capability &
106 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
107 if (network->capability & WLAN_CAPABILITY_BSS)
108 iwe.u.mode = IW_MODE_MASTER;
109 else
110 iwe.u.mode = IW_MODE_ADHOC;
111
112 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
113 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
114 #else
115 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
116 #endif
117 }
118
119 /* Add frequency/channel */
120 iwe.cmd = SIOCGIWFREQ;
121 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
122 iwe.u.freq.e = 3; */
123 iwe.u.freq.m = network->channel;
124 iwe.u.freq.e = 0;
125 iwe.u.freq.i = 0;
126 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
127 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
128 #else
129 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
130 #endif
131
132 /* Add encryption capability */
133 iwe.cmd = SIOCGIWENCODE;
134 if (network->capability & WLAN_CAPABILITY_PRIVACY)
135 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
136 else
137 iwe.u.data.flags = IW_ENCODE_DISABLED;
138 iwe.u.data.length = 0;
139 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
140 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
141 #else
142 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
143 #endif
144
145 /* Add basic and extended rates */
146 max_rate = 0;
147 p = custom;
148 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
149 for (i = 0, j = 0; i < network->rates_len; ) {
150 if (j < network->rates_ex_len &&
151 ((network->rates_ex[j] & 0x7F) <
152 (network->rates[i] & 0x7F)))
153 rate = network->rates_ex[j++] & 0x7F;
154 else
155 rate = network->rates[i++] & 0x7F;
156 if (rate > max_rate)
157 max_rate = rate;
158 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
159 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
160 }
161 for (; j < network->rates_ex_len; j++) {
162 rate = network->rates_ex[j] & 0x7F;
163 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
164 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
165 if (rate > max_rate)
166 max_rate = rate;
167 }
168
169 iwe.cmd = SIOCGIWRATE;
170 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
171 iwe.u.bitrate.value = max_rate * 500000;
172 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
173 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
174 #else
175 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN);
176 #endif
177
178 iwe.cmd = IWEVCUSTOM;
179 iwe.u.data.length = p - custom;
180 if (iwe.u.data.length)
181 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
182 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
183 #else
184 start = iwe_stream_add_point(start, stop, &iwe, custom);
185 #endif
186
187 /* Add quality statistics */
188 /* TODO: Fix these values... */
189 if (network->stats.signal == 0 || network->stats.rssi == 0)
190 printk("========>signal:%d, rssi:%d\n", network->stats.signal, network->stats.rssi);
191 iwe.cmd = IWEVQUAL;
192 // printk("SIGNAL: %d,RSSI: %d,NOISE: %d\n",network->stats.signal,network->stats.rssi,network->stats.noise);
193 iwe.u.qual.qual = network->stats.signalstrength;
194 iwe.u.qual.level = network->stats.signal;
195 iwe.u.qual.noise = network->stats.noise;
196 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
197 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
198 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
199 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
200 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
201 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
202 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
203 iwe.u.qual.updated = 7;
204 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
205 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
206 #else
207 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
208 #endif
209
210 iwe.cmd = IWEVCUSTOM;
211 p = custom;
212
213 iwe.u.data.length = p - custom;
214 if (iwe.u.data.length)
215 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
216 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
217 #else
218 start = iwe_stream_add_point(start, stop, &iwe, custom);
219 #endif
220
221 #if 0
222 if (ieee->wpa_enabled && network->wpa_ie_len){
223 char buf[MAX_WPA_IE_LEN * 2 + 30];
224 // printk("WPA IE\n");
225 u8 *p = buf;
226 p += sprintf(p, "wpa_ie=");
227 for (i = 0; i < network->wpa_ie_len; i++) {
228 p += sprintf(p, "%02x", network->wpa_ie[i]);
229 }
230
231 memset(&iwe, 0, sizeof(iwe));
232 iwe.cmd = IWEVCUSTOM;
233 iwe.u.data.length = strlen(buf);
234 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
235 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
236 #else
237 start = iwe_stream_add_point(start, stop, &iwe, buf);
238 #endif
239 }
240
241 if (ieee->wpa_enabled && network->rsn_ie_len){
242 char buf[MAX_WPA_IE_LEN * 2 + 30];
243
244 u8 *p = buf;
245 p += sprintf(p, "rsn_ie=");
246 for (i = 0; i < network->rsn_ie_len; i++) {
247 p += sprintf(p, "%02x", network->rsn_ie[i]);
248 }
249
250
251 #else
252 memset(&iwe, 0, sizeof(iwe));
253 if (network->wpa_ie_len) {
254 // printk("wpa_ie_len:%d\n", network->wpa_ie_len);
255 char buf[MAX_WPA_IE_LEN];
256 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
257 iwe.cmd = IWEVGENIE;
258 iwe.u.data.length = network->wpa_ie_len;
259 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
260 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
261 #else
262 start = iwe_stream_add_point(start, stop, &iwe, buf);
263 #endif
264 }
265
266 memset(&iwe, 0, sizeof(iwe));
267 if (network->rsn_ie_len) {
268 // printk("=====>rsn_ie_len:\n", network->rsn_ie_len);
269 #if 0
270 {
271 int i;
272 for (i=0; i<network->rsn_ie_len; i++);
273 printk("%2x ", network->rsn_ie[i]);
274 printk("\n");
275 }
276 #endif
277 char buf[MAX_WPA_IE_LEN];
278 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
279 iwe.cmd = IWEVGENIE;
280 iwe.u.data.length = network->rsn_ie_len;
281 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
282 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
283 #else
284 start = iwe_stream_add_point(start, stop, &iwe, buf);
285 #endif
286 }
287
288 #endif
289
290 /* Add EXTRA: Age to display seconds since last beacon/probe response
291 * for given network. */
292 iwe.cmd = IWEVCUSTOM;
293 p = custom;
294 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
295 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
296 iwe.u.data.length = p - custom;
297 if (iwe.u.data.length)
298 #if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))||IN_FEDORACORE_9)
299 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
300 #else
301 start = iwe_stream_add_point(start, stop, &iwe, custom);
302 #endif
303
304 return start;
305 }
306
307 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
308 struct iw_request_info *info,
309 union iwreq_data *wrqu, char *extra)
310 {
311 struct ieee80211_network *network;
312 unsigned long flags;
313 int err = 0;
314 char *ev = extra;
315 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
316 //char *stop = ev + IW_SCAN_MAX_DATA;
317 int i = 0;
318
319 IEEE80211_DEBUG_WX("Getting scan\n");
320 down(&ieee->wx_sem);
321 spin_lock_irqsave(&ieee->lock, flags);
322
323 if(!ieee->bHwRadioOff)
324 {
325 list_for_each_entry(network, &ieee->network_list, list) {
326 i++;
327
328 if((stop-ev)<200)
329 {
330 err = -E2BIG;
331 break;
332 }
333 if (ieee->scan_age == 0 ||
334 time_after(network->last_scanned + ieee->scan_age, jiffies))
335 {
336 ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
337 }
338 else
339 IEEE80211_DEBUG_SCAN(
340 "Not showing network '%s ("
341 MAC_FMT ")' due to age (%lums).\n",
342 escape_essid(network->ssid,
343 network->ssid_len),
344 MAC_ARG(network->bssid),
345 (jiffies - network->last_scanned) / (HZ / 100));
346 }
347 }
348 spin_unlock_irqrestore(&ieee->lock, flags);
349 up(&ieee->wx_sem);
350 wrqu->data.length = ev - extra;
351 wrqu->data.flags = 0;
352 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
353
354 return err;
355 }
356
357 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
358 struct iw_request_info *info,
359 union iwreq_data *wrqu, char *keybuf)
360 {
361 struct iw_point *erq = &(wrqu->encoding);
362 struct net_device *dev = ieee->dev;
363 struct ieee80211_security sec = {
364 .flags = 0
365 };
366 int i, key, key_provided, len;
367 struct ieee80211_crypt_data **crypt;
368
369 IEEE80211_DEBUG_WX("SET_ENCODE\n");
370
371 key = erq->flags & IW_ENCODE_INDEX;
372 if (key) {
373 if (key > WEP_KEYS)
374 return -EINVAL;
375 key--;
376 key_provided = 1;
377 } else {
378 key_provided = 0;
379 key = ieee->tx_keyidx;
380 }
381
382 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
383 "provided" : "default");
384
385 crypt = &ieee->crypt[key];
386
387 if (erq->flags & IW_ENCODE_DISABLED) {
388 if (key_provided && *crypt) {
389 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
390 key);
391 ieee80211_crypt_delayed_deinit(ieee, crypt);
392 } else
393 IEEE80211_DEBUG_WX("Disabling encryption.\n");
394
395 /* Check all the keys to see if any are still configured,
396 * and if no key index was provided, de-init them all */
397 for (i = 0; i < WEP_KEYS; i++) {
398 if (ieee->crypt[i] != NULL) {
399 if (key_provided)
400 break;
401 ieee80211_crypt_delayed_deinit(
402 ieee, &ieee->crypt[i]);
403 }
404 }
405
406 if (i == WEP_KEYS) {
407 sec.enabled = 0;
408 sec.level = SEC_LEVEL_0;
409 sec.flags |= SEC_ENABLED | SEC_LEVEL;
410 }
411
412 goto done;
413 }
414
415
416
417 sec.enabled = 1;
418 sec.flags |= SEC_ENABLED;
419
420 if (*crypt != NULL && (*crypt)->ops != NULL &&
421 strcmp((*crypt)->ops->name, "WEP") != 0) {
422 /* changing to use WEP; deinit previously used algorithm
423 * on this key */
424 ieee80211_crypt_delayed_deinit(ieee, crypt);
425 }
426
427 if (*crypt == NULL) {
428 struct ieee80211_crypt_data *new_crypt;
429
430 /* take WEP into use */
431 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
432 GFP_KERNEL);
433 if (new_crypt == NULL)
434 return -ENOMEM;
435 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
436 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
437 if (!new_crypt->ops) {
438 request_module("ieee80211_crypt_wep");
439 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
440 }
441
442 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
443 new_crypt->priv = new_crypt->ops->init(key);
444
445 if (!new_crypt->ops || !new_crypt->priv) {
446 kfree(new_crypt);
447 new_crypt = NULL;
448
449 printk(KERN_WARNING "%s: could not initialize WEP: "
450 "load module ieee80211_crypt_wep\n",
451 dev->name);
452 return -EOPNOTSUPP;
453 }
454 *crypt = new_crypt;
455 }
456
457 /* If a new key was provided, set it up */
458 if (erq->length > 0) {
459 len = erq->length <= 5 ? 5 : 13;
460 memcpy(sec.keys[key], keybuf, erq->length);
461 if (len > erq->length)
462 memset(sec.keys[key] + erq->length, 0,
463 len - erq->length);
464 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
465 key, escape_essid(sec.keys[key], len),
466 erq->length, len);
467 sec.key_sizes[key] = len;
468 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
469 (*crypt)->priv);
470 sec.flags |= (1 << key);
471 /* This ensures a key will be activated if no key is
472 * explicitely set */
473 if (key == sec.active_key)
474 sec.flags |= SEC_ACTIVE_KEY;
475 ieee->tx_keyidx = key;//by wb 080312
476 } else {
477 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
478 NULL, (*crypt)->priv);
479 if (len == 0) {
480 /* Set a default key of all 0 */
481 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
482 key);
483 memset(sec.keys[key], 0, 13);
484 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
485 (*crypt)->priv);
486 sec.key_sizes[key] = 13;
487 sec.flags |= (1 << key);
488 }
489
490 /* No key data - just set the default TX key index */
491 if (key_provided) {
492 IEEE80211_DEBUG_WX(
493 "Setting key %d to default Tx key.\n", key);
494 ieee->tx_keyidx = key;
495 sec.active_key = key;
496 sec.flags |= SEC_ACTIVE_KEY;
497 }
498 }
499
500 done:
501 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
502 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
503 sec.flags |= SEC_AUTH_MODE;
504 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
505 "OPEN" : "SHARED KEY");
506
507 /* For now we just support WEP, so only set that security level...
508 * TODO: When WPA is added this is one place that needs to change */
509 sec.flags |= SEC_LEVEL;
510 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
511
512 if (ieee->set_security)
513 ieee->set_security(dev, &sec);
514
515 /* Do not reset port if card is in Managed mode since resetting will
516 * generate new IEEE 802.11 authentication which may end up in looping
517 * with IEEE 802.1X. If your hardware requires a reset after WEP
518 * configuration (for example... Prism2), implement the reset_port in
519 * the callbacks structures used to initialize the 802.11 stack. */
520 if (ieee->reset_on_keychange &&
521 ieee->iw_mode != IW_MODE_INFRA &&
522 ieee->reset_port && ieee->reset_port(dev)) {
523 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
524 return -EINVAL;
525 }
526 return 0;
527 }
528
529 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
530 struct iw_request_info *info,
531 union iwreq_data *wrqu, char *keybuf)
532 {
533 struct iw_point *erq = &(wrqu->encoding);
534 int len, key;
535 struct ieee80211_crypt_data *crypt;
536
537 IEEE80211_DEBUG_WX("GET_ENCODE\n");
538
539 if(ieee->iw_mode == IW_MODE_MONITOR)
540 return -1;
541
542 key = erq->flags & IW_ENCODE_INDEX;
543 if (key) {
544 if (key > WEP_KEYS)
545 return -EINVAL;
546 key--;
547 } else
548 key = ieee->tx_keyidx;
549
550 crypt = ieee->crypt[key];
551 erq->flags = key + 1;
552
553 if (crypt == NULL || crypt->ops == NULL) {
554 erq->length = 0;
555 erq->flags |= IW_ENCODE_DISABLED;
556 return 0;
557 }
558
559 if (strcmp(crypt->ops->name, "WEP") != 0) {
560 /* only WEP is supported with wireless extensions, so just
561 * report that encryption is used */
562 erq->length = 0;
563 erq->flags |= IW_ENCODE_ENABLED;
564 return 0;
565 }
566
567 len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
568 erq->length = (len >= 0 ? len : 0);
569
570 erq->flags |= IW_ENCODE_ENABLED;
571
572 if (ieee->open_wep)
573 erq->flags |= IW_ENCODE_OPEN;
574 else
575 erq->flags |= IW_ENCODE_RESTRICTED;
576
577 return 0;
578 }
579
580 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
581 struct iw_request_info *info,
582 union iwreq_data *wrqu, char *extra)
583 {
584 struct net_device *dev = ieee->dev;
585 struct iw_point *encoding = &wrqu->encoding;
586 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
587 int i, idx, ret = 0;
588 int group_key = 0;
589 const char *alg, *module;
590 struct ieee80211_crypto_ops *ops;
591 struct ieee80211_crypt_data **crypt;
592
593 struct ieee80211_security sec = {
594 .flags = 0,
595 };
596 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
597 idx = encoding->flags & IW_ENCODE_INDEX;
598 if (idx) {
599 if (idx < 1 || idx > WEP_KEYS)
600 return -EINVAL;
601 idx--;
602 } else
603 idx = ieee->tx_keyidx;
604
605 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
606 crypt = &ieee->crypt[idx];
607 group_key = 1;
608 } else {
609 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
610 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
611 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
612 return -EINVAL;
613 if (ieee->iw_mode == IW_MODE_INFRA)
614 crypt = &ieee->crypt[idx];
615 else
616 return -EINVAL;
617 }
618
619 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
620 if ((encoding->flags & IW_ENCODE_DISABLED) ||
621 ext->alg == IW_ENCODE_ALG_NONE) {
622 if (*crypt)
623 ieee80211_crypt_delayed_deinit(ieee, crypt);
624
625 for (i = 0; i < WEP_KEYS; i++)
626 if (ieee->crypt[i] != NULL)
627 break;
628
629 if (i == WEP_KEYS) {
630 sec.enabled = 0;
631 // sec.encrypt = 0;
632 sec.level = SEC_LEVEL_0;
633 sec.flags |= SEC_LEVEL;
634 }
635 //printk("disabled: flag:%x\n", encoding->flags);
636 goto done;
637 }
638
639 sec.enabled = 1;
640 // sec.encrypt = 1;
641 #if 0
642 if (group_key ? !ieee->host_mc_decrypt :
643 !(ieee->host_encrypt || ieee->host_decrypt ||
644 ieee->host_encrypt_msdu))
645 goto skip_host_crypt;
646 #endif
647 switch (ext->alg) {
648 case IW_ENCODE_ALG_WEP:
649 alg = "WEP";
650 module = "ieee80211_crypt_wep";
651 break;
652 case IW_ENCODE_ALG_TKIP:
653 alg = "TKIP";
654 module = "ieee80211_crypt_tkip";
655 break;
656 case IW_ENCODE_ALG_CCMP:
657 alg = "CCMP";
658 module = "ieee80211_crypt_ccmp";
659 break;
660 default:
661 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
662 dev->name, ext->alg);
663 ret = -EINVAL;
664 goto done;
665 }
666 // printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
667
668 ops = ieee80211_get_crypto_ops(alg);
669 if (ops == NULL) {
670 request_module(module);
671 ops = ieee80211_get_crypto_ops(alg);
672 }
673 if (ops == NULL) {
674 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
675 dev->name, ext->alg);
676 printk("========>unknown crypto alg %d\n", ext->alg);
677 ret = -EINVAL;
678 goto done;
679 }
680
681 if (*crypt == NULL || (*crypt)->ops != ops) {
682 struct ieee80211_crypt_data *new_crypt;
683
684 ieee80211_crypt_delayed_deinit(ieee, crypt);
685
686 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
687 if (new_crypt == NULL) {
688 ret = -ENOMEM;
689 goto done;
690 }
691 new_crypt->ops = ops;
692 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
693 new_crypt->priv = new_crypt->ops->init(idx);
694 if (new_crypt->priv == NULL) {
695 kfree(new_crypt);
696 ret = -EINVAL;
697 goto done;
698 }
699 *crypt = new_crypt;
700
701 }
702
703 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
704 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
705 (*crypt)->priv) < 0) {
706 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
707 printk("key setting failed\n");
708 ret = -EINVAL;
709 goto done;
710 }
711 #if 1
712 //skip_host_crypt:
713 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
714 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
715 ieee->tx_keyidx = idx;
716 sec.active_key = idx;
717 sec.flags |= SEC_ACTIVE_KEY;
718 }
719
720 if (ext->alg != IW_ENCODE_ALG_NONE) {
721 memcpy(sec.keys[idx], ext->key, ext->key_len);
722 sec.key_sizes[idx] = ext->key_len;
723 sec.flags |= (1 << idx);
724 if (ext->alg == IW_ENCODE_ALG_WEP) {
725 // sec.encode_alg[idx] = SEC_ALG_WEP;
726 sec.flags |= SEC_LEVEL;
727 sec.level = SEC_LEVEL_1;
728 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
729 // sec.encode_alg[idx] = SEC_ALG_TKIP;
730 sec.flags |= SEC_LEVEL;
731 sec.level = SEC_LEVEL_2;
732 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
733 // sec.encode_alg[idx] = SEC_ALG_CCMP;
734 sec.flags |= SEC_LEVEL;
735 sec.level = SEC_LEVEL_3;
736 }
737 /* Don't set sec level for group keys. */
738 if (group_key)
739 sec.flags &= ~SEC_LEVEL;
740 }
741 #endif
742 done:
743 if (ieee->set_security)
744 ieee->set_security(ieee->dev, &sec);
745
746 if (ieee->reset_on_keychange &&
747 ieee->iw_mode != IW_MODE_INFRA &&
748 ieee->reset_port && ieee->reset_port(dev)) {
749 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
750 return -EINVAL;
751 }
752
753 return ret;
754 }
755 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
756 struct iw_request_info *info,
757 union iwreq_data *wrqu, char *extra)
758 {
759 struct iw_mlme *mlme = (struct iw_mlme *) extra;
760 // printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
761 #if 1
762 switch (mlme->cmd) {
763 case IW_MLME_DEAUTH:
764 case IW_MLME_DISASSOC:
765 // printk("disassoc now\n");
766 ieee80211_disassociate(ieee);
767 break;
768 default:
769 return -EOPNOTSUPP;
770 }
771 #endif
772 return 0;
773 }
774
775 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
776 struct iw_request_info *info,
777 struct iw_param *data, char *extra)
778 {
779 /*
780 struct ieee80211_security sec = {
781 .flags = SEC_AUTH_MODE,
782 }
783 */
784 //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
785 switch (data->flags & IW_AUTH_INDEX) {
786 case IW_AUTH_WPA_VERSION:
787 /*need to support wpa2 here*/
788 //printk("wpa version:%x\n", data->value);
789 break;
790 case IW_AUTH_CIPHER_PAIRWISE:
791 case IW_AUTH_CIPHER_GROUP:
792 case IW_AUTH_KEY_MGMT:
793 /*
794 * * Host AP driver does not use these parameters and allows
795 * * wpa_supplicant to control them internally.
796 * */
797 break;
798 case IW_AUTH_TKIP_COUNTERMEASURES:
799 ieee->tkip_countermeasures = data->value;
800 break;
801 case IW_AUTH_DROP_UNENCRYPTED:
802 ieee->drop_unencrypted = data->value;
803 break;
804
805 case IW_AUTH_80211_AUTH_ALG:
806 ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
807 //printk("open_wep:%d\n", ieee->open_wep);
808 break;
809
810 #if 1
811 case IW_AUTH_WPA_ENABLED:
812 ieee->wpa_enabled = (data->value)?1:0;
813 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
814 break;
815
816 #endif
817 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
818 ieee->ieee802_1x = data->value;
819 break;
820 case IW_AUTH_PRIVACY_INVOKED:
821 ieee->privacy_invoked = data->value;
822 break;
823 default:
824 return -EOPNOTSUPP;
825 }
826 return 0;
827 }
828
829 #if 1
830 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
831 {
832 #if 0
833 printk("====>%s()\n", __func__);
834 {
835 int i;
836 for (i=0; i<len; i++)
837 printk("%2x ", ie[i]&0xff);
838 printk("\n");
839 }
840 #endif
841 u8 *buf = NULL;
842
843 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
844 {
845 printk("return error out, len:%zu\n", len);
846 return -EINVAL;
847 }
848
849 if (len)
850 {
851 if (len != ie[1]+2){
852 printk("len:%zu, ie:%d\n", len, ie[1]);
853 return -EINVAL;
854 }
855 buf = kmalloc(len, GFP_KERNEL);
856 if (buf == NULL)
857 return -ENOMEM;
858 memcpy(buf, ie, len);
859 kfree(ieee->wpa_ie);
860 ieee->wpa_ie = buf;
861 ieee->wpa_ie_len = len;
862 }
863 else{
864 if (ieee->wpa_ie)
865 kfree(ieee->wpa_ie);
866 ieee->wpa_ie = NULL;
867 ieee->wpa_ie_len = 0;
868 }
869 // printk("<=====out %s()\n", __func__);
870
871 return 0;
872
873 }
874 #endif
875
876 #if 0
877 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie);
878 EXPORT_SYMBOL(ieee80211_wx_set_mlme);
879 EXPORT_SYMBOL(ieee80211_wx_set_auth);
880 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext);
881 EXPORT_SYMBOL(ieee80211_wx_get_scan);
882 EXPORT_SYMBOL(ieee80211_wx_set_encode);
883 EXPORT_SYMBOL(ieee80211_wx_get_encode);
884 #endif
885
|
This page was automatically generated by the
LXR engine.
|