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 Intel Linux Wireless <ilw@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/slab.h>
35 #include <linux/module.h>
36 #include <linux/jiffies.h>
38 #include <net/lib80211.h>
39 #include <linux/wireless.h>
43 static const char *libipw_modes[] = {
44 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
47 static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
49 unsigned long end = jiffies;
52 return jiffies_to_msecs(end - start);
54 return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
57 #define MAX_CUSTOM_LEN 64
58 static char *libipw_translate_scan(struct libipw_device *ieee,
59 char *start, char *stop,
60 struct libipw_network *network,
61 struct iw_request_info *info)
63 char custom[MAX_CUSTOM_LEN];
67 char *current_val; /* For rates */
70 /* First entry *MUST* be the AP MAC address */
72 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
73 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
74 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
76 /* Remaining entries will be displayed in the order we provide them */
79 iwe.cmd = SIOCGIWESSID;
81 iwe.u.data.length = min(network->ssid_len, (u8) 32);
82 start = iwe_stream_add_point(info, start, stop,
85 /* Add the protocol name */
86 iwe.cmd = SIOCGIWNAME;
87 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
88 libipw_modes[network->mode]);
89 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
92 iwe.cmd = SIOCGIWMODE;
93 if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
94 if (network->capability & WLAN_CAPABILITY_ESS)
95 iwe.u.mode = IW_MODE_MASTER;
97 iwe.u.mode = IW_MODE_ADHOC;
99 start = iwe_stream_add_event(info, start, stop,
100 &iwe, IW_EV_UINT_LEN);
103 /* Add channel and frequency */
104 /* Note : userspace automatically computes channel using iwrange */
105 iwe.cmd = SIOCGIWFREQ;
106 iwe.u.freq.m = libipw_channel_to_freq(ieee, network->channel);
109 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
111 /* Add encryption capability */
112 iwe.cmd = SIOCGIWENCODE;
113 if (network->capability & WLAN_CAPABILITY_PRIVACY)
114 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
116 iwe.u.data.flags = IW_ENCODE_DISABLED;
117 iwe.u.data.length = 0;
118 start = iwe_stream_add_point(info, start, stop,
119 &iwe, network->ssid);
121 /* Add basic and extended rates */
122 /* Rate : stuffing multiple values in a single event require a bit
123 * more of magic - Jean II */
124 current_val = start + iwe_stream_lcp_len(info);
125 iwe.cmd = SIOCGIWRATE;
126 /* Those two flags are ignored... */
127 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
129 for (i = 0, j = 0; i < network->rates_len;) {
130 if (j < network->rates_ex_len &&
131 ((network->rates_ex[j] & 0x7F) <
132 (network->rates[i] & 0x7F)))
133 rate = network->rates_ex[j++] & 0x7F;
135 rate = network->rates[i++] & 0x7F;
136 /* Bit rate given in 500 kb/s units (+ 0x80) */
137 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
138 /* Add new value to event */
139 current_val = iwe_stream_add_value(info, start, current_val,
140 stop, &iwe, IW_EV_PARAM_LEN);
142 for (; j < network->rates_ex_len; j++) {
143 rate = network->rates_ex[j] & 0x7F;
144 /* Bit rate given in 500 kb/s units (+ 0x80) */
145 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
146 /* Add new value to event */
147 current_val = iwe_stream_add_value(info, start, current_val,
148 stop, &iwe, IW_EV_PARAM_LEN);
150 /* Check if we added any rate */
151 if ((current_val - start) > iwe_stream_lcp_len(info))
154 /* Add quality statistics */
156 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
157 IW_QUAL_NOISE_UPDATED;
159 if (!(network->stats.mask & LIBIPW_STATMASK_RSSI)) {
160 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
161 IW_QUAL_LEVEL_INVALID;
164 if (ieee->perfect_rssi == ieee->worst_rssi)
165 iwe.u.qual.qual = 100;
169 (ieee->perfect_rssi - ieee->worst_rssi) *
170 (ieee->perfect_rssi - ieee->worst_rssi) -
171 (ieee->perfect_rssi - network->stats.rssi) *
172 (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
173 62 * (ieee->perfect_rssi -
174 network->stats.rssi))) /
175 ((ieee->perfect_rssi -
176 ieee->worst_rssi) * (ieee->perfect_rssi -
178 if (iwe.u.qual.qual > 100)
179 iwe.u.qual.qual = 100;
180 else if (iwe.u.qual.qual < 1)
184 if (!(network->stats.mask & LIBIPW_STATMASK_NOISE)) {
185 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
186 iwe.u.qual.noise = 0;
188 iwe.u.qual.noise = network->stats.noise;
191 if (!(network->stats.mask & LIBIPW_STATMASK_SIGNAL)) {
192 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
193 iwe.u.qual.level = 0;
195 iwe.u.qual.level = network->stats.signal;
198 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
200 iwe.cmd = IWEVCUSTOM;
203 iwe.u.data.length = p - custom;
204 if (iwe.u.data.length)
205 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
207 memset(&iwe, 0, sizeof(iwe));
208 if (network->wpa_ie_len) {
209 char buf[MAX_WPA_IE_LEN];
210 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
212 iwe.u.data.length = network->wpa_ie_len;
213 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
216 memset(&iwe, 0, sizeof(iwe));
217 if (network->rsn_ie_len) {
218 char buf[MAX_WPA_IE_LEN];
219 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
221 iwe.u.data.length = network->rsn_ie_len;
222 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
225 /* Add EXTRA: Age to display seconds since last beacon/probe response
226 * for given network. */
227 iwe.cmd = IWEVCUSTOM;
229 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
230 " Last beacon: %ums ago",
231 elapsed_jiffies_msecs(network->last_scanned));
232 iwe.u.data.length = p - custom;
233 if (iwe.u.data.length)
234 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
236 /* Add spectrum management information */
239 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
241 if (libipw_get_channel_flags(ieee, network->channel) &
243 iwe.cmd = IWEVCUSTOM;
244 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
247 if (libipw_get_channel_flags(ieee, network->channel) &
248 LIBIPW_CH_RADAR_DETECT) {
249 iwe.cmd = IWEVCUSTOM;
250 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
253 if (iwe.cmd == IWEVCUSTOM) {
254 iwe.u.data.length = p - custom;
255 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
261 #define SCAN_ITEM_SIZE 128
263 int libipw_wx_get_scan(struct libipw_device *ieee,
264 struct iw_request_info *info,
265 union iwreq_data *wrqu, char *extra)
267 struct libipw_network *network;
272 char *stop = ev + wrqu->data.length;
274 DECLARE_SSID_BUF(ssid);
276 LIBIPW_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 = libipw_translate_scan(ieee, ev, stop, network,
292 LIBIPW_DEBUG_SCAN("Not showing network '%s ("
293 "%pM)' due to age (%ums).\n",
294 print_ssid(ssid, network->ssid,
297 elapsed_jiffies_msecs(
298 network->last_scanned));
302 spin_unlock_irqrestore(&ieee->lock, flags);
304 wrqu->data.length = ev - extra;
305 wrqu->data.flags = 0;
307 LIBIPW_DEBUG_WX("exit: %d networks returned.\n", i);
312 int libipw_wx_set_encode(struct libipw_device *ieee,
313 struct iw_request_info *info,
314 union iwreq_data *wrqu, char *keybuf)
316 struct iw_point *erq = &(wrqu->encoding);
317 struct net_device *dev = ieee->dev;
318 struct libipw_security sec = {
321 int i, key, key_provided, len;
322 struct lib80211_crypt_data **crypt;
323 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
324 DECLARE_SSID_BUF(ssid);
326 LIBIPW_DEBUG_WX("SET_ENCODE\n");
328 key = erq->flags & IW_ENCODE_INDEX;
336 key = ieee->crypt_info.tx_keyidx;
339 LIBIPW_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
340 "provided" : "default");
342 crypt = &ieee->crypt_info.crypt[key];
344 if (erq->flags & IW_ENCODE_DISABLED) {
345 if (key_provided && *crypt) {
346 LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n",
348 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
350 LIBIPW_DEBUG_WX("Disabling encryption.\n");
352 /* Check all the keys to see if any are still configured,
353 * and if no key index was provided, de-init them all */
354 for (i = 0; i < WEP_KEYS; i++) {
355 if (ieee->crypt_info.crypt[i] != NULL) {
358 lib80211_crypt_delayed_deinit(&ieee->crypt_info,
359 &ieee->crypt_info.crypt[i]);
366 sec.level = SEC_LEVEL_0;
367 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
375 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
377 if (*crypt != NULL && (*crypt)->ops != NULL &&
378 strcmp((*crypt)->ops->name, "WEP") != 0) {
379 /* changing to use WEP; deinit previously used algorithm
381 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
384 if (*crypt == NULL && host_crypto) {
385 struct lib80211_crypt_data *new_crypt;
387 /* take WEP into use */
388 new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
390 if (new_crypt == NULL)
392 new_crypt->ops = lib80211_get_crypto_ops("WEP");
393 if (!new_crypt->ops) {
394 request_module("lib80211_crypt_wep");
395 new_crypt->ops = lib80211_get_crypto_ops("WEP");
398 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
399 new_crypt->priv = new_crypt->ops->init(key);
401 if (!new_crypt->ops || !new_crypt->priv) {
405 printk(KERN_WARNING "%s: could not initialize WEP: "
406 "load module lib80211_crypt_wep\n", dev->name);
412 /* If a new key was provided, set it up */
413 if (erq->length > 0) {
414 #ifdef CONFIG_LIBIPW_DEBUG
415 DECLARE_SSID_BUF(ssid);
418 len = erq->length <= 5 ? 5 : 13;
419 memcpy(sec.keys[key], keybuf, erq->length);
420 if (len > erq->length)
421 memset(sec.keys[key] + erq->length, 0,
423 LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
424 key, print_ssid(ssid, sec.keys[key], len),
426 sec.key_sizes[key] = len;
428 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
430 sec.flags |= (1 << key);
431 /* This ensures a key will be activated if no key is
433 if (key == sec.active_key)
434 sec.flags |= SEC_ACTIVE_KEY;
438 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
439 NULL, (*crypt)->priv);
441 /* Set a default key of all 0 */
442 LIBIPW_DEBUG_WX("Setting key %d to all "
444 memset(sec.keys[key], 0, 13);
445 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
447 sec.key_sizes[key] = 13;
448 sec.flags |= (1 << key);
451 /* No key data - just set the default TX key index */
453 LIBIPW_DEBUG_WX("Setting key %d to default Tx "
455 ieee->crypt_info.tx_keyidx = key;
456 sec.active_key = key;
457 sec.flags |= SEC_ACTIVE_KEY;
460 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
461 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
462 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
463 WLAN_AUTH_SHARED_KEY;
464 sec.flags |= SEC_AUTH_MODE;
465 LIBIPW_DEBUG_WX("Auth: %s\n",
466 sec.auth_mode == WLAN_AUTH_OPEN ?
467 "OPEN" : "SHARED KEY");
470 /* For now we just support WEP, so only set that security level...
471 * TODO: When WPA is added this is one place that needs to change */
472 sec.flags |= SEC_LEVEL;
473 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
474 sec.encode_alg[key] = SEC_ALG_WEP;
477 if (ieee->set_security)
478 ieee->set_security(dev, &sec);
480 /* Do not reset port if card is in Managed mode since resetting will
481 * generate new IEEE 802.11 authentication which may end up in looping
482 * with IEEE 802.1X. If your hardware requires a reset after WEP
483 * configuration (for example... Prism2), implement the reset_port in
484 * the callbacks structures used to initialize the 802.11 stack. */
485 if (ieee->reset_on_keychange &&
486 ieee->iw_mode != IW_MODE_INFRA &&
487 ieee->reset_port && ieee->reset_port(dev)) {
488 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
494 int libipw_wx_get_encode(struct libipw_device *ieee,
495 struct iw_request_info *info,
496 union iwreq_data *wrqu, char *keybuf)
498 struct iw_point *erq = &(wrqu->encoding);
500 struct lib80211_crypt_data *crypt;
501 struct libipw_security *sec = &ieee->sec;
503 LIBIPW_DEBUG_WX("GET_ENCODE\n");
505 key = erq->flags & IW_ENCODE_INDEX;
511 key = ieee->crypt_info.tx_keyidx;
513 crypt = ieee->crypt_info.crypt[key];
514 erq->flags = key + 1;
518 erq->flags |= IW_ENCODE_DISABLED;
522 len = sec->key_sizes[key];
523 memcpy(keybuf, sec->keys[key], len);
526 erq->flags |= IW_ENCODE_ENABLED;
529 erq->flags |= IW_ENCODE_OPEN;
531 erq->flags |= IW_ENCODE_RESTRICTED;
536 int libipw_wx_set_encodeext(struct libipw_device *ieee,
537 struct iw_request_info *info,
538 union iwreq_data *wrqu, char *extra)
540 struct net_device *dev = ieee->dev;
541 struct iw_point *encoding = &wrqu->encoding;
542 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
545 const char *alg, *module;
546 struct lib80211_crypto_ops *ops;
547 struct lib80211_crypt_data **crypt;
549 struct libipw_security sec = {
553 idx = encoding->flags & IW_ENCODE_INDEX;
555 if (idx < 1 || idx > WEP_KEYS)
559 idx = ieee->crypt_info.tx_keyidx;
561 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
562 crypt = &ieee->crypt_info.crypt[idx];
565 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
566 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
568 if (ieee->iw_mode == IW_MODE_INFRA)
569 crypt = &ieee->crypt_info.crypt[idx];
574 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
575 if ((encoding->flags & IW_ENCODE_DISABLED) ||
576 ext->alg == IW_ENCODE_ALG_NONE) {
578 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
580 for (i = 0; i < WEP_KEYS; i++)
581 if (ieee->crypt_info.crypt[i] != NULL)
587 sec.level = SEC_LEVEL_0;
588 sec.flags |= SEC_LEVEL;
596 if (group_key ? !ieee->host_mc_decrypt :
597 !(ieee->host_encrypt || ieee->host_decrypt ||
598 ieee->host_encrypt_msdu))
599 goto skip_host_crypt;
602 case IW_ENCODE_ALG_WEP:
604 module = "lib80211_crypt_wep";
606 case IW_ENCODE_ALG_TKIP:
608 module = "lib80211_crypt_tkip";
610 case IW_ENCODE_ALG_CCMP:
612 module = "lib80211_crypt_ccmp";
615 LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
616 dev->name, ext->alg);
621 ops = lib80211_get_crypto_ops(alg);
623 request_module(module);
624 ops = lib80211_get_crypto_ops(alg);
627 LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
628 dev->name, ext->alg);
633 if (*crypt == NULL || (*crypt)->ops != ops) {
634 struct lib80211_crypt_data *new_crypt;
636 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
638 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
639 if (new_crypt == NULL) {
643 new_crypt->ops = ops;
644 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
645 new_crypt->priv = new_crypt->ops->init(idx);
646 if (new_crypt->priv == NULL) {
654 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
655 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
656 (*crypt)->priv) < 0) {
657 LIBIPW_DEBUG_WX("%s: key setting failed\n", dev->name);
663 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
664 ieee->crypt_info.tx_keyidx = idx;
665 sec.active_key = idx;
666 sec.flags |= SEC_ACTIVE_KEY;
669 if (ext->alg != IW_ENCODE_ALG_NONE) {
670 memcpy(sec.keys[idx], ext->key, ext->key_len);
671 sec.key_sizes[idx] = ext->key_len;
672 sec.flags |= (1 << idx);
673 if (ext->alg == IW_ENCODE_ALG_WEP) {
674 sec.encode_alg[idx] = SEC_ALG_WEP;
675 sec.flags |= SEC_LEVEL;
676 sec.level = SEC_LEVEL_1;
677 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
678 sec.encode_alg[idx] = SEC_ALG_TKIP;
679 sec.flags |= SEC_LEVEL;
680 sec.level = SEC_LEVEL_2;
681 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
682 sec.encode_alg[idx] = SEC_ALG_CCMP;
683 sec.flags |= SEC_LEVEL;
684 sec.level = SEC_LEVEL_3;
686 /* Don't set sec level for group keys. */
688 sec.flags &= ~SEC_LEVEL;
691 if (ieee->set_security)
692 ieee->set_security(ieee->dev, &sec);
695 * Do not reset port if card is in Managed mode since resetting will
696 * generate new IEEE 802.11 authentication which may end up in looping
697 * with IEEE 802.1X. If your hardware requires a reset after WEP
698 * configuration (for example... Prism2), implement the reset_port in
699 * the callbacks structures used to initialize the 802.11 stack.
701 if (ieee->reset_on_keychange &&
702 ieee->iw_mode != IW_MODE_INFRA &&
703 ieee->reset_port && ieee->reset_port(dev)) {
704 LIBIPW_DEBUG_WX("%s: reset_port failed\n", dev->name);
711 int libipw_wx_get_encodeext(struct libipw_device *ieee,
712 struct iw_request_info *info,
713 union iwreq_data *wrqu, char *extra)
715 struct iw_point *encoding = &wrqu->encoding;
716 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
717 struct libipw_security *sec = &ieee->sec;
718 int idx, max_key_len;
720 max_key_len = encoding->length - sizeof(*ext);
724 idx = encoding->flags & IW_ENCODE_INDEX;
726 if (idx < 1 || idx > WEP_KEYS)
730 idx = ieee->crypt_info.tx_keyidx;
732 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
733 ext->alg != IW_ENCODE_ALG_WEP)
734 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
737 encoding->flags = idx + 1;
738 memset(ext, 0, sizeof(*ext));
741 ext->alg = IW_ENCODE_ALG_NONE;
743 encoding->flags |= IW_ENCODE_DISABLED;
745 if (sec->encode_alg[idx] == SEC_ALG_WEP)
746 ext->alg = IW_ENCODE_ALG_WEP;
747 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
748 ext->alg = IW_ENCODE_ALG_TKIP;
749 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
750 ext->alg = IW_ENCODE_ALG_CCMP;
754 ext->key_len = sec->key_sizes[idx];
755 memcpy(ext->key, sec->keys[idx], ext->key_len);
756 encoding->flags |= IW_ENCODE_ENABLED;
758 (ext->alg == IW_ENCODE_ALG_TKIP ||
759 ext->alg == IW_ENCODE_ALG_CCMP))
760 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
767 EXPORT_SYMBOL(libipw_wx_set_encodeext);
768 EXPORT_SYMBOL(libipw_wx_get_encodeext);
770 EXPORT_SYMBOL(libipw_wx_get_scan);
771 EXPORT_SYMBOL(libipw_wx_set_encode);
772 EXPORT_SYMBOL(libipw_wx_get_encode);