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 if (network->wpa_ie_len) {
197 char buf[MAX_WPA_IE_LEN * 2 + 30];
200 p += sprintf(p, "wpa_ie=");
201 for (i = 0; i < network->wpa_ie_len; i++) {
202 p += sprintf(p, "%02x", network->wpa_ie[i]);
205 memset(&iwe, 0, sizeof(iwe));
206 iwe.cmd = IWEVCUSTOM;
207 iwe.u.data.length = strlen(buf);
208 start = iwe_stream_add_point(start, stop, &iwe, buf);
211 if (network->rsn_ie_len) {
212 char buf[MAX_WPA_IE_LEN * 2 + 30];
215 p += sprintf(p, "rsn_ie=");
216 for (i = 0; i < network->rsn_ie_len; i++) {
217 p += sprintf(p, "%02x", network->rsn_ie[i]);
220 memset(&iwe, 0, sizeof(iwe));
221 iwe.cmd = IWEVCUSTOM;
222 iwe.u.data.length = strlen(buf);
223 start = iwe_stream_add_point(start, stop, &iwe, buf);
226 /* Add EXTRA: Age to display seconds since last beacon/probe response
227 * for given network. */
228 iwe.cmd = IWEVCUSTOM;
230 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
231 " Last beacon: %dms ago",
232 jiffies_to_msecs(jiffies - network->last_scanned));
233 iwe.u.data.length = p - custom;
234 if (iwe.u.data.length)
235 start = iwe_stream_add_point(start, stop, &iwe, custom);
237 /* Add spectrum management information */
240 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
242 if (ieee80211_get_channel_flags(ieee, network->channel) &
243 IEEE80211_CH_INVALID) {
244 iwe.cmd = IWEVCUSTOM;
245 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
248 if (ieee80211_get_channel_flags(ieee, network->channel) &
249 IEEE80211_CH_RADAR_DETECT) {
250 iwe.cmd = IWEVCUSTOM;
251 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
254 if (iwe.cmd == IWEVCUSTOM) {
255 iwe.u.data.length = p - custom;
256 start = iwe_stream_add_point(start, stop, &iwe, custom);
262 #define SCAN_ITEM_SIZE 128
264 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
265 struct iw_request_info *info,
266 union iwreq_data *wrqu, char *extra)
268 struct ieee80211_network *network;
273 char *stop = ev + wrqu->data.length;
276 IEEE80211_DEBUG_WX("Getting scan\n");
278 spin_lock_irqsave(&ieee->lock, flags);
280 list_for_each_entry(network, &ieee->network_list, list) {
282 if (stop - ev < SCAN_ITEM_SIZE) {
287 if (ieee->scan_age == 0 ||
288 time_after(network->last_scanned + ieee->scan_age, jiffies))
289 ev = ipw2100_translate_scan(ieee, ev, stop, network);
291 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
292 MAC_FMT ")' due to age (%dms).\n",
293 escape_essid(network->ssid,
295 MAC_ARG(network->bssid),
296 jiffies_to_msecs(jiffies -
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 ieee80211_crypt_data **crypt;
322 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
324 IEEE80211_DEBUG_WX("SET_ENCODE\n");
326 key = erq->flags & IW_ENCODE_INDEX;
334 key = ieee->tx_keyidx;
337 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
338 "provided" : "default");
340 crypt = &ieee->crypt[key];
342 if (erq->flags & IW_ENCODE_DISABLED) {
343 if (key_provided && *crypt) {
344 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
346 ieee80211_crypt_delayed_deinit(ieee, crypt);
348 IEEE80211_DEBUG_WX("Disabling encryption.\n");
350 /* Check all the keys to see if any are still configured,
351 * and if no key index was provided, de-init them all */
352 for (i = 0; i < WEP_KEYS; i++) {
353 if (ieee->crypt[i] != NULL) {
356 ieee80211_crypt_delayed_deinit(ieee,
364 sec.level = SEC_LEVEL_0;
365 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
373 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
375 if (*crypt != NULL && (*crypt)->ops != NULL &&
376 strcmp((*crypt)->ops->name, "WEP") != 0) {
377 /* changing to use WEP; deinit previously used algorithm
379 ieee80211_crypt_delayed_deinit(ieee, crypt);
382 if (*crypt == NULL && host_crypto) {
383 struct ieee80211_crypt_data *new_crypt;
385 /* take WEP into use */
386 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
388 if (new_crypt == NULL)
390 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
391 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
392 if (!new_crypt->ops) {
393 request_module("ieee80211_crypt_wep");
394 new_crypt->ops = ieee80211_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 ieee80211_crypt_wep\n", dev->name);
411 /* If a new key was provided, set it up */
412 if (erq->length > 0) {
413 len = erq->length <= 5 ? 5 : 13;
414 memcpy(sec.keys[key], keybuf, erq->length);
415 if (len > erq->length)
416 memset(sec.keys[key] + erq->length, 0,
418 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
419 key, escape_essid(sec.keys[key], len),
421 sec.key_sizes[key] = len;
423 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
425 sec.flags |= (1 << key);
426 /* This ensures a key will be activated if no key is
428 if (key == sec.active_key)
429 sec.flags |= SEC_ACTIVE_KEY;
433 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
434 NULL, (*crypt)->priv);
436 /* Set a default key of all 0 */
437 IEEE80211_DEBUG_WX("Setting key %d to all "
439 memset(sec.keys[key], 0, 13);
440 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
442 sec.key_sizes[key] = 13;
443 sec.flags |= (1 << key);
446 /* No key data - just set the default TX key index */
448 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
450 ieee->tx_keyidx = key;
451 sec.active_key = key;
452 sec.flags |= SEC_ACTIVE_KEY;
455 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
456 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
457 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
458 WLAN_AUTH_SHARED_KEY;
459 sec.flags |= SEC_AUTH_MODE;
460 IEEE80211_DEBUG_WX("Auth: %s\n",
461 sec.auth_mode == WLAN_AUTH_OPEN ?
462 "OPEN" : "SHARED KEY");
465 /* For now we just support WEP, so only set that security level...
466 * TODO: When WPA is added this is one place that needs to change */
467 sec.flags |= SEC_LEVEL;
468 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
469 sec.encode_alg[key] = SEC_ALG_WEP;
472 if (ieee->set_security)
473 ieee->set_security(dev, &sec);
475 /* Do not reset port if card is in Managed mode since resetting will
476 * generate new IEEE 802.11 authentication which may end up in looping
477 * with IEEE 802.1X. If your hardware requires a reset after WEP
478 * configuration (for example... Prism2), implement the reset_port in
479 * the callbacks structures used to initialize the 802.11 stack. */
480 if (ieee->reset_on_keychange &&
481 ieee->iw_mode != IW_MODE_INFRA &&
482 ieee->reset_port && ieee->reset_port(dev)) {
483 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
489 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
490 struct iw_request_info *info,
491 union iwreq_data *wrqu, char *keybuf)
493 struct iw_point *erq = &(wrqu->encoding);
495 struct ieee80211_crypt_data *crypt;
496 struct ieee80211_security *sec = &ieee->sec;
498 IEEE80211_DEBUG_WX("GET_ENCODE\n");
500 key = erq->flags & IW_ENCODE_INDEX;
506 key = ieee->tx_keyidx;
508 crypt = ieee->crypt[key];
509 erq->flags = key + 1;
513 erq->flags |= IW_ENCODE_DISABLED;
517 len = sec->key_sizes[key];
518 memcpy(keybuf, sec->keys[key], len);
520 erq->length = (len >= 0 ? len : 0);
521 erq->flags |= IW_ENCODE_ENABLED;
524 erq->flags |= IW_ENCODE_OPEN;
526 erq->flags |= IW_ENCODE_RESTRICTED;
531 int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
532 struct iw_request_info *info,
533 union iwreq_data *wrqu, char *extra)
535 struct net_device *dev = ieee->dev;
536 struct iw_point *encoding = &wrqu->encoding;
537 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
540 const char *alg, *module;
541 struct ieee80211_crypto_ops *ops;
542 struct ieee80211_crypt_data **crypt;
544 struct ieee80211_security sec = {
548 idx = encoding->flags & IW_ENCODE_INDEX;
550 if (idx < 1 || idx > WEP_KEYS)
554 idx = ieee->tx_keyidx;
556 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
557 crypt = &ieee->crypt[idx];
560 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
561 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
563 if (ieee->iw_mode == IW_MODE_INFRA)
564 crypt = &ieee->crypt[idx];
569 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
570 if ((encoding->flags & IW_ENCODE_DISABLED) ||
571 ext->alg == IW_ENCODE_ALG_NONE) {
573 ieee80211_crypt_delayed_deinit(ieee, crypt);
575 for (i = 0; i < WEP_KEYS; i++)
576 if (ieee->crypt[i] != NULL)
582 sec.level = SEC_LEVEL_0;
583 sec.flags |= SEC_LEVEL;
591 if (group_key ? !ieee->host_mc_decrypt :
592 !(ieee->host_encrypt || ieee->host_decrypt ||
593 ieee->host_encrypt_msdu))
594 goto skip_host_crypt;
597 case IW_ENCODE_ALG_WEP:
599 module = "ieee80211_crypt_wep";
601 case IW_ENCODE_ALG_TKIP:
603 module = "ieee80211_crypt_tkip";
605 case IW_ENCODE_ALG_CCMP:
607 module = "ieee80211_crypt_ccmp";
610 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
611 dev->name, ext->alg);
616 ops = ieee80211_get_crypto_ops(alg);
618 request_module(module);
619 ops = ieee80211_get_crypto_ops(alg);
622 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
623 dev->name, ext->alg);
628 if (*crypt == NULL || (*crypt)->ops != ops) {
629 struct ieee80211_crypt_data *new_crypt;
631 ieee80211_crypt_delayed_deinit(ieee, crypt);
633 new_crypt = (struct ieee80211_crypt_data *)
634 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
635 if (new_crypt == NULL) {
639 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
640 new_crypt->ops = ops;
641 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
642 new_crypt->priv = new_crypt->ops->init(idx);
643 if (new_crypt->priv == NULL) {
651 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
652 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
653 (*crypt)->priv) < 0) {
654 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
660 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
661 ieee->tx_keyidx = idx;
662 sec.active_key = idx;
663 sec.flags |= SEC_ACTIVE_KEY;
666 if (ext->alg != IW_ENCODE_ALG_NONE) {
667 memcpy(sec.keys[idx], ext->key, ext->key_len);
668 sec.key_sizes[idx] = ext->key_len;
669 sec.flags |= (1 << idx);
670 if (ext->alg == IW_ENCODE_ALG_WEP) {
671 sec.encode_alg[idx] = SEC_ALG_WEP;
672 sec.flags |= SEC_LEVEL;
673 sec.level = SEC_LEVEL_1;
674 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
675 sec.encode_alg[idx] = SEC_ALG_TKIP;
676 sec.flags |= SEC_LEVEL;
677 sec.level = SEC_LEVEL_2;
678 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
679 sec.encode_alg[idx] = SEC_ALG_CCMP;
680 sec.flags |= SEC_LEVEL;
681 sec.level = SEC_LEVEL_3;
683 /* Don't set sec level for group keys. */
685 sec.flags &= ~SEC_LEVEL;
688 if (ieee->set_security)
689 ieee->set_security(ieee->dev, &sec);
692 * Do not reset port if card is in Managed mode since resetting will
693 * generate new IEEE 802.11 authentication which may end up in looping
694 * with IEEE 802.1X. If your hardware requires a reset after WEP
695 * configuration (for example... Prism2), implement the reset_port in
696 * the callbacks structures used to initialize the 802.11 stack.
698 if (ieee->reset_on_keychange &&
699 ieee->iw_mode != IW_MODE_INFRA &&
700 ieee->reset_port && ieee->reset_port(dev)) {
701 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
708 int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
709 struct iw_request_info *info,
710 union iwreq_data *wrqu, char *extra)
712 struct iw_point *encoding = &wrqu->encoding;
713 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
714 struct ieee80211_security *sec = &ieee->sec;
715 int idx, max_key_len;
717 max_key_len = encoding->length - sizeof(*ext);
721 idx = encoding->flags & IW_ENCODE_INDEX;
723 if (idx < 1 || idx > WEP_KEYS)
727 idx = ieee->tx_keyidx;
729 if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
730 ext->alg != IW_ENCODE_ALG_WEP)
731 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
734 encoding->flags = idx + 1;
735 memset(ext, 0, sizeof(*ext));
738 ext->alg = IW_ENCODE_ALG_NONE;
740 encoding->flags |= IW_ENCODE_DISABLED;
742 if (sec->encode_alg[idx] == SEC_ALG_WEP)
743 ext->alg = IW_ENCODE_ALG_WEP;
744 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
745 ext->alg = IW_ENCODE_ALG_TKIP;
746 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
747 ext->alg = IW_ENCODE_ALG_CCMP;
751 ext->key_len = sec->key_sizes[idx];
752 memcpy(ext->key, sec->keys[idx], ext->key_len);
753 encoding->flags |= IW_ENCODE_ENABLED;
755 (ext->alg == IW_ENCODE_ALG_TKIP ||
756 ext->alg == IW_ENCODE_ALG_CCMP))
757 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
764 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
765 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
767 EXPORT_SYMBOL(ieee80211_wx_get_scan);
768 EXPORT_SYMBOL(ieee80211_wx_set_encode);
769 EXPORT_SYMBOL(ieee80211_wx_get_encode);