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 <net/ieee80211.h>
39 #include <linux/wireless.h>
41 static const char *ieee80211_modes[] = {
42 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
45 #define MAX_CUSTOM_LEN 64
46 static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
47 char *start, char *stop,
48 struct ieee80211_network *network,
49 struct iw_request_info *info)
51 char custom[MAX_CUSTOM_LEN];
55 char *current_val; /* For rates */
58 /* First entry *MUST* be the AP MAC address */
60 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
61 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
62 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
64 /* Remaining entries will be displayed in the order we provide them */
67 iwe.cmd = SIOCGIWESSID;
69 iwe.u.data.length = min(network->ssid_len, (u8) 32);
70 start = iwe_stream_add_point(info, start, stop,
73 /* Add the protocol name */
74 iwe.cmd = SIOCGIWNAME;
75 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
76 ieee80211_modes[network->mode]);
77 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
80 iwe.cmd = SIOCGIWMODE;
81 if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
82 if (network->capability & WLAN_CAPABILITY_ESS)
83 iwe.u.mode = IW_MODE_MASTER;
85 iwe.u.mode = IW_MODE_ADHOC;
87 start = iwe_stream_add_event(info, start, stop,
88 &iwe, IW_EV_UINT_LEN);
91 /* Add channel and frequency */
92 /* Note : userspace automatically computes channel using iwrange */
93 iwe.cmd = SIOCGIWFREQ;
94 iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
97 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
99 /* Add encryption capability */
100 iwe.cmd = SIOCGIWENCODE;
101 if (network->capability & WLAN_CAPABILITY_PRIVACY)
102 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
104 iwe.u.data.flags = IW_ENCODE_DISABLED;
105 iwe.u.data.length = 0;
106 start = iwe_stream_add_point(info, start, stop,
107 &iwe, network->ssid);
109 /* Add basic and extended rates */
110 /* Rate : stuffing multiple values in a single event require a bit
111 * more of magic - Jean II */
112 current_val = start + iwe_stream_lcp_len(info);
113 iwe.cmd = SIOCGIWRATE;
114 /* Those two flags are ignored... */
115 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
117 for (i = 0, j = 0; i < network->rates_len;) {
118 if (j < network->rates_ex_len &&
119 ((network->rates_ex[j] & 0x7F) <
120 (network->rates[i] & 0x7F)))
121 rate = network->rates_ex[j++] & 0x7F;
123 rate = network->rates[i++] & 0x7F;
124 /* Bit rate given in 500 kb/s units (+ 0x80) */
125 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
126 /* Add new value to event */
127 current_val = iwe_stream_add_value(info, start, current_val,
128 stop, &iwe, IW_EV_PARAM_LEN);
130 for (; j < network->rates_ex_len; j++) {
131 rate = network->rates_ex[j] & 0x7F;
132 /* Bit rate given in 500 kb/s units (+ 0x80) */
133 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
134 /* Add new value to event */
135 current_val = iwe_stream_add_value(info, start, current_val,
136 stop, &iwe, IW_EV_PARAM_LEN);
138 /* Check if we added any rate */
139 if ((current_val - start) > iwe_stream_lcp_len(info))
142 /* Add quality statistics */
144 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
145 IW_QUAL_NOISE_UPDATED;
147 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
148 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
149 IW_QUAL_LEVEL_INVALID;
152 if (ieee->perfect_rssi == ieee->worst_rssi)
153 iwe.u.qual.qual = 100;
157 (ieee->perfect_rssi - ieee->worst_rssi) *
158 (ieee->perfect_rssi - ieee->worst_rssi) -
159 (ieee->perfect_rssi - network->stats.rssi) *
160 (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
161 62 * (ieee->perfect_rssi -
162 network->stats.rssi))) /
163 ((ieee->perfect_rssi -
164 ieee->worst_rssi) * (ieee->perfect_rssi -
166 if (iwe.u.qual.qual > 100)
167 iwe.u.qual.qual = 100;
168 else if (iwe.u.qual.qual < 1)
172 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
173 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
174 iwe.u.qual.noise = 0;
176 iwe.u.qual.noise = network->stats.noise;
179 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
180 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
181 iwe.u.qual.level = 0;
183 iwe.u.qual.level = network->stats.signal;
186 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
188 iwe.cmd = IWEVCUSTOM;
191 iwe.u.data.length = p - custom;
192 if (iwe.u.data.length)
193 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
195 memset(&iwe, 0, sizeof(iwe));
196 if (network->wpa_ie_len) {
197 char buf[MAX_WPA_IE_LEN];
198 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
200 iwe.u.data.length = network->wpa_ie_len;
201 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
204 memset(&iwe, 0, sizeof(iwe));
205 if (network->rsn_ie_len) {
206 char buf[MAX_WPA_IE_LEN];
207 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
209 iwe.u.data.length = network->rsn_ie_len;
210 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
213 /* Add EXTRA: Age to display seconds since last beacon/probe response
214 * for given network. */
215 iwe.cmd = IWEVCUSTOM;
217 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
218 " Last beacon: %dms ago",
219 jiffies_to_msecs(jiffies - network->last_scanned));
220 iwe.u.data.length = p - custom;
221 if (iwe.u.data.length)
222 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
224 /* Add spectrum management information */
227 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
229 if (ieee80211_get_channel_flags(ieee, network->channel) &
230 IEEE80211_CH_INVALID) {
231 iwe.cmd = IWEVCUSTOM;
232 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
235 if (ieee80211_get_channel_flags(ieee, network->channel) &
236 IEEE80211_CH_RADAR_DETECT) {
237 iwe.cmd = IWEVCUSTOM;
238 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
241 if (iwe.cmd == IWEVCUSTOM) {
242 iwe.u.data.length = p - custom;
243 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
249 #define SCAN_ITEM_SIZE 128
251 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
252 struct iw_request_info *info,
253 union iwreq_data *wrqu, char *extra)
255 struct ieee80211_network *network;
260 char *stop = ev + wrqu->data.length;
262 DECLARE_SSID_BUF(ssid);
264 IEEE80211_DEBUG_WX("Getting scan\n");
266 spin_lock_irqsave(&ieee->lock, flags);
268 list_for_each_entry(network, &ieee->network_list, list) {
270 if (stop - ev < SCAN_ITEM_SIZE) {
275 if (ieee->scan_age == 0 ||
276 time_after(network->last_scanned + ieee->scan_age, jiffies))
277 ev = ieee80211_translate_scan(ieee, ev, stop, network,
280 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
281 "%pM)' due to age (%dms).\n",
282 print_ssid(ssid, network->ssid,
285 jiffies_to_msecs(jiffies -
290 spin_unlock_irqrestore(&ieee->lock, flags);
292 wrqu->data.length = ev - extra;
293 wrqu->data.flags = 0;
295 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
300 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
301 struct iw_request_info *info,
302 union iwreq_data *wrqu, char *keybuf)
304 struct iw_point *erq = &(wrqu->encoding);
305 struct net_device *dev = ieee->dev;
306 struct ieee80211_security sec = {
309 int i, key, key_provided, len;
310 struct ieee80211_crypt_data **crypt;
311 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
312 DECLARE_SSID_BUF(ssid);
314 IEEE80211_DEBUG_WX("SET_ENCODE\n");
316 key = erq->flags & IW_ENCODE_INDEX;
324 key = ieee->tx_keyidx;
327 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
328 "provided" : "default");
330 crypt = &ieee->crypt[key];
332 if (erq->flags & IW_ENCODE_DISABLED) {
333 if (key_provided && *crypt) {
334 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
336 ieee80211_crypt_delayed_deinit(ieee, crypt);
338 IEEE80211_DEBUG_WX("Disabling encryption.\n");
340 /* Check all the keys to see if any are still configured,
341 * and if no key index was provided, de-init them all */
342 for (i = 0; i < WEP_KEYS; i++) {
343 if (ieee->crypt[i] != NULL) {
346 ieee80211_crypt_delayed_deinit(ieee,
354 sec.level = SEC_LEVEL_0;
355 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
363 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
365 if (*crypt != NULL && (*crypt)->ops != NULL &&
366 strcmp((*crypt)->ops->name, "WEP") != 0) {
367 /* changing to use WEP; deinit previously used algorithm
369 ieee80211_crypt_delayed_deinit(ieee, crypt);
372 if (*crypt == NULL && host_crypto) {
373 struct ieee80211_crypt_data *new_crypt;
375 /* take WEP into use */
376 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
378 if (new_crypt == NULL)
380 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
381 if (!new_crypt->ops) {
382 request_module("ieee80211_crypt_wep");
383 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
386 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
387 new_crypt->priv = new_crypt->ops->init(key);
389 if (!new_crypt->ops || !new_crypt->priv) {
393 printk(KERN_WARNING "%s: could not initialize WEP: "
394 "load module ieee80211_crypt_wep\n", dev->name);
400 /* If a new key was provided, set it up */
401 if (erq->length > 0) {
402 len = erq->length <= 5 ? 5 : 13;
403 memcpy(sec.keys[key], keybuf, erq->length);
404 if (len > erq->length)
405 memset(sec.keys[key] + erq->length, 0,
407 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
408 key, print_ssid(ssid, sec.keys[key], len),
410 sec.key_sizes[key] = len;
412 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
414 sec.flags |= (1 << key);
415 /* This ensures a key will be activated if no key is
417 if (key == sec.active_key)
418 sec.flags |= SEC_ACTIVE_KEY;
422 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
423 NULL, (*crypt)->priv);
425 /* Set a default key of all 0 */
426 IEEE80211_DEBUG_WX("Setting key %d to all "
428 memset(sec.keys[key], 0, 13);
429 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
431 sec.key_sizes[key] = 13;
432 sec.flags |= (1 << key);
435 /* No key data - just set the default TX key index */
437 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
439 ieee->tx_keyidx = key;
440 sec.active_key = key;
441 sec.flags |= SEC_ACTIVE_KEY;
444 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
445 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
446 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
447 WLAN_AUTH_SHARED_KEY;
448 sec.flags |= SEC_AUTH_MODE;
449 IEEE80211_DEBUG_WX("Auth: %s\n",
450 sec.auth_mode == WLAN_AUTH_OPEN ?
451 "OPEN" : "SHARED KEY");
454 /* For now we just support WEP, so only set that security level...
455 * TODO: When WPA is added this is one place that needs to change */
456 sec.flags |= SEC_LEVEL;
457 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
458 sec.encode_alg[key] = SEC_ALG_WEP;
461 if (ieee->set_security)
462 ieee->set_security(dev, &sec);
464 /* Do not reset port if card is in Managed mode since resetting will
465 * generate new IEEE 802.11 authentication which may end up in looping
466 * with IEEE 802.1X. If your hardware requires a reset after WEP
467 * configuration (for example... Prism2), implement the reset_port in
468 * the callbacks structures used to initialize the 802.11 stack. */
469 if (ieee->reset_on_keychange &&
470 ieee->iw_mode != IW_MODE_INFRA &&
471 ieee->reset_port && ieee->reset_port(dev)) {
472 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
478 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
479 struct iw_request_info *info,
480 union iwreq_data *wrqu, char *keybuf)
482 struct iw_point *erq = &(wrqu->encoding);
484 struct ieee80211_crypt_data *crypt;
485 struct ieee80211_security *sec = &ieee->sec;
487 IEEE80211_DEBUG_WX("GET_ENCODE\n");
489 key = erq->flags & IW_ENCODE_INDEX;
495 key = ieee->tx_keyidx;
497 crypt = ieee->crypt[key];
498 erq->flags = key + 1;
502 erq->flags |= IW_ENCODE_DISABLED;
506 len = sec->key_sizes[key];
507 memcpy(keybuf, sec->keys[key], len);
510 erq->flags |= IW_ENCODE_ENABLED;
513 erq->flags |= IW_ENCODE_OPEN;
515 erq->flags |= IW_ENCODE_RESTRICTED;
520 int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
521 struct iw_request_info *info,
522 union iwreq_data *wrqu, char *extra)
524 struct net_device *dev = ieee->dev;
525 struct iw_point *encoding = &wrqu->encoding;
526 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
529 const char *alg, *module;
530 struct ieee80211_crypto_ops *ops;
531 struct ieee80211_crypt_data **crypt;
533 struct ieee80211_security sec = {
537 idx = encoding->flags & IW_ENCODE_INDEX;
539 if (idx < 1 || idx > WEP_KEYS)
543 idx = ieee->tx_keyidx;
545 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
546 crypt = &ieee->crypt[idx];
549 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
550 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
552 if (ieee->iw_mode == IW_MODE_INFRA)
553 crypt = &ieee->crypt[idx];
558 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
559 if ((encoding->flags & IW_ENCODE_DISABLED) ||
560 ext->alg == IW_ENCODE_ALG_NONE) {
562 ieee80211_crypt_delayed_deinit(ieee, crypt);
564 for (i = 0; i < WEP_KEYS; i++)
565 if (ieee->crypt[i] != NULL)
571 sec.level = SEC_LEVEL_0;
572 sec.flags |= SEC_LEVEL;
580 if (group_key ? !ieee->host_mc_decrypt :
581 !(ieee->host_encrypt || ieee->host_decrypt ||
582 ieee->host_encrypt_msdu))
583 goto skip_host_crypt;
586 case IW_ENCODE_ALG_WEP:
588 module = "ieee80211_crypt_wep";
590 case IW_ENCODE_ALG_TKIP:
592 module = "ieee80211_crypt_tkip";
594 case IW_ENCODE_ALG_CCMP:
596 module = "ieee80211_crypt_ccmp";
599 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
600 dev->name, ext->alg);
605 ops = ieee80211_get_crypto_ops(alg);
607 request_module(module);
608 ops = ieee80211_get_crypto_ops(alg);
611 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
612 dev->name, ext->alg);
617 if (*crypt == NULL || (*crypt)->ops != ops) {
618 struct ieee80211_crypt_data *new_crypt;
620 ieee80211_crypt_delayed_deinit(ieee, crypt);
622 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
623 if (new_crypt == NULL) {
627 new_crypt->ops = ops;
628 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
629 new_crypt->priv = new_crypt->ops->init(idx);
630 if (new_crypt->priv == NULL) {
638 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
639 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
640 (*crypt)->priv) < 0) {
641 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
647 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
648 ieee->tx_keyidx = idx;
649 sec.active_key = idx;
650 sec.flags |= SEC_ACTIVE_KEY;
653 if (ext->alg != IW_ENCODE_ALG_NONE) {
654 memcpy(sec.keys[idx], ext->key, ext->key_len);
655 sec.key_sizes[idx] = ext->key_len;
656 sec.flags |= (1 << idx);
657 if (ext->alg == IW_ENCODE_ALG_WEP) {
658 sec.encode_alg[idx] = SEC_ALG_WEP;
659 sec.flags |= SEC_LEVEL;
660 sec.level = SEC_LEVEL_1;
661 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
662 sec.encode_alg[idx] = SEC_ALG_TKIP;
663 sec.flags |= SEC_LEVEL;
664 sec.level = SEC_LEVEL_2;
665 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
666 sec.encode_alg[idx] = SEC_ALG_CCMP;
667 sec.flags |= SEC_LEVEL;
668 sec.level = SEC_LEVEL_3;
670 /* Don't set sec level for group keys. */
672 sec.flags &= ~SEC_LEVEL;
675 if (ieee->set_security)
676 ieee->set_security(ieee->dev, &sec);
679 * Do not reset port if card is in Managed mode since resetting will
680 * generate new IEEE 802.11 authentication which may end up in looping
681 * with IEEE 802.1X. If your hardware requires a reset after WEP
682 * configuration (for example... Prism2), implement the reset_port in
683 * the callbacks structures used to initialize the 802.11 stack.
685 if (ieee->reset_on_keychange &&
686 ieee->iw_mode != IW_MODE_INFRA &&
687 ieee->reset_port && ieee->reset_port(dev)) {
688 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
695 int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
696 struct iw_request_info *info,
697 union iwreq_data *wrqu, char *extra)
699 struct iw_point *encoding = &wrqu->encoding;
700 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
701 struct ieee80211_security *sec = &ieee->sec;
702 int idx, max_key_len;
704 max_key_len = encoding->length - sizeof(*ext);
708 idx = encoding->flags & IW_ENCODE_INDEX;
710 if (idx < 1 || idx > WEP_KEYS)
714 idx = ieee->tx_keyidx;
716 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
717 ext->alg != IW_ENCODE_ALG_WEP)
718 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
721 encoding->flags = idx + 1;
722 memset(ext, 0, sizeof(*ext));
725 ext->alg = IW_ENCODE_ALG_NONE;
727 encoding->flags |= IW_ENCODE_DISABLED;
729 if (sec->encode_alg[idx] == SEC_ALG_WEP)
730 ext->alg = IW_ENCODE_ALG_WEP;
731 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
732 ext->alg = IW_ENCODE_ALG_TKIP;
733 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
734 ext->alg = IW_ENCODE_ALG_CCMP;
738 ext->key_len = sec->key_sizes[idx];
739 memcpy(ext->key, sec->keys[idx], ext->key_len);
740 encoding->flags |= IW_ENCODE_ENABLED;
742 (ext->alg == IW_ENCODE_ALG_TKIP ||
743 ext->alg == IW_ENCODE_ALG_CCMP))
744 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
751 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
752 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
754 EXPORT_SYMBOL(ieee80211_wx_get_scan);
755 EXPORT_SYMBOL(ieee80211_wx_set_encode);
756 EXPORT_SYMBOL(ieee80211_wx_get_encode);