1 // SPDX-License-Identifier: GPL-2.0-only
2 /******************************************************************************
4 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
6 Portions of this file are based on the WEP enablement code provided by the
7 Host AP project hostap-drivers v0.1.3
8 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
10 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
14 Intel Linux Wireless <ilw@linux.intel.com>
15 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
17 ******************************************************************************/
19 #include <linux/hardirq.h>
20 #include <linux/kmod.h>
21 #include <linux/slab.h>
22 #include <linux/module.h>
23 #include <linux/jiffies.h>
25 #include <net/lib80211.h>
26 #include <linux/wireless.h>
30 static const char *libipw_modes
[] = {
31 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
34 static inline unsigned int elapsed_jiffies_msecs(unsigned long start
)
36 unsigned long end
= jiffies
;
39 return jiffies_to_msecs(end
- start
);
41 return jiffies_to_msecs(end
+ (MAX_JIFFY_OFFSET
- start
) + 1);
44 #define MAX_CUSTOM_LEN 64
45 static char *libipw_translate_scan(struct libipw_device
*ieee
,
46 char *start
, char *stop
,
47 struct libipw_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 iwe
.u
.data
.length
= min(network
->ssid_len
, (u8
) 32);
69 start
= iwe_stream_add_point(info
, start
, stop
,
72 /* Add the protocol name */
73 iwe
.cmd
= SIOCGIWNAME
;
74 snprintf(iwe
.u
.name
, IFNAMSIZ
, "IEEE 802.11%s",
75 libipw_modes
[network
->mode
]);
76 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_CHAR_LEN
);
79 iwe
.cmd
= SIOCGIWMODE
;
80 if (network
->capability
& (WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_IBSS
)) {
81 if (network
->capability
& WLAN_CAPABILITY_ESS
)
82 iwe
.u
.mode
= IW_MODE_MASTER
;
84 iwe
.u
.mode
= IW_MODE_ADHOC
;
86 start
= iwe_stream_add_event(info
, start
, stop
,
87 &iwe
, IW_EV_UINT_LEN
);
90 /* Add channel and frequency */
91 /* Note : userspace automatically computes channel using iwrange */
92 iwe
.cmd
= SIOCGIWFREQ
;
93 iwe
.u
.freq
.m
= libipw_channel_to_freq(ieee
, network
->channel
);
96 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
98 /* Add encryption capability */
99 iwe
.cmd
= SIOCGIWENCODE
;
100 if (network
->capability
& WLAN_CAPABILITY_PRIVACY
)
101 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
103 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
104 iwe
.u
.data
.length
= 0;
105 start
= iwe_stream_add_point(info
, start
, stop
,
106 &iwe
, network
->ssid
);
108 /* Add basic and extended rates */
109 /* Rate : stuffing multiple values in a single event require a bit
110 * more of magic - Jean II */
111 current_val
= start
+ iwe_stream_lcp_len(info
);
112 iwe
.cmd
= SIOCGIWRATE
;
113 /* Those two flags are ignored... */
114 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
116 for (i
= 0, j
= 0; i
< network
->rates_len
;) {
117 if (j
< network
->rates_ex_len
&&
118 ((network
->rates_ex
[j
] & 0x7F) <
119 (network
->rates
[i
] & 0x7F)))
120 rate
= network
->rates_ex
[j
++] & 0x7F;
122 rate
= network
->rates
[i
++] & 0x7F;
123 /* Bit rate given in 500 kb/s units (+ 0x80) */
124 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
125 /* Add new value to event */
126 current_val
= iwe_stream_add_value(info
, start
, current_val
,
127 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(info
, start
, current_val
,
135 stop
, &iwe
, IW_EV_PARAM_LEN
);
137 /* Check if we added any rate */
138 if ((current_val
- start
) > iwe_stream_lcp_len(info
))
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
& LIBIPW_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
& LIBIPW_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
& LIBIPW_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(info
, 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(info
, 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(info
, 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(info
, 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
+= scnprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
217 " Last beacon: %ums ago",
218 elapsed_jiffies_msecs(network
->last_scanned
));
219 iwe
.u
.data
.length
= p
- custom
;
220 if (iwe
.u
.data
.length
)
221 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
223 /* Add spectrum management information */
226 p
+= scnprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Channel flags: ");
228 if (libipw_get_channel_flags(ieee
, network
->channel
) &
230 iwe
.cmd
= IWEVCUSTOM
;
231 p
+= scnprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "INVALID ");
234 if (libipw_get_channel_flags(ieee
, network
->channel
) &
235 LIBIPW_CH_RADAR_DETECT
) {
236 iwe
.cmd
= IWEVCUSTOM
;
237 p
+= scnprintf(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(info
, start
, stop
, &iwe
, custom
);
248 #define SCAN_ITEM_SIZE 128
250 int libipw_wx_get_scan(struct libipw_device
*ieee
,
251 struct iw_request_info
*info
,
252 union iwreq_data
*wrqu
, char *extra
)
254 struct libipw_network
*network
;
259 char *stop
= ev
+ wrqu
->data
.length
;
262 LIBIPW_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
= libipw_translate_scan(ieee
, ev
, stop
, network
,
278 LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
279 network
->ssid_len
, network
->ssid
,
281 elapsed_jiffies_msecs(
282 network
->last_scanned
));
286 spin_unlock_irqrestore(&ieee
->lock
, flags
);
288 wrqu
->data
.length
= ev
- extra
;
289 wrqu
->data
.flags
= 0;
291 LIBIPW_DEBUG_WX("exit: %d networks returned.\n", i
);
296 int libipw_wx_set_encode(struct libipw_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 libipw_security sec
= {
305 int i
, key
, key_provided
, len
;
306 struct lib80211_crypt_data
**crypt
;
307 int host_crypto
= ieee
->host_encrypt
|| ieee
->host_decrypt
;
309 LIBIPW_DEBUG_WX("SET_ENCODE\n");
311 key
= erq
->flags
& IW_ENCODE_INDEX
;
319 key
= ieee
->crypt_info
.tx_keyidx
;
322 LIBIPW_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
323 "provided" : "default");
325 crypt
= &ieee
->crypt_info
.crypt
[key
];
327 if (erq
->flags
& IW_ENCODE_DISABLED
) {
328 if (key_provided
&& *crypt
) {
329 LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n",
331 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
333 LIBIPW_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_info
.crypt
[i
] != NULL
) {
341 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
,
342 &ieee
->crypt_info
.crypt
[i
]);
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 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
367 if (*crypt
== NULL
&& host_crypto
) {
368 struct lib80211_crypt_data
*new_crypt
;
370 /* take WEP into use */
371 new_crypt
= kzalloc(sizeof(struct lib80211_crypt_data
),
373 if (new_crypt
== NULL
)
375 new_crypt
->ops
= lib80211_get_crypto_ops("WEP");
376 if (!new_crypt
->ops
) {
377 request_module("lib80211_crypt_wep");
378 new_crypt
->ops
= lib80211_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 lib80211_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 LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
403 key
, len
, sec
.keys
[key
],
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 LIBIPW_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 LIBIPW_DEBUG_WX("Setting key %d to default Tx "
434 ieee
->crypt_info
.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 LIBIPW_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
);
462 int libipw_wx_get_encode(struct libipw_device
*ieee
,
463 struct iw_request_info
*info
,
464 union iwreq_data
*wrqu
, char *keybuf
)
466 struct iw_point
*erq
= &(wrqu
->encoding
);
468 struct libipw_security
*sec
= &ieee
->sec
;
470 LIBIPW_DEBUG_WX("GET_ENCODE\n");
472 key
= erq
->flags
& IW_ENCODE_INDEX
;
478 key
= ieee
->crypt_info
.tx_keyidx
;
480 erq
->flags
= key
+ 1;
484 erq
->flags
|= IW_ENCODE_DISABLED
;
488 len
= sec
->key_sizes
[key
];
489 memcpy(keybuf
, sec
->keys
[key
], len
);
492 erq
->flags
|= IW_ENCODE_ENABLED
;
495 erq
->flags
|= IW_ENCODE_OPEN
;
497 erq
->flags
|= IW_ENCODE_RESTRICTED
;
502 int libipw_wx_set_encodeext(struct libipw_device
*ieee
,
503 struct iw_request_info
*info
,
504 union iwreq_data
*wrqu
, char *extra
)
506 struct net_device
*dev
= ieee
->dev
;
507 struct iw_point
*encoding
= &wrqu
->encoding
;
508 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
511 const char *alg
, *module
;
512 struct lib80211_crypto_ops
*ops
;
513 struct lib80211_crypt_data
**crypt
;
515 struct libipw_security sec
= {
519 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
521 if (idx
< 1 || idx
> WEP_KEYS
)
525 idx
= ieee
->crypt_info
.tx_keyidx
;
527 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
528 crypt
= &ieee
->crypt_info
.crypt
[idx
];
531 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
532 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
534 if (ieee
->iw_mode
== IW_MODE_INFRA
)
535 crypt
= &ieee
->crypt_info
.crypt
[idx
];
540 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
541 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
542 ext
->alg
== IW_ENCODE_ALG_NONE
) {
544 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
546 for (i
= 0; i
< WEP_KEYS
; i
++)
547 if (ieee
->crypt_info
.crypt
[i
] != NULL
)
553 sec
.level
= SEC_LEVEL_0
;
554 sec
.flags
|= SEC_LEVEL
;
562 if (group_key
? !ieee
->host_mc_decrypt
:
563 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
564 ieee
->host_encrypt_msdu
))
565 goto skip_host_crypt
;
568 case IW_ENCODE_ALG_WEP
:
570 module
= "lib80211_crypt_wep";
572 case IW_ENCODE_ALG_TKIP
:
574 module
= "lib80211_crypt_tkip";
576 case IW_ENCODE_ALG_CCMP
:
578 module
= "lib80211_crypt_ccmp";
581 LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
582 dev
->name
, ext
->alg
);
587 ops
= lib80211_get_crypto_ops(alg
);
589 request_module(module
);
590 ops
= lib80211_get_crypto_ops(alg
);
593 LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
594 dev
->name
, ext
->alg
);
599 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
600 struct lib80211_crypt_data
*new_crypt
;
602 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
604 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
605 if (new_crypt
== NULL
) {
609 new_crypt
->ops
= ops
;
610 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
611 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
612 if (new_crypt
->priv
== NULL
) {
620 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
621 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
622 (*crypt
)->priv
) < 0) {
623 LIBIPW_DEBUG_WX("%s: key setting failed\n", dev
->name
);
629 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
630 ieee
->crypt_info
.tx_keyidx
= idx
;
631 sec
.active_key
= idx
;
632 sec
.flags
|= SEC_ACTIVE_KEY
;
635 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
636 memcpy(sec
.keys
[idx
], ext
->key
, ext
->key_len
);
637 sec
.key_sizes
[idx
] = ext
->key_len
;
638 sec
.flags
|= (1 << idx
);
639 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
640 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
641 sec
.flags
|= SEC_LEVEL
;
642 sec
.level
= SEC_LEVEL_1
;
643 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
644 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
645 sec
.flags
|= SEC_LEVEL
;
646 sec
.level
= SEC_LEVEL_2
;
647 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
648 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
649 sec
.flags
|= SEC_LEVEL
;
650 sec
.level
= SEC_LEVEL_3
;
652 /* Don't set sec level for group keys. */
654 sec
.flags
&= ~SEC_LEVEL
;
657 if (ieee
->set_security
)
658 ieee
->set_security(dev
, &sec
);
663 int libipw_wx_get_encodeext(struct libipw_device
*ieee
,
664 struct iw_request_info
*info
,
665 union iwreq_data
*wrqu
, char *extra
)
667 struct iw_point
*encoding
= &wrqu
->encoding
;
668 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
669 struct libipw_security
*sec
= &ieee
->sec
;
670 int idx
, max_key_len
;
672 max_key_len
= encoding
->length
- sizeof(*ext
);
676 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
678 if (idx
< 1 || idx
> WEP_KEYS
)
682 idx
= ieee
->crypt_info
.tx_keyidx
;
684 if (!(ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) &&
685 ext
->alg
!= IW_ENCODE_ALG_WEP
)
686 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
689 encoding
->flags
= idx
+ 1;
690 memset(ext
, 0, sizeof(*ext
));
693 ext
->alg
= IW_ENCODE_ALG_NONE
;
695 encoding
->flags
|= IW_ENCODE_DISABLED
;
697 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
698 ext
->alg
= IW_ENCODE_ALG_WEP
;
699 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
700 ext
->alg
= IW_ENCODE_ALG_TKIP
;
701 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
702 ext
->alg
= IW_ENCODE_ALG_CCMP
;
706 ext
->key_len
= sec
->key_sizes
[idx
];
707 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
708 encoding
->flags
|= IW_ENCODE_ENABLED
;
710 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
711 ext
->alg
== IW_ENCODE_ALG_CCMP
))
712 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
719 EXPORT_SYMBOL(libipw_wx_set_encodeext
);
720 EXPORT_SYMBOL(libipw_wx_get_encodeext
);
722 EXPORT_SYMBOL(libipw_wx_get_scan
);
723 EXPORT_SYMBOL(libipw_wx_set_encode
);
724 EXPORT_SYMBOL(libipw_wx_get_encode
);