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/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 *ieee80211_translate_scan(struct ieee80211_device *ieee,
46 char *start, char *stop,
47 struct ieee80211_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 if (network->flags & NETWORK_EMPTY_ESSID) {
69 iwe.u.data.length = sizeof("<hidden>");
70 start = iwe_stream_add_point(info, start, stop,
73 iwe.u.data.length = min(network->ssid_len, (u8) 32);
74 start = iwe_stream_add_point(info, start, stop,
78 /* Add the protocol name */
79 iwe.cmd = SIOCGIWNAME;
80 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
81 ieee80211_modes[network->mode]);
82 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
85 iwe.cmd = SIOCGIWMODE;
86 if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
87 if (network->capability & WLAN_CAPABILITY_ESS)
88 iwe.u.mode = IW_MODE_MASTER;
90 iwe.u.mode = IW_MODE_ADHOC;
92 start = iwe_stream_add_event(info, start, stop,
93 &iwe, IW_EV_UINT_LEN);
96 /* Add channel and frequency */
97 /* Note : userspace automatically computes channel using iwrange */
98 iwe.cmd = SIOCGIWFREQ;
99 iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
102 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
104 /* Add encryption capability */
105 iwe.cmd = SIOCGIWENCODE;
106 if (network->capability & WLAN_CAPABILITY_PRIVACY)
107 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
109 iwe.u.data.flags = IW_ENCODE_DISABLED;
110 iwe.u.data.length = 0;
111 start = iwe_stream_add_point(info, start, stop,
112 &iwe, network->ssid);
114 /* Add basic and extended rates */
115 /* Rate : stuffing multiple values in a single event require a bit
116 * more of magic - Jean II */
117 current_val = start + iwe_stream_lcp_len(info);
118 iwe.cmd = SIOCGIWRATE;
119 /* Those two flags are ignored... */
120 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
122 for (i = 0, j = 0; i < network->rates_len;) {
123 if (j < network->rates_ex_len &&
124 ((network->rates_ex[j] & 0x7F) <
125 (network->rates[i] & 0x7F)))
126 rate = network->rates_ex[j++] & 0x7F;
128 rate = network->rates[i++] & 0x7F;
129 /* Bit rate given in 500 kb/s units (+ 0x80) */
130 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
131 /* Add new value to event */
132 current_val = iwe_stream_add_value(info, start, current_val,
133 stop, &iwe, IW_EV_PARAM_LEN);
135 for (; j < network->rates_ex_len; j++) {
136 rate = network->rates_ex[j] & 0x7F;
137 /* Bit rate given in 500 kb/s units (+ 0x80) */
138 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
139 /* Add new value to event */
140 current_val = iwe_stream_add_value(info, start, current_val,
141 stop, &iwe, IW_EV_PARAM_LEN);
143 /* Check if we added any rate */
144 if ((current_val - start) > iwe_stream_lcp_len(info))
147 /* Add quality statistics */
149 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
150 IW_QUAL_NOISE_UPDATED;
152 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
153 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
154 IW_QUAL_LEVEL_INVALID;
157 if (ieee->perfect_rssi == ieee->worst_rssi)
158 iwe.u.qual.qual = 100;
162 (ieee->perfect_rssi - ieee->worst_rssi) *
163 (ieee->perfect_rssi - ieee->worst_rssi) -
164 (ieee->perfect_rssi - network->stats.rssi) *
165 (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
166 62 * (ieee->perfect_rssi -
167 network->stats.rssi))) /
168 ((ieee->perfect_rssi -
169 ieee->worst_rssi) * (ieee->perfect_rssi -
171 if (iwe.u.qual.qual > 100)
172 iwe.u.qual.qual = 100;
173 else if (iwe.u.qual.qual < 1)
177 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
178 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
179 iwe.u.qual.noise = 0;
181 iwe.u.qual.noise = network->stats.noise;
184 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
185 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
186 iwe.u.qual.level = 0;
188 iwe.u.qual.level = network->stats.signal;
191 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
193 iwe.cmd = IWEVCUSTOM;
196 iwe.u.data.length = p - custom;
197 if (iwe.u.data.length)
198 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
200 memset(&iwe, 0, sizeof(iwe));
201 if (network->wpa_ie_len) {
202 char buf[MAX_WPA_IE_LEN];
203 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
205 iwe.u.data.length = network->wpa_ie_len;
206 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
209 memset(&iwe, 0, sizeof(iwe));
210 if (network->rsn_ie_len) {
211 char buf[MAX_WPA_IE_LEN];
212 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
214 iwe.u.data.length = network->rsn_ie_len;
215 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
218 /* Add EXTRA: Age to display seconds since last beacon/probe response
219 * for given network. */
220 iwe.cmd = IWEVCUSTOM;
222 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
223 " Last beacon: %dms ago",
224 jiffies_to_msecs(jiffies - network->last_scanned));
225 iwe.u.data.length = p - custom;
226 if (iwe.u.data.length)
227 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
229 /* Add spectrum management information */
232 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
234 if (ieee80211_get_channel_flags(ieee, network->channel) &
235 IEEE80211_CH_INVALID) {
236 iwe.cmd = IWEVCUSTOM;
237 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
240 if (ieee80211_get_channel_flags(ieee, network->channel) &
241 IEEE80211_CH_RADAR_DETECT) {
242 iwe.cmd = IWEVCUSTOM;
243 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
246 if (iwe.cmd == IWEVCUSTOM) {
247 iwe.u.data.length = p - custom;
248 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
254 #define SCAN_ITEM_SIZE 128
256 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
257 struct iw_request_info *info,
258 union iwreq_data *wrqu, char *extra)
260 struct ieee80211_network *network;
265 char *stop = ev + wrqu->data.length;
268 IEEE80211_DEBUG_WX("Getting scan\n");
270 spin_lock_irqsave(&ieee->lock, flags);
272 list_for_each_entry(network, &ieee->network_list, list) {
274 if (stop - ev < SCAN_ITEM_SIZE) {
279 if (ieee->scan_age == 0 ||
280 time_after(network->last_scanned + ieee->scan_age, jiffies))
281 ev = ieee80211_translate_scan(ieee, ev, stop, network,
284 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
285 "%pM)' due to age (%dms).\n",
286 escape_ssid(network->ssid,
289 jiffies_to_msecs(jiffies -
294 spin_unlock_irqrestore(&ieee->lock, flags);
296 wrqu->data.length = ev - extra;
297 wrqu->data.flags = 0;
299 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
304 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
305 struct iw_request_info *info,
306 union iwreq_data *wrqu, char *keybuf)
308 struct iw_point *erq = &(wrqu->encoding);
309 struct net_device *dev = ieee->dev;
310 struct ieee80211_security sec = {
313 int i, key, key_provided, len;
314 struct ieee80211_crypt_data **crypt;
315 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
317 IEEE80211_DEBUG_WX("SET_ENCODE\n");
319 key = erq->flags & IW_ENCODE_INDEX;
327 key = ieee->tx_keyidx;
330 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
331 "provided" : "default");
333 crypt = &ieee->crypt[key];
335 if (erq->flags & IW_ENCODE_DISABLED) {
336 if (key_provided && *crypt) {
337 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
339 ieee80211_crypt_delayed_deinit(ieee, crypt);
341 IEEE80211_DEBUG_WX("Disabling encryption.\n");
343 /* Check all the keys to see if any are still configured,
344 * and if no key index was provided, de-init them all */
345 for (i = 0; i < WEP_KEYS; i++) {
346 if (ieee->crypt[i] != NULL) {
349 ieee80211_crypt_delayed_deinit(ieee,
357 sec.level = SEC_LEVEL_0;
358 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
366 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
368 if (*crypt != NULL && (*crypt)->ops != NULL &&
369 strcmp((*crypt)->ops->name, "WEP") != 0) {
370 /* changing to use WEP; deinit previously used algorithm
372 ieee80211_crypt_delayed_deinit(ieee, crypt);
375 if (*crypt == NULL && host_crypto) {
376 struct ieee80211_crypt_data *new_crypt;
378 /* take WEP into use */
379 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
381 if (new_crypt == NULL)
383 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
384 if (!new_crypt->ops) {
385 request_module("ieee80211_crypt_wep");
386 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
389 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
390 new_crypt->priv = new_crypt->ops->init(key);
392 if (!new_crypt->ops || !new_crypt->priv) {
396 printk(KERN_WARNING "%s: could not initialize WEP: "
397 "load module ieee80211_crypt_wep\n", dev->name);
403 /* If a new key was provided, set it up */
404 if (erq->length > 0) {
405 len = erq->length <= 5 ? 5 : 13;
406 memcpy(sec.keys[key], keybuf, erq->length);
407 if (len > erq->length)
408 memset(sec.keys[key] + erq->length, 0,
410 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
411 key, escape_ssid(sec.keys[key], len),
413 sec.key_sizes[key] = len;
415 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
417 sec.flags |= (1 << key);
418 /* This ensures a key will be activated if no key is
420 if (key == sec.active_key)
421 sec.flags |= SEC_ACTIVE_KEY;
425 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
426 NULL, (*crypt)->priv);
428 /* Set a default key of all 0 */
429 IEEE80211_DEBUG_WX("Setting key %d to all "
431 memset(sec.keys[key], 0, 13);
432 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
434 sec.key_sizes[key] = 13;
435 sec.flags |= (1 << key);
438 /* No key data - just set the default TX key index */
440 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
442 ieee->tx_keyidx = key;
443 sec.active_key = key;
444 sec.flags |= SEC_ACTIVE_KEY;
447 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
448 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
449 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
450 WLAN_AUTH_SHARED_KEY;
451 sec.flags |= SEC_AUTH_MODE;
452 IEEE80211_DEBUG_WX("Auth: %s\n",
453 sec.auth_mode == WLAN_AUTH_OPEN ?
454 "OPEN" : "SHARED KEY");
457 /* For now we just support WEP, so only set that security level...
458 * TODO: When WPA is added this is one place that needs to change */
459 sec.flags |= SEC_LEVEL;
460 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
461 sec.encode_alg[key] = SEC_ALG_WEP;
464 if (ieee->set_security)
465 ieee->set_security(dev, &sec);
467 /* Do not reset port if card is in Managed mode since resetting will
468 * generate new IEEE 802.11 authentication which may end up in looping
469 * with IEEE 802.1X. If your hardware requires a reset after WEP
470 * configuration (for example... Prism2), implement the reset_port in
471 * the callbacks structures used to initialize the 802.11 stack. */
472 if (ieee->reset_on_keychange &&
473 ieee->iw_mode != IW_MODE_INFRA &&
474 ieee->reset_port && ieee->reset_port(dev)) {
475 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
481 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
482 struct iw_request_info *info,
483 union iwreq_data *wrqu, char *keybuf)
485 struct iw_point *erq = &(wrqu->encoding);
487 struct ieee80211_crypt_data *crypt;
488 struct ieee80211_security *sec = &ieee->sec;
490 IEEE80211_DEBUG_WX("GET_ENCODE\n");
492 key = erq->flags & IW_ENCODE_INDEX;
498 key = ieee->tx_keyidx;
500 crypt = ieee->crypt[key];
501 erq->flags = key + 1;
505 erq->flags |= IW_ENCODE_DISABLED;
509 len = sec->key_sizes[key];
510 memcpy(keybuf, sec->keys[key], len);
513 erq->flags |= IW_ENCODE_ENABLED;
516 erq->flags |= IW_ENCODE_OPEN;
518 erq->flags |= IW_ENCODE_RESTRICTED;
523 int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
524 struct iw_request_info *info,
525 union iwreq_data *wrqu, char *extra)
527 struct net_device *dev = ieee->dev;
528 struct iw_point *encoding = &wrqu->encoding;
529 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
532 const char *alg, *module;
533 struct ieee80211_crypto_ops *ops;
534 struct ieee80211_crypt_data **crypt;
536 struct ieee80211_security sec = {
540 idx = encoding->flags & IW_ENCODE_INDEX;
542 if (idx < 1 || idx > WEP_KEYS)
546 idx = ieee->tx_keyidx;
548 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
549 crypt = &ieee->crypt[idx];
552 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
553 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
555 if (ieee->iw_mode == IW_MODE_INFRA)
556 crypt = &ieee->crypt[idx];
561 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
562 if ((encoding->flags & IW_ENCODE_DISABLED) ||
563 ext->alg == IW_ENCODE_ALG_NONE) {
565 ieee80211_crypt_delayed_deinit(ieee, crypt);
567 for (i = 0; i < WEP_KEYS; i++)
568 if (ieee->crypt[i] != NULL)
574 sec.level = SEC_LEVEL_0;
575 sec.flags |= SEC_LEVEL;
583 if (group_key ? !ieee->host_mc_decrypt :
584 !(ieee->host_encrypt || ieee->host_decrypt ||
585 ieee->host_encrypt_msdu))
586 goto skip_host_crypt;
589 case IW_ENCODE_ALG_WEP:
591 module = "ieee80211_crypt_wep";
593 case IW_ENCODE_ALG_TKIP:
595 module = "ieee80211_crypt_tkip";
597 case IW_ENCODE_ALG_CCMP:
599 module = "ieee80211_crypt_ccmp";
602 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
603 dev->name, ext->alg);
608 ops = ieee80211_get_crypto_ops(alg);
610 request_module(module);
611 ops = ieee80211_get_crypto_ops(alg);
614 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
615 dev->name, ext->alg);
620 if (*crypt == NULL || (*crypt)->ops != ops) {
621 struct ieee80211_crypt_data *new_crypt;
623 ieee80211_crypt_delayed_deinit(ieee, crypt);
625 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
626 if (new_crypt == NULL) {
630 new_crypt->ops = ops;
631 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
632 new_crypt->priv = new_crypt->ops->init(idx);
633 if (new_crypt->priv == NULL) {
641 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
642 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
643 (*crypt)->priv) < 0) {
644 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
650 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
651 ieee->tx_keyidx = idx;
652 sec.active_key = idx;
653 sec.flags |= SEC_ACTIVE_KEY;
656 if (ext->alg != IW_ENCODE_ALG_NONE) {
657 memcpy(sec.keys[idx], ext->key, ext->key_len);
658 sec.key_sizes[idx] = ext->key_len;
659 sec.flags |= (1 << idx);
660 if (ext->alg == IW_ENCODE_ALG_WEP) {
661 sec.encode_alg[idx] = SEC_ALG_WEP;
662 sec.flags |= SEC_LEVEL;
663 sec.level = SEC_LEVEL_1;
664 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
665 sec.encode_alg[idx] = SEC_ALG_TKIP;
666 sec.flags |= SEC_LEVEL;
667 sec.level = SEC_LEVEL_2;
668 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
669 sec.encode_alg[idx] = SEC_ALG_CCMP;
670 sec.flags |= SEC_LEVEL;
671 sec.level = SEC_LEVEL_3;
673 /* Don't set sec level for group keys. */
675 sec.flags &= ~SEC_LEVEL;
678 if (ieee->set_security)
679 ieee->set_security(ieee->dev, &sec);
682 * Do not reset port if card is in Managed mode since resetting will
683 * generate new IEEE 802.11 authentication which may end up in looping
684 * with IEEE 802.1X. If your hardware requires a reset after WEP
685 * configuration (for example... Prism2), implement the reset_port in
686 * the callbacks structures used to initialize the 802.11 stack.
688 if (ieee->reset_on_keychange &&
689 ieee->iw_mode != IW_MODE_INFRA &&
690 ieee->reset_port && ieee->reset_port(dev)) {
691 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
698 int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
699 struct iw_request_info *info,
700 union iwreq_data *wrqu, char *extra)
702 struct iw_point *encoding = &wrqu->encoding;
703 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
704 struct ieee80211_security *sec = &ieee->sec;
705 int idx, max_key_len;
707 max_key_len = encoding->length - sizeof(*ext);
711 idx = encoding->flags & IW_ENCODE_INDEX;
713 if (idx < 1 || idx > WEP_KEYS)
717 idx = ieee->tx_keyidx;
719 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
720 ext->alg != IW_ENCODE_ALG_WEP)
721 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
724 encoding->flags = idx + 1;
725 memset(ext, 0, sizeof(*ext));
728 ext->alg = IW_ENCODE_ALG_NONE;
730 encoding->flags |= IW_ENCODE_DISABLED;
732 if (sec->encode_alg[idx] == SEC_ALG_WEP)
733 ext->alg = IW_ENCODE_ALG_WEP;
734 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
735 ext->alg = IW_ENCODE_ALG_TKIP;
736 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
737 ext->alg = IW_ENCODE_ALG_CCMP;
741 ext->key_len = sec->key_sizes[idx];
742 memcpy(ext->key, sec->keys[idx], ext->key_len);
743 encoding->flags |= IW_ENCODE_ENABLED;
745 (ext->alg == IW_ENCODE_ALG_TKIP ||
746 ext->alg == IW_ENCODE_ALG_CCMP))
747 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
754 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
755 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
757 EXPORT_SYMBOL(ieee80211_wx_get_scan);
758 EXPORT_SYMBOL(ieee80211_wx_set_encode);
759 EXPORT_SYMBOL(ieee80211_wx_get_encode);