1 /******************************************************************************
3 Copyright(c) 2004 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 inline 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;
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 - network->stats.rssi))) /
162 ((ieee->perfect_rssi - ieee->worst_rssi) *
163 (ieee->perfect_rssi - ieee->worst_rssi));
164 if (iwe.u.qual.qual > 100)
165 iwe.u.qual.qual = 100;
166 else if (iwe.u.qual.qual < 1)
170 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
171 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
172 iwe.u.qual.noise = 0;
174 iwe.u.qual.noise = network->stats.noise;
177 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
179 iwe.cmd = IWEVCUSTOM;
182 iwe.u.data.length = p - custom;
183 if (iwe.u.data.length)
184 start = iwe_stream_add_point(start, stop, &iwe, custom);
186 if (network->wpa_ie_len) {
187 char buf[MAX_WPA_IE_LEN * 2 + 30];
190 p += sprintf(p, "wpa_ie=");
191 for (i = 0; i < network->wpa_ie_len; i++) {
192 p += sprintf(p, "%02x", network->wpa_ie[i]);
195 memset(&iwe, 0, sizeof(iwe));
196 iwe.cmd = IWEVCUSTOM;
197 iwe.u.data.length = strlen(buf);
198 start = iwe_stream_add_point(start, stop, &iwe, buf);
201 if (network->rsn_ie_len) {
202 char buf[MAX_WPA_IE_LEN * 2 + 30];
205 p += sprintf(p, "rsn_ie=");
206 for (i = 0; i < network->rsn_ie_len; i++) {
207 p += sprintf(p, "%02x", network->rsn_ie[i]);
210 memset(&iwe, 0, sizeof(iwe));
211 iwe.cmd = IWEVCUSTOM;
212 iwe.u.data.length = strlen(buf);
213 start = iwe_stream_add_point(start, stop, &iwe, buf);
216 /* Add EXTRA: Age to display seconds since last beacon/probe response
217 * for given network. */
218 iwe.cmd = IWEVCUSTOM;
220 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
221 " Last beacon: %dms ago",
222 jiffies_to_msecs(jiffies - network->last_scanned));
223 iwe.u.data.length = p - custom;
224 if (iwe.u.data.length)
225 start = iwe_stream_add_point(start, stop, &iwe, custom);
230 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
231 struct iw_request_info *info,
232 union iwreq_data *wrqu, char *extra)
234 struct ieee80211_network *network;
238 char *stop = ev + IW_SCAN_MAX_DATA;
241 IEEE80211_DEBUG_WX("Getting scan\n");
243 spin_lock_irqsave(&ieee->lock, flags);
245 list_for_each_entry(network, &ieee->network_list, list) {
247 if (ieee->scan_age == 0 ||
248 time_after(network->last_scanned + ieee->scan_age, jiffies))
249 ev = ipw2100_translate_scan(ieee, ev, stop, network);
251 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
252 MAC_FMT ")' due to age (%dms).\n",
253 escape_essid(network->ssid,
255 MAC_ARG(network->bssid),
256 jiffies_to_msecs(jiffies -
261 spin_unlock_irqrestore(&ieee->lock, flags);
263 wrqu->data.length = ev - extra;
264 wrqu->data.flags = 0;
266 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
271 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
272 struct iw_request_info *info,
273 union iwreq_data *wrqu, char *keybuf)
275 struct iw_point *erq = &(wrqu->encoding);
276 struct net_device *dev = ieee->dev;
277 struct ieee80211_security sec = {
280 int i, key, key_provided, len;
281 struct ieee80211_crypt_data **crypt;
282 int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
284 IEEE80211_DEBUG_WX("SET_ENCODE\n");
286 key = erq->flags & IW_ENCODE_INDEX;
294 key = ieee->tx_keyidx;
297 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
298 "provided" : "default");
300 crypt = &ieee->crypt[key];
302 if (erq->flags & IW_ENCODE_DISABLED) {
303 if (key_provided && *crypt) {
304 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
306 ieee80211_crypt_delayed_deinit(ieee, crypt);
308 IEEE80211_DEBUG_WX("Disabling encryption.\n");
310 /* Check all the keys to see if any are still configured,
311 * and if no key index was provided, de-init them all */
312 for (i = 0; i < WEP_KEYS; i++) {
313 if (ieee->crypt[i] != NULL) {
316 ieee80211_crypt_delayed_deinit(ieee,
324 sec.level = SEC_LEVEL_0;
325 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
333 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
335 if (*crypt != NULL && (*crypt)->ops != NULL &&
336 strcmp((*crypt)->ops->name, "WEP") != 0) {
337 /* changing to use WEP; deinit previously used algorithm
339 ieee80211_crypt_delayed_deinit(ieee, crypt);
342 if (*crypt == NULL && host_crypto) {
343 struct ieee80211_crypt_data *new_crypt;
345 /* take WEP into use */
346 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
348 if (new_crypt == NULL)
350 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
351 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
352 if (!new_crypt->ops) {
353 request_module("ieee80211_crypt_wep");
354 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
357 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
358 new_crypt->priv = new_crypt->ops->init(ieee, key);
360 if (!new_crypt->ops || !new_crypt->priv) {
364 printk(KERN_WARNING "%s: could not initialize WEP: "
365 "load module ieee80211_crypt_wep\n", dev->name);
371 /* If a new key was provided, set it up */
372 if (erq->length > 0) {
373 len = erq->length <= 5 ? 5 : 13;
374 memcpy(sec.keys[key], keybuf, erq->length);
375 if (len > erq->length)
376 memset(sec.keys[key] + erq->length, 0,
378 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
379 key, escape_essid(sec.keys[key], len),
381 sec.key_sizes[key] = len;
383 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
385 sec.flags |= (1 << key);
386 /* This ensures a key will be activated if no key is
388 if (key == sec.active_key)
389 sec.flags |= SEC_ACTIVE_KEY;
393 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
394 NULL, (*crypt)->priv);
396 /* Set a default key of all 0 */
397 IEEE80211_DEBUG_WX("Setting key %d to all "
399 memset(sec.keys[key], 0, 13);
400 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
402 sec.key_sizes[key] = 13;
403 sec.flags |= (1 << key);
406 /* No key data - just set the default TX key index */
408 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
410 ieee->tx_keyidx = key;
411 sec.active_key = key;
412 sec.flags |= SEC_ACTIVE_KEY;
415 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
416 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
417 sec.flags |= SEC_AUTH_MODE;
418 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
419 "OPEN" : "SHARED KEY");
421 /* For now we just support WEP, so only set that security level...
422 * TODO: When WPA is added this is one place that needs to change */
423 sec.flags |= SEC_LEVEL;
424 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
425 sec.encode_alg[key] = SEC_ALG_WEP;
428 if (ieee->set_security)
429 ieee->set_security(dev, &sec);
431 /* Do not reset port if card is in Managed mode since resetting will
432 * generate new IEEE 802.11 authentication which may end up in looping
433 * with IEEE 802.1X. If your hardware requires a reset after WEP
434 * configuration (for example... Prism2), implement the reset_port in
435 * the callbacks structures used to initialize the 802.11 stack. */
436 if (ieee->reset_on_keychange &&
437 ieee->iw_mode != IW_MODE_INFRA &&
438 ieee->reset_port && ieee->reset_port(dev)) {
439 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
445 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
446 struct iw_request_info *info,
447 union iwreq_data *wrqu, char *keybuf)
449 struct iw_point *erq = &(wrqu->encoding);
451 struct ieee80211_crypt_data *crypt;
452 struct ieee80211_security *sec = &ieee->sec;
454 IEEE80211_DEBUG_WX("GET_ENCODE\n");
456 key = erq->flags & IW_ENCODE_INDEX;
462 key = ieee->tx_keyidx;
464 crypt = ieee->crypt[key];
465 erq->flags = key + 1;
469 erq->flags |= IW_ENCODE_DISABLED;
473 len = sec->key_sizes[key];
474 memcpy(keybuf, sec->keys[key], len);
476 erq->length = (len >= 0 ? len : 0);
477 erq->flags |= IW_ENCODE_ENABLED;
480 erq->flags |= IW_ENCODE_OPEN;
482 erq->flags |= IW_ENCODE_RESTRICTED;
487 #if WIRELESS_EXT > 17
488 int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
489 struct iw_request_info *info,
490 union iwreq_data *wrqu, char *extra)
492 struct net_device *dev = ieee->dev;
493 struct iw_point *encoding = &wrqu->encoding;
494 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
496 const char *alg, *module;
497 struct ieee80211_crypto_ops *ops;
498 struct ieee80211_crypt_data **crypt;
500 struct ieee80211_security sec = {
504 idx = encoding->flags & IW_ENCODE_INDEX;
506 if (idx < 1 || idx > WEP_KEYS)
510 idx = ieee->tx_keyidx;
512 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
513 crypt = &ieee->crypt[idx];
517 if (ieee->iw_mode == IW_MODE_INFRA)
518 crypt = &ieee->crypt[idx];
523 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
524 if ((encoding->flags & IW_ENCODE_DISABLED) ||
525 ext->alg == IW_ENCODE_ALG_NONE) {
527 ieee80211_crypt_delayed_deinit(ieee, crypt);
529 for (i = 0; i < WEP_KEYS; i++)
530 if (ieee->crypt[i] != NULL)
536 sec.level = SEC_LEVEL_0;
537 sec.flags |= SEC_LEVEL;
545 if (!(ieee->host_encrypt || ieee->host_decrypt))
546 goto skip_host_crypt;
549 case IW_ENCODE_ALG_WEP:
551 module = "ieee80211_crypt_wep";
553 case IW_ENCODE_ALG_TKIP:
555 module = "ieee80211_crypt_tkip";
557 case IW_ENCODE_ALG_CCMP:
559 module = "ieee80211_crypt_ccmp";
562 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
563 dev->name, ext->alg);
568 ops = ieee80211_get_crypto_ops(alg);
570 request_module(module);
571 ops = ieee80211_get_crypto_ops(alg);
574 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
575 dev->name, ext->alg);
580 if (*crypt == NULL || (*crypt)->ops != ops) {
581 struct ieee80211_crypt_data *new_crypt;
583 ieee80211_crypt_delayed_deinit(ieee, crypt);
585 new_crypt = (struct ieee80211_crypt_data *)
586 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
587 if (new_crypt == NULL) {
591 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
592 new_crypt->ops = ops;
593 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
594 new_crypt->priv = new_crypt->ops->init(ieee, idx);
595 if (new_crypt->priv == NULL) {
603 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
604 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
605 (*crypt)->priv) < 0) {
606 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
612 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
613 ieee->tx_keyidx = idx;
614 sec.active_key = idx;
615 sec.flags |= SEC_ACTIVE_KEY;
618 if (ext->alg != IW_ENCODE_ALG_NONE) {
619 memcpy(sec.keys[idx], ext->key, ext->key_len);
620 sec.key_sizes[idx] = ext->key_len;
621 sec.flags |= (1 << idx);
622 if (ext->alg == IW_ENCODE_ALG_WEP) {
623 sec.encode_alg[idx] = SEC_ALG_WEP;
624 sec.flags |= SEC_LEVEL;
625 sec.level = SEC_LEVEL_1;
626 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
627 sec.encode_alg[idx] = SEC_ALG_TKIP;
628 sec.flags |= SEC_LEVEL;
629 sec.level = SEC_LEVEL_2;
630 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
631 sec.encode_alg[idx] = SEC_ALG_CCMP;
632 sec.flags |= SEC_LEVEL;
633 sec.level = SEC_LEVEL_3;
637 if (ieee->set_security)
638 ieee->set_security(ieee->dev, &sec);
641 * Do not reset port if card is in Managed mode since resetting will
642 * generate new IEEE 802.11 authentication which may end up in looping
643 * with IEEE 802.1X. If your hardware requires a reset after WEP
644 * configuration (for example... Prism2), implement the reset_port in
645 * the callbacks structures used to initialize the 802.11 stack.
647 if (ieee->reset_on_keychange &&
648 ieee->iw_mode != IW_MODE_INFRA &&
649 ieee->reset_port && ieee->reset_port(dev)) {
650 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
657 int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
658 struct iw_request_info *info,
659 union iwreq_data *wrqu, char *extra)
661 struct iw_point *encoding = &wrqu->encoding;
662 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
663 struct ieee80211_security *sec = &ieee->sec;
664 int idx, max_key_len;
666 max_key_len = encoding->length - sizeof(*ext);
670 idx = encoding->flags & IW_ENCODE_INDEX;
672 if (idx < 1 || idx > WEP_KEYS)
676 idx = ieee->tx_keyidx;
678 if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
679 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
682 encoding->flags = idx + 1;
683 memset(ext, 0, sizeof(*ext));
686 ext->alg = IW_ENCODE_ALG_NONE;
688 encoding->flags |= IW_ENCODE_DISABLED;
690 if (sec->encode_alg[idx] == SEC_ALG_WEP)
691 ext->alg = IW_ENCODE_ALG_WEP;
692 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
693 ext->alg = IW_ENCODE_ALG_TKIP;
694 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
695 ext->alg = IW_ENCODE_ALG_CCMP;
699 ext->key_len = sec->key_sizes[idx];
700 memcpy(ext->key, sec->keys[idx], ext->key_len);
701 encoding->flags |= IW_ENCODE_ENABLED;
703 (ext->alg == IW_ENCODE_ALG_TKIP ||
704 ext->alg == IW_ENCODE_ALG_CCMP))
705 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
712 EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
713 EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
716 EXPORT_SYMBOL(ieee80211_wx_get_scan);
717 EXPORT_SYMBOL(ieee80211_wx_set_encode);
718 EXPORT_SYMBOL(ieee80211_wx_get_encode);