blob: a08b97a09512a92c4544d1cfe22983945b1e7464 [file] [log] [blame]
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001/******************************************************************************
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"
38static const char *ieee80211_modes[] = {
39 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
40};
41
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080042#define MAX_CUSTOM_LEN 64
43static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
44 char *start, char *stop,
45 struct ieee80211_network *network,
46 struct iw_request_info *info)
47{
48 char custom[MAX_CUSTOM_LEN];
49 char *p;
50 struct iw_event iwe;
51 int i, j;
52 u8 max_rate, rate;
53
54 /* First entry *MUST* be the AP MAC address */
55 iwe.cmd = SIOCGIWAP;
56 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
57 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080058 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080059
60 /* Remaining entries will be displayed in the order we provide them */
61
62 /* Add the ESSID */
63 iwe.cmd = SIOCGIWESSID;
64 iwe.u.data.flags = 1;
65 //YJ,modified,080903,for hidden ap
66 //if (network->flags & NETWORK_EMPTY_ESSID) {
67 if (network->ssid_len == 0) {
68 //YJ,modified,080903,end
69 iwe.u.data.length = sizeof("<hidden>");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080070 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080071 } else {
72 iwe.u.data.length = min(network->ssid_len, (u8)32);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080073 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080074 }
75 //printk("ESSID: %s\n",network->ssid);
76 /* Add the protocol name */
77 iwe.cmd = SIOCGIWNAME;
78 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080079 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080080
81 /* Add mode */
82 iwe.cmd = SIOCGIWMODE;
83 if (network->capability &
84 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
85 if (network->capability & WLAN_CAPABILITY_BSS)
86 iwe.u.mode = IW_MODE_MASTER;
87 else
88 iwe.u.mode = IW_MODE_ADHOC;
89
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080090 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080091 }
92
93 /* Add frequency/channel */
94 iwe.cmd = SIOCGIWFREQ;
95/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
96 iwe.u.freq.e = 3; */
97 iwe.u.freq.m = network->channel;
98 iwe.u.freq.e = 0;
99 iwe.u.freq.i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800100 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800101
102 /* Add encryption capability */
103 iwe.cmd = SIOCGIWENCODE;
104 if (network->capability & WLAN_CAPABILITY_PRIVACY)
105 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
106 else
107 iwe.u.data.flags = IW_ENCODE_DISABLED;
108 iwe.u.data.length = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800109 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800110
111 /* Add basic and extended rates */
112 max_rate = 0;
113 p = custom;
114 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
115 for (i = 0, j = 0; i < network->rates_len; ) {
116 if (j < network->rates_ex_len &&
117 ((network->rates_ex[j] & 0x7F) <
118 (network->rates[i] & 0x7F)))
119 rate = network->rates_ex[j++] & 0x7F;
120 else
121 rate = network->rates[i++] & 0x7F;
122 if (rate > max_rate)
123 max_rate = rate;
124 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
125 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
126 }
127 for (; j < network->rates_ex_len; j++) {
128 rate = network->rates_ex[j] & 0x7F;
129 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
130 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
131 if (rate > max_rate)
132 max_rate = rate;
133 }
134
135 iwe.cmd = SIOCGIWRATE;
136 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
137 iwe.u.bitrate.value = max_rate * 500000;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800138 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800139
140 iwe.cmd = IWEVCUSTOM;
141 iwe.u.data.length = p - custom;
142 if (iwe.u.data.length)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800143 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800144
145 /* Add quality statistics */
146 /* TODO: Fix these values... */
147 if (network->stats.signal == 0 || network->stats.rssi == 0)
148 printk("========>signal:%d, rssi:%d\n", network->stats.signal, network->stats.rssi);
149 iwe.cmd = IWEVQUAL;
150// printk("SIGNAL: %d,RSSI: %d,NOISE: %d\n",network->stats.signal,network->stats.rssi,network->stats.noise);
151 iwe.u.qual.qual = network->stats.signalstrength;
152 iwe.u.qual.level = network->stats.signal;
153 iwe.u.qual.noise = network->stats.noise;
154 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
155 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
156 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
157 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
158 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
159 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
160 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
161 iwe.u.qual.updated = 7;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800162 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800163
164 iwe.cmd = IWEVCUSTOM;
165 p = custom;
166
167 iwe.u.data.length = p - custom;
168 if (iwe.u.data.length)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800169 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800170
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800171 memset(&iwe, 0, sizeof(iwe));
172 if (network->wpa_ie_len) {
173 // printk("wpa_ie_len:%d\n", network->wpa_ie_len);
174 char buf[MAX_WPA_IE_LEN];
175 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
176 iwe.cmd = IWEVGENIE;
177 iwe.u.data.length = network->wpa_ie_len;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800178 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800179 }
180
181 memset(&iwe, 0, sizeof(iwe));
182 if (network->rsn_ie_len) {
183 // printk("=====>rsn_ie_len:\n", network->rsn_ie_len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800184 char buf[MAX_WPA_IE_LEN];
185 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
186 iwe.cmd = IWEVGENIE;
187 iwe.u.data.length = network->rsn_ie_len;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800188 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800189 }
190
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800191 /* Add EXTRA: Age to display seconds since last beacon/probe response
192 * for given network. */
193 iwe.cmd = IWEVCUSTOM;
194 p = custom;
195 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
196 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
197 iwe.u.data.length = p - custom;
198 if (iwe.u.data.length)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800199 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800200
201 return start;
202}
203
204int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
205 struct iw_request_info *info,
206 union iwreq_data *wrqu, char *extra)
207{
208 struct ieee80211_network *network;
209 unsigned long flags;
210 int err = 0;
211 char *ev = extra;
212 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
213 //char *stop = ev + IW_SCAN_MAX_DATA;
214 int i = 0;
215
216 IEEE80211_DEBUG_WX("Getting scan\n");
217 down(&ieee->wx_sem);
218 spin_lock_irqsave(&ieee->lock, flags);
219
220 if(!ieee->bHwRadioOff)
221 {
222 list_for_each_entry(network, &ieee->network_list, list) {
223 i++;
224
225 if((stop-ev)<200)
226 {
227 err = -E2BIG;
228 break;
229 }
230 if (ieee->scan_age == 0 ||
231 time_after(network->last_scanned + ieee->scan_age, jiffies))
232 {
233 ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
234 }
235 else
236 IEEE80211_DEBUG_SCAN(
237 "Not showing network '%s ("
238 MAC_FMT ")' due to age (%lums).\n",
239 escape_essid(network->ssid,
240 network->ssid_len),
241 MAC_ARG(network->bssid),
242 (jiffies - network->last_scanned) / (HZ / 100));
243 }
244 }
245 spin_unlock_irqrestore(&ieee->lock, flags);
246 up(&ieee->wx_sem);
247 wrqu->data.length = ev - extra;
248 wrqu->data.flags = 0;
249 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
250
251 return err;
252}
253
254int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
255 struct iw_request_info *info,
256 union iwreq_data *wrqu, char *keybuf)
257{
258 struct iw_point *erq = &(wrqu->encoding);
259 struct net_device *dev = ieee->dev;
260 struct ieee80211_security sec = {
261 .flags = 0
262 };
263 int i, key, key_provided, len;
264 struct ieee80211_crypt_data **crypt;
265
266 IEEE80211_DEBUG_WX("SET_ENCODE\n");
267
268 key = erq->flags & IW_ENCODE_INDEX;
269 if (key) {
270 if (key > WEP_KEYS)
271 return -EINVAL;
272 key--;
273 key_provided = 1;
274 } else {
275 key_provided = 0;
276 key = ieee->tx_keyidx;
277 }
278
279 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
280 "provided" : "default");
281
282 crypt = &ieee->crypt[key];
283
284 if (erq->flags & IW_ENCODE_DISABLED) {
285 if (key_provided && *crypt) {
286 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
287 key);
288 ieee80211_crypt_delayed_deinit(ieee, crypt);
289 } else
290 IEEE80211_DEBUG_WX("Disabling encryption.\n");
291
292 /* Check all the keys to see if any are still configured,
293 * and if no key index was provided, de-init them all */
294 for (i = 0; i < WEP_KEYS; i++) {
295 if (ieee->crypt[i] != NULL) {
296 if (key_provided)
297 break;
298 ieee80211_crypt_delayed_deinit(
299 ieee, &ieee->crypt[i]);
300 }
301 }
302
303 if (i == WEP_KEYS) {
304 sec.enabled = 0;
305 sec.level = SEC_LEVEL_0;
306 sec.flags |= SEC_ENABLED | SEC_LEVEL;
307 }
308
309 goto done;
310 }
311
312
313
314 sec.enabled = 1;
315 sec.flags |= SEC_ENABLED;
316
317 if (*crypt != NULL && (*crypt)->ops != NULL &&
318 strcmp((*crypt)->ops->name, "WEP") != 0) {
319 /* changing to use WEP; deinit previously used algorithm
320 * on this key */
321 ieee80211_crypt_delayed_deinit(ieee, crypt);
322 }
323
324 if (*crypt == NULL) {
325 struct ieee80211_crypt_data *new_crypt;
326
327 /* take WEP into use */
328 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
329 GFP_KERNEL);
330 if (new_crypt == NULL)
331 return -ENOMEM;
332 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
333 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
Herton Ronaldo Krzesinskia010a332009-10-02 11:03:38 -0300334 if (!new_crypt->ops)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800335 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800336
Herton Ronaldo Krzesinskia010a332009-10-02 11:03:38 -0300337 if (new_crypt->ops)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800338 new_crypt->priv = new_crypt->ops->init(key);
339
340 if (!new_crypt->ops || !new_crypt->priv) {
341 kfree(new_crypt);
342 new_crypt = NULL;
343
344 printk(KERN_WARNING "%s: could not initialize WEP: "
345 "load module ieee80211_crypt_wep\n",
346 dev->name);
347 return -EOPNOTSUPP;
348 }
349 *crypt = new_crypt;
350 }
351
352 /* If a new key was provided, set it up */
353 if (erq->length > 0) {
354 len = erq->length <= 5 ? 5 : 13;
355 memcpy(sec.keys[key], keybuf, erq->length);
356 if (len > erq->length)
357 memset(sec.keys[key] + erq->length, 0,
358 len - erq->length);
359 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
360 key, escape_essid(sec.keys[key], len),
361 erq->length, len);
362 sec.key_sizes[key] = len;
363 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
364 (*crypt)->priv);
365 sec.flags |= (1 << key);
366 /* This ensures a key will be activated if no key is
367 * explicitely set */
368 if (key == sec.active_key)
369 sec.flags |= SEC_ACTIVE_KEY;
370 ieee->tx_keyidx = key;//by wb 080312
371 } else {
372 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
373 NULL, (*crypt)->priv);
374 if (len == 0) {
375 /* Set a default key of all 0 */
376 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
377 key);
378 memset(sec.keys[key], 0, 13);
379 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
380 (*crypt)->priv);
381 sec.key_sizes[key] = 13;
382 sec.flags |= (1 << key);
383 }
384
385 /* No key data - just set the default TX key index */
386 if (key_provided) {
387 IEEE80211_DEBUG_WX(
388 "Setting key %d to default Tx key.\n", key);
389 ieee->tx_keyidx = key;
390 sec.active_key = key;
391 sec.flags |= SEC_ACTIVE_KEY;
392 }
393 }
394
395 done:
396 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
397 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
398 sec.flags |= SEC_AUTH_MODE;
399 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
400 "OPEN" : "SHARED KEY");
401
402 /* For now we just support WEP, so only set that security level...
403 * TODO: When WPA is added this is one place that needs to change */
404 sec.flags |= SEC_LEVEL;
405 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
406
407 if (ieee->set_security)
408 ieee->set_security(dev, &sec);
409
410 /* Do not reset port if card is in Managed mode since resetting will
411 * generate new IEEE 802.11 authentication which may end up in looping
412 * with IEEE 802.1X. If your hardware requires a reset after WEP
413 * configuration (for example... Prism2), implement the reset_port in
414 * the callbacks structures used to initialize the 802.11 stack. */
415 if (ieee->reset_on_keychange &&
416 ieee->iw_mode != IW_MODE_INFRA &&
417 ieee->reset_port && ieee->reset_port(dev)) {
418 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
419 return -EINVAL;
420 }
421 return 0;
422}
423
424int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
425 struct iw_request_info *info,
426 union iwreq_data *wrqu, char *keybuf)
427{
428 struct iw_point *erq = &(wrqu->encoding);
429 int len, key;
430 struct ieee80211_crypt_data *crypt;
431
432 IEEE80211_DEBUG_WX("GET_ENCODE\n");
433
434 if(ieee->iw_mode == IW_MODE_MONITOR)
435 return -1;
436
437 key = erq->flags & IW_ENCODE_INDEX;
438 if (key) {
439 if (key > WEP_KEYS)
440 return -EINVAL;
441 key--;
442 } else
443 key = ieee->tx_keyidx;
444
445 crypt = ieee->crypt[key];
446 erq->flags = key + 1;
447
448 if (crypt == NULL || crypt->ops == NULL) {
449 erq->length = 0;
450 erq->flags |= IW_ENCODE_DISABLED;
451 return 0;
452 }
453
454 if (strcmp(crypt->ops->name, "WEP") != 0) {
455 /* only WEP is supported with wireless extensions, so just
456 * report that encryption is used */
457 erq->length = 0;
458 erq->flags |= IW_ENCODE_ENABLED;
459 return 0;
460 }
461
462 len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
463 erq->length = (len >= 0 ? len : 0);
464
465 erq->flags |= IW_ENCODE_ENABLED;
466
467 if (ieee->open_wep)
468 erq->flags |= IW_ENCODE_OPEN;
469 else
470 erq->flags |= IW_ENCODE_RESTRICTED;
471
472 return 0;
473}
474
475int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
476 struct iw_request_info *info,
477 union iwreq_data *wrqu, char *extra)
478{
479 struct net_device *dev = ieee->dev;
480 struct iw_point *encoding = &wrqu->encoding;
481 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
482 int i, idx, ret = 0;
483 int group_key = 0;
Herton Ronaldo Krzesinskia010a332009-10-02 11:03:38 -0300484 const char *alg;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800485 struct ieee80211_crypto_ops *ops;
486 struct ieee80211_crypt_data **crypt;
487
488 struct ieee80211_security sec = {
489 .flags = 0,
490 };
491 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
492 idx = encoding->flags & IW_ENCODE_INDEX;
493 if (idx) {
494 if (idx < 1 || idx > WEP_KEYS)
495 return -EINVAL;
496 idx--;
497 } else
498 idx = ieee->tx_keyidx;
499
500 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
501 crypt = &ieee->crypt[idx];
502 group_key = 1;
503 } else {
504 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
505 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
506 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
507 return -EINVAL;
508 if (ieee->iw_mode == IW_MODE_INFRA)
509 crypt = &ieee->crypt[idx];
510 else
511 return -EINVAL;
512 }
513
514 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
515 if ((encoding->flags & IW_ENCODE_DISABLED) ||
516 ext->alg == IW_ENCODE_ALG_NONE) {
517 if (*crypt)
518 ieee80211_crypt_delayed_deinit(ieee, crypt);
519
520 for (i = 0; i < WEP_KEYS; i++)
521 if (ieee->crypt[i] != NULL)
522 break;
523
524 if (i == WEP_KEYS) {
525 sec.enabled = 0;
526 // sec.encrypt = 0;
527 sec.level = SEC_LEVEL_0;
528 sec.flags |= SEC_LEVEL;
529 }
530 //printk("disabled: flag:%x\n", encoding->flags);
531 goto done;
532 }
533
534 sec.enabled = 1;
535 // sec.encrypt = 1;
Bartlomiej Zolnierkiewicz5521a512009-06-28 16:19:23 +0200536
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800537 switch (ext->alg) {
538 case IW_ENCODE_ALG_WEP:
539 alg = "WEP";
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800540 break;
541 case IW_ENCODE_ALG_TKIP:
542 alg = "TKIP";
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800543 break;
544 case IW_ENCODE_ALG_CCMP:
545 alg = "CCMP";
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800546 break;
547 default:
548 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
549 dev->name, ext->alg);
550 ret = -EINVAL;
551 goto done;
552 }
Harvey Harrisond599edc2009-01-07 14:31:57 -0800553// printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800554
555 ops = ieee80211_get_crypto_ops(alg);
Herton Ronaldo Krzesinskia010a332009-10-02 11:03:38 -0300556 if (ops == NULL)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800557 ops = ieee80211_get_crypto_ops(alg);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800558 if (ops == NULL) {
559 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
560 dev->name, ext->alg);
561 printk("========>unknown crypto alg %d\n", ext->alg);
562 ret = -EINVAL;
563 goto done;
564 }
565
566 if (*crypt == NULL || (*crypt)->ops != ops) {
567 struct ieee80211_crypt_data *new_crypt;
568
569 ieee80211_crypt_delayed_deinit(ieee, crypt);
570
571 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
572 if (new_crypt == NULL) {
573 ret = -ENOMEM;
574 goto done;
575 }
576 new_crypt->ops = ops;
Herton Ronaldo Krzesinskia010a332009-10-02 11:03:38 -0300577 if (new_crypt->ops)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800578 new_crypt->priv = new_crypt->ops->init(idx);
579 if (new_crypt->priv == NULL) {
580 kfree(new_crypt);
581 ret = -EINVAL;
582 goto done;
583 }
584 *crypt = new_crypt;
585
586 }
587
588 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
589 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
590 (*crypt)->priv) < 0) {
591 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
592 printk("key setting failed\n");
593 ret = -EINVAL;
594 goto done;
595 }
596#if 1
597 //skip_host_crypt:
598 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
599 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
600 ieee->tx_keyidx = idx;
601 sec.active_key = idx;
602 sec.flags |= SEC_ACTIVE_KEY;
603 }
604
605 if (ext->alg != IW_ENCODE_ALG_NONE) {
606 memcpy(sec.keys[idx], ext->key, ext->key_len);
607 sec.key_sizes[idx] = ext->key_len;
608 sec.flags |= (1 << idx);
609 if (ext->alg == IW_ENCODE_ALG_WEP) {
610 // sec.encode_alg[idx] = SEC_ALG_WEP;
611 sec.flags |= SEC_LEVEL;
612 sec.level = SEC_LEVEL_1;
613 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
614 // sec.encode_alg[idx] = SEC_ALG_TKIP;
615 sec.flags |= SEC_LEVEL;
616 sec.level = SEC_LEVEL_2;
617 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
618 // sec.encode_alg[idx] = SEC_ALG_CCMP;
619 sec.flags |= SEC_LEVEL;
620 sec.level = SEC_LEVEL_3;
621 }
622 /* Don't set sec level for group keys. */
623 if (group_key)
624 sec.flags &= ~SEC_LEVEL;
625 }
626#endif
627done:
628 if (ieee->set_security)
629 ieee->set_security(ieee->dev, &sec);
630
631 if (ieee->reset_on_keychange &&
632 ieee->iw_mode != IW_MODE_INFRA &&
633 ieee->reset_port && ieee->reset_port(dev)) {
634 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
635 return -EINVAL;
636 }
637
638 return ret;
639}
640int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
641 struct iw_request_info *info,
642 union iwreq_data *wrqu, char *extra)
643{
644 struct iw_mlme *mlme = (struct iw_mlme *) extra;
Harvey Harrisond599edc2009-01-07 14:31:57 -0800645// printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800646#if 1
647 switch (mlme->cmd) {
648 case IW_MLME_DEAUTH:
649 case IW_MLME_DISASSOC:
650 // printk("disassoc now\n");
651 ieee80211_disassociate(ieee);
652 break;
653 default:
654 return -EOPNOTSUPP;
655 }
656#endif
657 return 0;
658}
659
660int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
661 struct iw_request_info *info,
662 struct iw_param *data, char *extra)
663{
664/*
665 struct ieee80211_security sec = {
666 .flags = SEC_AUTH_MODE,
667 }
668*/
669 //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
670 switch (data->flags & IW_AUTH_INDEX) {
671 case IW_AUTH_WPA_VERSION:
672 /*need to support wpa2 here*/
673 //printk("wpa version:%x\n", data->value);
674 break;
675 case IW_AUTH_CIPHER_PAIRWISE:
676 case IW_AUTH_CIPHER_GROUP:
677 case IW_AUTH_KEY_MGMT:
678 /*
679 * * Host AP driver does not use these parameters and allows
680 * * wpa_supplicant to control them internally.
681 * */
682 break;
683 case IW_AUTH_TKIP_COUNTERMEASURES:
684 ieee->tkip_countermeasures = data->value;
685 break;
686 case IW_AUTH_DROP_UNENCRYPTED:
687 ieee->drop_unencrypted = data->value;
688 break;
689
690 case IW_AUTH_80211_AUTH_ALG:
691 ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
692 //printk("open_wep:%d\n", ieee->open_wep);
693 break;
694
695#if 1
696 case IW_AUTH_WPA_ENABLED:
697 ieee->wpa_enabled = (data->value)?1:0;
698 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
699 break;
700
701#endif
702 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
703 ieee->ieee802_1x = data->value;
704 break;
705 case IW_AUTH_PRIVACY_INVOKED:
706 ieee->privacy_invoked = data->value;
707 break;
708 default:
709 return -EOPNOTSUPP;
710 }
711 return 0;
712}
713
714#if 1
715int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
716{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800717 u8 *buf = NULL;
718
719 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
720 {
Randy Dunlap4913aff2009-02-11 13:19:35 -0800721 printk("return error out, len:%zu\n", len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800722 return -EINVAL;
723 }
724
725 if (len)
726 {
727 if (len != ie[1]+2){
Randy Dunlap4913aff2009-02-11 13:19:35 -0800728 printk("len:%zu, ie:%d\n", len, ie[1]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800729 return -EINVAL;
730 }
731 buf = kmalloc(len, GFP_KERNEL);
732 if (buf == NULL)
733 return -ENOMEM;
734 memcpy(buf, ie, len);
735 kfree(ieee->wpa_ie);
736 ieee->wpa_ie = buf;
737 ieee->wpa_ie_len = len;
738 }
739 else{
740 if (ieee->wpa_ie)
741 kfree(ieee->wpa_ie);
742 ieee->wpa_ie = NULL;
743 ieee->wpa_ie_len = 0;
744 }
Harvey Harrisond599edc2009-01-07 14:31:57 -0800745// printk("<=====out %s()\n", __func__);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800746
747 return 0;
748
749}
750#endif