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/lib80211.h>
38 #include <linux/wireless.h>
40 #include "ieee80211.h"
42 static const char *ieee80211_modes[] = {
43 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
46 static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
48 unsigned long end = jiffies;
51 return jiffies_to_msecs(end - start);
53 return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
56 #define MAX_CUSTOM_LEN 64
57 static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
58 char *start, char *stop,
59 struct ieee80211_network *network,
60 struct iw_request_info *info)
62 char custom[MAX_CUSTOM_LEN];
66 char *current_val; /* For rates */
69 /* First entry *MUST* be the AP MAC address */
71 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
72 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
73 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
75 /* Remaining entries will be displayed in the order we provide them */
78 iwe.cmd = SIOCGIWESSID;
80 iwe.u.data.length = min(network->ssid_len, (u8) 32);
81 start = iwe_stream_add_point(info, start, stop,
84 /* Add the protocol name */
85 iwe.cmd = SIOCGIWNAME;
86 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
87 ieee80211_modes[network->mode]);
88 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
91 iwe.cmd = SIOCGIWMODE;
92 if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
93 if (network->capability & WLAN_CAPABILITY_ESS)
94 iwe.u.mode = IW_MODE_MASTER;
96 iwe.u.mode = IW_MODE_ADHOC;
98 start = iwe_stream_add_event(info, start, stop,
99 &iwe, IW_EV_UINT_LEN);
102 /* Add channel and frequency */
103 /* Note : userspace automatically computes channel using iwrange */
104 iwe.cmd = SIOCGIWFREQ;
105 iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
108 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
110 /* Add encryption capability */
111 iwe.cmd = SIOCGIWENCODE;
112 if (network->capability & WLAN_CAPABILITY_PRIVACY)
113 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
115 iwe.u.data.flags = IW_ENCODE_DISABLED;
116 iwe.u.data.length = 0;
117 start = iwe_stream_add_point(info, start, stop,
118 &iwe, network->ssid);
120 /* Add basic and extended rates */
121 /* Rate : stuffing multiple values in a single event require a bit
122 * more of magic - Jean II */
123 current_val = start + iwe_stream_lcp_len(info);
124 iwe.cmd = SIOCGIWRATE;
125 /* Those two flags are ignored... */
126 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
128 for (i = 0, j = 0; i < network->rates_len;) {
129 if (j < network->rates_ex_len &&
130 ((network->rates_ex[j] & 0x7F) <
131 (network->rates[i] & 0x7F)))
132 rate = network->rates_ex[j++] & 0x7F;
134 rate = network->rates[i++] & 0x7F;
135 /* Bit rate given in 500 kb/s units (+ 0x80) */
136 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
137 /* Add new value to event */
138 current_val = iwe_stream_add_value(info, start, current_val,
139 stop, &iwe, IW_EV_PARAM_LEN);
141 for (; j < network->rates_ex_len; j++) {
142 rate = network->rates_ex[j] & 0x7F;
143 /* Bit rate given in 500 kb/s units (+ 0x80) */
144 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
145 /* Add new value to event */
146 current_val = iwe_stream_add_value(info, start, current_val,
147 stop, &iwe, IW_EV_PARAM_LEN);
149 /* Check if we added any rate */
150 if ((current_val - start) > iwe_stream_lcp_len(info))
153 /* Add quality statistics */
155 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
156 IW_QUAL_NOISE_UPDATED;
158 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
159 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
160 IW_QUAL_LEVEL_INVALID;
163 if (ieee->perfect_rssi == ieee->worst_rssi)
164 iwe.u.qual.qual = 100;
168 (ieee->perfect_rssi - ieee->worst_rssi) *
169 (ieee->perfect_rssi - ieee->worst_rssi) -
170 (ieee->perfect_rssi - network->stats.rssi) *
171 (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
172 62 * (ieee->perfect_rssi -
173 network->stats.rssi))) /
174 ((ieee->perfect_rssi -
175 ieee->worst_rssi) * (ieee->perfect_rssi -
177 if (iwe.u.qual.qual > 100)
178 iwe.u.qual.qual = 100;
179 else if (iwe.u.qual.qual < 1)
183 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
184 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
185 iwe.u.qual.noise = 0;
187 iwe.u.qual.noise = network->stats.noise;
190 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
191 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
192 iwe.u.qual.level = 0;
194 iwe.u.qual.level = network->stats.signal;
197 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
199 iwe.cmd = IWEVCUSTOM;
202 iwe.u.data.length = p - custom;
203 if (iwe.u.data.length)
204 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
206 memset(&iwe, 0, sizeof(iwe));
207 if (network->wpa_ie_len) {
208 char buf[MAX_WPA_IE_LEN];
209 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
211 iwe.u.data.length = network->wpa_ie_len;
212 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
215 memset(&iwe, 0, sizeof(iwe));
216 if (network->rsn_ie_len) {
217 char buf[MAX_WPA_IE_LEN];
218 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
220 iwe.u.data.length = network->rsn_ie_len;
221 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
224 /* Add EXTRA: Age to display seconds since last beacon/probe response
225 * for given network. */
226 iwe.cmd = IWEVCUSTOM;
228 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
229 " Last beacon: %ums ago",
230 elapsed_jiffies_msecs(network->last_scanned));
231 iwe.u.data.length = p - custom;
232 if (iwe.u.data.length)
233 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
235 /* Add spectrum management information */
238 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
240 if (ieee80211_get_channel_flags(ieee, network->channel) &
241 IEEE80211_CH_INVALID) {
242 iwe.cmd = IWEVCUSTOM;
243 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
246 if (ieee80211_get_channel_flags(ieee, network->channel) &
247 IEEE80211_CH_RADAR_DETECT) {
248 iwe.cmd = IWEVCUSTOM;
249 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
252 if (iwe.cmd == IWEVCUSTOM) {
253 iwe.u.data.length = p - custom;
254 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
260 #define SCAN_ITEM_SIZE 128
262 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
263 struct iw_request_info *info,
264 union iwreq_data *wrqu, char *extra)
266 struct ieee80211_network *network;
271 char *stop = ev + wrqu->data.length;
273 DECLARE_SSID_BUF(ssid);
275 IEEE80211_DEBUG_WX("Getting scan\n");
277 spin_lock_irqsave(&ieee->lock, flags);
279 list_for_each_entry(network, &ieee->network_list, list) {
281 if (stop - ev < SCAN_ITEM_SIZE) {
286 if (ieee->scan_age == 0 ||
287 time_after(network->last_scanned + ieee->scan_age, jiffies))
288 ev = ieee80211_translate_scan(ieee, ev, stop, network,
291 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
292 "%pM)' due to age (%ums).\n",
293 print_ssid(ssid, network->ssid,
296 elapsed_jiffies_msecs(
297 network->last_scanned));
301 spin_unlock_irqrestore(&ieee->lock, flags);
303 wrqu->data.length = ev - extra;
304 wrqu->data.flags = 0;
306 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
311 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
312 struct iw_request_info *info,
313 union iwreq_data *wrqu, char *keybuf)
315 struct iw_point *erq = &(wrqu->encoding);
316 struct net_device *dev = ieee->dev;
317 struct ieee80211_security sec = {
320 int i, key, key_provided, len;
321 struct lib80211_crypt_data **crypt;
322 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
323 DECLARE_SSID_BUF(ssid);
325 IEEE80211_DEBUG_WX("SET_ENCODE\n");
327 key = erq->flags & IW_ENCODE_INDEX;
335 key = ieee->crypt_info.tx_keyidx;
338 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
339 "provided" : "default");
341 crypt = &ieee->crypt_info.crypt[key];
343 if (erq->flags & IW_ENCODE_DISABLED) {
344 if (key_provided && *crypt) {
345 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
347 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
349 IEEE80211_DEBUG_WX("Disabling encryption.\n");
351 /* Check all the keys to see if any are still configured,
352 * and if no key index was provided, de-init them all */
353 for (i = 0; i < WEP_KEYS; i++) {
354 if (ieee->crypt_info.crypt[i] != NULL) {
357 lib80211_crypt_delayed_deinit(&ieee->crypt_info,
358 &ieee->crypt_info.crypt[i]);
365 sec.level = SEC_LEVEL_0;
366 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
374 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
376 if (*crypt != NULL && (*crypt)->ops != NULL &&
377 strcmp((*crypt)->ops->name, "WEP") != 0) {
378 /* changing to use WEP; deinit previously used algorithm
380 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
383 if (*crypt == NULL && host_crypto) {
384 struct lib80211_crypt_data *new_crypt;
386 /* take WEP into use */
387 new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
389 if (new_crypt == NULL)
391 new_crypt->ops = lib80211_get_crypto_ops("WEP");
392 if (!new_crypt->ops) {
393 request_module("lib80211_crypt_wep");
394 new_crypt->ops = lib80211_get_crypto_ops("WEP");
397 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
398 new_crypt->priv = new_crypt->ops->init(key);
400 if (!new_crypt->ops || !new_crypt->priv) {
404 printk(KERN_WARNING "%s: could not initialize WEP: "
405 "load module lib80211_crypt_wep\n", dev->name);
411 /* If a new key was provided, set it up */
412 if (erq->length > 0) {
413 #ifdef CONFIG_IEEE80211_DEBUG
414 DECLARE_SSID_BUF(ssid);
417 len = erq->length <= 5 ? 5 : 13;
418 memcpy(sec.keys[key], keybuf, erq->length);
419 if (len > erq->length)
420 memset(sec.keys[key] + erq->length, 0,
422 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
423 key, print_ssid(ssid, sec.keys[key], len),
425 sec.key_sizes[key] = len;
427 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
429 sec.flags |= (1 << key);
430 /* This ensures a key will be activated if no key is
432 if (key == sec.active_key)
433 sec.flags |= SEC_ACTIVE_KEY;
437 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
438 NULL, (*crypt)->priv);
440 /* Set a default key of all 0 */
441 IEEE80211_DEBUG_WX("Setting key %d to all "
443 memset(sec.keys[key], 0, 13);
444 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
446 sec.key_sizes[key] = 13;
447 sec.flags |= (1 << key);
450 /* No key data - just set the default TX key index */
452 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
454 ieee->crypt_info.tx_keyidx = key;
455 sec.active_key = key;
456 sec.flags |= SEC_ACTIVE_KEY;
459 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
460 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
461 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
462 WLAN_AUTH_SHARED_KEY;
463 sec.flags |= SEC_AUTH_MODE;
464 IEEE80211_DEBUG_WX("Auth: %s\n",
465 sec.auth_mode == WLAN_AUTH_OPEN ?
466 "OPEN" : "SHARED KEY");
469 /* For now we just support WEP, so only set that security level...
470 * TODO: When WPA is added this is one place that needs to change */
471 sec.flags |= SEC_LEVEL;
472 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
473 sec.encode_alg[key] = SEC_ALG_WEP;
476 if (ieee->set_security)
477 ieee->set_security(dev, &sec);
479 /* Do not reset port if card is in Managed mode since resetting will
480 * generate new IEEE 802.11 authentication which may end up in looping
481 * with IEEE 802.1X. If your hardware requires a reset after WEP
482 * configuration (for example... Prism2), implement the reset_port in
483 * the callbacks structures used to initialize the 802.11 stack. */
484 if (ieee->reset_on_keychange &&
485 ieee->iw_mode != IW_MODE_INFRA &&
486 ieee->reset_port && ieee->reset_port(dev)) {
487 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
493 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
494 struct iw_request_info *info,
495 union iwreq_data *wrqu, char *keybuf)
497 struct iw_point *erq = &(wrqu->encoding);
499 struct lib80211_crypt_data *crypt;
500 struct ieee80211_security *sec = &ieee->sec;
502 IEEE80211_DEBUG_WX("GET_ENCODE\n");
504 key = erq->flags & IW_ENCODE_INDEX;
510 key = ieee->crypt_info.tx_keyidx;
512 crypt = ieee->crypt_info.crypt[key];
513 erq->flags = key + 1;
517 erq->flags |= IW_ENCODE_DISABLED;
521 len = sec->key_sizes[key];
522 memcpy(keybuf, sec->keys[key], len);
525 erq->flags |= IW_ENCODE_ENABLED;
528 erq->flags |= IW_ENCODE_OPEN;
530 erq->flags |= IW_ENCODE_RESTRICTED;
535 int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
536 struct iw_request_info *info,
537 union iwreq_data *wrqu, char *extra)
539 struct net_device *dev = ieee->dev;
540 struct iw_point *encoding = &wrqu->encoding;
541 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
544 const char *alg, *module;
545 struct lib80211_crypto_ops *ops;
546 struct lib80211_crypt_data **crypt;
548 struct ieee80211_security sec = {
552 idx = encoding->flags & IW_ENCODE_INDEX;
554 if (idx < 1 || idx > WEP_KEYS)
558 idx = ieee->crypt_info.tx_keyidx;
560 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
561 crypt = &ieee->crypt_info.crypt[idx];
564 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
565 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
567 if (ieee->iw_mode == IW_MODE_INFRA)
568 crypt = &ieee->crypt_info.crypt[idx];
573 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
574 if ((encoding->flags & IW_ENCODE_DISABLED) ||
575 ext->alg == IW_ENCODE_ALG_NONE) {
577 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
579 for (i = 0; i < WEP_KEYS; i++)
580 if (ieee->crypt_info.crypt[i] != NULL)
586 sec.level = SEC_LEVEL_0;
587 sec.flags |= SEC_LEVEL;
595 if (group_key ? !ieee->host_mc_decrypt :
596 !(ieee->host_encrypt || ieee->host_decrypt ||
597 ieee->host_encrypt_msdu))
598 goto skip_host_crypt;
601 case IW_ENCODE_ALG_WEP:
603 module = "lib80211_crypt_wep";
605 case IW_ENCODE_ALG_TKIP:
607 module = "lib80211_crypt_tkip";
609 case IW_ENCODE_ALG_CCMP:
611 module = "lib80211_crypt_ccmp";
614 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
615 dev->name, ext->alg);
620 ops = lib80211_get_crypto_ops(alg);
622 request_module(module);
623 ops = lib80211_get_crypto_ops(alg);
626 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
627 dev->name, ext->alg);
632 if (*crypt == NULL || (*crypt)->ops != ops) {
633 struct lib80211_crypt_data *new_crypt;
635 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
637 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
638 if (new_crypt == NULL) {
642 new_crypt->ops = ops;
643 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
644 new_crypt->priv = new_crypt->ops->init(idx);
645 if (new_crypt->priv == NULL) {
653 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
654 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
655 (*crypt)->priv) < 0) {
656 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
662 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
663 ieee->crypt_info.tx_keyidx = idx;
664 sec.active_key = idx;
665 sec.flags |= SEC_ACTIVE_KEY;
668 if (ext->alg != IW_ENCODE_ALG_NONE) {
669 memcpy(sec.keys[idx], ext->key, ext->key_len);
670 sec.key_sizes[idx] = ext->key_len;
671 sec.flags |= (1 << idx);
672 if (ext->alg == IW_ENCODE_ALG_WEP) {
673 sec.encode_alg[idx] = SEC_ALG_WEP;
674 sec.flags |= SEC_LEVEL;
675 sec.level = SEC_LEVEL_1;
676 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
677 sec.encode_alg[idx] = SEC_ALG_TKIP;
678 sec.flags |= SEC_LEVEL;
679 sec.level = SEC_LEVEL_2;
680 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
681 sec.encode_alg[idx] = SEC_ALG_CCMP;
682 sec.flags |= SEC_LEVEL;
683 sec.level = SEC_LEVEL_3;
685 /* Don't set sec level for group keys. */
687 sec.flags &= ~SEC_LEVEL;
690 if (ieee->set_security)
691 ieee->set_security(ieee->dev, &sec);
694 * Do not reset port if card is in Managed mode since resetting will
695 * generate new IEEE 802.11 authentication which may end up in looping
696 * with IEEE 802.1X. If your hardware requires a reset after WEP
697 * configuration (for example... Prism2), implement the reset_port in
698 * the callbacks structures used to initialize the 802.11 stack.
700 if (ieee->reset_on_keychange &&
701 ieee->iw_mode != IW_MODE_INFRA &&
702 ieee->reset_port && ieee->reset_port(dev)) {
703 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
710 int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
711 struct iw_request_info *info,
712 union iwreq_data *wrqu, char *extra)
714 struct iw_point *encoding = &wrqu->encoding;
715 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
716 struct ieee80211_security *sec = &ieee->sec;
717 int idx, max_key_len;
719 max_key_len = encoding->length - sizeof(*ext);
723 idx = encoding->flags & IW_ENCODE_INDEX;
725 if (idx < 1 || idx > WEP_KEYS)
729 idx = ieee->crypt_info.tx_keyidx;
731 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
732 ext->alg != IW_ENCODE_ALG_WEP)
733 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
736 encoding->flags = idx + 1;
737 memset(ext, 0, sizeof(*ext));
740 ext->alg = IW_ENCODE_ALG_NONE;
742 encoding->flags |= IW_ENCODE_DISABLED;
744 if (sec->encode_alg[idx] == SEC_ALG_WEP)
745 ext->alg = IW_ENCODE_ALG_WEP;
746 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
747 ext->alg = IW_ENCODE_ALG_TKIP;
748 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
749 ext->alg = IW_ENCODE_ALG_CCMP;
753 ext->key_len = sec->key_sizes[idx];
754 memcpy(ext->key, sec->keys[idx], ext->key_len);
755 encoding->flags |= IW_ENCODE_ENABLED;
757 (ext->alg == IW_ENCODE_ALG_TKIP ||
758 ext->alg == IW_ENCODE_ALG_CCMP))
759 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
766 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
767 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
769 EXPORT_SYMBOL(ieee80211_wx_get_scan);
770 EXPORT_SYMBOL(ieee80211_wx_set_encode);
771 EXPORT_SYMBOL(ieee80211_wx_get_encode);