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>
24 #include <linux/wireless.h>
27 static const char *libipw_modes
[] = {
28 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
31 static inline unsigned int elapsed_jiffies_msecs(unsigned long start
)
33 unsigned long end
= jiffies
;
36 return jiffies_to_msecs(end
- start
);
38 return jiffies_to_msecs(end
+ (MAX_JIFFY_OFFSET
- start
) + 1);
41 #define MAX_CUSTOM_LEN 64
42 static char *libipw_translate_scan(struct libipw_device
*ieee
,
43 char *start
, char *stop
,
44 struct libipw_network
*network
,
45 struct iw_request_info
*info
)
47 char custom
[MAX_CUSTOM_LEN
];
51 char *current_val
; /* For rates */
54 /* First entry *MUST* be the AP MAC address */
56 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
57 memcpy(iwe
.u
.ap_addr
.sa_data
, network
->bssid
, ETH_ALEN
);
58 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_ADDR_LEN
);
60 /* Remaining entries will be displayed in the order we provide them */
63 iwe
.cmd
= SIOCGIWESSID
;
65 iwe
.u
.data
.length
= min(network
->ssid_len
, (u8
) 32);
66 start
= iwe_stream_add_point(info
, start
, stop
,
69 /* Add the protocol name */
70 iwe
.cmd
= SIOCGIWNAME
;
71 snprintf(iwe
.u
.name
, IFNAMSIZ
, "IEEE 802.11%s",
72 libipw_modes
[network
->mode
]);
73 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_CHAR_LEN
);
76 iwe
.cmd
= SIOCGIWMODE
;
77 if (network
->capability
& (WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_IBSS
)) {
78 if (network
->capability
& WLAN_CAPABILITY_ESS
)
79 iwe
.u
.mode
= IW_MODE_MASTER
;
81 iwe
.u
.mode
= IW_MODE_ADHOC
;
83 start
= iwe_stream_add_event(info
, start
, stop
,
84 &iwe
, IW_EV_UINT_LEN
);
87 /* Add channel and frequency */
88 /* Note : userspace automatically computes channel using iwrange */
89 iwe
.cmd
= SIOCGIWFREQ
;
90 iwe
.u
.freq
.m
= libipw_channel_to_freq(ieee
, network
->channel
);
93 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_FREQ_LEN
);
95 /* Add encryption capability */
96 iwe
.cmd
= SIOCGIWENCODE
;
97 if (network
->capability
& WLAN_CAPABILITY_PRIVACY
)
98 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
100 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
101 iwe
.u
.data
.length
= 0;
102 start
= iwe_stream_add_point(info
, start
, stop
,
103 &iwe
, network
->ssid
);
105 /* Add basic and extended rates */
106 /* Rate : stuffing multiple values in a single event require a bit
107 * more of magic - Jean II */
108 current_val
= start
+ iwe_stream_lcp_len(info
);
109 iwe
.cmd
= SIOCGIWRATE
;
110 /* Those two flags are ignored... */
111 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
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;
120 /* Bit rate given in 500 kb/s units (+ 0x80) */
121 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
122 /* Add new value to event */
123 current_val
= iwe_stream_add_value(info
, start
, current_val
,
124 stop
, &iwe
, IW_EV_PARAM_LEN
);
126 for (; j
< network
->rates_ex_len
; j
++) {
127 rate
= network
->rates_ex
[j
] & 0x7F;
128 /* Bit rate given in 500 kb/s units (+ 0x80) */
129 iwe
.u
.bitrate
.value
= ((rate
& 0x7f) * 500000);
130 /* Add new value to event */
131 current_val
= iwe_stream_add_value(info
, start
, current_val
,
132 stop
, &iwe
, IW_EV_PARAM_LEN
);
134 /* Check if we added any rate */
135 if ((current_val
- start
) > iwe_stream_lcp_len(info
))
138 /* Add quality statistics */
140 iwe
.u
.qual
.updated
= IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
|
141 IW_QUAL_NOISE_UPDATED
;
143 if (!(network
->stats
.mask
& LIBIPW_STATMASK_RSSI
)) {
144 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
|
145 IW_QUAL_LEVEL_INVALID
;
148 if (ieee
->perfect_rssi
== ieee
->worst_rssi
)
149 iwe
.u
.qual
.qual
= 100;
153 (ieee
->perfect_rssi
- ieee
->worst_rssi
) *
154 (ieee
->perfect_rssi
- ieee
->worst_rssi
) -
155 (ieee
->perfect_rssi
- network
->stats
.rssi
) *
156 (15 * (ieee
->perfect_rssi
- ieee
->worst_rssi
) +
157 62 * (ieee
->perfect_rssi
-
158 network
->stats
.rssi
))) /
159 ((ieee
->perfect_rssi
-
160 ieee
->worst_rssi
) * (ieee
->perfect_rssi
-
162 if (iwe
.u
.qual
.qual
> 100)
163 iwe
.u
.qual
.qual
= 100;
164 else if (iwe
.u
.qual
.qual
< 1)
168 if (!(network
->stats
.mask
& LIBIPW_STATMASK_NOISE
)) {
169 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
170 iwe
.u
.qual
.noise
= 0;
172 iwe
.u
.qual
.noise
= network
->stats
.noise
;
175 if (!(network
->stats
.mask
& LIBIPW_STATMASK_SIGNAL
)) {
176 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
177 iwe
.u
.qual
.level
= 0;
179 iwe
.u
.qual
.level
= network
->stats
.signal
;
182 start
= iwe_stream_add_event(info
, start
, stop
, &iwe
, IW_EV_QUAL_LEN
);
184 iwe
.cmd
= IWEVCUSTOM
;
187 iwe
.u
.data
.length
= p
- custom
;
188 if (iwe
.u
.data
.length
)
189 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
191 memset(&iwe
, 0, sizeof(iwe
));
192 if (network
->wpa_ie_len
) {
193 char buf
[MAX_WPA_IE_LEN
];
194 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
196 iwe
.u
.data
.length
= network
->wpa_ie_len
;
197 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
200 memset(&iwe
, 0, sizeof(iwe
));
201 if (network
->rsn_ie_len
) {
202 char buf
[MAX_WPA_IE_LEN
];
203 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
205 iwe
.u
.data
.length
= network
->rsn_ie_len
;
206 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, buf
);
209 /* Add EXTRA: Age to display seconds since last beacon/probe response
210 * for given network. */
211 iwe
.cmd
= IWEVCUSTOM
;
213 p
+= scnprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
214 " Last beacon: %ums ago",
215 elapsed_jiffies_msecs(network
->last_scanned
));
216 iwe
.u
.data
.length
= p
- custom
;
217 if (iwe
.u
.data
.length
)
218 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
220 /* Add spectrum management information */
223 p
+= scnprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Channel flags: ");
225 if (libipw_get_channel_flags(ieee
, network
->channel
) &
227 iwe
.cmd
= IWEVCUSTOM
;
228 p
+= scnprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "INVALID ");
231 if (libipw_get_channel_flags(ieee
, network
->channel
) &
232 LIBIPW_CH_RADAR_DETECT
) {
233 iwe
.cmd
= IWEVCUSTOM
;
234 p
+= scnprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), "DFS ");
237 if (iwe
.cmd
== IWEVCUSTOM
) {
238 iwe
.u
.data
.length
= p
- custom
;
239 start
= iwe_stream_add_point(info
, start
, stop
, &iwe
, custom
);
245 #define SCAN_ITEM_SIZE 128
247 int libipw_wx_get_scan(struct libipw_device
*ieee
,
248 struct iw_request_info
*info
,
249 union iwreq_data
*wrqu
, char *extra
)
251 struct libipw_network
*network
;
256 char *stop
= ev
+ wrqu
->data
.length
;
259 LIBIPW_DEBUG_WX("Getting scan\n");
261 spin_lock_irqsave(&ieee
->lock
, flags
);
263 list_for_each_entry(network
, &ieee
->network_list
, list
) {
265 if (stop
- ev
< SCAN_ITEM_SIZE
) {
270 if (ieee
->scan_age
== 0 ||
271 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
272 ev
= libipw_translate_scan(ieee
, ev
, stop
, network
,
275 LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
276 network
->ssid_len
, network
->ssid
,
278 elapsed_jiffies_msecs(
279 network
->last_scanned
));
283 spin_unlock_irqrestore(&ieee
->lock
, flags
);
285 wrqu
->data
.length
= ev
- extra
;
286 wrqu
->data
.flags
= 0;
288 LIBIPW_DEBUG_WX("exit: %d networks returned.\n", i
);
293 int libipw_wx_set_encode(struct libipw_device
*ieee
,
294 struct iw_request_info
*info
,
295 union iwreq_data
*wrqu
, char *keybuf
)
297 struct iw_point
*erq
= &(wrqu
->encoding
);
298 struct net_device
*dev
= ieee
->dev
;
299 struct libipw_security sec
= {
302 int i
, key
, key_provided
, len
;
303 struct libipw_crypt_data
**crypt
;
304 int host_crypto
= ieee
->host_encrypt
|| ieee
->host_decrypt
;
306 LIBIPW_DEBUG_WX("SET_ENCODE\n");
308 key
= erq
->flags
& IW_ENCODE_INDEX
;
316 key
= ieee
->crypt_info
.tx_keyidx
;
319 LIBIPW_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
320 "provided" : "default");
322 crypt
= &ieee
->crypt_info
.crypt
[key
];
324 if (erq
->flags
& IW_ENCODE_DISABLED
) {
325 if (key_provided
&& *crypt
) {
326 LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n",
328 libipw_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
330 LIBIPW_DEBUG_WX("Disabling encryption.\n");
332 /* Check all the keys to see if any are still configured,
333 * and if no key index was provided, de-init them all */
334 for (i
= 0; i
< WEP_KEYS
; i
++) {
335 if (ieee
->crypt_info
.crypt
[i
] != NULL
) {
338 libipw_crypt_delayed_deinit(&ieee
->crypt_info
,
339 &ieee
->crypt_info
.crypt
[i
]);
346 sec
.level
= SEC_LEVEL_0
;
347 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
| SEC_ENCRYPT
;
355 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
357 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
358 strcmp((*crypt
)->ops
->name
, "WEP") != 0) {
359 /* changing to use WEP; deinit previously used algorithm
361 libipw_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
364 if (*crypt
== NULL
&& host_crypto
) {
365 struct libipw_crypt_data
*new_crypt
;
367 /* take WEP into use */
368 new_crypt
= kzalloc(sizeof(struct libipw_crypt_data
),
370 if (new_crypt
== NULL
)
372 new_crypt
->ops
= libipw_get_crypto_ops("WEP");
373 if (!new_crypt
->ops
) {
374 request_module("libipw_crypt_wep");
375 new_crypt
->ops
= libipw_get_crypto_ops("WEP");
378 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
379 new_crypt
->priv
= new_crypt
->ops
->init(key
);
381 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
385 printk(KERN_WARNING
"%s: could not initialize WEP: "
386 "load module libipw_crypt_wep\n", dev
->name
);
392 /* If a new key was provided, set it up */
393 if (erq
->length
> 0) {
394 len
= erq
->length
<= 5 ? 5 : 13;
395 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
396 if (len
> erq
->length
)
397 memset(sec
.keys
[key
] + erq
->length
, 0,
399 LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
400 key
, len
, sec
.keys
[key
],
402 sec
.key_sizes
[key
] = len
;
404 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
406 sec
.flags
|= (1 << key
);
407 /* This ensures a key will be activated if no key is
409 if (key
== sec
.active_key
)
410 sec
.flags
|= SEC_ACTIVE_KEY
;
414 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
415 NULL
, (*crypt
)->priv
);
417 /* Set a default key of all 0 */
418 LIBIPW_DEBUG_WX("Setting key %d to all "
420 memset(sec
.keys
[key
], 0, 13);
421 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
423 sec
.key_sizes
[key
] = 13;
424 sec
.flags
|= (1 << key
);
427 /* No key data - just set the default TX key index */
429 LIBIPW_DEBUG_WX("Setting key %d to default Tx "
431 ieee
->crypt_info
.tx_keyidx
= key
;
432 sec
.active_key
= key
;
433 sec
.flags
|= SEC_ACTIVE_KEY
;
436 if (erq
->flags
& (IW_ENCODE_OPEN
| IW_ENCODE_RESTRICTED
)) {
437 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
438 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
439 WLAN_AUTH_SHARED_KEY
;
440 sec
.flags
|= SEC_AUTH_MODE
;
441 LIBIPW_DEBUG_WX("Auth: %s\n",
442 sec
.auth_mode
== WLAN_AUTH_OPEN
?
443 "OPEN" : "SHARED KEY");
446 /* For now we just support WEP, so only set that security level...
447 * TODO: When WPA is added this is one place that needs to change */
448 sec
.flags
|= SEC_LEVEL
;
449 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
450 sec
.encode_alg
[key
] = SEC_ALG_WEP
;
453 if (ieee
->set_security
)
454 ieee
->set_security(dev
, &sec
);
459 int libipw_wx_get_encode(struct libipw_device
*ieee
,
460 struct iw_request_info
*info
,
461 union iwreq_data
*wrqu
, char *keybuf
)
463 struct iw_point
*erq
= &(wrqu
->encoding
);
465 struct libipw_security
*sec
= &ieee
->sec
;
467 LIBIPW_DEBUG_WX("GET_ENCODE\n");
469 key
= erq
->flags
& IW_ENCODE_INDEX
;
475 key
= ieee
->crypt_info
.tx_keyidx
;
477 erq
->flags
= key
+ 1;
481 erq
->flags
|= IW_ENCODE_DISABLED
;
485 len
= sec
->key_sizes
[key
];
486 memcpy(keybuf
, sec
->keys
[key
], len
);
489 erq
->flags
|= IW_ENCODE_ENABLED
;
492 erq
->flags
|= IW_ENCODE_OPEN
;
494 erq
->flags
|= IW_ENCODE_RESTRICTED
;
499 int libipw_wx_set_encodeext(struct libipw_device
*ieee
,
500 struct iw_request_info
*info
,
501 union iwreq_data
*wrqu
, char *extra
)
503 struct net_device
*dev
= ieee
->dev
;
504 struct iw_point
*encoding
= &wrqu
->encoding
;
505 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
508 const char *alg
, *module
;
509 const struct libipw_crypto_ops
*ops
;
510 struct libipw_crypt_data
**crypt
;
512 struct libipw_security sec
= {
516 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
518 if (idx
< 1 || idx
> WEP_KEYS
)
522 idx
= ieee
->crypt_info
.tx_keyidx
;
524 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
525 crypt
= &ieee
->crypt_info
.crypt
[idx
];
528 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
529 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
531 if (ieee
->iw_mode
== IW_MODE_INFRA
)
532 crypt
= &ieee
->crypt_info
.crypt
[idx
];
537 sec
.flags
|= SEC_ENABLED
| SEC_ENCRYPT
;
538 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
539 ext
->alg
== IW_ENCODE_ALG_NONE
) {
541 libipw_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
543 for (i
= 0; i
< WEP_KEYS
; i
++)
544 if (ieee
->crypt_info
.crypt
[i
] != NULL
)
550 sec
.level
= SEC_LEVEL_0
;
551 sec
.flags
|= SEC_LEVEL
;
559 if (group_key
? !ieee
->host_mc_decrypt
:
560 !(ieee
->host_encrypt
|| ieee
->host_decrypt
||
561 ieee
->host_encrypt_msdu
))
562 goto skip_host_crypt
;
565 case IW_ENCODE_ALG_WEP
:
567 module
= "libipw_crypt_wep";
569 case IW_ENCODE_ALG_TKIP
:
571 module
= "libipw_crypt_tkip";
573 case IW_ENCODE_ALG_CCMP
:
575 module
= "libipw_crypt_ccmp";
578 LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
579 dev
->name
, ext
->alg
);
584 ops
= libipw_get_crypto_ops(alg
);
586 request_module(module
);
587 ops
= libipw_get_crypto_ops(alg
);
590 LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
591 dev
->name
, ext
->alg
);
596 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
597 struct libipw_crypt_data
*new_crypt
;
599 libipw_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
601 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
602 if (new_crypt
== NULL
) {
606 new_crypt
->ops
= ops
;
607 if (new_crypt
->ops
&& try_module_get(new_crypt
->ops
->owner
))
608 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
609 if (new_crypt
->priv
== NULL
) {
617 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
618 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
619 (*crypt
)->priv
) < 0) {
620 LIBIPW_DEBUG_WX("%s: key setting failed\n", dev
->name
);
626 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
627 ieee
->crypt_info
.tx_keyidx
= idx
;
628 sec
.active_key
= idx
;
629 sec
.flags
|= SEC_ACTIVE_KEY
;
632 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
633 int key_len
= clamp_val(ext
->key_len
, 0, SCM_KEY_LEN
);
635 memcpy(sec
.keys
[idx
], ext
->key
, key_len
);
636 sec
.key_sizes
[idx
] = key_len
;
637 sec
.flags
|= (1 << idx
);
638 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
639 sec
.encode_alg
[idx
] = SEC_ALG_WEP
;
640 sec
.flags
|= SEC_LEVEL
;
641 sec
.level
= SEC_LEVEL_1
;
642 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
643 sec
.encode_alg
[idx
] = SEC_ALG_TKIP
;
644 sec
.flags
|= SEC_LEVEL
;
645 sec
.level
= SEC_LEVEL_2
;
646 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
647 sec
.encode_alg
[idx
] = SEC_ALG_CCMP
;
648 sec
.flags
|= SEC_LEVEL
;
649 sec
.level
= SEC_LEVEL_3
;
651 /* Don't set sec level for group keys. */
653 sec
.flags
&= ~SEC_LEVEL
;
656 if (ieee
->set_security
)
657 ieee
->set_security(dev
, &sec
);
662 int libipw_wx_get_encodeext(struct libipw_device
*ieee
,
663 struct iw_request_info
*info
,
664 union iwreq_data
*wrqu
, char *extra
)
666 struct iw_point
*encoding
= &wrqu
->encoding
;
667 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
668 struct libipw_security
*sec
= &ieee
->sec
;
669 int idx
, max_key_len
;
671 max_key_len
= encoding
->length
- sizeof(*ext
);
675 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
677 if (idx
< 1 || idx
> WEP_KEYS
)
681 idx
= ieee
->crypt_info
.tx_keyidx
;
683 if (!(ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) &&
684 ext
->alg
!= IW_ENCODE_ALG_WEP
)
685 if (idx
!= 0 || ieee
->iw_mode
!= IW_MODE_INFRA
)
688 encoding
->flags
= idx
+ 1;
689 memset(ext
, 0, sizeof(*ext
));
692 ext
->alg
= IW_ENCODE_ALG_NONE
;
694 encoding
->flags
|= IW_ENCODE_DISABLED
;
696 if (sec
->encode_alg
[idx
] == SEC_ALG_WEP
)
697 ext
->alg
= IW_ENCODE_ALG_WEP
;
698 else if (sec
->encode_alg
[idx
] == SEC_ALG_TKIP
)
699 ext
->alg
= IW_ENCODE_ALG_TKIP
;
700 else if (sec
->encode_alg
[idx
] == SEC_ALG_CCMP
)
701 ext
->alg
= IW_ENCODE_ALG_CCMP
;
705 ext
->key_len
= sec
->key_sizes
[idx
];
706 memcpy(ext
->key
, sec
->keys
[idx
], ext
->key_len
);
707 encoding
->flags
|= IW_ENCODE_ENABLED
;
709 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
710 ext
->alg
== IW_ENCODE_ALG_CCMP
))
711 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
718 EXPORT_SYMBOL(libipw_wx_set_encodeext
);
719 EXPORT_SYMBOL(libipw_wx_get_encodeext
);
721 EXPORT_SYMBOL(libipw_wx_get_scan
);
722 EXPORT_SYMBOL(libipw_wx_set_encode
);
723 EXPORT_SYMBOL(libipw_wx_get_encode
);