]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[mirror_ubuntu-artful-kernel.git] / drivers / staging / rtl8187se / ieee80211 / ieee80211_wx.c
CommitLineData
c8d86be3
GKH
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>
c8d86be3 33#include <linux/kmod.h>
5a0e3ad6 34#include <linux/slab.h>
c8d86be3
GKH
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
c8d86be3
GKH
42#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);
c8d86be3 58 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
c8d86be3
GKH
59
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>");
c8d86be3 70 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
c8d86be3
GKH
71 } else {
72 iwe.u.data.length = min(network->ssid_len, (u8)32);
c8d86be3 73 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
c8d86be3
GKH
74 }
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]);
c8d86be3 79 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
c8d86be3
GKH
80
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
c8d86be3 90 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
c8d86be3
GKH
91 }
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;
c8d86be3 100 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
c8d86be3
GKH
101
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;
c8d86be3 109 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
c8d86be3
GKH
110
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;
c8d86be3 138 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
c8d86be3
GKH
139
140 iwe.cmd = IWEVCUSTOM;
141 iwe.u.data.length = p - custom;
142 if (iwe.u.data.length)
c8d86be3 143 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
c8d86be3
GKH
144
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;
c8d86be3 162 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
c8d86be3
GKH
163
164 iwe.cmd = IWEVCUSTOM;
165 p = custom;
166
167 iwe.u.data.length = p - custom;
168 if (iwe.u.data.length)
c8d86be3 169 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
c8d86be3 170
c8d86be3
GKH
171 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;
c8d86be3 178 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
c8d86be3
GKH
179 }
180
181 memset(&iwe, 0, sizeof(iwe));
182 if (network->rsn_ie_len) {
183 // printk("=====>rsn_ie_len:\n", network->rsn_ie_len);
c8d86be3
GKH
184 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;
c8d86be3 188 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
c8d86be3
GKH
189 }
190
c8d86be3
GKH
191 /* 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)
c8d86be3 199 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
c8d86be3
GKH
200
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 ("
0ee9f67c 238 "%pM)' due to age (%lums).\n",
c8d86be3
GKH
239 escape_essid(network->ssid,
240 network->ssid_len),
0ee9f67c 241 network->bssid,
c8d86be3
GKH
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");
a010a337 334 if (!new_crypt->ops)
c8d86be3 335 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
c8d86be3 336
a010a337 337 if (new_crypt->ops)
c8d86be3
GKH
338 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;
a010a337 484 const char *alg;
c8d86be3
GKH
485 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;
5521a513 536
c8d86be3
GKH
537 switch (ext->alg) {
538 case IW_ENCODE_ALG_WEP:
539 alg = "WEP";
c8d86be3
GKH
540 break;
541 case IW_ENCODE_ALG_TKIP:
542 alg = "TKIP";
c8d86be3
GKH
543 break;
544 case IW_ENCODE_ALG_CCMP:
545 alg = "CCMP";
c8d86be3
GKH
546 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 }
d599edca 553// printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
c8d86be3
GKH
554
555 ops = ieee80211_get_crypto_ops(alg);
a010a337 556 if (ops == NULL)
c8d86be3 557 ops = ieee80211_get_crypto_ops(alg);
c8d86be3
GKH
558 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;
a010a337 577 if (new_crypt->ops)
c8d86be3
GKH
578 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;
d599edca 645// printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
c8d86be3
GKH
646#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;
1832664a 698 //printk("enable wpa:%d\n", ieee->wpa_enabled);
c8d86be3
GKH
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{
c8d86be3
GKH
717 u8 *buf = NULL;
718
719 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
720 {
4913affd 721 printk("return error out, len:%zu\n", len);
c8d86be3
GKH
722 return -EINVAL;
723 }
724
725 if (len)
726 {
727 if (len != ie[1]+2){
4913affd 728 printk("len:%zu, ie:%d\n", len, ie[1]);
c8d86be3
GKH
729 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 }
d599edca 745// printk("<=====out %s()\n", __func__);
c8d86be3
GKH
746
747 return 0;
748
749}
750#endif