1 /******************************************************************************
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
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
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
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.
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
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.
24 The full GNU General Public License is included in this distribution in the
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
31 ******************************************************************************/
32 #include <linux/wireless.h>
33 #include <linux/version.h>
34 #include <linux/kmod.h>
35 #include <linux/slab.h>
36 #include <linux/module.h>
38 #include "ieee80211.h"
43 struct modes_unit ieee80211_modes
[] = {
52 #define iwe_stream_add_event_rsl iwe_stream_add_event
54 #define MAX_CUSTOM_LEN 64
55 static inline char *rtl819x_translate_scan(struct ieee80211_device
*ieee
,
56 char *start
, char *stop
,
57 struct ieee80211_network
*network
,
58 struct iw_request_info
*info
)
60 char custom
[MAX_CUSTOM_LEN
];
61 char proto_name
[IFNAMSIZ
];
62 char *pname
= proto_name
;
67 static u8 EWC11NHTCap
[] = {0x00, 0x90, 0x4c, 0x33};
69 /* First entry *MUST* be the AP MAC address */
71 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
72 memcpy(iwe
.u
.ap_addr
.sa_data
, network
->bssid
, ETH_ALEN
);
73 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
, IW_EV_ADDR_LEN
);
74 /* Remaining entries will be displayed in the order we provide them */
77 iwe
.cmd
= SIOCGIWESSID
;
79 // if (network->flags & NETWORK_EMPTY_ESSID) {
80 if (network
->ssid_len
== 0) {
81 iwe
.u
.data
.length
= sizeof("<hidden>");
82 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, "<hidden>");
84 iwe
.u
.data
.length
= min(network
->ssid_len
, (u8
)32);
85 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, network
->ssid
);
87 /* Add the protocol name */
88 iwe
.cmd
= SIOCGIWNAME
;
89 for(i
=0; i
<ARRAY_SIZE(ieee80211_modes
); i
++) {
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
;
96 snprintf(iwe
.u
.name
, IFNAMSIZ
, "IEEE802.11%s", proto_name
);
97 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
, IW_EV_CHAR_LEN
);
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
;
105 iwe
.u
.mode
= IW_MODE_ADHOC
;
106 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
, IW_EV_UINT_LEN
);
109 /* Add frequency/channel */
110 iwe
.cmd
= SIOCGIWFREQ
;
111 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
113 iwe
.u
.freq
.m
= network
->channel
;
116 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
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
;
122 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
123 iwe
.u
.data
.length
= 0;
124 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, network
->ssid
);
125 /* Add basic and extended rates */
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;
135 rate
= network
->rates
[i
++] & 0x7F;
138 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
139 "%d%s ", rate
>> 1, (rate
& 1) ? ".5" : "");
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" : "");
149 if (network
->mode
>= IEEE_N_24G
)//add N rate here;
151 PHT_CAPABILITY_ELE ht_cap
= NULL
;
152 bool is40M
= false, isShortGI
= false;
154 if (!memcmp(network
->bssht
.bdHTCapBuf
, EWC11NHTCap
, 4))
155 ht_cap
= (PHT_CAPABILITY_ELE
)&network
->bssht
.bdHTCapBuf
[4];
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);
163 max_mcs
= HTGetHighestMCSRate(ieee
, ht_cap
->MCS
, MCS_FILTER_ALL
);
164 rate
= MCS_DATA_RATE
[is40M
][isShortGI
][max_mcs
&0x7f];
168 iwe
.cmd
= SIOCGIWRATE
;
169 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
170 iwe
.u
.bitrate
.value
= max_rate
* 500000;
171 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
,
173 iwe
.cmd
= IWEVCUSTOM
;
174 iwe
.u
.data
.length
= p
- custom
;
175 if (iwe
.u
.data
.length
)
176 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
177 /* Add quality statistics */
178 /* TODO: Fix these values... */
180 iwe
.u
.qual
.qual
= network
->stats
.signal
;
181 iwe
.u
.qual
.level
= network
->stats
.rssi
;
182 iwe
.u
.qual
.noise
= network
->stats
.noise
;
183 iwe
.u
.qual
.updated
= network
->stats
.mask
& IEEE80211_STATMASK_WEMASK
;
184 if (!(network
->stats
.mask
& IEEE80211_STATMASK_RSSI
))
185 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
186 if (!(network
->stats
.mask
& IEEE80211_STATMASK_NOISE
))
187 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
188 if (!(network
->stats
.mask
& IEEE80211_STATMASK_SIGNAL
))
189 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
;
190 iwe
.u
.qual
.updated
= 7;
191 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
, IW_EV_QUAL_LEN
);
192 iwe
.cmd
= IWEVCUSTOM
;
195 iwe
.u
.data
.length
= p
- custom
;
196 if (iwe
.u
.data
.length
)
197 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
198 #if (WIRELESS_EXT < 18)
199 if (ieee
->wpa_enabled
&& network
->wpa_ie_len
){
200 char buf
[MAX_WPA_IE_LEN
* 2 + 30];
201 // printk("WPA IE\n");
203 p
+= sprintf(p
, "wpa_ie=");
204 for (i
= 0; i
< network
->wpa_ie_len
; i
++) {
205 p
+= sprintf(p
, "%02x", network
->wpa_ie
[i
]);
208 memset(&iwe
, 0, sizeof(iwe
));
209 iwe
.cmd
= IWEVCUSTOM
;
210 iwe
.u
.data
.length
= strlen(buf
);
211 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
214 if (ieee
->wpa_enabled
&& network
->rsn_ie_len
){
215 char buf
[MAX_WPA_IE_LEN
* 2 + 30];
218 p
+= sprintf(p
, "rsn_ie=");
219 for (i
= 0; i
< network
->rsn_ie_len
; i
++) {
220 p
+= sprintf(p
, "%02x", network
->rsn_ie
[i
]);
223 memset(&iwe
, 0, sizeof(iwe
));
224 iwe
.cmd
= IWEVCUSTOM
;
225 iwe
.u
.data
.length
= strlen(buf
);
226 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
229 memset(&iwe
, 0, sizeof(iwe
));
230 if (network
->wpa_ie_len
)
232 char buf
[MAX_WPA_IE_LEN
];
233 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
235 iwe
.u
.data
.length
= network
->wpa_ie_len
;
236 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
238 memset(&iwe
, 0, sizeof(iwe
));
239 if (network
->rsn_ie_len
)
241 char buf
[MAX_WPA_IE_LEN
];
242 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
244 iwe
.u
.data
.length
= network
->rsn_ie_len
;
245 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
250 /* Add EXTRA: Age to display seconds since last beacon/probe response
251 * for given network. */
252 iwe
.cmd
= IWEVCUSTOM
;
254 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
255 " Last beacon: %lums ago", (jiffies
- network
->last_scanned
) / (HZ
/ 100));
256 iwe
.u
.data
.length
= p
- custom
;
257 if (iwe
.u
.data
.length
)
258 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
263 int ieee80211_wx_get_scan(struct ieee80211_device
*ieee
,
264 struct iw_request_info
*info
,
265 union iwreq_data
*wrqu
, char *extra
)
267 struct ieee80211_network
*network
;
271 // char *stop = ev + IW_SCAN_MAX_DATA;
272 char *stop
= ev
+ wrqu
->data
.length
;//IW_SCAN_MAX_DATA;
273 //char *stop = ev + IW_SCAN_MAX_DATA;
276 IEEE80211_DEBUG_WX("Getting scan\n");
278 spin_lock_irqsave(&ieee
->lock
, flags
);
280 list_for_each_entry(network
, &ieee
->network_list
, list
) {
287 if (ieee
->scan_age
== 0 ||
288 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
289 ev
= rtl819x_translate_scan(ieee
, ev
, stop
, network
, info
);
291 IEEE80211_DEBUG_SCAN(
292 "Not showing network '%s ("
293 "%pM)' due to age (%lums).\n",
294 escape_essid(network
->ssid
,
297 (jiffies
- network
->last_scanned
) / (HZ
/ 100));
300 spin_unlock_irqrestore(&ieee
->lock
, flags
);
302 wrqu
->data
.length
= ev
- extra
;
303 wrqu
->data
.flags
= 0;
305 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i
);
310 int ieee80211_wx_set_encode(struct ieee80211_device
*ieee
,
311 struct iw_request_info
*info
,
312 union iwreq_data
*wrqu
, char *keybuf
)
314 struct iw_point
*erq
= &(wrqu
->encoding
);
315 struct net_device
*dev
= ieee
->dev
;
316 struct ieee80211_security sec
= {
319 int i
, key
, key_provided
, len
;
320 struct ieee80211_crypt_data
**crypt
;
322 IEEE80211_DEBUG_WX("SET_ENCODE\n");
324 key
= erq
->flags
& IW_ENCODE_INDEX
;
332 key
= ieee
->tx_keyidx
;
335 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
336 "provided" : "default");
337 crypt
= &ieee
->crypt
[key
];
339 if (erq
->flags
& IW_ENCODE_DISABLED
) {
340 if (key_provided
&& *crypt
) {
341 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
343 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
345 IEEE80211_DEBUG_WX("Disabling encryption.\n");
347 /* Check all the keys to see if any are still configured,
348 * and if no key index was provided, de-init them all */
349 for (i
= 0; i
< WEP_KEYS
; i
++) {
350 if (ieee
->crypt
[i
] != NULL
) {
353 ieee80211_crypt_delayed_deinit(
354 ieee
, &ieee
->crypt
[i
]);
360 sec
.level
= SEC_LEVEL_0
;
361 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
;
370 sec
.flags
|= SEC_ENABLED
;
372 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
373 strcmp((*crypt
)->ops
->name
, "WEP") != 0) {
374 /* changing to use WEP; deinit previously used algorithm
376 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
379 if (*crypt
== NULL
) {
380 struct ieee80211_crypt_data
*new_crypt
;
382 /* take WEP into use */
383 new_crypt
= kzalloc(sizeof(struct ieee80211_crypt_data
),
385 if (new_crypt
== NULL
)
387 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
389 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
391 new_crypt
->priv
= new_crypt
->ops
->init(key
);
393 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
397 printk(KERN_WARNING
"%s: could not initialize WEP: "
398 "load module ieee80211_crypt_wep\n",
405 /* If a new key was provided, set it up */
406 if (erq
->length
> 0) {
407 len
= erq
->length
<= 5 ? 5 : 13;
408 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
409 if (len
> erq
->length
)
410 memset(sec
.keys
[key
] + erq
->length
, 0,
412 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
413 key
, escape_essid(sec
.keys
[key
], len
),
415 sec
.key_sizes
[key
] = len
;
416 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
418 sec
.flags
|= (1 << key
);
419 /* This ensures a key will be activated if no key is
421 if (key
== sec
.active_key
)
422 sec
.flags
|= SEC_ACTIVE_KEY
;
423 ieee
->tx_keyidx
= key
;
426 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
427 NULL
, (*crypt
)->priv
);
429 /* Set a default key of all 0 */
430 printk("Setting key %d to all zero.\n",
433 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
435 memset(sec
.keys
[key
], 0, 13);
436 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
438 sec
.key_sizes
[key
] = 13;
439 sec
.flags
|= (1 << key
);
442 /* No key data - just set the default TX key index */
445 "Setting key %d to default Tx key.\n", key
);
446 ieee
->tx_keyidx
= key
;
447 sec
.active_key
= key
;
448 sec
.flags
|= SEC_ACTIVE_KEY
;
453 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
454 ieee
->auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
: WLAN_AUTH_SHARED_KEY
;
455 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
: WLAN_AUTH_SHARED_KEY
;
456 sec
.flags
|= SEC_AUTH_MODE
;
457 IEEE80211_DEBUG_WX("Auth: %s\n", sec
.auth_mode
== WLAN_AUTH_OPEN
?
458 "OPEN" : "SHARED KEY");
460 /* For now we just support WEP, so only set that security level...
461 * TODO: When WPA is added this is one place that needs to change */
462 sec
.flags
|= SEC_LEVEL
;
463 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
465 if (ieee
->set_security
)
466 ieee
->set_security(dev
, &sec
);
468 /* Do not reset port if card is in Managed mode since resetting will
469 * generate new IEEE 802.11 authentication which may end up in looping
470 * with IEEE 802.1X. If your hardware requires a reset after WEP
471 * configuration (for example... Prism2), implement the reset_port in
472 * the callbacks structures used to initialize the 802.11 stack. */
473 if (ieee
->reset_on_keychange
&&
474 ieee
->iw_mode
!= IW_MODE_INFRA
&&
475 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
476 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
482 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
483 struct iw_request_info
*info
,
484 union iwreq_data
*wrqu
, char *keybuf
)
486 struct iw_point
*erq
= &(wrqu
->encoding
);
488 struct ieee80211_crypt_data
*crypt
;
490 IEEE80211_DEBUG_WX("GET_ENCODE\n");
492 if(ieee
->iw_mode
== IW_MODE_MONITOR
)
495 key
= erq
->flags
& IW_ENCODE_INDEX
;
501 key
= ieee
->tx_keyidx
;
503 crypt
= ieee
->crypt
[key
];
504 erq
->flags
= key
+ 1;
506 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
508 erq
->flags
|= IW_ENCODE_DISABLED
;
511 len
= crypt
->ops
->get_key(keybuf
, SCM_KEY_LEN
, NULL
, crypt
->priv
);
512 erq
->length
= (len
>= 0 ? len
: 0);
514 erq
->flags
|= IW_ENCODE_ENABLED
;
517 erq
->flags
|= IW_ENCODE_OPEN
;
519 erq
->flags
|= IW_ENCODE_RESTRICTED
;
523 #if (WIRELESS_EXT >= 18)
524 int ieee80211_wx_set_encode_ext(struct ieee80211_device
*ieee
,
525 struct iw_request_info
*info
,
526 union iwreq_data
*wrqu
, char *extra
)
529 struct net_device
*dev
= ieee
->dev
;
530 struct iw_point
*encoding
= &wrqu
->encoding
;
531 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
535 struct ieee80211_crypto_ops
*ops
;
536 struct ieee80211_crypt_data
**crypt
;
538 struct ieee80211_security sec
= {
541 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
542 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
544 if (idx
< 1 || idx
> WEP_KEYS
)
548 idx
= ieee
->tx_keyidx
;
550 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
552 crypt
= &ieee
->crypt
[idx
];
556 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
557 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
558 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
560 if (ieee
->iw_mode
== IW_MODE_INFRA
)
562 crypt
= &ieee
->crypt
[idx
];
568 sec
.flags
|= SEC_ENABLED
;// | SEC_ENCRYPT;
569 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
570 ext
->alg
== IW_ENCODE_ALG_NONE
) {
572 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
574 for (i
= 0; i
< WEP_KEYS
; i
++)
576 if (ieee
->crypt
[i
] != NULL
)
583 sec
.level
= SEC_LEVEL_0
;
584 sec
.flags
|= SEC_LEVEL
;
586 //printk("disabled: flag:%x\n", encoding->flags);
593 case IW_ENCODE_ALG_WEP
:
596 case IW_ENCODE_ALG_TKIP
:
599 case IW_ENCODE_ALG_CCMP
:
603 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
604 dev
->name
, ext
->alg
);
608 printk("alg name:%s\n",alg
);
610 ops
= ieee80211_get_crypto_ops(alg
);
612 ops
= ieee80211_get_crypto_ops(alg
);
614 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
615 dev
->name
, ext
->alg
);
616 printk("========>unknown crypto alg %d\n", ext
->alg
);
621 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
622 struct ieee80211_crypt_data
*new_crypt
;
624 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
626 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
627 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
629 new_crypt
= kmalloc(sizeof(*new_crypt
), GFP_KERNEL
);
630 memset(new_crypt
,0,sizeof(*new_crypt
));
632 if (new_crypt
== NULL
) {
636 new_crypt
->ops
= ops
;
638 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
639 if (new_crypt
->priv
== NULL
) {
648 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
649 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
650 (*crypt
)->priv
) < 0) {
651 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
652 printk("key setting failed\n");
657 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
658 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
659 ieee
->tx_keyidx
= idx
;
660 sec
.active_key
= idx
;
661 sec
.flags
|= SEC_ACTIVE_KEY
;
664 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
665 //memcpy(sec.keys[idx], ext->key, ext->key_len);
666 sec
.key_sizes
[idx
] = ext
->key_len
;
667 sec
.flags
|= (1 << idx
);
668 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
669 // sec.encode_alg[idx] = SEC_ALG_WEP;
670 sec
.flags
|= SEC_LEVEL
;
671 sec
.level
= SEC_LEVEL_1
;
672 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
673 // sec.encode_alg[idx] = SEC_ALG_TKIP;
674 sec
.flags
|= SEC_LEVEL
;
675 sec
.level
= SEC_LEVEL_2
;
676 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
677 // sec.encode_alg[idx] = SEC_ALG_CCMP;
678 sec
.flags
|= SEC_LEVEL
;
679 sec
.level
= SEC_LEVEL_3
;
681 /* Don't set sec level for group keys. */
683 sec
.flags
&= ~SEC_LEVEL
;
686 if (ieee
->set_security
)
687 ieee
->set_security(ieee
->dev
, &sec
);
689 if (ieee
->reset_on_keychange
&&
690 ieee
->iw_mode
!= IW_MODE_INFRA
&&
691 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
692 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
698 int ieee80211_wx_get_encode_ext(struct ieee80211_device
*ieee
,
699 struct iw_request_info
*info
,
700 union iwreq_data
*wrqu
, char *extra
)
702 struct iw_point
*encoding
= &wrqu
->encoding
;
703 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
704 struct ieee80211_crypt_data
*crypt
;
705 int idx
, max_key_len
;
707 max_key_len
= encoding
->length
- sizeof(*ext
);
711 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
713 if (idx
< 1 || idx
> WEP_KEYS
)
717 idx
= ieee
->tx_keyidx
;
719 if (!(ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) &&
720 ext
->alg
!= IW_ENCODE_ALG_WEP
)
721 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
724 crypt
= ieee
->crypt
[idx
];
725 encoding
->flags
= idx
+ 1;
726 memset(ext
, 0, sizeof(*ext
));
728 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
729 ext
->alg
= IW_ENCODE_ALG_NONE
;
731 encoding
->flags
|= IW_ENCODE_DISABLED
;
733 if (strcmp(crypt
->ops
->name
, "WEP") == 0 )
734 ext
->alg
= IW_ENCODE_ALG_WEP
;
735 else if (strcmp(crypt
->ops
->name
, "TKIP"))
736 ext
->alg
= IW_ENCODE_ALG_TKIP
;
737 else if (strcmp(crypt
->ops
->name
, "CCMP"))
738 ext
->alg
= IW_ENCODE_ALG_CCMP
;
741 ext
->key_len
= crypt
->ops
->get_key(ext
->key
, SCM_KEY_LEN
, NULL
, crypt
->priv
);
742 encoding
->flags
|= IW_ENCODE_ENABLED
;
744 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
745 ext
->alg
== IW_ENCODE_ALG_CCMP
))
746 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
753 int ieee80211_wx_set_mlme(struct ieee80211_device
*ieee
,
754 struct iw_request_info
*info
,
755 union iwreq_data
*wrqu
, char *extra
)
757 struct iw_mlme
*mlme
= (struct iw_mlme
*) extra
;
760 case IW_MLME_DISASSOC
:
761 ieee80211_disassociate(ieee
);
769 int ieee80211_wx_set_auth(struct ieee80211_device
*ieee
,
770 struct iw_request_info
*info
,
771 struct iw_param
*data
, char *extra
)
773 switch (data
->flags
& IW_AUTH_INDEX
) {
774 case IW_AUTH_WPA_VERSION
:
775 /*need to support wpa2 here*/
776 //printk("wpa version:%x\n", data->value);
778 case IW_AUTH_CIPHER_PAIRWISE
:
779 case IW_AUTH_CIPHER_GROUP
:
780 case IW_AUTH_KEY_MGMT
:
782 * * Host AP driver does not use these parameters and allows
783 * * wpa_supplicant to control them internally.
786 case IW_AUTH_TKIP_COUNTERMEASURES
:
787 ieee
->tkip_countermeasures
= data
->value
;
789 case IW_AUTH_DROP_UNENCRYPTED
:
790 ieee
->drop_unencrypted
= data
->value
;
793 case IW_AUTH_80211_AUTH_ALG
:
794 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
795 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
796 if(data
->value
& IW_AUTH_ALG_SHARED_KEY
){
800 else if(data
->value
& IW_AUTH_ALG_OPEN_SYSTEM
){
804 else if(data
->value
& IW_AUTH_ALG_LEAP
){
807 //printk("hahahaa:LEAP\n");
811 //printk("open_wep:%d\n", ieee->open_wep);
814 case IW_AUTH_WPA_ENABLED
:
815 ieee
->wpa_enabled
= (data
->value
)?1:0;
816 //printk("enable wpa:%d\n", ieee->wpa_enabled);
818 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
819 ieee
->ieee802_1x
= data
->value
;
821 case IW_AUTH_PRIVACY_INVOKED
:
822 ieee
->privacy_invoked
= data
->value
;
830 int ieee80211_wx_set_gen_ie(struct ieee80211_device
*ieee
, u8
*ie
, size_t len
)
834 if (len
>MAX_WPA_IE_LEN
|| (len
&& ie
== NULL
))
836 // printk("return error out, len:%d\n", len);
845 printk("len:%zu, ie:%d\n", len
, ie
[1]);
848 buf
= kmemdup(ie
, len
, GFP_KERNEL
);
853 ieee
->wpa_ie_len
= len
;
859 ieee
->wpa_ie_len
= 0;