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 ******************************************************************************/
32 #include <linux/wireless.h>
33 #include <linux/kmod.h>
34 #include <linux/module.h>
36 #include "ieee80211.h"
42 struct modes_unit ieee80211_modes[] = {
51 #define iwe_stream_add_event_rsl iwe_stream_add_event
53 #define MAX_CUSTOM_LEN 64
54 static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
55 char *start, char *stop,
56 struct ieee80211_network *network,
57 struct iw_request_info *info)
59 char custom[MAX_CUSTOM_LEN];
60 char proto_name[IFNAMSIZ];
61 char *pname = proto_name;
66 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
68 /* First entry *MUST* be the AP MAC address */
70 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
71 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
72 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
74 /* Remaining entries will be displayed in the order we provide them */
77 iwe.cmd = SIOCGIWESSID;
79 // if (network->flags & NETWORK_EMPTY_ESSID) {
80 if (network->ssid_len == 0) {
81 iwe.u.data.length = sizeof("<hidden>");
82 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
84 iwe.u.data.length = min(network->ssid_len, (u8)32);
85 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
87 /* Add the protocol name */
88 iwe.cmd = SIOCGIWNAME;
89 for(i=0; i<ARRAY_SIZE(ieee80211_modes); i++) {
90 if(network->mode&(1<<i)) {
91 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
92 pname +=ieee80211_modes[i].mode_size;
96 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
97 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
99 iwe.cmd = SIOCGIWMODE;
100 if (network->capability &
101 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
102 if (network->capability & WLAN_CAPABILITY_BSS)
103 iwe.u.mode = IW_MODE_MASTER;
105 iwe.u.mode = IW_MODE_ADHOC;
106 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
109 /* Add frequency/channel */
110 iwe.cmd = SIOCGIWFREQ;
111 /* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
113 iwe.u.freq.m = network->channel;
116 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
117 /* Add encryption capability */
118 iwe.cmd = SIOCGIWENCODE;
119 if (network->capability & WLAN_CAPABILITY_PRIVACY)
120 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
122 iwe.u.data.flags = IW_ENCODE_DISABLED;
123 iwe.u.data.length = 0;
124 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
125 /* Add basic and extended rates */
128 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
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;
138 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
139 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
141 for (; j < network->rates_ex_len; j++) {
142 rate = network->rates_ex[j] & 0x7F;
143 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
144 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
149 if (network->mode >= IEEE_N_24G)//add N rate here;
151 PHT_CAPABILITY_ELE ht_cap = NULL;
152 bool is40M = false, isShortGI = false;
154 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
155 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
157 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
158 is40M = (ht_cap->ChlWidth)?1:0;
159 isShortGI = (ht_cap->ChlWidth)?
160 ((ht_cap->ShortGI40Mhz)?1:0):
161 ((ht_cap->ShortGI20Mhz)?1:0);
163 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
164 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
169 iwe.cmd = SIOCGIWRATE;
170 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
171 iwe.u.bitrate.value = max_rate * 500000;
172 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
175 iwe.cmd = IWEVCUSTOM;
176 iwe.u.data.length = p - custom;
177 if (iwe.u.data.length)
178 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
180 /* Add quality statistics */
181 /* TODO: Fix these values... */
183 iwe.u.qual.qual = network->stats.signal;
184 iwe.u.qual.level = network->stats.rssi;
185 iwe.u.qual.noise = network->stats.noise;
186 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
187 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
188 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
189 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
190 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
191 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
192 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
193 iwe.u.qual.updated = 7;
194 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
195 iwe.cmd = IWEVCUSTOM;
198 iwe.u.data.length = p - custom;
199 if (iwe.u.data.length)
200 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
202 memset(&iwe, 0, sizeof(iwe));
203 if (network->wpa_ie_len)
205 char buf[MAX_WPA_IE_LEN];
206 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
208 iwe.u.data.length = network->wpa_ie_len;
209 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
211 memset(&iwe, 0, sizeof(iwe));
212 if (network->rsn_ie_len)
214 char buf[MAX_WPA_IE_LEN];
215 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
217 iwe.u.data.length = network->rsn_ie_len;
218 start = iwe_stream_add_point(info, 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: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
227 iwe.u.data.length = p - custom;
228 if (iwe.u.data.length)
229 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
234 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
235 struct iw_request_info *info,
236 union iwreq_data *wrqu, char *extra)
238 struct ieee80211_network *network;
242 // char *stop = ev + IW_SCAN_MAX_DATA;
243 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
244 //char *stop = ev + IW_SCAN_MAX_DATA;
247 IEEE80211_DEBUG_WX("Getting scan\n");
249 spin_lock_irqsave(&ieee->lock, flags);
251 list_for_each_entry(network, &ieee->network_list, list) {
258 if (ieee->scan_age == 0 ||
259 time_after(network->last_scanned + ieee->scan_age, jiffies))
260 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
262 IEEE80211_DEBUG_SCAN(
263 "Not showing network '%s ("
264 "%pM)' due to age (%lums).\n",
265 escape_essid(network->ssid,
268 (jiffies - network->last_scanned) / (HZ / 100));
271 spin_unlock_irqrestore(&ieee->lock, flags);
273 wrqu->data.length = ev - extra;
274 wrqu->data.flags = 0;
276 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
281 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
282 struct iw_request_info *info,
283 union iwreq_data *wrqu, char *keybuf)
285 struct iw_point *erq = &(wrqu->encoding);
286 struct net_device *dev = ieee->dev;
287 struct ieee80211_security sec = {
290 int i, key, key_provided, len;
291 struct ieee80211_crypt_data **crypt;
293 IEEE80211_DEBUG_WX("SET_ENCODE\n");
295 key = erq->flags & IW_ENCODE_INDEX;
303 key = ieee->tx_keyidx;
306 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
307 "provided" : "default");
308 crypt = &ieee->crypt[key];
310 if (erq->flags & IW_ENCODE_DISABLED) {
311 if (key_provided && *crypt) {
312 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
314 ieee80211_crypt_delayed_deinit(ieee, crypt);
316 IEEE80211_DEBUG_WX("Disabling encryption.\n");
318 /* Check all the keys to see if any are still configured,
319 * and if no key index was provided, de-init them all */
320 for (i = 0; i < WEP_KEYS; i++) {
321 if (ieee->crypt[i] != NULL) {
324 ieee80211_crypt_delayed_deinit(
325 ieee, &ieee->crypt[i]);
331 sec.level = SEC_LEVEL_0;
332 sec.flags |= SEC_ENABLED | SEC_LEVEL;
341 sec.flags |= SEC_ENABLED;
343 if (*crypt != NULL && (*crypt)->ops != NULL &&
344 strcmp((*crypt)->ops->name, "WEP") != 0) {
345 /* changing to use WEP; deinit previously used algorithm
347 ieee80211_crypt_delayed_deinit(ieee, crypt);
350 if (*crypt == NULL) {
351 struct ieee80211_crypt_data *new_crypt;
353 /* take WEP into use */
354 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
356 if (new_crypt == NULL)
358 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
359 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
361 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
363 new_crypt->priv = new_crypt->ops->init(key);
365 if (!new_crypt->ops || !new_crypt->priv) {
369 printk(KERN_WARNING "%s: could not initialize WEP: "
370 "load module ieee80211_crypt_wep\n",
377 /* If a new key was provided, set it up */
378 if (erq->length > 0) {
379 len = erq->length <= 5 ? 5 : 13;
380 memcpy(sec.keys[key], keybuf, erq->length);
381 if (len > erq->length)
382 memset(sec.keys[key] + erq->length, 0,
384 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
385 key, escape_essid(sec.keys[key], len),
387 sec.key_sizes[key] = len;
388 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
390 sec.flags |= (1 << key);
391 /* This ensures a key will be activated if no key is
393 if (key == sec.active_key)
394 sec.flags |= SEC_ACTIVE_KEY;
395 ieee->tx_keyidx = key;
398 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
399 NULL, (*crypt)->priv);
401 /* Set a default key of all 0 */
402 printk("Setting key %d to all zero.\n",
405 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
407 memset(sec.keys[key], 0, 13);
408 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
410 sec.key_sizes[key] = 13;
411 sec.flags |= (1 << key);
414 /* No key data - just set the default TX key index */
417 "Setting key %d to default Tx key.\n", key);
418 ieee->tx_keyidx = key;
419 sec.active_key = key;
420 sec.flags |= SEC_ACTIVE_KEY;
425 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
426 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
427 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
428 sec.flags |= SEC_AUTH_MODE;
429 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
430 "OPEN" : "SHARED KEY");
432 /* For now we just support WEP, so only set that security level...
433 * TODO: When WPA is added this is one place that needs to change */
434 sec.flags |= SEC_LEVEL;
435 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
437 if (ieee->set_security)
438 ieee->set_security(dev, &sec);
440 /* Do not reset port if card is in Managed mode since resetting will
441 * generate new IEEE 802.11 authentication which may end up in looping
442 * with IEEE 802.1X. If your hardware requires a reset after WEP
443 * configuration (for example... Prism2), implement the reset_port in
444 * the callbacks structures used to initialize the 802.11 stack. */
445 if (ieee->reset_on_keychange &&
446 ieee->iw_mode != IW_MODE_INFRA &&
447 ieee->reset_port && ieee->reset_port(dev)) {
448 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
454 int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
455 struct iw_request_info *info,
456 union iwreq_data *wrqu, char *keybuf)
458 struct iw_point *erq = &(wrqu->encoding);
460 struct ieee80211_crypt_data *crypt;
462 IEEE80211_DEBUG_WX("GET_ENCODE\n");
464 if(ieee->iw_mode == IW_MODE_MONITOR)
467 key = erq->flags & IW_ENCODE_INDEX;
473 key = ieee->tx_keyidx;
475 crypt = ieee->crypt[key];
476 erq->flags = key + 1;
478 if (crypt == NULL || crypt->ops == NULL) {
480 erq->flags |= IW_ENCODE_DISABLED;
484 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
485 erq->length = (len >= 0 ? len : 0);
487 erq->flags |= IW_ENCODE_ENABLED;
490 erq->flags |= IW_ENCODE_OPEN;
492 erq->flags |= IW_ENCODE_RESTRICTED;
497 int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
498 struct iw_request_info *info,
499 union iwreq_data *wrqu, char *extra)
502 struct net_device *dev = ieee->dev;
503 struct iw_point *encoding = &wrqu->encoding;
504 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
508 struct ieee80211_crypto_ops *ops;
509 struct ieee80211_crypt_data **crypt;
511 struct ieee80211_security sec = {
514 //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
515 idx = encoding->flags & IW_ENCODE_INDEX;
517 if (idx < 1 || idx > WEP_KEYS)
521 idx = ieee->tx_keyidx;
523 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
525 crypt = &ieee->crypt[idx];
529 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
530 //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
531 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
533 if (ieee->iw_mode == IW_MODE_INFRA)
535 crypt = &ieee->crypt[idx];
541 sec.flags |= SEC_ENABLED;
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++)
550 if (ieee->crypt[i] != NULL)
557 sec.level = SEC_LEVEL_0;
558 sec.flags |= SEC_LEVEL;
560 //printk("disabled: flag:%x\n", encoding->flags);
568 case IW_ENCODE_ALG_WEP:
571 case IW_ENCODE_ALG_TKIP:
574 case IW_ENCODE_ALG_CCMP:
578 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
579 dev->name, ext->alg);
583 printk("alg name:%s\n",alg);
585 ops = ieee80211_get_crypto_ops(alg);
587 ops = ieee80211_get_crypto_ops(alg);
589 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
590 dev->name, ext->alg);
591 printk("========>unknown crypto alg %d\n", ext->alg);
596 if (*crypt == NULL || (*crypt)->ops != ops) {
597 struct ieee80211_crypt_data *new_crypt;
599 ieee80211_crypt_delayed_deinit(ieee, crypt);
601 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
602 if (new_crypt == NULL) {
606 new_crypt->ops = ops;
608 new_crypt->priv = new_crypt->ops->init(idx);
609 if (new_crypt->priv == NULL) {
618 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
619 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
620 (*crypt)->priv) < 0) {
621 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
622 printk("key setting failed\n");
628 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
629 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
630 ieee->tx_keyidx = idx;
631 sec.active_key = idx;
632 sec.flags |= SEC_ACTIVE_KEY;
635 if (ext->alg != IW_ENCODE_ALG_NONE) {
636 //memcpy(sec.keys[idx], ext->key, ext->key_len);
637 sec.key_sizes[idx] = ext->key_len;
638 sec.flags |= (1 << idx);
639 if (ext->alg == IW_ENCODE_ALG_WEP) {
640 sec.flags |= SEC_LEVEL;
641 sec.level = SEC_LEVEL_1;
642 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
643 sec.flags |= SEC_LEVEL;
644 sec.level = SEC_LEVEL_2;
645 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
646 sec.flags |= SEC_LEVEL;
647 sec.level = SEC_LEVEL_3;
649 /* Don't set sec level for group keys. */
651 sec.flags &= ~SEC_LEVEL;
655 if (ieee->set_security)
656 ieee->set_security(ieee->dev, &sec);
658 if (ieee->reset_on_keychange &&
659 ieee->iw_mode != IW_MODE_INFRA &&
660 ieee->reset_port && ieee->reset_port(dev)) {
661 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
668 int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
669 struct iw_request_info *info,
670 union iwreq_data *wrqu, char *extra)
672 struct iw_mlme *mlme = (struct iw_mlme *) extra;
676 case IW_MLME_DISASSOC:
677 ieee80211_disassociate(ieee);
686 int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
687 struct iw_request_info *info,
688 struct iw_param *data, char *extra)
690 switch (data->flags & IW_AUTH_INDEX) {
691 case IW_AUTH_WPA_VERSION:
692 /*need to support wpa2 here*/
693 //printk("wpa version:%x\n", data->value);
695 case IW_AUTH_CIPHER_PAIRWISE:
696 case IW_AUTH_CIPHER_GROUP:
697 case IW_AUTH_KEY_MGMT:
699 * * Host AP driver does not use these parameters and allows
700 * * wpa_supplicant to control them internally.
703 case IW_AUTH_TKIP_COUNTERMEASURES:
704 ieee->tkip_countermeasures = data->value;
706 case IW_AUTH_DROP_UNENCRYPTED:
707 ieee->drop_unencrypted = data->value;
710 case IW_AUTH_80211_AUTH_ALG:
711 //printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
712 // ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
713 if(data->value & IW_AUTH_ALG_SHARED_KEY){
717 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
721 else if(data->value & IW_AUTH_ALG_LEAP){
724 //printk("hahahaa:LEAP\n");
728 //printk("open_wep:%d\n", ieee->open_wep);
732 case IW_AUTH_WPA_ENABLED:
733 ieee->wpa_enabled = (data->value)?1:0;
734 //printk("enable wpa:%d\n", ieee->wpa_enabled);
738 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
739 ieee->ieee802_1x = data->value;
741 case IW_AUTH_PRIVACY_INVOKED:
742 ieee->privacy_invoked = data->value;
752 int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
756 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
758 // printk("return error out, len:%d\n", len);
767 printk("len: %Zd, ie:%d\n", len, ie[1]);
770 buf = kmalloc(len, GFP_KERNEL);
773 memcpy(buf, ie, len);
776 ieee->wpa_ie_len = len;
782 ieee->wpa_ie_len = 0;