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
<(sizeof(ieee80211_modes
)/sizeof(ieee80211_modes
[0])); 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
= kmalloc(sizeof(struct ieee80211_crypt_data
),
385 if (new_crypt
== NULL
)
387 memset(new_crypt
, 0, sizeof(struct ieee80211_crypt_data
));
388 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
389 if (!new_crypt
->ops
) {
390 request_module("ieee80211_crypt_wep");
391 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
393 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
394 new_crypt
->priv
= new_crypt
->ops
->init(key
);
396 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
400 printk(KERN_WARNING
"%s: could not initialize WEP: "
401 "load module ieee80211_crypt_wep\n",
408 /* If a new key was provided, set it up */
409 if (erq
->length
> 0) {
410 len
= erq
->length
<= 5 ? 5 : 13;
411 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
412 if (len
> erq
->length
)
413 memset(sec
.keys
[key
] + erq
->length
, 0,
415 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
416 key
, escape_essid(sec
.keys
[key
], len
),
418 sec
.key_sizes
[key
] = len
;
419 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
421 sec
.flags
|= (1 << key
);
422 /* This ensures a key will be activated if no key is
424 if (key
== sec
.active_key
)
425 sec
.flags
|= SEC_ACTIVE_KEY
;
426 ieee
->tx_keyidx
= key
;
429 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
430 NULL
, (*crypt
)->priv
);
432 /* Set a default key of all 0 */
433 printk("Setting key %d to all zero.\n",
436 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
438 memset(sec
.keys
[key
], 0, 13);
439 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
441 sec
.key_sizes
[key
] = 13;
442 sec
.flags
|= (1 << key
);
445 /* No key data - just set the default TX key index */
448 "Setting key %d to default Tx key.\n", key
);
449 ieee
->tx_keyidx
= key
;
450 sec
.active_key
= key
;
451 sec
.flags
|= SEC_ACTIVE_KEY
;
456 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
457 ieee
->auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
: WLAN_AUTH_SHARED_KEY
;
458 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
: WLAN_AUTH_SHARED_KEY
;
459 sec
.flags
|= SEC_AUTH_MODE
;
460 IEEE80211_DEBUG_WX("Auth: %s\n", sec
.auth_mode
== WLAN_AUTH_OPEN
?
461 "OPEN" : "SHARED KEY");
463 /* For now we just support WEP, so only set that security level...
464 * TODO: When WPA is added this is one place that needs to change */
465 sec
.flags
|= SEC_LEVEL
;
466 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
468 if (ieee
->set_security
)
469 ieee
->set_security(dev
, &sec
);
471 /* Do not reset port if card is in Managed mode since resetting will
472 * generate new IEEE 802.11 authentication which may end up in looping
473 * with IEEE 802.1X. If your hardware requires a reset after WEP
474 * configuration (for example... Prism2), implement the reset_port in
475 * the callbacks structures used to initialize the 802.11 stack. */
476 if (ieee
->reset_on_keychange
&&
477 ieee
->iw_mode
!= IW_MODE_INFRA
&&
478 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
479 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
485 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
486 struct iw_request_info
*info
,
487 union iwreq_data
*wrqu
, char *keybuf
)
489 struct iw_point
*erq
= &(wrqu
->encoding
);
491 struct ieee80211_crypt_data
*crypt
;
493 IEEE80211_DEBUG_WX("GET_ENCODE\n");
495 if(ieee
->iw_mode
== IW_MODE_MONITOR
)
498 key
= erq
->flags
& IW_ENCODE_INDEX
;
504 key
= ieee
->tx_keyidx
;
506 crypt
= ieee
->crypt
[key
];
507 erq
->flags
= key
+ 1;
509 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
511 erq
->flags
|= IW_ENCODE_DISABLED
;
514 len
= crypt
->ops
->get_key(keybuf
, SCM_KEY_LEN
, NULL
, crypt
->priv
);
515 erq
->length
= (len
>= 0 ? len
: 0);
517 erq
->flags
|= IW_ENCODE_ENABLED
;
520 erq
->flags
|= IW_ENCODE_OPEN
;
522 erq
->flags
|= IW_ENCODE_RESTRICTED
;
526 #if (WIRELESS_EXT >= 18)
527 int ieee80211_wx_set_encode_ext(struct ieee80211_device
*ieee
,
528 struct iw_request_info
*info
,
529 union iwreq_data
*wrqu
, char *extra
)
532 struct net_device
*dev
= ieee
->dev
;
533 struct iw_point
*encoding
= &wrqu
->encoding
;
534 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
537 const char *alg
, *module
;
538 struct ieee80211_crypto_ops
*ops
;
539 struct ieee80211_crypt_data
**crypt
;
541 struct ieee80211_security sec
= {
544 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
545 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
547 if (idx
< 1 || idx
> WEP_KEYS
)
551 idx
= ieee
->tx_keyidx
;
553 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
555 crypt
= &ieee
->crypt
[idx
];
559 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
560 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
561 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
563 if (ieee
->iw_mode
== IW_MODE_INFRA
)
565 crypt
= &ieee
->crypt
[idx
];
571 sec
.flags
|= SEC_ENABLED
;// | SEC_ENCRYPT;
572 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
573 ext
->alg
== IW_ENCODE_ALG_NONE
) {
575 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
577 for (i
= 0; i
< WEP_KEYS
; i
++)
579 if (ieee
->crypt
[i
] != NULL
)
586 sec
.level
= SEC_LEVEL_0
;
587 sec
.flags
|= SEC_LEVEL
;
589 //printk("disabled: flag:%x\n", encoding->flags);
596 case IW_ENCODE_ALG_WEP
:
598 module
= "ieee80211_crypt_wep";
600 case IW_ENCODE_ALG_TKIP
:
602 module
= "ieee80211_crypt_tkip";
604 case IW_ENCODE_ALG_CCMP
:
606 module
= "ieee80211_crypt_ccmp";
609 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
610 dev
->name
, ext
->alg
);
614 printk("alg name:%s\n",alg
);
616 ops
= ieee80211_get_crypto_ops(alg
);
618 request_module(module
);
619 ops
= ieee80211_get_crypto_ops(alg
);
622 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
623 dev
->name
, ext
->alg
);
624 printk("========>unknown crypto alg %d\n", ext
->alg
);
629 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
630 struct ieee80211_crypt_data
*new_crypt
;
632 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
634 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
635 if (new_crypt
== NULL
) {
639 new_crypt
->ops
= ops
;
640 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
641 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
642 if (new_crypt
->priv
== NULL
) {
651 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
652 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
653 (*crypt
)->priv
) < 0) {
654 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
655 printk("key setting failed\n");
660 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
661 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
662 ieee
->tx_keyidx
= idx
;
663 sec
.active_key
= idx
;
664 sec
.flags
|= SEC_ACTIVE_KEY
;
667 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
668 //memcpy(sec.keys[idx], ext->key, ext->key_len);
669 sec
.key_sizes
[idx
] = ext
->key_len
;
670 sec
.flags
|= (1 << idx
);
671 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
672 // sec.encode_alg[idx] = SEC_ALG_WEP;
673 sec
.flags
|= SEC_LEVEL
;
674 sec
.level
= SEC_LEVEL_1
;
675 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
676 // sec.encode_alg[idx] = SEC_ALG_TKIP;
677 sec
.flags
|= SEC_LEVEL
;
678 sec
.level
= SEC_LEVEL_2
;
679 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
680 // sec.encode_alg[idx] = SEC_ALG_CCMP;
681 sec
.flags
|= SEC_LEVEL
;
682 sec
.level
= SEC_LEVEL_3
;
684 /* Don't set sec level for group keys. */
686 sec
.flags
&= ~SEC_LEVEL
;
689 if (ieee
->set_security
)
690 ieee
->set_security(ieee
->dev
, &sec
);
692 if (ieee
->reset_on_keychange
&&
693 ieee
->iw_mode
!= IW_MODE_INFRA
&&
694 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
695 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
701 int ieee80211_wx_get_encode_ext(struct ieee80211_device
*ieee
,
702 struct iw_request_info
*info
,
703 union iwreq_data
*wrqu
, char *extra
)
705 struct iw_point
*encoding
= &wrqu
->encoding
;
706 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
707 struct ieee80211_crypt_data
*crypt
;
708 int idx
, max_key_len
;
710 max_key_len
= encoding
->length
- sizeof(*ext
);
714 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
716 if (idx
< 1 || idx
> WEP_KEYS
)
720 idx
= ieee
->tx_keyidx
;
722 if (!(ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) &&
723 ext
->alg
!= IW_ENCODE_ALG_WEP
)
724 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
727 crypt
= ieee
->crypt
[idx
];
728 encoding
->flags
= idx
+ 1;
729 memset(ext
, 0, sizeof(*ext
));
731 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
732 ext
->alg
= IW_ENCODE_ALG_NONE
;
734 encoding
->flags
|= IW_ENCODE_DISABLED
;
736 if (strcmp(crypt
->ops
->name
, "WEP") == 0 )
737 ext
->alg
= IW_ENCODE_ALG_WEP
;
738 else if (strcmp(crypt
->ops
->name
, "TKIP"))
739 ext
->alg
= IW_ENCODE_ALG_TKIP
;
740 else if (strcmp(crypt
->ops
->name
, "CCMP"))
741 ext
->alg
= IW_ENCODE_ALG_CCMP
;
744 ext
->key_len
= crypt
->ops
->get_key(ext
->key
, SCM_KEY_LEN
, NULL
, crypt
->priv
);
745 encoding
->flags
|= IW_ENCODE_ENABLED
;
747 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
748 ext
->alg
== IW_ENCODE_ALG_CCMP
))
749 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
756 int ieee80211_wx_set_mlme(struct ieee80211_device
*ieee
,
757 struct iw_request_info
*info
,
758 union iwreq_data
*wrqu
, char *extra
)
760 struct iw_mlme
*mlme
= (struct iw_mlme
*) extra
;
763 case IW_MLME_DISASSOC
:
764 ieee80211_disassociate(ieee
);
772 int ieee80211_wx_set_auth(struct ieee80211_device
*ieee
,
773 struct iw_request_info
*info
,
774 struct iw_param
*data
, char *extra
)
776 switch (data
->flags
& IW_AUTH_INDEX
) {
777 case IW_AUTH_WPA_VERSION
:
778 /*need to support wpa2 here*/
779 //printk("wpa version:%x\n", data->value);
781 case IW_AUTH_CIPHER_PAIRWISE
:
782 case IW_AUTH_CIPHER_GROUP
:
783 case IW_AUTH_KEY_MGMT
:
785 * * Host AP driver does not use these parameters and allows
786 * * wpa_supplicant to control them internally.
789 case IW_AUTH_TKIP_COUNTERMEASURES
:
790 ieee
->tkip_countermeasures
= data
->value
;
792 case IW_AUTH_DROP_UNENCRYPTED
:
793 ieee
->drop_unencrypted
= data
->value
;
796 case IW_AUTH_80211_AUTH_ALG
:
797 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
798 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
799 if(data
->value
& IW_AUTH_ALG_SHARED_KEY
){
803 else if(data
->value
& IW_AUTH_ALG_OPEN_SYSTEM
){
807 else if(data
->value
& IW_AUTH_ALG_LEAP
){
810 //printk("hahahaa:LEAP\n");
814 //printk("open_wep:%d\n", ieee->open_wep);
817 case IW_AUTH_WPA_ENABLED
:
818 ieee
->wpa_enabled
= (data
->value
)?1:0;
819 //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
822 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
823 ieee
->ieee802_1x
= data
->value
;
825 case IW_AUTH_PRIVACY_INVOKED
:
826 ieee
->privacy_invoked
= data
->value
;
834 int ieee80211_wx_set_gen_ie(struct ieee80211_device
*ieee
, u8
*ie
, size_t len
)
838 if (len
>MAX_WPA_IE_LEN
|| (len
&& ie
== NULL
))
840 // printk("return error out, len:%d\n", len);
849 printk("len:%zu, ie:%d\n", len
, ie
[1]);
852 buf
= kmalloc(len
, GFP_KERNEL
);
855 memcpy(buf
, ie
, len
);
858 ieee
->wpa_ie_len
= len
;
864 ieee
->wpa_ie_len
= 0;
870 EXPORT_SYMBOL(ieee80211_wx_set_gen_ie
);
871 #if (WIRELESS_EXT >= 18)
872 EXPORT_SYMBOL(ieee80211_wx_set_mlme
);
873 EXPORT_SYMBOL(ieee80211_wx_set_auth
);
874 EXPORT_SYMBOL(ieee80211_wx_set_encode_ext
);
875 EXPORT_SYMBOL(ieee80211_wx_get_encode_ext
);
877 EXPORT_SYMBOL(ieee80211_wx_get_scan
);
878 EXPORT_SYMBOL(ieee80211_wx_set_encode
);
879 EXPORT_SYMBOL(ieee80211_wx_get_encode
);