1 /******************************************************************************
3 Copyright(c) 2004-2005 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 <j@w1.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 ******************************************************************************/
33 #include <linux/kmod.h>
34 #include <linux/module.h>
35 #include <linux/jiffies.h>
37 #include <net/ieee80211.h>
38 #include <linux/wireless.h>
40 static const char *ieee80211_modes
[] = {
41 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
44 #define MAX_CUSTOM_LEN 64
45 static char *ieee80211_translate_scan(struct ieee80211_device
*ieee
,
46 char *start
, char *stop
,
47 struct ieee80211_network
*network
)
49 char custom
[MAX_CUSTOM_LEN
];
53 char *current_val
; /* For rates */
56 /* First entry *MUST* be the AP MAC address */
58 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
59 memcpy(iwe
.u
.ap_addr
.sa_data
, network
->bssid
, ETH_ALEN
);
60 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_ADDR_LEN
);
62 /* Remaining entries will be displayed in the order we provide them */
65 iwe
.cmd
= SIOCGIWESSID
;
67 if (network
->flags
& NETWORK_EMPTY_ESSID
) {
68 iwe
.u
.data
.length
= sizeof("<hidden>");
69 start
= iwe_stream_add_point(start
, stop
, &iwe
, "<hidden>");
71 iwe
.u
.data
.length
= min(network
->ssid_len
, (u8
) 32);
72 start
= iwe_stream_add_point(start
, stop
, &iwe
, network
->ssid
);
75 /* Add the protocol name */
76 iwe
.cmd
= SIOCGIWNAME
;
77 snprintf(iwe
.u
.name
, IFNAMSIZ
, "IEEE 802.11%s",
78 ieee80211_modes
[network
->mode
]);
79 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_CHAR_LEN
);
82 iwe
.cmd
= SIOCGIWMODE
;
83 if (network
->capability
& (WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_IBSS
)) {
84 if (network
->capability
& WLAN_CAPABILITY_ESS
)
85 iwe
.u
.mode
= IW_MODE_MASTER
;
87 iwe
.u
.mode
= IW_MODE_ADHOC
;
89 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_UINT_LEN
);
92 /* Add channel and frequency */
93 iwe
.cmd
= SIOCGIWFREQ
;
94 iwe
.u
.freq
.m
= network
->channel
;
97 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
99 iwe
.u
.freq
.m
= ieee80211_channel_to_freq(ieee
, network
->channel
);
101 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
103 /* Add encryption capability */
104 iwe
.cmd
= SIOCGIWENCODE
;
105 if (network
->capability
& WLAN_CAPABILITY_PRIVACY
)
106 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
108 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
109 iwe
.u
.data
.length
= 0;
110 start
= iwe_stream_add_point(start
, stop
, &iwe
, network
->ssid
);
112 /* Add basic and extended rates */
113 /* Rate : stuffing multiple values in a single event require a bit
114 * more of magic - Jean II */
115 current_val
= start
+ IW_EV_LCP_LEN
;
116 iwe
.cmd
= SIOCGIWRATE
;
117 /* Those two flags are ignored... */
118 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
120 for (i
= 0, j
= 0; i
< network
->rates_len
;) {
121 if (j
< network
->rates_ex_len
&&
122 ((network
->rates_ex
[j
] & 0x7F) <
123 (network
->rates
[i
] & 0x7F)))
124 rate
= network
->rates_ex
[j
++] & 0x7F;
126 rate
= network
->rates
[i
++] & 0x7F;
127 /* Bit rate given in 500 kb/s units (+ 0x80) */
128 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
129 /* Add new value to event */
130 current_val
= iwe_stream_add_value(start
, current_val
, stop
, &iwe
, IW_EV_PARAM_LEN
);
132 for (; j
< network
->rates_ex_len
; j
++) {
133 rate
= network
->rates_ex
[j
] & 0x7F;
134 /* Bit rate given in 500 kb/s units (+ 0x80) */
135 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
136 /* Add new value to event */
137 current_val
= iwe_stream_add_value(start
, current_val
, stop
, &iwe
, IW_EV_PARAM_LEN
);
139 /* Check if we added any rate */
140 if((current_val
- start
) > IW_EV_LCP_LEN
)
143 /* Add quality statistics */
145 iwe
.u
.qual
.updated
= IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
|
146 IW_QUAL_NOISE_UPDATED
;
148 if (!(network
->stats
.mask
& IEEE80211_STATMASK_RSSI
)) {
149 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
|
150 IW_QUAL_LEVEL_INVALID
;
153 if (ieee
->perfect_rssi
== ieee
->worst_rssi
)
154 iwe
.u
.qual
.qual
= 100;
158 (ieee
->perfect_rssi
- ieee
->worst_rssi
) *
159 (ieee
->perfect_rssi
- ieee
->worst_rssi
) -
160 (ieee
->perfect_rssi
- network
->stats
.rssi
) *
161 (15 * (ieee
->perfect_rssi
- ieee
->worst_rssi
) +
162 62 * (ieee
->perfect_rssi
-
163 network
->stats
.rssi
))) /
164 ((ieee
->perfect_rssi
-
165 ieee
->worst_rssi
) * (ieee
->perfect_rssi
-
167 if (iwe
.u
.qual
.qual
> 100)
168 iwe
.u
.qual
.qual
= 100;
169 else if (iwe
.u
.qual
.qual
< 1)
173 if (!(network
->stats
.mask
& IEEE80211_STATMASK_NOISE
)) {
174 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
175 iwe
.u
.qual
.noise
= 0;
177 iwe
.u
.qual
.noise
= network
->stats
.noise
;
180 if (!(network
->stats
.mask
& IEEE80211_STATMASK_SIGNAL
)) {
181 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
182 iwe
.u
.qual
.level
= 0;
184 iwe
.u
.qual
.level
= network
->stats
.signal
;
187 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_QUAL_LEN
);
189 iwe
.cmd
= IWEVCUSTOM
;
192 iwe
.u
.data
.length
= p
- custom
;
193 if (iwe
.u
.data
.length
)
194 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
196 memset(&iwe
, 0, sizeof(iwe
));
197 if (network
->wpa_ie_len
) {
198 char buf
[MAX_WPA_IE_LEN
];
199 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
201 iwe
.u
.data
.length
= network
->wpa_ie_len
;
202 start
= iwe_stream_add_point(start
, stop
, &iwe
, buf
);
205 memset(&iwe
, 0, sizeof(iwe
));
206 if (network
->rsn_ie_len
) {
207 char buf
[MAX_WPA_IE_LEN
];
208 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
210 iwe
.u
.data
.length
= network
->rsn_ie_len
;
211 start
= iwe_stream_add_point(start
, stop
, &iwe
, buf
);
214 /* Add EXTRA: Age to display seconds since last beacon/probe response
215 * for given network. */
216 iwe
.cmd
= IWEVCUSTOM
;
218 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
219 " Last beacon: %dms ago",
220 jiffies_to_msecs(jiffies
- network
->last_scanned
));
221 iwe
.u
.data
.length
= p
- custom
;
222 if (iwe
.u
.data
.length
)
223 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
225 /* Add spectrum management information */
228 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Channel flags: ");
230 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
231 IEEE80211_CH_INVALID
) {
232 iwe
.cmd
= IWEVCUSTOM
;
233 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "INVALID ");
236 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
237 IEEE80211_CH_RADAR_DETECT
) {
238 iwe
.cmd
= IWEVCUSTOM
;
239 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "DFS ");
242 if (iwe
.cmd
== IWEVCUSTOM
) {
243 iwe
.u
.data
.length
= p
- custom
;
244 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
250 #define SCAN_ITEM_SIZE 128
252 int ieee80211_wx_get_scan(struct ieee80211_device
*ieee
,
253 struct iw_request_info
*info
,
254 union iwreq_data
*wrqu
, char *extra
)
256 struct ieee80211_network
*network
;
261 char *stop
= ev
+ wrqu
->data
.length
;
264 IEEE80211_DEBUG_WX("Getting scan\n");
266 spin_lock_irqsave(&ieee
->lock
, flags
);
268 list_for_each_entry(network
, &ieee
->network_list
, list
) {
270 if (stop
- ev
< SCAN_ITEM_SIZE
) {
275 if (ieee
->scan_age
== 0 ||
276 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
277 ev
= ieee80211_translate_scan(ieee
, ev
, stop
, network
);
279 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
280 MAC_FMT
")' due to age (%dms).\n",
281 escape_essid(network
->ssid
,
283 MAC_ARG(network
->bssid
),
284 jiffies_to_msecs(jiffies
-
289 spin_unlock_irqrestore(&ieee
->lock
, flags
);
291 wrqu
->data
.length
= ev
- extra
;
292 wrqu
->data
.flags
= 0;
294 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i
);
299 int ieee80211_wx_set_encode(struct ieee80211_device
*ieee
,
300 struct iw_request_info
*info
,
301 union iwreq_data
*wrqu
, char *keybuf
)
303 struct iw_point
*erq
= &(wrqu
->encoding
);
304 struct net_device
*dev
= ieee
->dev
;
305 struct ieee80211_security sec
= {
308 int i
, key
, key_provided
, len
;
309 struct ieee80211_crypt_data
**crypt
;
310 int host_crypto
= ieee
->host_encrypt
|| ieee
->host_decrypt
|| ieee
->host_build_iv
;
312 IEEE80211_DEBUG_WX("SET_ENCODE\n");
314 key
= erq
->flags
& IW_ENCODE_INDEX
;
322 key
= ieee
->tx_keyidx
;
325 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
326 "provided" : "default");
328 crypt
= &ieee
->crypt
[key
];
330 if (erq
->flags
& IW_ENCODE_DISABLED
) {
331 if (key_provided
&& *crypt
) {
332 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
334 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
336 IEEE80211_DEBUG_WX("Disabling encryption.\n");
338 /* Check all the keys to see if any are still configured,
339 * and if no key index was provided, de-init them all */
340 for (i
= 0; i
< WEP_KEYS
; i
++) {
341 if (ieee
->crypt
[i
] != NULL
) {
344 ieee80211_crypt_delayed_deinit(ieee
,
352 sec
.level
= SEC_LEVEL_0
;
353 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
| SEC_ENCRYPT
;
361 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
363 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
364 strcmp((*crypt
)->ops
->name
, "WEP") != 0) {
365 /* changing to use WEP; deinit previously used algorithm
367 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
370 if (*crypt
== NULL
&& host_crypto
) {
371 struct ieee80211_crypt_data
*new_crypt
;
373 /* take WEP into use */
374 new_crypt
= kzalloc(sizeof(struct ieee80211_crypt_data
),
376 if (new_crypt
== NULL
)
378 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
379 if (!new_crypt
->ops
) {
380 request_module("ieee80211_crypt_wep");
381 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
384 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
385 new_crypt
->priv
= new_crypt
->ops
->init(key
);
387 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
391 printk(KERN_WARNING
"%s: could not initialize WEP: "
392 "load module ieee80211_crypt_wep\n", dev
->name
);
398 /* If a new key was provided, set it up */
399 if (erq
->length
> 0) {
400 len
= erq
->length
<= 5 ? 5 : 13;
401 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
402 if (len
> erq
->length
)
403 memset(sec
.keys
[key
] + erq
->length
, 0,
405 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
406 key
, escape_essid(sec
.keys
[key
], len
),
408 sec
.key_sizes
[key
] = len
;
410 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
412 sec
.flags
|= (1 << key
);
413 /* This ensures a key will be activated if no key is
415 if (key
== sec
.active_key
)
416 sec
.flags
|= SEC_ACTIVE_KEY
;
420 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
421 NULL
, (*crypt
)->priv
);
423 /* Set a default key of all 0 */
424 IEEE80211_DEBUG_WX("Setting key %d to all "
426 memset(sec
.keys
[key
], 0, 13);
427 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
429 sec
.key_sizes
[key
] = 13;
430 sec
.flags
|= (1 << key
);
433 /* No key data - just set the default TX key index */
435 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
437 ieee
->tx_keyidx
= key
;
438 sec
.active_key
= key
;
439 sec
.flags
|= SEC_ACTIVE_KEY
;
442 if (erq
->flags
& (IW_ENCODE_OPEN
| IW_ENCODE_RESTRICTED
)) {
443 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
444 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
445 WLAN_AUTH_SHARED_KEY
;
446 sec
.flags
|= SEC_AUTH_MODE
;
447 IEEE80211_DEBUG_WX("Auth: %s\n",
448 sec
.auth_mode
== WLAN_AUTH_OPEN
?
449 "OPEN" : "SHARED KEY");
452 /* For now we just support WEP, so only set that security level...
453 * TODO: When WPA is added this is one place that needs to change */
454 sec
.flags
|= SEC_LEVEL
;
455 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
456 sec
.encode_alg
[key
] = SEC_ALG_WEP
;
459 if (ieee
->set_security
)
460 ieee
->set_security(dev
, &sec
);
462 /* Do not reset port if card is in Managed mode since resetting will
463 * generate new IEEE 802.11 authentication which may end up in looping
464 * with IEEE 802.1X. If your hardware requires a reset after WEP
465 * configuration (for example... Prism2), implement the reset_port in
466 * the callbacks structures used to initialize the 802.11 stack. */
467 if (ieee
->reset_on_keychange
&&
468 ieee
->iw_mode
!= IW_MODE_INFRA
&&
469 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
470 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
476 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
477 struct iw_request_info
*info
,
478 union iwreq_data
*wrqu
, char *keybuf
)
480 struct iw_point
*erq
= &(wrqu
->encoding
);
482 struct ieee80211_crypt_data
*crypt
;
483 struct ieee80211_security
*sec
= &ieee
->sec
;
485 IEEE80211_DEBUG_WX("GET_ENCODE\n");
487 key
= erq
->flags
& IW_ENCODE_INDEX
;
493 key
= ieee
->tx_keyidx
;
495 crypt
= ieee
->crypt
[key
];
496 erq
->flags
= key
+ 1;
500 erq
->flags
|= IW_ENCODE_DISABLED
;
504 len
= sec
->key_sizes
[key
];
505 memcpy(keybuf
, sec
->keys
[key
], len
);
508 erq
->flags
|= IW_ENCODE_ENABLED
;
511 erq
->flags
|= IW_ENCODE_OPEN
;
513 erq
->flags
|= IW_ENCODE_RESTRICTED
;
518 int ieee80211_wx_set_encodeext(struct ieee80211_device
*ieee
,
519 struct iw_request_info
*info
,
520 union iwreq_data
*wrqu
, char *extra
)
522 struct net_device
*dev
= ieee
->dev
;
523 struct iw_point
*encoding
= &wrqu
->encoding
;
524 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
527 const char *alg
, *module
;
528 struct ieee80211_crypto_ops
*ops
;
529 struct ieee80211_crypt_data
**crypt
;
531 struct ieee80211_security sec
= {
535 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
537 if (idx
< 1 || idx
> WEP_KEYS
)
541 idx
= ieee
->tx_keyidx
;
543 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
544 crypt
= &ieee
->crypt
[idx
];
547 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
548 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
550 if (ieee
->iw_mode
== IW_MODE_INFRA
)
551 crypt
= &ieee
->crypt
[idx
];
556 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
557 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
558 ext
->alg
== IW_ENCODE_ALG_NONE
) {
560 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
562 for (i
= 0; i
< WEP_KEYS
; i
++)
563 if (ieee
->crypt
[i
] != NULL
)
569 sec
.level
= SEC_LEVEL_0
;
570 sec
.flags
|= SEC_LEVEL
;
578 if (group_key
? !ieee
->host_mc_decrypt
:
579 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
580 ieee
->host_encrypt_msdu
))
581 goto skip_host_crypt
;
584 case IW_ENCODE_ALG_WEP
:
586 module
= "ieee80211_crypt_wep";
588 case IW_ENCODE_ALG_TKIP
:
590 module
= "ieee80211_crypt_tkip";
592 case IW_ENCODE_ALG_CCMP
:
594 module
= "ieee80211_crypt_ccmp";
597 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
598 dev
->name
, ext
->alg
);
603 ops
= ieee80211_get_crypto_ops(alg
);
605 request_module(module
);
606 ops
= ieee80211_get_crypto_ops(alg
);
609 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
610 dev
->name
, ext
->alg
);
615 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
616 struct ieee80211_crypt_data
*new_crypt
;
618 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
620 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
621 if (new_crypt
== NULL
) {
625 new_crypt
->ops
= ops
;
626 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
627 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
628 if (new_crypt
->priv
== NULL
) {
636 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
637 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
638 (*crypt
)->priv
) < 0) {
639 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
645 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
646 ieee
->tx_keyidx
= idx
;
647 sec
.active_key
= idx
;
648 sec
.flags
|= SEC_ACTIVE_KEY
;
651 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
652 memcpy(sec
.keys
[idx
], ext
->key
, ext
->key_len
);
653 sec
.key_sizes
[idx
] = ext
->key_len
;
654 sec
.flags
|= (1 << idx
);
655 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
656 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
657 sec
.flags
|= SEC_LEVEL
;
658 sec
.level
= SEC_LEVEL_1
;
659 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
660 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
661 sec
.flags
|= SEC_LEVEL
;
662 sec
.level
= SEC_LEVEL_2
;
663 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
664 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
665 sec
.flags
|= SEC_LEVEL
;
666 sec
.level
= SEC_LEVEL_3
;
668 /* Don't set sec level for group keys. */
670 sec
.flags
&= ~SEC_LEVEL
;
673 if (ieee
->set_security
)
674 ieee
->set_security(ieee
->dev
, &sec
);
677 * Do not reset port if card is in Managed mode since resetting will
678 * generate new IEEE 802.11 authentication which may end up in looping
679 * with IEEE 802.1X. If your hardware requires a reset after WEP
680 * configuration (for example... Prism2), implement the reset_port in
681 * the callbacks structures used to initialize the 802.11 stack.
683 if (ieee
->reset_on_keychange
&&
684 ieee
->iw_mode
!= IW_MODE_INFRA
&&
685 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
686 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
693 int ieee80211_wx_get_encodeext(struct ieee80211_device
*ieee
,
694 struct iw_request_info
*info
,
695 union iwreq_data
*wrqu
, char *extra
)
697 struct iw_point
*encoding
= &wrqu
->encoding
;
698 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
699 struct ieee80211_security
*sec
= &ieee
->sec
;
700 int idx
, max_key_len
;
702 max_key_len
= encoding
->length
- sizeof(*ext
);
706 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
708 if (idx
< 1 || idx
> WEP_KEYS
)
712 idx
= ieee
->tx_keyidx
;
714 if (!ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
&&
715 ext
->alg
!= IW_ENCODE_ALG_WEP
)
716 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
719 encoding
->flags
= idx
+ 1;
720 memset(ext
, 0, sizeof(*ext
));
723 ext
->alg
= IW_ENCODE_ALG_NONE
;
725 encoding
->flags
|= IW_ENCODE_DISABLED
;
727 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
728 ext
->alg
= IW_ENCODE_ALG_WEP
;
729 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
730 ext
->alg
= IW_ENCODE_ALG_TKIP
;
731 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
732 ext
->alg
= IW_ENCODE_ALG_CCMP
;
736 ext
->key_len
= sec
->key_sizes
[idx
];
737 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
738 encoding
->flags
|= IW_ENCODE_ENABLED
;
740 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
741 ext
->alg
== IW_ENCODE_ALG_CCMP
))
742 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
749 int ieee80211_wx_set_auth(struct net_device
*dev
,
750 struct iw_request_info
*info
,
751 union iwreq_data
*wrqu
,
754 struct ieee80211_device
*ieee
= netdev_priv(dev
);
758 spin_lock_irqsave(&ieee
->lock
, flags
);
760 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
761 case IW_AUTH_WPA_VERSION
:
762 case IW_AUTH_CIPHER_PAIRWISE
:
763 case IW_AUTH_CIPHER_GROUP
:
764 case IW_AUTH_KEY_MGMT
:
766 * Host AP driver does not use these parameters and allows
767 * wpa_supplicant to control them internally.
770 case IW_AUTH_TKIP_COUNTERMEASURES
:
772 case IW_AUTH_DROP_UNENCRYPTED
:
773 ieee
->drop_unencrypted
= !!wrqu
->param
.value
;
775 case IW_AUTH_80211_AUTH_ALG
:
777 case IW_AUTH_WPA_ENABLED
:
778 ieee
->privacy_invoked
= ieee
->wpa_enabled
= !!wrqu
->param
.value
;
780 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
781 ieee
->ieee802_1x
= !!wrqu
->param
.value
;
783 case IW_AUTH_PRIVACY_INVOKED
:
784 ieee
->privacy_invoked
= !!wrqu
->param
.value
;
790 spin_unlock_irqrestore(&ieee
->lock
, flags
);
794 int ieee80211_wx_get_auth(struct net_device
*dev
,
795 struct iw_request_info
*info
,
796 union iwreq_data
*wrqu
,
799 struct ieee80211_device
*ieee
= netdev_priv(dev
);
803 spin_lock_irqsave(&ieee
->lock
, flags
);
805 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
806 case IW_AUTH_WPA_VERSION
:
807 case IW_AUTH_CIPHER_PAIRWISE
:
808 case IW_AUTH_CIPHER_GROUP
:
809 case IW_AUTH_KEY_MGMT
:
810 case IW_AUTH_TKIP_COUNTERMEASURES
: /* FIXME */
811 case IW_AUTH_80211_AUTH_ALG
: /* FIXME */
813 * Host AP driver does not use these parameters and allows
814 * wpa_supplicant to control them internally.
818 case IW_AUTH_DROP_UNENCRYPTED
:
819 wrqu
->param
.value
= ieee
->drop_unencrypted
;
821 case IW_AUTH_WPA_ENABLED
:
822 wrqu
->param
.value
= ieee
->wpa_enabled
;
824 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
825 wrqu
->param
.value
= ieee
->ieee802_1x
;
831 spin_unlock_irqrestore(&ieee
->lock
, flags
);
835 EXPORT_SYMBOL(ieee80211_wx_set_encodeext
);
836 EXPORT_SYMBOL(ieee80211_wx_get_encodeext
);
838 EXPORT_SYMBOL(ieee80211_wx_get_scan
);
839 EXPORT_SYMBOL(ieee80211_wx_set_encode
);
840 EXPORT_SYMBOL(ieee80211_wx_get_encode
);
842 EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth
);
843 EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth
);