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 /* Note : userspace automatically computes channel using iwrange */
94 iwe
.cmd
= SIOCGIWFREQ
;
95 iwe
.u
.freq
.m
= ieee80211_channel_to_freq(ieee
, network
->channel
);
98 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
100 /* Add encryption capability */
101 iwe
.cmd
= SIOCGIWENCODE
;
102 if (network
->capability
& WLAN_CAPABILITY_PRIVACY
)
103 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
105 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
106 iwe
.u
.data
.length
= 0;
107 start
= iwe_stream_add_point(start
, stop
, &iwe
, network
->ssid
);
109 /* Add basic and extended rates */
110 /* Rate : stuffing multiple values in a single event require a bit
111 * more of magic - Jean II */
112 current_val
= start
+ IW_EV_LCP_LEN
;
113 iwe
.cmd
= SIOCGIWRATE
;
114 /* Those two flags are ignored... */
115 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
117 for (i
= 0, j
= 0; i
< network
->rates_len
;) {
118 if (j
< network
->rates_ex_len
&&
119 ((network
->rates_ex
[j
] & 0x7F) <
120 (network
->rates
[i
] & 0x7F)))
121 rate
= network
->rates_ex
[j
++] & 0x7F;
123 rate
= network
->rates
[i
++] & 0x7F;
124 /* Bit rate given in 500 kb/s units (+ 0x80) */
125 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
126 /* Add new value to event */
127 current_val
= iwe_stream_add_value(start
, current_val
, stop
, &iwe
, IW_EV_PARAM_LEN
);
129 for (; j
< network
->rates_ex_len
; j
++) {
130 rate
= network
->rates_ex
[j
] & 0x7F;
131 /* Bit rate given in 500 kb/s units (+ 0x80) */
132 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
133 /* Add new value to event */
134 current_val
= iwe_stream_add_value(start
, current_val
, stop
, &iwe
, IW_EV_PARAM_LEN
);
136 /* Check if we added any rate */
137 if((current_val
- start
) > IW_EV_LCP_LEN
)
140 /* Add quality statistics */
142 iwe
.u
.qual
.updated
= IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
|
143 IW_QUAL_NOISE_UPDATED
;
145 if (!(network
->stats
.mask
& IEEE80211_STATMASK_RSSI
)) {
146 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
|
147 IW_QUAL_LEVEL_INVALID
;
150 if (ieee
->perfect_rssi
== ieee
->worst_rssi
)
151 iwe
.u
.qual
.qual
= 100;
155 (ieee
->perfect_rssi
- ieee
->worst_rssi
) *
156 (ieee
->perfect_rssi
- ieee
->worst_rssi
) -
157 (ieee
->perfect_rssi
- network
->stats
.rssi
) *
158 (15 * (ieee
->perfect_rssi
- ieee
->worst_rssi
) +
159 62 * (ieee
->perfect_rssi
-
160 network
->stats
.rssi
))) /
161 ((ieee
->perfect_rssi
-
162 ieee
->worst_rssi
) * (ieee
->perfect_rssi
-
164 if (iwe
.u
.qual
.qual
> 100)
165 iwe
.u
.qual
.qual
= 100;
166 else if (iwe
.u
.qual
.qual
< 1)
170 if (!(network
->stats
.mask
& IEEE80211_STATMASK_NOISE
)) {
171 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
172 iwe
.u
.qual
.noise
= 0;
174 iwe
.u
.qual
.noise
= network
->stats
.noise
;
177 if (!(network
->stats
.mask
& IEEE80211_STATMASK_SIGNAL
)) {
178 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
179 iwe
.u
.qual
.level
= 0;
181 iwe
.u
.qual
.level
= network
->stats
.signal
;
184 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_QUAL_LEN
);
186 iwe
.cmd
= IWEVCUSTOM
;
189 iwe
.u
.data
.length
= p
- custom
;
190 if (iwe
.u
.data
.length
)
191 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
193 memset(&iwe
, 0, sizeof(iwe
));
194 if (network
->wpa_ie_len
) {
195 char buf
[MAX_WPA_IE_LEN
];
196 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
198 iwe
.u
.data
.length
= network
->wpa_ie_len
;
199 start
= iwe_stream_add_point(start
, stop
, &iwe
, buf
);
202 memset(&iwe
, 0, sizeof(iwe
));
203 if (network
->rsn_ie_len
) {
204 char buf
[MAX_WPA_IE_LEN
];
205 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
207 iwe
.u
.data
.length
= network
->rsn_ie_len
;
208 start
= iwe_stream_add_point(start
, stop
, &iwe
, buf
);
211 /* Add EXTRA: Age to display seconds since last beacon/probe response
212 * for given network. */
213 iwe
.cmd
= IWEVCUSTOM
;
215 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
216 " Last beacon: %dms ago",
217 jiffies_to_msecs(jiffies
- network
->last_scanned
));
218 iwe
.u
.data
.length
= p
- custom
;
219 if (iwe
.u
.data
.length
)
220 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
222 /* Add spectrum management information */
225 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Channel flags: ");
227 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
228 IEEE80211_CH_INVALID
) {
229 iwe
.cmd
= IWEVCUSTOM
;
230 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "INVALID ");
233 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
234 IEEE80211_CH_RADAR_DETECT
) {
235 iwe
.cmd
= IWEVCUSTOM
;
236 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "DFS ");
239 if (iwe
.cmd
== IWEVCUSTOM
) {
240 iwe
.u
.data
.length
= p
- custom
;
241 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
247 #define SCAN_ITEM_SIZE 128
249 int ieee80211_wx_get_scan(struct ieee80211_device
*ieee
,
250 struct iw_request_info
*info
,
251 union iwreq_data
*wrqu
, char *extra
)
253 struct ieee80211_network
*network
;
258 char *stop
= ev
+ wrqu
->data
.length
;
261 IEEE80211_DEBUG_WX("Getting scan\n");
263 spin_lock_irqsave(&ieee
->lock
, flags
);
265 list_for_each_entry(network
, &ieee
->network_list
, list
) {
267 if (stop
- ev
< SCAN_ITEM_SIZE
) {
272 if (ieee
->scan_age
== 0 ||
273 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
274 ev
= ieee80211_translate_scan(ieee
, ev
, stop
, network
);
276 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
277 MAC_FMT
")' due to age (%dms).\n",
278 escape_essid(network
->ssid
,
280 MAC_ARG(network
->bssid
),
281 jiffies_to_msecs(jiffies
-
286 spin_unlock_irqrestore(&ieee
->lock
, flags
);
288 wrqu
->data
.length
= ev
- extra
;
289 wrqu
->data
.flags
= 0;
291 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i
);
296 int ieee80211_wx_set_encode(struct ieee80211_device
*ieee
,
297 struct iw_request_info
*info
,
298 union iwreq_data
*wrqu
, char *keybuf
)
300 struct iw_point
*erq
= &(wrqu
->encoding
);
301 struct net_device
*dev
= ieee
->dev
;
302 struct ieee80211_security sec
= {
305 int i
, key
, key_provided
, len
;
306 struct ieee80211_crypt_data
**crypt
;
307 int host_crypto
= ieee
->host_encrypt
|| ieee
->host_decrypt
|| ieee
->host_build_iv
;
309 IEEE80211_DEBUG_WX("SET_ENCODE\n");
311 key
= erq
->flags
& IW_ENCODE_INDEX
;
319 key
= ieee
->tx_keyidx
;
322 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
323 "provided" : "default");
325 crypt
= &ieee
->crypt
[key
];
327 if (erq
->flags
& IW_ENCODE_DISABLED
) {
328 if (key_provided
&& *crypt
) {
329 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
331 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
333 IEEE80211_DEBUG_WX("Disabling encryption.\n");
335 /* Check all the keys to see if any are still configured,
336 * and if no key index was provided, de-init them all */
337 for (i
= 0; i
< WEP_KEYS
; i
++) {
338 if (ieee
->crypt
[i
] != NULL
) {
341 ieee80211_crypt_delayed_deinit(ieee
,
349 sec
.level
= SEC_LEVEL_0
;
350 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
| SEC_ENCRYPT
;
358 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
360 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
361 strcmp((*crypt
)->ops
->name
, "WEP") != 0) {
362 /* changing to use WEP; deinit previously used algorithm
364 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
367 if (*crypt
== NULL
&& host_crypto
) {
368 struct ieee80211_crypt_data
*new_crypt
;
370 /* take WEP into use */
371 new_crypt
= kzalloc(sizeof(struct ieee80211_crypt_data
),
373 if (new_crypt
== NULL
)
375 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
376 if (!new_crypt
->ops
) {
377 request_module("ieee80211_crypt_wep");
378 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
381 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
382 new_crypt
->priv
= new_crypt
->ops
->init(key
);
384 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
388 printk(KERN_WARNING
"%s: could not initialize WEP: "
389 "load module ieee80211_crypt_wep\n", dev
->name
);
395 /* If a new key was provided, set it up */
396 if (erq
->length
> 0) {
397 len
= erq
->length
<= 5 ? 5 : 13;
398 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
399 if (len
> erq
->length
)
400 memset(sec
.keys
[key
] + erq
->length
, 0,
402 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
403 key
, escape_essid(sec
.keys
[key
], len
),
405 sec
.key_sizes
[key
] = len
;
407 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
409 sec
.flags
|= (1 << key
);
410 /* This ensures a key will be activated if no key is
412 if (key
== sec
.active_key
)
413 sec
.flags
|= SEC_ACTIVE_KEY
;
417 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
418 NULL
, (*crypt
)->priv
);
420 /* Set a default key of all 0 */
421 IEEE80211_DEBUG_WX("Setting key %d to all "
423 memset(sec
.keys
[key
], 0, 13);
424 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
426 sec
.key_sizes
[key
] = 13;
427 sec
.flags
|= (1 << key
);
430 /* No key data - just set the default TX key index */
432 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
434 ieee
->tx_keyidx
= key
;
435 sec
.active_key
= key
;
436 sec
.flags
|= SEC_ACTIVE_KEY
;
439 if (erq
->flags
& (IW_ENCODE_OPEN
| IW_ENCODE_RESTRICTED
)) {
440 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
441 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
442 WLAN_AUTH_SHARED_KEY
;
443 sec
.flags
|= SEC_AUTH_MODE
;
444 IEEE80211_DEBUG_WX("Auth: %s\n",
445 sec
.auth_mode
== WLAN_AUTH_OPEN
?
446 "OPEN" : "SHARED KEY");
449 /* For now we just support WEP, so only set that security level...
450 * TODO: When WPA is added this is one place that needs to change */
451 sec
.flags
|= SEC_LEVEL
;
452 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
453 sec
.encode_alg
[key
] = SEC_ALG_WEP
;
456 if (ieee
->set_security
)
457 ieee
->set_security(dev
, &sec
);
459 /* Do not reset port if card is in Managed mode since resetting will
460 * generate new IEEE 802.11 authentication which may end up in looping
461 * with IEEE 802.1X. If your hardware requires a reset after WEP
462 * configuration (for example... Prism2), implement the reset_port in
463 * the callbacks structures used to initialize the 802.11 stack. */
464 if (ieee
->reset_on_keychange
&&
465 ieee
->iw_mode
!= IW_MODE_INFRA
&&
466 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
467 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
473 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
474 struct iw_request_info
*info
,
475 union iwreq_data
*wrqu
, char *keybuf
)
477 struct iw_point
*erq
= &(wrqu
->encoding
);
479 struct ieee80211_crypt_data
*crypt
;
480 struct ieee80211_security
*sec
= &ieee
->sec
;
482 IEEE80211_DEBUG_WX("GET_ENCODE\n");
484 key
= erq
->flags
& IW_ENCODE_INDEX
;
490 key
= ieee
->tx_keyidx
;
492 crypt
= ieee
->crypt
[key
];
493 erq
->flags
= key
+ 1;
497 erq
->flags
|= IW_ENCODE_DISABLED
;
501 len
= sec
->key_sizes
[key
];
502 memcpy(keybuf
, sec
->keys
[key
], len
);
505 erq
->flags
|= IW_ENCODE_ENABLED
;
508 erq
->flags
|= IW_ENCODE_OPEN
;
510 erq
->flags
|= IW_ENCODE_RESTRICTED
;
515 int ieee80211_wx_set_encodeext(struct ieee80211_device
*ieee
,
516 struct iw_request_info
*info
,
517 union iwreq_data
*wrqu
, char *extra
)
519 struct net_device
*dev
= ieee
->dev
;
520 struct iw_point
*encoding
= &wrqu
->encoding
;
521 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
524 const char *alg
, *module
;
525 struct ieee80211_crypto_ops
*ops
;
526 struct ieee80211_crypt_data
**crypt
;
528 struct ieee80211_security sec
= {
532 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
534 if (idx
< 1 || idx
> WEP_KEYS
)
538 idx
= ieee
->tx_keyidx
;
540 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
541 crypt
= &ieee
->crypt
[idx
];
544 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
545 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
547 if (ieee
->iw_mode
== IW_MODE_INFRA
)
548 crypt
= &ieee
->crypt
[idx
];
553 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
554 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
555 ext
->alg
== IW_ENCODE_ALG_NONE
) {
557 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
559 for (i
= 0; i
< WEP_KEYS
; i
++)
560 if (ieee
->crypt
[i
] != NULL
)
566 sec
.level
= SEC_LEVEL_0
;
567 sec
.flags
|= SEC_LEVEL
;
575 if (group_key
? !ieee
->host_mc_decrypt
:
576 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
577 ieee
->host_encrypt_msdu
))
578 goto skip_host_crypt
;
581 case IW_ENCODE_ALG_WEP
:
583 module
= "ieee80211_crypt_wep";
585 case IW_ENCODE_ALG_TKIP
:
587 module
= "ieee80211_crypt_tkip";
589 case IW_ENCODE_ALG_CCMP
:
591 module
= "ieee80211_crypt_ccmp";
594 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
595 dev
->name
, ext
->alg
);
600 ops
= ieee80211_get_crypto_ops(alg
);
602 request_module(module
);
603 ops
= ieee80211_get_crypto_ops(alg
);
606 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
607 dev
->name
, ext
->alg
);
612 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
613 struct ieee80211_crypt_data
*new_crypt
;
615 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
617 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
618 if (new_crypt
== NULL
) {
622 new_crypt
->ops
= ops
;
623 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
624 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
625 if (new_crypt
->priv
== NULL
) {
633 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
634 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
635 (*crypt
)->priv
) < 0) {
636 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
642 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
643 ieee
->tx_keyidx
= idx
;
644 sec
.active_key
= idx
;
645 sec
.flags
|= SEC_ACTIVE_KEY
;
648 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
649 memcpy(sec
.keys
[idx
], ext
->key
, ext
->key_len
);
650 sec
.key_sizes
[idx
] = ext
->key_len
;
651 sec
.flags
|= (1 << idx
);
652 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
653 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
654 sec
.flags
|= SEC_LEVEL
;
655 sec
.level
= SEC_LEVEL_1
;
656 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
657 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
658 sec
.flags
|= SEC_LEVEL
;
659 sec
.level
= SEC_LEVEL_2
;
660 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
661 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
662 sec
.flags
|= SEC_LEVEL
;
663 sec
.level
= SEC_LEVEL_3
;
665 /* Don't set sec level for group keys. */
667 sec
.flags
&= ~SEC_LEVEL
;
670 if (ieee
->set_security
)
671 ieee
->set_security(ieee
->dev
, &sec
);
674 * Do not reset port if card is in Managed mode since resetting will
675 * generate new IEEE 802.11 authentication which may end up in looping
676 * with IEEE 802.1X. If your hardware requires a reset after WEP
677 * configuration (for example... Prism2), implement the reset_port in
678 * the callbacks structures used to initialize the 802.11 stack.
680 if (ieee
->reset_on_keychange
&&
681 ieee
->iw_mode
!= IW_MODE_INFRA
&&
682 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
683 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
690 int ieee80211_wx_get_encodeext(struct ieee80211_device
*ieee
,
691 struct iw_request_info
*info
,
692 union iwreq_data
*wrqu
, char *extra
)
694 struct iw_point
*encoding
= &wrqu
->encoding
;
695 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
696 struct ieee80211_security
*sec
= &ieee
->sec
;
697 int idx
, max_key_len
;
699 max_key_len
= encoding
->length
- sizeof(*ext
);
703 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
705 if (idx
< 1 || idx
> WEP_KEYS
)
709 idx
= ieee
->tx_keyidx
;
711 if (!ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
&&
712 ext
->alg
!= IW_ENCODE_ALG_WEP
)
713 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
716 encoding
->flags
= idx
+ 1;
717 memset(ext
, 0, sizeof(*ext
));
720 ext
->alg
= IW_ENCODE_ALG_NONE
;
722 encoding
->flags
|= IW_ENCODE_DISABLED
;
724 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
725 ext
->alg
= IW_ENCODE_ALG_WEP
;
726 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
727 ext
->alg
= IW_ENCODE_ALG_TKIP
;
728 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
729 ext
->alg
= IW_ENCODE_ALG_CCMP
;
733 ext
->key_len
= sec
->key_sizes
[idx
];
734 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
735 encoding
->flags
|= IW_ENCODE_ENABLED
;
737 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
738 ext
->alg
== IW_ENCODE_ALG_CCMP
))
739 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
746 int ieee80211_wx_set_auth(struct net_device
*dev
,
747 struct iw_request_info
*info
,
748 union iwreq_data
*wrqu
,
751 struct ieee80211_device
*ieee
= netdev_priv(dev
);
755 spin_lock_irqsave(&ieee
->lock
, flags
);
757 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
758 case IW_AUTH_WPA_VERSION
:
759 case IW_AUTH_CIPHER_PAIRWISE
:
760 case IW_AUTH_CIPHER_GROUP
:
761 case IW_AUTH_KEY_MGMT
:
763 * Host AP driver does not use these parameters and allows
764 * wpa_supplicant to control them internally.
767 case IW_AUTH_TKIP_COUNTERMEASURES
:
769 case IW_AUTH_DROP_UNENCRYPTED
:
770 ieee
->drop_unencrypted
= !!wrqu
->param
.value
;
772 case IW_AUTH_80211_AUTH_ALG
:
774 case IW_AUTH_WPA_ENABLED
:
775 ieee
->privacy_invoked
= ieee
->wpa_enabled
= !!wrqu
->param
.value
;
777 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
778 ieee
->ieee802_1x
= !!wrqu
->param
.value
;
780 case IW_AUTH_PRIVACY_INVOKED
:
781 ieee
->privacy_invoked
= !!wrqu
->param
.value
;
787 spin_unlock_irqrestore(&ieee
->lock
, flags
);
791 int ieee80211_wx_get_auth(struct net_device
*dev
,
792 struct iw_request_info
*info
,
793 union iwreq_data
*wrqu
,
796 struct ieee80211_device
*ieee
= netdev_priv(dev
);
800 spin_lock_irqsave(&ieee
->lock
, flags
);
802 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
803 case IW_AUTH_WPA_VERSION
:
804 case IW_AUTH_CIPHER_PAIRWISE
:
805 case IW_AUTH_CIPHER_GROUP
:
806 case IW_AUTH_KEY_MGMT
:
807 case IW_AUTH_TKIP_COUNTERMEASURES
: /* FIXME */
808 case IW_AUTH_80211_AUTH_ALG
: /* FIXME */
810 * Host AP driver does not use these parameters and allows
811 * wpa_supplicant to control them internally.
815 case IW_AUTH_DROP_UNENCRYPTED
:
816 wrqu
->param
.value
= ieee
->drop_unencrypted
;
818 case IW_AUTH_WPA_ENABLED
:
819 wrqu
->param
.value
= ieee
->wpa_enabled
;
821 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
822 wrqu
->param
.value
= ieee
->ieee802_1x
;
828 spin_unlock_irqrestore(&ieee
->lock
, flags
);
832 EXPORT_SYMBOL(ieee80211_wx_set_encodeext
);
833 EXPORT_SYMBOL(ieee80211_wx_get_encodeext
);
835 EXPORT_SYMBOL(ieee80211_wx_get_scan
);
836 EXPORT_SYMBOL(ieee80211_wx_set_encode
);
837 EXPORT_SYMBOL(ieee80211_wx_get_encode
);
839 EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth
);
840 EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth
);