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;
152 iwe.u.qual.level = 0;
154 iwe.u.qual.level = network->stats.rssi;
155 if (ieee->perfect_rssi == ieee->worst_rssi)
156 iwe.u.qual.qual = 100;
160 (ieee->perfect_rssi - ieee->worst_rssi) *
161 (ieee->perfect_rssi - ieee->worst_rssi) -
162 (ieee->perfect_rssi - network->stats.rssi) *
163 (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
164 62 * (ieee->perfect_rssi -
165 network->stats.rssi))) /
166 ((ieee->perfect_rssi -
167 ieee->worst_rssi) * (ieee->perfect_rssi -
169 if (iwe.u.qual.qual > 100)
170 iwe.u.qual.qual = 100;
171 else if (iwe.u.qual.qual < 1)
175 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
176 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
177 iwe.u.qual.noise = 0;
179 iwe.u.qual.noise = network->stats.noise;
182 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
184 iwe.cmd = IWEVCUSTOM;
187 iwe.u.data.length = p - custom;
188 if (iwe.u.data.length)
189 start = iwe_stream_add_point(start, stop, &iwe, custom);
191 if (network->wpa_ie_len) {
192 char buf[MAX_WPA_IE_LEN * 2 + 30];
195 p += sprintf(p, "wpa_ie=");
196 for (i = 0; i < network->wpa_ie_len; i++) {
197 p += sprintf(p, "%02x", network->wpa_ie[i]);
200 memset(&iwe, 0, sizeof(iwe));
201 iwe.cmd = IWEVCUSTOM;
202 iwe.u.data.length = strlen(buf);
203 start = iwe_stream_add_point(start, stop, &iwe, buf);
206 if (network->rsn_ie_len) {
207 char buf[MAX_WPA_IE_LEN * 2 + 30];
210 p += sprintf(p, "rsn_ie=");
211 for (i = 0; i < network->rsn_ie_len; i++) {
212 p += sprintf(p, "%02x", network->rsn_ie[i]);
215 memset(&iwe, 0, sizeof(iwe));
216 iwe.cmd = IWEVCUSTOM;
217 iwe.u.data.length = strlen(buf);
218 start = iwe_stream_add_point(start, stop, &iwe, buf);
221 /* Add EXTRA: Age to display seconds since last beacon/probe response
222 * for given network. */
223 iwe.cmd = IWEVCUSTOM;
225 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
226 " Last beacon: %dms ago",
227 jiffies_to_msecs(jiffies - network->last_scanned));
228 iwe.u.data.length = p - custom;
229 if (iwe.u.data.length)
230 start = iwe_stream_add_point(start, stop, &iwe, custom);
235 #define SCAN_ITEM_SIZE 128
237 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
238 struct iw_request_info *info,
239 union iwreq_data *wrqu, char *extra)
241 struct ieee80211_network *network;
246 char *stop = ev + wrqu->data.length;
249 IEEE80211_DEBUG_WX("Getting scan\n");
251 spin_lock_irqsave(&ieee->lock, flags);
253 list_for_each_entry(network, &ieee->network_list, list) {
255 if (stop - ev < SCAN_ITEM_SIZE) {
260 if (ieee->scan_age == 0 ||
261 time_after(network->last_scanned + ieee->scan_age, jiffies))
262 ev = ipw2100_translate_scan(ieee, ev, stop, network);
264 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
265 MAC_FMT ")' due to age (%dms).\n",
266 escape_essid(network->ssid,
268 MAC_ARG(network->bssid),
269 jiffies_to_msecs(jiffies -
274 spin_unlock_irqrestore(&ieee->lock, flags);
276 wrqu->data.length = ev - extra;
277 wrqu->data.flags = 0;
279 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
284 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
285 struct iw_request_info *info,
286 union iwreq_data *wrqu, char *keybuf)
288 struct iw_point *erq = &(wrqu->encoding);
289 struct net_device *dev = ieee->dev;
290 struct ieee80211_security sec = {
293 int i, key, key_provided, len;
294 struct ieee80211_crypt_data **crypt;
295 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
297 IEEE80211_DEBUG_WX("SET_ENCODE\n");
299 key = erq->flags & IW_ENCODE_INDEX;
307 key = ieee->tx_keyidx;
310 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
311 "provided" : "default");
313 crypt = &ieee->crypt[key];
315 if (erq->flags & IW_ENCODE_DISABLED) {
316 if (key_provided && *crypt) {
317 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
319 ieee80211_crypt_delayed_deinit(ieee, crypt);
321 IEEE80211_DEBUG_WX("Disabling encryption.\n");
323 /* Check all the keys to see if any are still configured,
324 * and if no key index was provided, de-init them all */
325 for (i = 0; i < WEP_KEYS; i++) {
326 if (ieee->crypt[i] != NULL) {
329 ieee80211_crypt_delayed_deinit(ieee,
337 sec.level = SEC_LEVEL_0;
338 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
346 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
348 if (*crypt != NULL && (*crypt)->ops != NULL &&
349 strcmp((*crypt)->ops->name, "WEP") != 0) {
350 /* changing to use WEP; deinit previously used algorithm
352 ieee80211_crypt_delayed_deinit(ieee, crypt);
355 if (*crypt == NULL && host_crypto) {
356 struct ieee80211_crypt_data *new_crypt;
358 /* take WEP into use */
359 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
361 if (new_crypt == NULL)
363 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
364 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
365 if (!new_crypt->ops) {
366 request_module("ieee80211_crypt_wep");
367 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
370 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
371 new_crypt->priv = new_crypt->ops->init(key);
373 if (!new_crypt->ops || !new_crypt->priv) {
377 printk(KERN_WARNING "%s: could not initialize WEP: "
378 "load module ieee80211_crypt_wep\n", dev->name);
384 /* If a new key was provided, set it up */
385 if (erq->length > 0) {
386 len = erq->length <= 5 ? 5 : 13;
387 memcpy(sec.keys[key], keybuf, erq->length);
388 if (len > erq->length)
389 memset(sec.keys[key] + erq->length, 0,
391 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
392 key, escape_essid(sec.keys[key], len),
394 sec.key_sizes[key] = len;
396 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
398 sec.flags |= (1 << key);
399 /* This ensures a key will be activated if no key is
401 if (key == sec.active_key)
402 sec.flags |= SEC_ACTIVE_KEY;
406 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
407 NULL, (*crypt)->priv);
409 /* Set a default key of all 0 */
410 IEEE80211_DEBUG_WX("Setting key %d to all "
412 memset(sec.keys[key], 0, 13);
413 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
415 sec.key_sizes[key] = 13;
416 sec.flags |= (1 << key);
419 /* No key data - just set the default TX key index */
421 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
423 ieee->tx_keyidx = key;
424 sec.active_key = key;
425 sec.flags |= SEC_ACTIVE_KEY;
428 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
429 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
430 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
431 WLAN_AUTH_SHARED_KEY;
432 sec.flags |= SEC_AUTH_MODE;
433 IEEE80211_DEBUG_WX("Auth: %s\n",
434 sec.auth_mode == WLAN_AUTH_OPEN ?
435 "OPEN" : "SHARED KEY");
438 /* For now we just support WEP, so only set that security level...
439 * TODO: When WPA is added this is one place that needs to change */
440 sec.flags |= SEC_LEVEL;
441 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
442 sec.encode_alg[key] = SEC_ALG_WEP;
445 if (ieee->set_security)
446 ieee->set_security(dev, &sec);
448 /* Do not reset port if card is in Managed mode since resetting will
449 * generate new IEEE 802.11 authentication which may end up in looping
450 * with IEEE 802.1X. If your hardware requires a reset after WEP
451 * configuration (for example... Prism2), implement the reset_port in
452 * the callbacks structures used to initialize the 802.11 stack. */
453 if (ieee->reset_on_keychange &&
454 ieee->iw_mode != IW_MODE_INFRA &&
455 ieee->reset_port && ieee->reset_port(dev)) {
456 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
462 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
463 struct iw_request_info *info,
464 union iwreq_data *wrqu, char *keybuf)
466 struct iw_point *erq = &(wrqu->encoding);
468 struct ieee80211_crypt_data *crypt;
469 struct ieee80211_security *sec = &ieee->sec;
471 IEEE80211_DEBUG_WX("GET_ENCODE\n");
473 key = erq->flags & IW_ENCODE_INDEX;
479 key = ieee->tx_keyidx;
481 crypt = ieee->crypt[key];
482 erq->flags = key + 1;
486 erq->flags |= IW_ENCODE_DISABLED;
490 len = sec->key_sizes[key];
491 memcpy(keybuf, sec->keys[key], len);
493 erq->length = (len >= 0 ? len : 0);
494 erq->flags |= IW_ENCODE_ENABLED;
497 erq->flags |= IW_ENCODE_OPEN;
499 erq->flags |= IW_ENCODE_RESTRICTED;
504 int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
505 struct iw_request_info *info,
506 union iwreq_data *wrqu, char *extra)
508 struct net_device *dev = ieee->dev;
509 struct iw_point *encoding = &wrqu->encoding;
510 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
513 const char *alg, *module;
514 struct ieee80211_crypto_ops *ops;
515 struct ieee80211_crypt_data **crypt;
517 struct ieee80211_security sec = {
521 idx = encoding->flags & IW_ENCODE_INDEX;
523 if (idx < 1 || idx > WEP_KEYS)
527 idx = ieee->tx_keyidx;
529 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
530 crypt = &ieee->crypt[idx];
533 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
534 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
536 if (ieee->iw_mode == IW_MODE_INFRA)
537 crypt = &ieee->crypt[idx];
542 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
543 if ((encoding->flags & IW_ENCODE_DISABLED) ||
544 ext->alg == IW_ENCODE_ALG_NONE) {
546 ieee80211_crypt_delayed_deinit(ieee, crypt);
548 for (i = 0; i < WEP_KEYS; i++)
549 if (ieee->crypt[i] != NULL)
555 sec.level = SEC_LEVEL_0;
556 sec.flags |= SEC_LEVEL;
564 if (group_key ? !ieee->host_mc_decrypt :
565 !(ieee->host_encrypt || ieee->host_decrypt ||
566 ieee->host_encrypt_msdu))
567 goto skip_host_crypt;
570 case IW_ENCODE_ALG_WEP:
572 module = "ieee80211_crypt_wep";
574 case IW_ENCODE_ALG_TKIP:
576 module = "ieee80211_crypt_tkip";
578 case IW_ENCODE_ALG_CCMP:
580 module = "ieee80211_crypt_ccmp";
583 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
584 dev->name, ext->alg);
589 ops = ieee80211_get_crypto_ops(alg);
591 request_module(module);
592 ops = ieee80211_get_crypto_ops(alg);
595 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
596 dev->name, ext->alg);
601 if (*crypt == NULL || (*crypt)->ops != ops) {
602 struct ieee80211_crypt_data *new_crypt;
604 ieee80211_crypt_delayed_deinit(ieee, crypt);
606 new_crypt = (struct ieee80211_crypt_data *)
607 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
608 if (new_crypt == NULL) {
612 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
613 new_crypt->ops = ops;
614 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
615 new_crypt->priv = new_crypt->ops->init(idx);
616 if (new_crypt->priv == NULL) {
624 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
625 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
626 (*crypt)->priv) < 0) {
627 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
633 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
634 ieee->tx_keyidx = idx;
635 sec.active_key = idx;
636 sec.flags |= SEC_ACTIVE_KEY;
639 if (ext->alg != IW_ENCODE_ALG_NONE) {
640 memcpy(sec.keys[idx], ext->key, ext->key_len);
641 sec.key_sizes[idx] = ext->key_len;
642 sec.flags |= (1 << idx);
643 if (ext->alg == IW_ENCODE_ALG_WEP) {
644 sec.encode_alg[idx] = SEC_ALG_WEP;
645 sec.flags |= SEC_LEVEL;
646 sec.level = SEC_LEVEL_1;
647 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
648 sec.encode_alg[idx] = SEC_ALG_TKIP;
649 sec.flags |= SEC_LEVEL;
650 sec.level = SEC_LEVEL_2;
651 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
652 sec.encode_alg[idx] = SEC_ALG_CCMP;
653 sec.flags |= SEC_LEVEL;
654 sec.level = SEC_LEVEL_3;
656 /* Don't set sec level for group keys. */
658 sec.flags &= ~SEC_LEVEL;
661 if (ieee->set_security)
662 ieee->set_security(ieee->dev, &sec);
665 * Do not reset port if card is in Managed mode since resetting will
666 * generate new IEEE 802.11 authentication which may end up in looping
667 * with IEEE 802.1X. If your hardware requires a reset after WEP
668 * configuration (for example... Prism2), implement the reset_port in
669 * the callbacks structures used to initialize the 802.11 stack.
671 if (ieee->reset_on_keychange &&
672 ieee->iw_mode != IW_MODE_INFRA &&
673 ieee->reset_port && ieee->reset_port(dev)) {
674 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
681 int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
682 struct iw_request_info *info,
683 union iwreq_data *wrqu, char *extra)
685 struct iw_point *encoding = &wrqu->encoding;
686 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
687 struct ieee80211_security *sec = &ieee->sec;
688 int idx, max_key_len;
690 max_key_len = encoding->length - sizeof(*ext);
694 idx = encoding->flags & IW_ENCODE_INDEX;
696 if (idx < 1 || idx > WEP_KEYS)
700 idx = ieee->tx_keyidx;
702 if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
703 ext->alg != IW_ENCODE_ALG_WEP)
704 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
707 encoding->flags = idx + 1;
708 memset(ext, 0, sizeof(*ext));
711 ext->alg = IW_ENCODE_ALG_NONE;
713 encoding->flags |= IW_ENCODE_DISABLED;
715 if (sec->encode_alg[idx] == SEC_ALG_WEP)
716 ext->alg = IW_ENCODE_ALG_WEP;
717 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
718 ext->alg = IW_ENCODE_ALG_TKIP;
719 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
720 ext->alg = IW_ENCODE_ALG_CCMP;
724 ext->key_len = sec->key_sizes[idx];
725 memcpy(ext->key, sec->keys[idx], ext->key_len);
726 encoding->flags |= IW_ENCODE_ENABLED;
728 (ext->alg == IW_ENCODE_ALG_TKIP ||
729 ext->alg == IW_ENCODE_ALG_CCMP))
730 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
737 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
738 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
740 EXPORT_SYMBOL(ieee80211_wx_get_scan);
741 EXPORT_SYMBOL(ieee80211_wx_set_encode);
742 EXPORT_SYMBOL(ieee80211_wx_get_encode);