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