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
,
48 struct iw_request_info
*info
)
50 char custom
[MAX_CUSTOM_LEN
];
54 char *current_val
; /* For rates */
57 /* First entry *MUST* be the AP MAC address */
59 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
60 memcpy(iwe
.u
.ap_addr
.sa_data
, network
->bssid
, ETH_ALEN
);
61 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_ADDR_LEN
);
63 /* Remaining entries will be displayed in the order we provide them */
66 iwe
.cmd
= SIOCGIWESSID
;
68 if (network
->flags
& NETWORK_EMPTY_ESSID
) {
69 iwe
.u
.data
.length
= sizeof("<hidden>");
70 start
= iwe_stream_add_point(info
, start
, stop
,
73 iwe
.u
.data
.length
= min(network
->ssid_len
, (u8
) 32);
74 start
= iwe_stream_add_point(info
, start
, stop
,
78 /* Add the protocol name */
79 iwe
.cmd
= SIOCGIWNAME
;
80 snprintf(iwe
.u
.name
, IFNAMSIZ
, "IEEE 802.11%s",
81 ieee80211_modes
[network
->mode
]);
82 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_CHAR_LEN
);
85 iwe
.cmd
= SIOCGIWMODE
;
86 if (network
->capability
& (WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_IBSS
)) {
87 if (network
->capability
& WLAN_CAPABILITY_ESS
)
88 iwe
.u
.mode
= IW_MODE_MASTER
;
90 iwe
.u
.mode
= IW_MODE_ADHOC
;
92 start
= iwe_stream_add_event(info
, start
, stop
,
93 &iwe
, IW_EV_UINT_LEN
);
96 /* Add channel and frequency */
97 /* Note : userspace automatically computes channel using iwrange */
98 iwe
.cmd
= SIOCGIWFREQ
;
99 iwe
.u
.freq
.m
= ieee80211_channel_to_freq(ieee
, network
->channel
);
102 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
104 /* Add encryption capability */
105 iwe
.cmd
= SIOCGIWENCODE
;
106 if (network
->capability
& WLAN_CAPABILITY_PRIVACY
)
107 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
109 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
110 iwe
.u
.data
.length
= 0;
111 start
= iwe_stream_add_point(info
, start
, stop
,
112 &iwe
, network
->ssid
);
114 /* Add basic and extended rates */
115 /* Rate : stuffing multiple values in a single event require a bit
116 * more of magic - Jean II */
117 current_val
= start
+ iwe_stream_lcp_len(info
);
118 iwe
.cmd
= SIOCGIWRATE
;
119 /* Those two flags are ignored... */
120 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
122 for (i
= 0, j
= 0; i
< network
->rates_len
;) {
123 if (j
< network
->rates_ex_len
&&
124 ((network
->rates_ex
[j
] & 0x7F) <
125 (network
->rates
[i
] & 0x7F)))
126 rate
= network
->rates_ex
[j
++] & 0x7F;
128 rate
= network
->rates
[i
++] & 0x7F;
129 /* Bit rate given in 500 kb/s units (+ 0x80) */
130 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
131 /* Add new value to event */
132 current_val
= iwe_stream_add_value(info
, start
, current_val
,
133 stop
, &iwe
, IW_EV_PARAM_LEN
);
135 for (; j
< network
->rates_ex_len
; j
++) {
136 rate
= network
->rates_ex
[j
] & 0x7F;
137 /* Bit rate given in 500 kb/s units (+ 0x80) */
138 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
139 /* Add new value to event */
140 current_val
= iwe_stream_add_value(info
, start
, current_val
,
141 stop
, &iwe
, IW_EV_PARAM_LEN
);
143 /* Check if we added any rate */
144 if ((current_val
- start
) > iwe_stream_lcp_len(info
))
147 /* Add quality statistics */
149 iwe
.u
.qual
.updated
= IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
|
150 IW_QUAL_NOISE_UPDATED
;
152 if (!(network
->stats
.mask
& IEEE80211_STATMASK_RSSI
)) {
153 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
|
154 IW_QUAL_LEVEL_INVALID
;
157 if (ieee
->perfect_rssi
== ieee
->worst_rssi
)
158 iwe
.u
.qual
.qual
= 100;
162 (ieee
->perfect_rssi
- ieee
->worst_rssi
) *
163 (ieee
->perfect_rssi
- ieee
->worst_rssi
) -
164 (ieee
->perfect_rssi
- network
->stats
.rssi
) *
165 (15 * (ieee
->perfect_rssi
- ieee
->worst_rssi
) +
166 62 * (ieee
->perfect_rssi
-
167 network
->stats
.rssi
))) /
168 ((ieee
->perfect_rssi
-
169 ieee
->worst_rssi
) * (ieee
->perfect_rssi
-
171 if (iwe
.u
.qual
.qual
> 100)
172 iwe
.u
.qual
.qual
= 100;
173 else if (iwe
.u
.qual
.qual
< 1)
177 if (!(network
->stats
.mask
& IEEE80211_STATMASK_NOISE
)) {
178 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
179 iwe
.u
.qual
.noise
= 0;
181 iwe
.u
.qual
.noise
= network
->stats
.noise
;
184 if (!(network
->stats
.mask
& IEEE80211_STATMASK_SIGNAL
)) {
185 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
186 iwe
.u
.qual
.level
= 0;
188 iwe
.u
.qual
.level
= network
->stats
.signal
;
191 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_QUAL_LEN
);
193 iwe
.cmd
= IWEVCUSTOM
;
196 iwe
.u
.data
.length
= p
- custom
;
197 if (iwe
.u
.data
.length
)
198 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
200 memset(&iwe
, 0, sizeof(iwe
));
201 if (network
->wpa_ie_len
) {
202 char buf
[MAX_WPA_IE_LEN
];
203 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
205 iwe
.u
.data
.length
= network
->wpa_ie_len
;
206 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
209 memset(&iwe
, 0, sizeof(iwe
));
210 if (network
->rsn_ie_len
) {
211 char buf
[MAX_WPA_IE_LEN
];
212 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
214 iwe
.u
.data
.length
= network
->rsn_ie_len
;
215 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
218 /* Add EXTRA: Age to display seconds since last beacon/probe response
219 * for given network. */
220 iwe
.cmd
= IWEVCUSTOM
;
222 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
223 " Last beacon: %dms ago",
224 jiffies_to_msecs(jiffies
- network
->last_scanned
));
225 iwe
.u
.data
.length
= p
- custom
;
226 if (iwe
.u
.data
.length
)
227 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
229 /* Add spectrum management information */
232 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Channel flags: ");
234 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
235 IEEE80211_CH_INVALID
) {
236 iwe
.cmd
= IWEVCUSTOM
;
237 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "INVALID ");
240 if (ieee80211_get_channel_flags(ieee
, network
->channel
) &
241 IEEE80211_CH_RADAR_DETECT
) {
242 iwe
.cmd
= IWEVCUSTOM
;
243 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "DFS ");
246 if (iwe
.cmd
== IWEVCUSTOM
) {
247 iwe
.u
.data
.length
= p
- custom
;
248 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
254 #define SCAN_ITEM_SIZE 128
256 int ieee80211_wx_get_scan(struct ieee80211_device
*ieee
,
257 struct iw_request_info
*info
,
258 union iwreq_data
*wrqu
, char *extra
)
260 struct ieee80211_network
*network
;
265 char *stop
= ev
+ wrqu
->data
.length
;
267 DECLARE_MAC_BUF(mac
);
269 IEEE80211_DEBUG_WX("Getting scan\n");
271 spin_lock_irqsave(&ieee
->lock
, flags
);
273 list_for_each_entry(network
, &ieee
->network_list
, list
) {
275 if (stop
- ev
< SCAN_ITEM_SIZE
) {
280 if (ieee
->scan_age
== 0 ||
281 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
282 ev
= ieee80211_translate_scan(ieee
, ev
, stop
, network
,
285 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
286 "%s)' due to age (%dms).\n",
287 escape_essid(network
->ssid
,
289 print_mac(mac
, network
->bssid
),
290 jiffies_to_msecs(jiffies
-
295 spin_unlock_irqrestore(&ieee
->lock
, flags
);
297 wrqu
->data
.length
= ev
- extra
;
298 wrqu
->data
.flags
= 0;
300 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i
);
305 int ieee80211_wx_set_encode(struct ieee80211_device
*ieee
,
306 struct iw_request_info
*info
,
307 union iwreq_data
*wrqu
, char *keybuf
)
309 struct iw_point
*erq
= &(wrqu
->encoding
);
310 struct net_device
*dev
= ieee
->dev
;
311 struct ieee80211_security sec
= {
314 int i
, key
, key_provided
, len
;
315 struct ieee80211_crypt_data
**crypt
;
316 int host_crypto
= ieee
->host_encrypt
|| ieee
->host_decrypt
|| ieee
->host_build_iv
;
318 IEEE80211_DEBUG_WX("SET_ENCODE\n");
320 key
= erq
->flags
& IW_ENCODE_INDEX
;
328 key
= ieee
->tx_keyidx
;
331 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
332 "provided" : "default");
334 crypt
= &ieee
->crypt
[key
];
336 if (erq
->flags
& IW_ENCODE_DISABLED
) {
337 if (key_provided
&& *crypt
) {
338 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
340 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
342 IEEE80211_DEBUG_WX("Disabling encryption.\n");
344 /* Check all the keys to see if any are still configured,
345 * and if no key index was provided, de-init them all */
346 for (i
= 0; i
< WEP_KEYS
; i
++) {
347 if (ieee
->crypt
[i
] != NULL
) {
350 ieee80211_crypt_delayed_deinit(ieee
,
358 sec
.level
= SEC_LEVEL_0
;
359 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
| SEC_ENCRYPT
;
367 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
369 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
370 strcmp((*crypt
)->ops
->name
, "WEP") != 0) {
371 /* changing to use WEP; deinit previously used algorithm
373 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
376 if (*crypt
== NULL
&& host_crypto
) {
377 struct ieee80211_crypt_data
*new_crypt
;
379 /* take WEP into use */
380 new_crypt
= kzalloc(sizeof(struct ieee80211_crypt_data
),
382 if (new_crypt
== NULL
)
384 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
385 if (!new_crypt
->ops
) {
386 request_module("ieee80211_crypt_wep");
387 new_crypt
->ops
= ieee80211_get_crypto_ops("WEP");
390 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
391 new_crypt
->priv
= new_crypt
->ops
->init(key
);
393 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
397 printk(KERN_WARNING
"%s: could not initialize WEP: "
398 "load module ieee80211_crypt_wep\n", dev
->name
);
404 /* If a new key was provided, set it up */
405 if (erq
->length
> 0) {
406 len
= erq
->length
<= 5 ? 5 : 13;
407 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
408 if (len
> erq
->length
)
409 memset(sec
.keys
[key
] + erq
->length
, 0,
411 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
412 key
, escape_essid(sec
.keys
[key
], len
),
414 sec
.key_sizes
[key
] = len
;
416 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
418 sec
.flags
|= (1 << key
);
419 /* This ensures a key will be activated if no key is
421 if (key
== sec
.active_key
)
422 sec
.flags
|= SEC_ACTIVE_KEY
;
426 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
427 NULL
, (*crypt
)->priv
);
429 /* Set a default key of all 0 */
430 IEEE80211_DEBUG_WX("Setting key %d to all "
432 memset(sec
.keys
[key
], 0, 13);
433 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
435 sec
.key_sizes
[key
] = 13;
436 sec
.flags
|= (1 << key
);
439 /* No key data - just set the default TX key index */
441 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
443 ieee
->tx_keyidx
= key
;
444 sec
.active_key
= key
;
445 sec
.flags
|= SEC_ACTIVE_KEY
;
448 if (erq
->flags
& (IW_ENCODE_OPEN
| IW_ENCODE_RESTRICTED
)) {
449 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
450 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
451 WLAN_AUTH_SHARED_KEY
;
452 sec
.flags
|= SEC_AUTH_MODE
;
453 IEEE80211_DEBUG_WX("Auth: %s\n",
454 sec
.auth_mode
== WLAN_AUTH_OPEN
?
455 "OPEN" : "SHARED KEY");
458 /* For now we just support WEP, so only set that security level...
459 * TODO: When WPA is added this is one place that needs to change */
460 sec
.flags
|= SEC_LEVEL
;
461 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
462 sec
.encode_alg
[key
] = SEC_ALG_WEP
;
465 if (ieee
->set_security
)
466 ieee
->set_security(dev
, &sec
);
468 /* Do not reset port if card is in Managed mode since resetting will
469 * generate new IEEE 802.11 authentication which may end up in looping
470 * with IEEE 802.1X. If your hardware requires a reset after WEP
471 * configuration (for example... Prism2), implement the reset_port in
472 * the callbacks structures used to initialize the 802.11 stack. */
473 if (ieee
->reset_on_keychange
&&
474 ieee
->iw_mode
!= IW_MODE_INFRA
&&
475 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
476 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
482 int ieee80211_wx_get_encode(struct ieee80211_device
*ieee
,
483 struct iw_request_info
*info
,
484 union iwreq_data
*wrqu
, char *keybuf
)
486 struct iw_point
*erq
= &(wrqu
->encoding
);
488 struct ieee80211_crypt_data
*crypt
;
489 struct ieee80211_security
*sec
= &ieee
->sec
;
491 IEEE80211_DEBUG_WX("GET_ENCODE\n");
493 key
= erq
->flags
& IW_ENCODE_INDEX
;
499 key
= ieee
->tx_keyidx
;
501 crypt
= ieee
->crypt
[key
];
502 erq
->flags
= key
+ 1;
506 erq
->flags
|= IW_ENCODE_DISABLED
;
510 len
= sec
->key_sizes
[key
];
511 memcpy(keybuf
, sec
->keys
[key
], len
);
514 erq
->flags
|= IW_ENCODE_ENABLED
;
517 erq
->flags
|= IW_ENCODE_OPEN
;
519 erq
->flags
|= IW_ENCODE_RESTRICTED
;
524 int ieee80211_wx_set_encodeext(struct ieee80211_device
*ieee
,
525 struct iw_request_info
*info
,
526 union iwreq_data
*wrqu
, char *extra
)
528 struct net_device
*dev
= ieee
->dev
;
529 struct iw_point
*encoding
= &wrqu
->encoding
;
530 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
533 const char *alg
, *module
;
534 struct ieee80211_crypto_ops
*ops
;
535 struct ieee80211_crypt_data
**crypt
;
537 struct ieee80211_security sec
= {
541 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
543 if (idx
< 1 || idx
> WEP_KEYS
)
547 idx
= ieee
->tx_keyidx
;
549 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
550 crypt
= &ieee
->crypt
[idx
];
553 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
554 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
556 if (ieee
->iw_mode
== IW_MODE_INFRA
)
557 crypt
= &ieee
->crypt
[idx
];
562 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
563 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
564 ext
->alg
== IW_ENCODE_ALG_NONE
) {
566 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
568 for (i
= 0; i
< WEP_KEYS
; i
++)
569 if (ieee
->crypt
[i
] != NULL
)
575 sec
.level
= SEC_LEVEL_0
;
576 sec
.flags
|= SEC_LEVEL
;
584 if (group_key
? !ieee
->host_mc_decrypt
:
585 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
586 ieee
->host_encrypt_msdu
))
587 goto skip_host_crypt
;
590 case IW_ENCODE_ALG_WEP
:
592 module
= "ieee80211_crypt_wep";
594 case IW_ENCODE_ALG_TKIP
:
596 module
= "ieee80211_crypt_tkip";
598 case IW_ENCODE_ALG_CCMP
:
600 module
= "ieee80211_crypt_ccmp";
603 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
604 dev
->name
, ext
->alg
);
609 ops
= ieee80211_get_crypto_ops(alg
);
611 request_module(module
);
612 ops
= ieee80211_get_crypto_ops(alg
);
615 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
616 dev
->name
, ext
->alg
);
621 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
622 struct ieee80211_crypt_data
*new_crypt
;
624 ieee80211_crypt_delayed_deinit(ieee
, crypt
);
626 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
627 if (new_crypt
== NULL
) {
631 new_crypt
->ops
= ops
;
632 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
633 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
634 if (new_crypt
->priv
== NULL
) {
642 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
643 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
644 (*crypt
)->priv
) < 0) {
645 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev
->name
);
651 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
652 ieee
->tx_keyidx
= idx
;
653 sec
.active_key
= idx
;
654 sec
.flags
|= SEC_ACTIVE_KEY
;
657 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
658 memcpy(sec
.keys
[idx
], ext
->key
, ext
->key_len
);
659 sec
.key_sizes
[idx
] = ext
->key_len
;
660 sec
.flags
|= (1 << idx
);
661 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
662 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
663 sec
.flags
|= SEC_LEVEL
;
664 sec
.level
= SEC_LEVEL_1
;
665 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
666 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
667 sec
.flags
|= SEC_LEVEL
;
668 sec
.level
= SEC_LEVEL_2
;
669 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
670 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
671 sec
.flags
|= SEC_LEVEL
;
672 sec
.level
= SEC_LEVEL_3
;
674 /* Don't set sec level for group keys. */
676 sec
.flags
&= ~SEC_LEVEL
;
679 if (ieee
->set_security
)
680 ieee
->set_security(ieee
->dev
, &sec
);
683 * Do not reset port if card is in Managed mode since resetting will
684 * generate new IEEE 802.11 authentication which may end up in looping
685 * with IEEE 802.1X. If your hardware requires a reset after WEP
686 * configuration (for example... Prism2), implement the reset_port in
687 * the callbacks structures used to initialize the 802.11 stack.
689 if (ieee
->reset_on_keychange
&&
690 ieee
->iw_mode
!= IW_MODE_INFRA
&&
691 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
692 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
699 int ieee80211_wx_get_encodeext(struct ieee80211_device
*ieee
,
700 struct iw_request_info
*info
,
701 union iwreq_data
*wrqu
, char *extra
)
703 struct iw_point
*encoding
= &wrqu
->encoding
;
704 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
705 struct ieee80211_security
*sec
= &ieee
->sec
;
706 int idx
, max_key_len
;
708 max_key_len
= encoding
->length
- sizeof(*ext
);
712 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
714 if (idx
< 1 || idx
> WEP_KEYS
)
718 idx
= ieee
->tx_keyidx
;
720 if (!(ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) &&
721 ext
->alg
!= IW_ENCODE_ALG_WEP
)
722 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
725 encoding
->flags
= idx
+ 1;
726 memset(ext
, 0, sizeof(*ext
));
729 ext
->alg
= IW_ENCODE_ALG_NONE
;
731 encoding
->flags
|= IW_ENCODE_DISABLED
;
733 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
734 ext
->alg
= IW_ENCODE_ALG_WEP
;
735 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
736 ext
->alg
= IW_ENCODE_ALG_TKIP
;
737 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
738 ext
->alg
= IW_ENCODE_ALG_CCMP
;
742 ext
->key_len
= sec
->key_sizes
[idx
];
743 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
744 encoding
->flags
|= IW_ENCODE_ENABLED
;
746 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
747 ext
->alg
== IW_ENCODE_ALG_CCMP
))
748 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
755 EXPORT_SYMBOL(ieee80211_wx_set_encodeext
);
756 EXPORT_SYMBOL(ieee80211_wx_get_encodeext
);
758 EXPORT_SYMBOL(ieee80211_wx_get_scan
);
759 EXPORT_SYMBOL(ieee80211_wx_set_encode
);
760 EXPORT_SYMBOL(ieee80211_wx_get_encode
);