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 <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 ******************************************************************************/
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 frequency/channel */
93 iwe
.cmd
= SIOCGIWFREQ
;
94 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
96 iwe
.u
.freq
.m
= network
->channel
;
99 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
101 /* Add encryption capability */
102 iwe
.cmd
= SIOCGIWENCODE
;
103 if (network
->capability
& WLAN_CAPABILITY_PRIVACY
)
104 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
106 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
107 iwe
.u
.data
.length
= 0;
108 start
= iwe_stream_add_point(start
, stop
, &iwe
, network
->ssid
);
110 /* Add basic and extended rates */
111 /* Rate : stuffing multiple values in a single event require a bit
112 * more of magic - Jean II */
113 current_val
= start
+ IW_EV_LCP_LEN
;
114 iwe
.cmd
= SIOCGIWRATE
;
115 /* Those two flags are ignored... */
116 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
118 for (i
= 0, j
= 0; i
< network
->rates_len
;) {
119 if (j
< network
->rates_ex_len
&&
120 ((network
->rates_ex
[j
] & 0x7F) <
121 (network
->rates
[i
] & 0x7F)))
122 rate
= network
->rates_ex
[j
++] & 0x7F;
124 rate
= network
->rates
[i
++] & 0x7F;
125 /* Bit rate given in 500 kb/s units (+ 0x80) */
126 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
127 /* Add new value to event */
128 current_val
= iwe_stream_add_value(start
, current_val
, stop
, &iwe
, IW_EV_PARAM_LEN
);
130 for (; j
< network
->rates_ex_len
; j
++) {
131 rate
= network
->rates_ex
[j
] & 0x7F;
132 /* Bit rate given in 500 kb/s units (+ 0x80) */
133 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
134 /* Add new value to event */
135 current_val
= iwe_stream_add_value(start
, current_val
, stop
, &iwe
, IW_EV_PARAM_LEN
);
137 /* Check if we added any rate */
138 if((current_val
- start
) > IW_EV_LCP_LEN
)
141 /* Add quality statistics */
143 iwe
.u
.qual
.updated
= IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
|
144 IW_QUAL_NOISE_UPDATED
;
146 if (!(network
->stats
.mask
& IEEE80211_STATMASK_RSSI
)) {
147 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
|
148 IW_QUAL_LEVEL_INVALID
;
151 if (ieee
->perfect_rssi
== ieee
->worst_rssi
)
152 iwe
.u
.qual
.qual
= 100;
156 (ieee
->perfect_rssi
- ieee
->worst_rssi
) *
157 (ieee
->perfect_rssi
- ieee
->worst_rssi
) -
158 (ieee
->perfect_rssi
- network
->stats
.rssi
) *
159 (15 * (ieee
->perfect_rssi
- ieee
->worst_rssi
) +
160 62 * (ieee
->perfect_rssi
-
161 network
->stats
.rssi
))) /
162 ((ieee
->perfect_rssi
-
163 ieee
->worst_rssi
) * (ieee
->perfect_rssi
-
165 if (iwe
.u
.qual
.qual
> 100)
166 iwe
.u
.qual
.qual
= 100;
167 else if (iwe
.u
.qual
.qual
< 1)
171 if (!(network
->stats
.mask
& IEEE80211_STATMASK_NOISE
)) {
172 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
173 iwe
.u
.qual
.noise
= 0;
175 iwe
.u
.qual
.noise
= network
->stats
.noise
;
178 if (!(network
->stats
.mask
& IEEE80211_STATMASK_SIGNAL
)) {
179 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
180 iwe
.u
.qual
.level
= 0;
182 iwe
.u
.qual
.level
= network
->stats
.signal
;
185 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_QUAL_LEN
);
187 iwe
.cmd
= IWEVCUSTOM
;
190 iwe
.u
.data
.length
= p
- custom
;
191 if (iwe
.u
.data
.length
)
192 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
194 memset(&iwe
, 0, sizeof(iwe
));
195 if (network
->wpa_ie_len
) {
196 char buf
[MAX_WPA_IE_LEN
];
197 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
199 iwe
.u
.data
.length
= network
->wpa_ie_len
;
200 start
= iwe_stream_add_point(start
, stop
, &iwe
, buf
);
203 memset(&iwe
, 0, sizeof(iwe
));
204 if (network
->rsn_ie_len
) {
205 char buf
[MAX_WPA_IE_LEN
];
206 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
208 iwe
.u
.data
.length
= network
->rsn_ie_len
;
209 start
= iwe_stream_add_point(start
, stop
, &iwe
, buf
);
212 /* Add EXTRA: Age to display seconds since last beacon/probe response
213 * for given network. */
214 iwe
.cmd
= IWEVCUSTOM
;
216 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
217 " Last beacon: %dms ago",
218 jiffies_to_msecs(jiffies
- network
->last_scanned
));
219 iwe
.u
.data
.length
= p
- custom
;
220 if (iwe
.u
.data
.length
)
221 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
223 /* Add spectrum management information */
226 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Channel flags: ");
228 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
229 IEEE80211_CH_INVALID
) {
230 iwe
.cmd
= IWEVCUSTOM
;
231 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "INVALID ");
234 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
235 IEEE80211_CH_RADAR_DETECT
) {
236 iwe
.cmd
= IWEVCUSTOM
;
237 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "DFS ");
240 if (iwe
.cmd
== IWEVCUSTOM
) {
241 iwe
.u
.data
.length
= p
- custom
;
242 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
248 #define SCAN_ITEM_SIZE 128
250 int ieee80211_wx_get_scan(struct ieee80211_device
*ieee
,
251 struct iw_request_info
*info
,
252 union iwreq_data
*wrqu
, char *extra
)
254 struct ieee80211_network
*network
;
259 char *stop
= ev
+ wrqu
->data
.length
;
262 IEEE80211_DEBUG_WX("Getting scan\n");
264 spin_lock_irqsave(&ieee
->lock
, flags
);
266 list_for_each_entry(network
, &ieee
->network_list
, list
) {
268 if (stop
- ev
< SCAN_ITEM_SIZE
) {
273 if (ieee
->scan_age
== 0 ||
274 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
275 ev
= ieee80211_translate_scan(ieee
, ev
, stop
, network
);
277 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
278 MAC_FMT
")' due to age (%dms).\n",
279 escape_essid(network
->ssid
,
281 MAC_ARG(network
->bssid
),
282 jiffies_to_msecs(jiffies
-
287 spin_unlock_irqrestore(&ieee
->lock
, flags
);
289 wrqu
->data
.length
= ev
- extra
;
290 wrqu
->data
.flags
= 0;
292 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i
);
297 int ieee80211_wx_set_encode(struct ieee80211_device
*ieee
,
298 struct iw_request_info
*info
,
299 union iwreq_data
*wrqu
, char *keybuf
)
301 struct iw_point
*erq
= &(wrqu
->encoding
);
302 struct net_device
*dev
= ieee
->dev
;
303 struct ieee80211_security sec
= {
306 int i
, key
, key_provided
, len
;
307 struct ieee80211_crypt_data
**crypt
;
308 int host_crypto
= ieee
->host_encrypt
|| ieee
->host_decrypt
|| ieee
->host_build_iv
;
310 IEEE80211_DEBUG_WX("SET_ENCODE\n");
312 key
= erq
->flags
& IW_ENCODE_INDEX
;
320 key
= ieee
->tx_keyidx
;
323 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
324 "provided" : "default");
326 crypt
= &ieee
->crypt
[key
];
328 if (erq
->flags
& IW_ENCODE_DISABLED
) {
329 if (key_provided
&& *crypt
) {
330 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
332 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
334 IEEE80211_DEBUG_WX("Disabling encryption.\n");
336 /* Check all the keys to see if any are still configured,
337 * and if no key index was provided, de-init them all */
338 for (i
= 0; i
< WEP_KEYS
; i
++) {
339 if (ieee
->crypt
[i
] != NULL
) {
342 ieee80211_crypt_delayed_deinit(ieee
,
350 sec
.level
= SEC_LEVEL_0
;
351 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
| SEC_ENCRYPT
;
359 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
361 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
362 strcmp((*crypt
)->ops
->name
, "WEP") != 0) {
363 /* changing to use WEP; deinit previously used algorithm
365 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
368 if (*crypt
== NULL
&& host_crypto
) {
369 struct ieee80211_crypt_data
*new_crypt
;
371 /* take WEP into use */
372 new_crypt
= kmalloc(sizeof(struct ieee80211_crypt_data
),
374 if (new_crypt
== NULL
)
376 memset(new_crypt
, 0, sizeof(struct ieee80211_crypt_data
));
377 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
378 if (!new_crypt
->ops
) {
379 request_module("ieee80211_crypt_wep");
380 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
383 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
384 new_crypt
->priv
= new_crypt
->ops
->init(key
);
386 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
390 printk(KERN_WARNING
"%s: could not initialize WEP: "
391 "load module ieee80211_crypt_wep\n", dev
->name
);
397 /* If a new key was provided, set it up */
398 if (erq
->length
> 0) {
399 len
= erq
->length
<= 5 ? 5 : 13;
400 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
401 if (len
> erq
->length
)
402 memset(sec
.keys
[key
] + erq
->length
, 0,
404 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
405 key
, escape_essid(sec
.keys
[key
], len
),
407 sec
.key_sizes
[key
] = len
;
409 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
411 sec
.flags
|= (1 << key
);
412 /* This ensures a key will be activated if no key is
414 if (key
== sec
.active_key
)
415 sec
.flags
|= SEC_ACTIVE_KEY
;
419 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
420 NULL
, (*crypt
)->priv
);
422 /* Set a default key of all 0 */
423 IEEE80211_DEBUG_WX("Setting key %d to all "
425 memset(sec
.keys
[key
], 0, 13);
426 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
428 sec
.key_sizes
[key
] = 13;
429 sec
.flags
|= (1 << key
);
432 /* No key data - just set the default TX key index */
434 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
436 ieee
->tx_keyidx
= key
;
437 sec
.active_key
= key
;
438 sec
.flags
|= SEC_ACTIVE_KEY
;
441 if (erq
->flags
& (IW_ENCODE_OPEN
| IW_ENCODE_RESTRICTED
)) {
442 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
443 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
444 WLAN_AUTH_SHARED_KEY
;
445 sec
.flags
|= SEC_AUTH_MODE
;
446 IEEE80211_DEBUG_WX("Auth: %s\n",
447 sec
.auth_mode
== WLAN_AUTH_OPEN
?
448 "OPEN" : "SHARED KEY");
451 /* For now we just support WEP, so only set that security level...
452 * TODO: When WPA is added this is one place that needs to change */
453 sec
.flags
|= SEC_LEVEL
;
454 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
455 sec
.encode_alg
[key
] = SEC_ALG_WEP
;
458 if (ieee
->set_security
)
459 ieee
->set_security(dev
, &sec
);
461 /* Do not reset port if card is in Managed mode since resetting will
462 * generate new IEEE 802.11 authentication which may end up in looping
463 * with IEEE 802.1X. If your hardware requires a reset after WEP
464 * configuration (for example... Prism2), implement the reset_port in
465 * the callbacks structures used to initialize the 802.11 stack. */
466 if (ieee
->reset_on_keychange
&&
467 ieee
->iw_mode
!= IW_MODE_INFRA
&&
468 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
469 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
475 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
476 struct iw_request_info
*info
,
477 union iwreq_data
*wrqu
, char *keybuf
)
479 struct iw_point
*erq
= &(wrqu
->encoding
);
481 struct ieee80211_crypt_data
*crypt
;
482 struct ieee80211_security
*sec
= &ieee
->sec
;
484 IEEE80211_DEBUG_WX("GET_ENCODE\n");
486 key
= erq
->flags
& IW_ENCODE_INDEX
;
492 key
= ieee
->tx_keyidx
;
494 crypt
= ieee
->crypt
[key
];
495 erq
->flags
= key
+ 1;
499 erq
->flags
|= IW_ENCODE_DISABLED
;
503 len
= sec
->key_sizes
[key
];
504 memcpy(keybuf
, sec
->keys
[key
], len
);
507 erq
->flags
|= IW_ENCODE_ENABLED
;
510 erq
->flags
|= IW_ENCODE_OPEN
;
512 erq
->flags
|= IW_ENCODE_RESTRICTED
;
517 int ieee80211_wx_set_encodeext(struct ieee80211_device
*ieee
,
518 struct iw_request_info
*info
,
519 union iwreq_data
*wrqu
, char *extra
)
521 struct net_device
*dev
= ieee
->dev
;
522 struct iw_point
*encoding
= &wrqu
->encoding
;
523 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
526 const char *alg
, *module
;
527 struct ieee80211_crypto_ops
*ops
;
528 struct ieee80211_crypt_data
**crypt
;
530 struct ieee80211_security sec
= {
534 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
536 if (idx
< 1 || idx
> WEP_KEYS
)
540 idx
= ieee
->tx_keyidx
;
542 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
543 crypt
= &ieee
->crypt
[idx
];
546 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
547 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
549 if (ieee
->iw_mode
== IW_MODE_INFRA
)
550 crypt
= &ieee
->crypt
[idx
];
555 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
556 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
557 ext
->alg
== IW_ENCODE_ALG_NONE
) {
559 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
561 for (i
= 0; i
< WEP_KEYS
; i
++)
562 if (ieee
->crypt
[i
] != NULL
)
568 sec
.level
= SEC_LEVEL_0
;
569 sec
.flags
|= SEC_LEVEL
;
577 if (group_key
? !ieee
->host_mc_decrypt
:
578 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
579 ieee
->host_encrypt_msdu
))
580 goto skip_host_crypt
;
583 case IW_ENCODE_ALG_WEP
:
585 module
= "ieee80211_crypt_wep";
587 case IW_ENCODE_ALG_TKIP
:
589 module
= "ieee80211_crypt_tkip";
591 case IW_ENCODE_ALG_CCMP
:
593 module
= "ieee80211_crypt_ccmp";
596 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
597 dev
->name
, ext
->alg
);
602 ops
= ieee80211_get_crypto_ops(alg
);
604 request_module(module
);
605 ops
= ieee80211_get_crypto_ops(alg
);
608 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
609 dev
->name
, ext
->alg
);
614 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
615 struct ieee80211_crypt_data
*new_crypt
;
617 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
619 new_crypt
= (struct ieee80211_crypt_data
*)
620 kmalloc(sizeof(*new_crypt
), GFP_KERNEL
);
621 if (new_crypt
== NULL
) {
625 memset(new_crypt
, 0, sizeof(struct ieee80211_crypt_data
));
626 new_crypt
->ops
= ops
;
627 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
628 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
629 if (new_crypt
->priv
== NULL
) {
637 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
638 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
639 (*crypt
)->priv
) < 0) {
640 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
646 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
647 ieee
->tx_keyidx
= idx
;
648 sec
.active_key
= idx
;
649 sec
.flags
|= SEC_ACTIVE_KEY
;
652 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
653 memcpy(sec
.keys
[idx
], ext
->key
, ext
->key_len
);
654 sec
.key_sizes
[idx
] = ext
->key_len
;
655 sec
.flags
|= (1 << idx
);
656 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
657 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
658 sec
.flags
|= SEC_LEVEL
;
659 sec
.level
= SEC_LEVEL_1
;
660 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
661 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
662 sec
.flags
|= SEC_LEVEL
;
663 sec
.level
= SEC_LEVEL_2
;
664 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
665 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
666 sec
.flags
|= SEC_LEVEL
;
667 sec
.level
= SEC_LEVEL_3
;
669 /* Don't set sec level for group keys. */
671 sec
.flags
&= ~SEC_LEVEL
;
674 if (ieee
->set_security
)
675 ieee
->set_security(ieee
->dev
, &sec
);
678 * Do not reset port if card is in Managed mode since resetting will
679 * generate new IEEE 802.11 authentication which may end up in looping
680 * with IEEE 802.1X. If your hardware requires a reset after WEP
681 * configuration (for example... Prism2), implement the reset_port in
682 * the callbacks structures used to initialize the 802.11 stack.
684 if (ieee
->reset_on_keychange
&&
685 ieee
->iw_mode
!= IW_MODE_INFRA
&&
686 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
687 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
694 int ieee80211_wx_get_encodeext(struct ieee80211_device
*ieee
,
695 struct iw_request_info
*info
,
696 union iwreq_data
*wrqu
, char *extra
)
698 struct iw_point
*encoding
= &wrqu
->encoding
;
699 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
700 struct ieee80211_security
*sec
= &ieee
->sec
;
701 int idx
, max_key_len
;
703 max_key_len
= encoding
->length
- sizeof(*ext
);
707 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
709 if (idx
< 1 || idx
> WEP_KEYS
)
713 idx
= ieee
->tx_keyidx
;
715 if (!ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
&&
716 ext
->alg
!= IW_ENCODE_ALG_WEP
)
717 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
720 encoding
->flags
= idx
+ 1;
721 memset(ext
, 0, sizeof(*ext
));
724 ext
->alg
= IW_ENCODE_ALG_NONE
;
726 encoding
->flags
|= IW_ENCODE_DISABLED
;
728 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
729 ext
->alg
= IW_ENCODE_ALG_WEP
;
730 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
731 ext
->alg
= IW_ENCODE_ALG_TKIP
;
732 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
733 ext
->alg
= IW_ENCODE_ALG_CCMP
;
737 ext
->key_len
= sec
->key_sizes
[idx
];
738 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
739 encoding
->flags
|= IW_ENCODE_ENABLED
;
741 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
742 ext
->alg
== IW_ENCODE_ALG_CCMP
))
743 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
750 int ieee80211_wx_set_auth(struct net_device
*dev
,
751 struct iw_request_info
*info
,
752 union iwreq_data
*wrqu
,
755 struct ieee80211_device
*ieee
= netdev_priv(dev
);
759 spin_lock_irqsave(&ieee
->lock
, flags
);
761 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
762 case IW_AUTH_WPA_VERSION
:
763 case IW_AUTH_CIPHER_PAIRWISE
:
764 case IW_AUTH_CIPHER_GROUP
:
765 case IW_AUTH_KEY_MGMT
:
767 * Host AP driver does not use these parameters and allows
768 * wpa_supplicant to control them internally.
771 case IW_AUTH_TKIP_COUNTERMEASURES
:
773 case IW_AUTH_DROP_UNENCRYPTED
:
774 ieee
->drop_unencrypted
= !!wrqu
->param
.value
;
776 case IW_AUTH_80211_AUTH_ALG
:
778 case IW_AUTH_WPA_ENABLED
:
779 ieee
->privacy_invoked
= ieee
->wpa_enabled
= !!wrqu
->param
.value
;
781 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
782 ieee
->ieee802_1x
= !!wrqu
->param
.value
;
784 case IW_AUTH_PRIVACY_INVOKED
:
785 ieee
->privacy_invoked
= !!wrqu
->param
.value
;
791 spin_unlock_irqrestore(&ieee
->lock
, flags
);
795 int ieee80211_wx_get_auth(struct net_device
*dev
,
796 struct iw_request_info
*info
,
797 union iwreq_data
*wrqu
,
800 struct ieee80211_device
*ieee
= netdev_priv(dev
);
804 spin_lock_irqsave(&ieee
->lock
, flags
);
806 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
807 case IW_AUTH_WPA_VERSION
:
808 case IW_AUTH_CIPHER_PAIRWISE
:
809 case IW_AUTH_CIPHER_GROUP
:
810 case IW_AUTH_KEY_MGMT
:
811 case IW_AUTH_TKIP_COUNTERMEASURES
: /* FIXME */
812 case IW_AUTH_80211_AUTH_ALG
: /* FIXME */
814 * Host AP driver does not use these parameters and allows
815 * wpa_supplicant to control them internally.
819 case IW_AUTH_DROP_UNENCRYPTED
:
820 wrqu
->param
.value
= ieee
->drop_unencrypted
;
822 case IW_AUTH_WPA_ENABLED
:
823 wrqu
->param
.value
= ieee
->wpa_enabled
;
825 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
826 wrqu
->param
.value
= ieee
->ieee802_1x
;
832 spin_unlock_irqrestore(&ieee
->lock
, flags
);
836 EXPORT_SYMBOL(ieee80211_wx_set_encodeext
);
837 EXPORT_SYMBOL(ieee80211_wx_get_encodeext
);
839 EXPORT_SYMBOL(ieee80211_wx_get_scan
);
840 EXPORT_SYMBOL(ieee80211_wx_set_encode
);
841 EXPORT_SYMBOL(ieee80211_wx_get_encode
);
843 EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth
);
844 EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth
);