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
= kzalloc(sizeof(struct ieee80211_crypt_data
),
374 if (new_crypt
== NULL
)
376 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
377 if (!new_crypt
->ops
) {
378 request_module("ieee80211_crypt_wep");
379 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
382 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
383 new_crypt
->priv
= new_crypt
->ops
->init(key
);
385 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
389 printk(KERN_WARNING
"%s: could not initialize WEP: "
390 "load module ieee80211_crypt_wep\n", dev
->name
);
396 /* If a new key was provided, set it up */
397 if (erq
->length
> 0) {
398 len
= erq
->length
<= 5 ? 5 : 13;
399 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
400 if (len
> erq
->length
)
401 memset(sec
.keys
[key
] + erq
->length
, 0,
403 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
404 key
, escape_essid(sec
.keys
[key
], len
),
406 sec
.key_sizes
[key
] = len
;
408 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
410 sec
.flags
|= (1 << key
);
411 /* This ensures a key will be activated if no key is
413 if (key
== sec
.active_key
)
414 sec
.flags
|= SEC_ACTIVE_KEY
;
418 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
419 NULL
, (*crypt
)->priv
);
421 /* Set a default key of all 0 */
422 IEEE80211_DEBUG_WX("Setting key %d to all "
424 memset(sec
.keys
[key
], 0, 13);
425 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
427 sec
.key_sizes
[key
] = 13;
428 sec
.flags
|= (1 << key
);
431 /* No key data - just set the default TX key index */
433 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
435 ieee
->tx_keyidx
= key
;
436 sec
.active_key
= key
;
437 sec
.flags
|= SEC_ACTIVE_KEY
;
440 if (erq
->flags
& (IW_ENCODE_OPEN
| IW_ENCODE_RESTRICTED
)) {
441 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
442 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
443 WLAN_AUTH_SHARED_KEY
;
444 sec
.flags
|= SEC_AUTH_MODE
;
445 IEEE80211_DEBUG_WX("Auth: %s\n",
446 sec
.auth_mode
== WLAN_AUTH_OPEN
?
447 "OPEN" : "SHARED KEY");
450 /* For now we just support WEP, so only set that security level...
451 * TODO: When WPA is added this is one place that needs to change */
452 sec
.flags
|= SEC_LEVEL
;
453 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
454 sec
.encode_alg
[key
] = SEC_ALG_WEP
;
457 if (ieee
->set_security
)
458 ieee
->set_security(dev
, &sec
);
460 /* Do not reset port if card is in Managed mode since resetting will
461 * generate new IEEE 802.11 authentication which may end up in looping
462 * with IEEE 802.1X. If your hardware requires a reset after WEP
463 * configuration (for example... Prism2), implement the reset_port in
464 * the callbacks structures used to initialize the 802.11 stack. */
465 if (ieee
->reset_on_keychange
&&
466 ieee
->iw_mode
!= IW_MODE_INFRA
&&
467 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
468 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
474 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
475 struct iw_request_info
*info
,
476 union iwreq_data
*wrqu
, char *keybuf
)
478 struct iw_point
*erq
= &(wrqu
->encoding
);
480 struct ieee80211_crypt_data
*crypt
;
481 struct ieee80211_security
*sec
= &ieee
->sec
;
483 IEEE80211_DEBUG_WX("GET_ENCODE\n");
485 key
= erq
->flags
& IW_ENCODE_INDEX
;
491 key
= ieee
->tx_keyidx
;
493 crypt
= ieee
->crypt
[key
];
494 erq
->flags
= key
+ 1;
498 erq
->flags
|= IW_ENCODE_DISABLED
;
502 len
= sec
->key_sizes
[key
];
503 memcpy(keybuf
, sec
->keys
[key
], len
);
506 erq
->flags
|= IW_ENCODE_ENABLED
;
509 erq
->flags
|= IW_ENCODE_OPEN
;
511 erq
->flags
|= IW_ENCODE_RESTRICTED
;
516 int ieee80211_wx_set_encodeext(struct ieee80211_device
*ieee
,
517 struct iw_request_info
*info
,
518 union iwreq_data
*wrqu
, char *extra
)
520 struct net_device
*dev
= ieee
->dev
;
521 struct iw_point
*encoding
= &wrqu
->encoding
;
522 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
525 const char *alg
, *module
;
526 struct ieee80211_crypto_ops
*ops
;
527 struct ieee80211_crypt_data
**crypt
;
529 struct ieee80211_security sec
= {
533 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
535 if (idx
< 1 || idx
> WEP_KEYS
)
539 idx
= ieee
->tx_keyidx
;
541 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
542 crypt
= &ieee
->crypt
[idx
];
545 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
546 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
548 if (ieee
->iw_mode
== IW_MODE_INFRA
)
549 crypt
= &ieee
->crypt
[idx
];
554 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
555 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
556 ext
->alg
== IW_ENCODE_ALG_NONE
) {
558 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
560 for (i
= 0; i
< WEP_KEYS
; i
++)
561 if (ieee
->crypt
[i
] != NULL
)
567 sec
.level
= SEC_LEVEL_0
;
568 sec
.flags
|= SEC_LEVEL
;
576 if (group_key
? !ieee
->host_mc_decrypt
:
577 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
578 ieee
->host_encrypt_msdu
))
579 goto skip_host_crypt
;
582 case IW_ENCODE_ALG_WEP
:
584 module
= "ieee80211_crypt_wep";
586 case IW_ENCODE_ALG_TKIP
:
588 module
= "ieee80211_crypt_tkip";
590 case IW_ENCODE_ALG_CCMP
:
592 module
= "ieee80211_crypt_ccmp";
595 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
596 dev
->name
, ext
->alg
);
601 ops
= ieee80211_get_crypto_ops(alg
);
603 request_module(module
);
604 ops
= ieee80211_get_crypto_ops(alg
);
607 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
608 dev
->name
, ext
->alg
);
613 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
614 struct ieee80211_crypt_data
*new_crypt
;
616 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
618 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
619 if (new_crypt
== NULL
) {
623 new_crypt
->ops
= ops
;
624 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
625 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
626 if (new_crypt
->priv
== NULL
) {
634 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
635 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
636 (*crypt
)->priv
) < 0) {
637 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
643 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
644 ieee
->tx_keyidx
= idx
;
645 sec
.active_key
= idx
;
646 sec
.flags
|= SEC_ACTIVE_KEY
;
649 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
650 memcpy(sec
.keys
[idx
], ext
->key
, ext
->key_len
);
651 sec
.key_sizes
[idx
] = ext
->key_len
;
652 sec
.flags
|= (1 << idx
);
653 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
654 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
655 sec
.flags
|= SEC_LEVEL
;
656 sec
.level
= SEC_LEVEL_1
;
657 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
658 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
659 sec
.flags
|= SEC_LEVEL
;
660 sec
.level
= SEC_LEVEL_2
;
661 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
662 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
663 sec
.flags
|= SEC_LEVEL
;
664 sec
.level
= SEC_LEVEL_3
;
666 /* Don't set sec level for group keys. */
668 sec
.flags
&= ~SEC_LEVEL
;
671 if (ieee
->set_security
)
672 ieee
->set_security(ieee
->dev
, &sec
);
675 * Do not reset port if card is in Managed mode since resetting will
676 * generate new IEEE 802.11 authentication which may end up in looping
677 * with IEEE 802.1X. If your hardware requires a reset after WEP
678 * configuration (for example... Prism2), implement the reset_port in
679 * the callbacks structures used to initialize the 802.11 stack.
681 if (ieee
->reset_on_keychange
&&
682 ieee
->iw_mode
!= IW_MODE_INFRA
&&
683 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
684 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
691 int ieee80211_wx_get_encodeext(struct ieee80211_device
*ieee
,
692 struct iw_request_info
*info
,
693 union iwreq_data
*wrqu
, char *extra
)
695 struct iw_point
*encoding
= &wrqu
->encoding
;
696 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
697 struct ieee80211_security
*sec
= &ieee
->sec
;
698 int idx
, max_key_len
;
700 max_key_len
= encoding
->length
- sizeof(*ext
);
704 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
706 if (idx
< 1 || idx
> WEP_KEYS
)
710 idx
= ieee
->tx_keyidx
;
712 if (!ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
&&
713 ext
->alg
!= IW_ENCODE_ALG_WEP
)
714 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
717 encoding
->flags
= idx
+ 1;
718 memset(ext
, 0, sizeof(*ext
));
721 ext
->alg
= IW_ENCODE_ALG_NONE
;
723 encoding
->flags
|= IW_ENCODE_DISABLED
;
725 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
726 ext
->alg
= IW_ENCODE_ALG_WEP
;
727 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
728 ext
->alg
= IW_ENCODE_ALG_TKIP
;
729 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
730 ext
->alg
= IW_ENCODE_ALG_CCMP
;
734 ext
->key_len
= sec
->key_sizes
[idx
];
735 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
736 encoding
->flags
|= IW_ENCODE_ENABLED
;
738 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
739 ext
->alg
== IW_ENCODE_ALG_CCMP
))
740 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
747 int ieee80211_wx_set_auth(struct net_device
*dev
,
748 struct iw_request_info
*info
,
749 union iwreq_data
*wrqu
,
752 struct ieee80211_device
*ieee
= netdev_priv(dev
);
756 spin_lock_irqsave(&ieee
->lock
, flags
);
758 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
759 case IW_AUTH_WPA_VERSION
:
760 case IW_AUTH_CIPHER_PAIRWISE
:
761 case IW_AUTH_CIPHER_GROUP
:
762 case IW_AUTH_KEY_MGMT
:
764 * Host AP driver does not use these parameters and allows
765 * wpa_supplicant to control them internally.
768 case IW_AUTH_TKIP_COUNTERMEASURES
:
770 case IW_AUTH_DROP_UNENCRYPTED
:
771 ieee
->drop_unencrypted
= !!wrqu
->param
.value
;
773 case IW_AUTH_80211_AUTH_ALG
:
775 case IW_AUTH_WPA_ENABLED
:
776 ieee
->privacy_invoked
= ieee
->wpa_enabled
= !!wrqu
->param
.value
;
778 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
779 ieee
->ieee802_1x
= !!wrqu
->param
.value
;
781 case IW_AUTH_PRIVACY_INVOKED
:
782 ieee
->privacy_invoked
= !!wrqu
->param
.value
;
788 spin_unlock_irqrestore(&ieee
->lock
, flags
);
792 int ieee80211_wx_get_auth(struct net_device
*dev
,
793 struct iw_request_info
*info
,
794 union iwreq_data
*wrqu
,
797 struct ieee80211_device
*ieee
= netdev_priv(dev
);
801 spin_lock_irqsave(&ieee
->lock
, flags
);
803 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
804 case IW_AUTH_WPA_VERSION
:
805 case IW_AUTH_CIPHER_PAIRWISE
:
806 case IW_AUTH_CIPHER_GROUP
:
807 case IW_AUTH_KEY_MGMT
:
808 case IW_AUTH_TKIP_COUNTERMEASURES
: /* FIXME */
809 case IW_AUTH_80211_AUTH_ALG
: /* FIXME */
811 * Host AP driver does not use these parameters and allows
812 * wpa_supplicant to control them internally.
816 case IW_AUTH_DROP_UNENCRYPTED
:
817 wrqu
->param
.value
= ieee
->drop_unencrypted
;
819 case IW_AUTH_WPA_ENABLED
:
820 wrqu
->param
.value
= ieee
->wpa_enabled
;
822 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
823 wrqu
->param
.value
= ieee
->ieee802_1x
;
829 spin_unlock_irqrestore(&ieee
->lock
, flags
);
833 EXPORT_SYMBOL(ieee80211_wx_set_encodeext
);
834 EXPORT_SYMBOL(ieee80211_wx_get_encodeext
);
836 EXPORT_SYMBOL(ieee80211_wx_get_scan
);
837 EXPORT_SYMBOL(ieee80211_wx_set_encode
);
838 EXPORT_SYMBOL(ieee80211_wx_get_encode
);
840 EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth
);
841 EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth
);