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 *ipw2100_translate_scan(struct ieee80211_device
*ieee
,
46 char *start
, char *stop
,
47 struct ieee80211_network
*network
)
49 char custom
[MAX_CUSTOM_LEN
];
55 /* First entry *MUST* be the AP MAC address */
57 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
58 memcpy(iwe
.u
.ap_addr
.sa_data
, network
->bssid
, ETH_ALEN
);
59 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_ADDR_LEN
);
61 /* Remaining entries will be displayed in the order we provide them */
64 iwe
.cmd
= SIOCGIWESSID
;
66 if (network
->flags
& NETWORK_EMPTY_ESSID
) {
67 iwe
.u
.data
.length
= sizeof("<hidden>");
68 start
= iwe_stream_add_point(start
, stop
, &iwe
, "<hidden>");
70 iwe
.u
.data
.length
= min(network
->ssid_len
, (u8
) 32);
71 start
= iwe_stream_add_point(start
, stop
, &iwe
, network
->ssid
);
74 /* Add the protocol name */
75 iwe
.cmd
= SIOCGIWNAME
;
76 snprintf(iwe
.u
.name
, IFNAMSIZ
, "IEEE 802.11%s",
77 ieee80211_modes
[network
->mode
]);
78 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_CHAR_LEN
);
81 iwe
.cmd
= SIOCGIWMODE
;
82 if (network
->capability
& (WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_IBSS
)) {
83 if (network
->capability
& WLAN_CAPABILITY_ESS
)
84 iwe
.u
.mode
= IW_MODE_MASTER
;
86 iwe
.u
.mode
= IW_MODE_ADHOC
;
88 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_UINT_LEN
);
91 /* Add frequency/channel */
92 iwe
.cmd
= SIOCGIWFREQ
;
93 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
95 iwe
.u
.freq
.m
= 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 */
112 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Rates (Mb/s): ");
113 for (i
= 0, j
= 0; i
< network
->rates_len
;) {
114 if (j
< network
->rates_ex_len
&&
115 ((network
->rates_ex
[j
] & 0x7F) <
116 (network
->rates
[i
] & 0x7F)))
117 rate
= network
->rates_ex
[j
++] & 0x7F;
119 rate
= network
->rates
[i
++] & 0x7F;
122 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
123 "%d%s ", rate
>> 1, (rate
& 1) ? ".5" : "");
125 for (; j
< network
->rates_ex_len
; j
++) {
126 rate
= network
->rates_ex
[j
] & 0x7F;
127 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
128 "%d%s ", rate
>> 1, (rate
& 1) ? ".5" : "");
133 iwe
.cmd
= SIOCGIWRATE
;
134 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
135 iwe
.u
.bitrate
.value
= max_rate
* 500000;
136 start
= iwe_stream_add_event(start
, stop
, &iwe
, IW_EV_PARAM_LEN
);
138 iwe
.cmd
= IWEVCUSTOM
;
139 iwe
.u
.data
.length
= p
- custom
;
140 if (iwe
.u
.data
.length
)
141 start
= iwe_stream_add_point(start
, stop
, &iwe
, custom
);
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
= ipw2100_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
= kmalloc(sizeof(struct ieee80211_crypt_data
),
376 if (new_crypt
== NULL
)
378 memset(new_crypt
, 0, sizeof(struct ieee80211_crypt_data
));
379 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
380 if (!new_crypt
->ops
) {
381 request_module("ieee80211_crypt_wep");
382 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
385 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
386 new_crypt
->priv
= new_crypt
->ops
->init(key
);
388 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
392 printk(KERN_WARNING
"%s: could not initialize WEP: "
393 "load module ieee80211_crypt_wep\n", dev
->name
);
399 /* If a new key was provided, set it up */
400 if (erq
->length
> 0) {
401 len
= erq
->length
<= 5 ? 5 : 13;
402 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
403 if (len
> erq
->length
)
404 memset(sec
.keys
[key
] + erq
->length
, 0,
406 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
407 key
, escape_essid(sec
.keys
[key
], len
),
409 sec
.key_sizes
[key
] = len
;
411 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
413 sec
.flags
|= (1 << key
);
414 /* This ensures a key will be activated if no key is
416 if (key
== sec
.active_key
)
417 sec
.flags
|= SEC_ACTIVE_KEY
;
421 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
422 NULL
, (*crypt
)->priv
);
424 /* Set a default key of all 0 */
425 IEEE80211_DEBUG_WX("Setting key %d to all "
427 memset(sec
.keys
[key
], 0, 13);
428 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
430 sec
.key_sizes
[key
] = 13;
431 sec
.flags
|= (1 << key
);
434 /* No key data - just set the default TX key index */
436 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
438 ieee
->tx_keyidx
= key
;
439 sec
.active_key
= key
;
440 sec
.flags
|= SEC_ACTIVE_KEY
;
443 if (erq
->flags
& (IW_ENCODE_OPEN
| IW_ENCODE_RESTRICTED
)) {
444 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
445 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
446 WLAN_AUTH_SHARED_KEY
;
447 sec
.flags
|= SEC_AUTH_MODE
;
448 IEEE80211_DEBUG_WX("Auth: %s\n",
449 sec
.auth_mode
== WLAN_AUTH_OPEN
?
450 "OPEN" : "SHARED KEY");
453 /* For now we just support WEP, so only set that security level...
454 * TODO: When WPA is added this is one place that needs to change */
455 sec
.flags
|= SEC_LEVEL
;
456 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
457 sec
.encode_alg
[key
] = SEC_ALG_WEP
;
460 if (ieee
->set_security
)
461 ieee
->set_security(dev
, &sec
);
463 /* Do not reset port if card is in Managed mode since resetting will
464 * generate new IEEE 802.11 authentication which may end up in looping
465 * with IEEE 802.1X. If your hardware requires a reset after WEP
466 * configuration (for example... Prism2), implement the reset_port in
467 * the callbacks structures used to initialize the 802.11 stack. */
468 if (ieee
->reset_on_keychange
&&
469 ieee
->iw_mode
!= IW_MODE_INFRA
&&
470 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
471 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
477 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
478 struct iw_request_info
*info
,
479 union iwreq_data
*wrqu
, char *keybuf
)
481 struct iw_point
*erq
= &(wrqu
->encoding
);
483 struct ieee80211_crypt_data
*crypt
;
484 struct ieee80211_security
*sec
= &ieee
->sec
;
486 IEEE80211_DEBUG_WX("GET_ENCODE\n");
488 key
= erq
->flags
& IW_ENCODE_INDEX
;
494 key
= ieee
->tx_keyidx
;
496 crypt
= ieee
->crypt
[key
];
497 erq
->flags
= key
+ 1;
501 erq
->flags
|= IW_ENCODE_DISABLED
;
505 len
= sec
->key_sizes
[key
];
506 memcpy(keybuf
, sec
->keys
[key
], len
);
508 erq
->length
= (len
>= 0 ? len
: 0);
509 erq
->flags
|= IW_ENCODE_ENABLED
;
512 erq
->flags
|= IW_ENCODE_OPEN
;
514 erq
->flags
|= IW_ENCODE_RESTRICTED
;
519 int ieee80211_wx_set_encodeext(struct ieee80211_device
*ieee
,
520 struct iw_request_info
*info
,
521 union iwreq_data
*wrqu
, char *extra
)
523 struct net_device
*dev
= ieee
->dev
;
524 struct iw_point
*encoding
= &wrqu
->encoding
;
525 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
528 const char *alg
, *module
;
529 struct ieee80211_crypto_ops
*ops
;
530 struct ieee80211_crypt_data
**crypt
;
532 struct ieee80211_security sec
= {
536 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
538 if (idx
< 1 || idx
> WEP_KEYS
)
542 idx
= ieee
->tx_keyidx
;
544 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
545 crypt
= &ieee
->crypt
[idx
];
548 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
549 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
551 if (ieee
->iw_mode
== IW_MODE_INFRA
)
552 crypt
= &ieee
->crypt
[idx
];
557 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
558 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
559 ext
->alg
== IW_ENCODE_ALG_NONE
) {
561 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
563 for (i
= 0; i
< WEP_KEYS
; i
++)
564 if (ieee
->crypt
[i
] != NULL
)
570 sec
.level
= SEC_LEVEL_0
;
571 sec
.flags
|= SEC_LEVEL
;
579 if (group_key
? !ieee
->host_mc_decrypt
:
580 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
581 ieee
->host_encrypt_msdu
))
582 goto skip_host_crypt
;
585 case IW_ENCODE_ALG_WEP
:
587 module
= "ieee80211_crypt_wep";
589 case IW_ENCODE_ALG_TKIP
:
591 module
= "ieee80211_crypt_tkip";
593 case IW_ENCODE_ALG_CCMP
:
595 module
= "ieee80211_crypt_ccmp";
598 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
599 dev
->name
, ext
->alg
);
604 ops
= ieee80211_get_crypto_ops(alg
);
606 request_module(module
);
607 ops
= ieee80211_get_crypto_ops(alg
);
610 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
611 dev
->name
, ext
->alg
);
616 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
617 struct ieee80211_crypt_data
*new_crypt
;
619 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
621 new_crypt
= (struct ieee80211_crypt_data
*)
622 kmalloc(sizeof(*new_crypt
), GFP_KERNEL
);
623 if (new_crypt
== NULL
) {
627 memset(new_crypt
, 0, sizeof(struct ieee80211_crypt_data
));
628 new_crypt
->ops
= ops
;
629 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
630 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
631 if (new_crypt
->priv
== NULL
) {
639 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
640 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
641 (*crypt
)->priv
) < 0) {
642 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
648 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
649 ieee
->tx_keyidx
= idx
;
650 sec
.active_key
= idx
;
651 sec
.flags
|= SEC_ACTIVE_KEY
;
654 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
655 memcpy(sec
.keys
[idx
], ext
->key
, ext
->key_len
);
656 sec
.key_sizes
[idx
] = ext
->key_len
;
657 sec
.flags
|= (1 << idx
);
658 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
659 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
660 sec
.flags
|= SEC_LEVEL
;
661 sec
.level
= SEC_LEVEL_1
;
662 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
663 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
664 sec
.flags
|= SEC_LEVEL
;
665 sec
.level
= SEC_LEVEL_2
;
666 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
667 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
668 sec
.flags
|= SEC_LEVEL
;
669 sec
.level
= SEC_LEVEL_3
;
671 /* Don't set sec level for group keys. */
673 sec
.flags
&= ~SEC_LEVEL
;
676 if (ieee
->set_security
)
677 ieee
->set_security(ieee
->dev
, &sec
);
680 * Do not reset port if card is in Managed mode since resetting will
681 * generate new IEEE 802.11 authentication which may end up in looping
682 * with IEEE 802.1X. If your hardware requires a reset after WEP
683 * configuration (for example... Prism2), implement the reset_port in
684 * the callbacks structures used to initialize the 802.11 stack.
686 if (ieee
->reset_on_keychange
&&
687 ieee
->iw_mode
!= IW_MODE_INFRA
&&
688 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
689 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
696 int ieee80211_wx_get_encodeext(struct ieee80211_device
*ieee
,
697 struct iw_request_info
*info
,
698 union iwreq_data
*wrqu
, char *extra
)
700 struct iw_point
*encoding
= &wrqu
->encoding
;
701 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
702 struct ieee80211_security
*sec
= &ieee
->sec
;
703 int idx
, max_key_len
;
705 max_key_len
= encoding
->length
- sizeof(*ext
);
709 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
711 if (idx
< 1 || idx
> WEP_KEYS
)
715 idx
= ieee
->tx_keyidx
;
717 if (!ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
&&
718 ext
->alg
!= IW_ENCODE_ALG_WEP
)
719 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
722 encoding
->flags
= idx
+ 1;
723 memset(ext
, 0, sizeof(*ext
));
726 ext
->alg
= IW_ENCODE_ALG_NONE
;
728 encoding
->flags
|= IW_ENCODE_DISABLED
;
730 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
731 ext
->alg
= IW_ENCODE_ALG_WEP
;
732 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
733 ext
->alg
= IW_ENCODE_ALG_TKIP
;
734 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
735 ext
->alg
= IW_ENCODE_ALG_CCMP
;
739 ext
->key_len
= sec
->key_sizes
[idx
];
740 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
741 encoding
->flags
|= IW_ENCODE_ENABLED
;
743 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
744 ext
->alg
== IW_ENCODE_ALG_CCMP
))
745 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
752 int ieee80211_wx_set_auth(struct net_device
*dev
,
753 struct iw_request_info
*info
,
754 union iwreq_data
*wrqu
,
757 struct ieee80211_device
*ieee
= netdev_priv(dev
);
761 spin_lock_irqsave(&ieee
->lock
, flags
);
763 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
764 case IW_AUTH_WPA_VERSION
:
765 case IW_AUTH_CIPHER_PAIRWISE
:
766 case IW_AUTH_CIPHER_GROUP
:
767 case IW_AUTH_KEY_MGMT
:
769 * Host AP driver does not use these parameters and allows
770 * wpa_supplicant to control them internally.
773 case IW_AUTH_TKIP_COUNTERMEASURES
:
775 case IW_AUTH_DROP_UNENCRYPTED
:
776 ieee
->drop_unencrypted
= !!wrqu
->param
.value
;
778 case IW_AUTH_80211_AUTH_ALG
:
780 case IW_AUTH_WPA_ENABLED
:
781 ieee
->privacy_invoked
= ieee
->wpa_enabled
= !!wrqu
->param
.value
;
783 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
784 ieee
->ieee802_1x
= !!wrqu
->param
.value
;
786 case IW_AUTH_PRIVACY_INVOKED
:
787 ieee
->privacy_invoked
= !!wrqu
->param
.value
;
793 spin_unlock_irqrestore(&ieee
->lock
, flags
);
797 int ieee80211_wx_get_auth(struct net_device
*dev
,
798 struct iw_request_info
*info
,
799 union iwreq_data
*wrqu
,
802 struct ieee80211_device
*ieee
= netdev_priv(dev
);
806 spin_lock_irqsave(&ieee
->lock
, flags
);
808 switch (wrqu
->param
.flags
& IW_AUTH_INDEX
) {
809 case IW_AUTH_WPA_VERSION
:
810 case IW_AUTH_CIPHER_PAIRWISE
:
811 case IW_AUTH_CIPHER_GROUP
:
812 case IW_AUTH_KEY_MGMT
:
813 case IW_AUTH_TKIP_COUNTERMEASURES
: /* FIXME */
814 case IW_AUTH_80211_AUTH_ALG
: /* FIXME */
816 * Host AP driver does not use these parameters and allows
817 * wpa_supplicant to control them internally.
821 case IW_AUTH_DROP_UNENCRYPTED
:
822 wrqu
->param
.value
= ieee
->drop_unencrypted
;
824 case IW_AUTH_WPA_ENABLED
:
825 wrqu
->param
.value
= ieee
->wpa_enabled
;
827 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
828 wrqu
->param
.value
= ieee
->ieee802_1x
;
834 spin_unlock_irqrestore(&ieee
->lock
, flags
);
838 EXPORT_SYMBOL(ieee80211_wx_set_encodeext
);
839 EXPORT_SYMBOL(ieee80211_wx_get_encodeext
);
841 EXPORT_SYMBOL(ieee80211_wx_get_scan
);
842 EXPORT_SYMBOL(ieee80211_wx_set_encode
);
843 EXPORT_SYMBOL(ieee80211_wx_get_encode
);
845 EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth
);
846 EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth
);