⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee80211_wx.c

📁 intelWiFi 芯片linux下 802.11 driver
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************  Copyright(c) 2004-2005 Intel Corporation. All rights reserved.  Portions of this file are based on the WEP enablement code provided by the  Host AP project hostap-drivers v0.1.3  Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen  <j@w1.fi>  Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>  This program is free software; you can redistribute it and/or modify it  under the terms of version 2 of the GNU General Public License as  published by the Free Software Foundation.  This program is distributed in the hope that it will be useful, but WITHOUT  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  more details.  You should have received a copy of the GNU General Public License along with  this program; if not, write to the Free Software Foundation, Inc., 59  Temple Place - Suite 330, Boston, MA  02111-1307, USA.  The full GNU General Public License is included in this distribution in the  file called LICENSE.  Contact Information:  James P. Ketrenos <ipw2100-admin@linux.intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497******************************************************************************/#include <linux/kmod.h>#include <linux/module.h>#include <linux/jiffies.h>#include "compat.h"#include <net/ieee80211.h>#include <linux/wireless.h>static const char *ieee80211_modes[] = {	"?", "a", "b", "ab", "g", "ag", "bg", "abg"};#define MAX_CUSTOM_LEN 64static char *ieee80211_translate_scan(struct ieee80211_device *ieee,					   char *start, char *stop,					   struct ieee80211_network *network){	char custom[MAX_CUSTOM_LEN];	char *p;	struct iw_event iwe;	int i, j;	char *current_val;	/* For rates */	u8 rate;	/* First entry *MUST* be the AP MAC address */	iwe.cmd = SIOCGIWAP;	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;	memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);	/* Remaining entries will be displayed in the order we provide them */	/* Add the ESSID */	iwe.cmd = SIOCGIWESSID;	iwe.u.data.flags = 1;	if (network->flags & NETWORK_EMPTY_ESSID) {		iwe.u.data.length = sizeof("<hidden>");		start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");	} else {		iwe.u.data.length = min(network->ssid_len, (u8) 32);		start = iwe_stream_add_point(start, stop, &iwe, network->ssid);	}	/* Add the protocol name */	iwe.cmd = SIOCGIWNAME;	snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",		 ieee80211_modes[network->mode]);	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN);	/* Add mode */	iwe.cmd = SIOCGIWMODE;	if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {		if (network->capability & WLAN_CAPABILITY_ESS)			iwe.u.mode = IW_MODE_MASTER;		else			iwe.u.mode = IW_MODE_ADHOC;		start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);	}	/* Add channel and frequency */	iwe.cmd = SIOCGIWFREQ;	iwe.u.freq.m = network->channel;	iwe.u.freq.e = 0;	iwe.u.freq.i = 0;	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);	iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);	iwe.u.freq.e = 6;	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);	/* Add encryption capability */	iwe.cmd = SIOCGIWENCODE;	if (network->capability & WLAN_CAPABILITY_PRIVACY)		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;	else		iwe.u.data.flags = IW_ENCODE_DISABLED;	iwe.u.data.length = 0;	start = iwe_stream_add_point(start, stop, &iwe, network->ssid);	/* Add basic and extended rates */	/* Rate : stuffing multiple values in a single event require a bit	 * more of magic - Jean II */	current_val = start + IW_EV_LCP_LEN;	iwe.cmd = SIOCGIWRATE;	/* Those two flags are ignored... */	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;	for (i = 0, j = 0; i < network->rates_len;) {		if (j < network->rates_ex_len &&		    ((network->rates_ex[j] & 0x7F) <		     (network->rates[i] & 0x7F)))			rate = network->rates_ex[j++] & 0x7F;		else			rate = network->rates[i++] & 0x7F;		/* Bit rate given in 500 kb/s units (+ 0x80) */		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);		/* Add new value to event */		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);	}	for (; j < network->rates_ex_len; j++) {		rate = network->rates_ex[j] & 0x7F;		/* Bit rate given in 500 kb/s units (+ 0x80) */		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);		/* Add new value to event */		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);	}	/* Check if we added any rate */	if((current_val - start) > IW_EV_LCP_LEN)		start = current_val;	/* Add quality statistics */	iwe.cmd = IWEVQUAL;	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |	    IW_QUAL_NOISE_UPDATED;	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |		    IW_QUAL_LEVEL_INVALID;		iwe.u.qual.qual = 0;	} else {		if (ieee->perfect_rssi == ieee->worst_rssi)			iwe.u.qual.qual = 100;		else			iwe.u.qual.qual =			    (100 *			     (ieee->perfect_rssi - ieee->worst_rssi) *			     (ieee->perfect_rssi - ieee->worst_rssi) -			     (ieee->perfect_rssi - network->stats.rssi) *			     (15 * (ieee->perfect_rssi - ieee->worst_rssi) +			      62 * (ieee->perfect_rssi -				    network->stats.rssi))) /			    ((ieee->perfect_rssi -			      ieee->worst_rssi) * (ieee->perfect_rssi -						   ieee->worst_rssi));		if (iwe.u.qual.qual > 100)			iwe.u.qual.qual = 100;		else if (iwe.u.qual.qual < 1)			iwe.u.qual.qual = 0;	}	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;		iwe.u.qual.noise = 0;	} else {		iwe.u.qual.noise = network->stats.noise;	}	if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;		iwe.u.qual.level = 0;	} else {		iwe.u.qual.level = network->stats.signal;	}	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);	iwe.cmd = IWEVCUSTOM;	p = custom;	iwe.u.data.length = p - custom;	if (iwe.u.data.length)		start = iwe_stream_add_point(start, stop, &iwe, custom);	memset(&iwe, 0, sizeof(iwe));	if (network->wpa_ie_len) {#ifdef IWEVGENIE		char buf[MAX_WPA_IE_LEN];		memcpy(buf, network->wpa_ie, network->wpa_ie_len);		iwe.cmd = IWEVGENIE;		iwe.u.data.length = network->wpa_ie_len;#else		char buf[MAX_WPA_IE_LEN * 2 + 30];		u8 *p = buf;		p += sprintf(p, "wpa_ie=");		for (i = 0; i < network->wpa_ie_len; i++) {			p += sprintf(p, "%02x", network->wpa_ie[i]);		}		iwe.cmd = IWEVCUSTOM;		iwe.u.data.length = strlen(buf);#endif		start = iwe_stream_add_point(start, stop, &iwe, buf);	}	memset(&iwe, 0, sizeof(iwe));	if (network->rsn_ie_len) {#ifdef IWEVGENIE		char buf[MAX_WPA_IE_LEN];		memcpy(buf, network->rsn_ie, network->rsn_ie_len);		iwe.cmd = IWEVGENIE;		iwe.u.data.length = network->rsn_ie_len;#else		char buf[MAX_WPA_IE_LEN * 2 + 30];		u8 *p = buf;		p += sprintf(p, "rsn_ie=");		for (i = 0; i < network->rsn_ie_len; i++) {			p += sprintf(p, "%02x", network->rsn_ie[i]);		}		iwe.cmd = IWEVCUSTOM;		iwe.u.data.length = strlen(buf);#endif		start = iwe_stream_add_point(start, stop, &iwe, buf);	}	/* Add EXTRA: Age to display seconds since last beacon/probe response	 * for given network. */	iwe.cmd = IWEVCUSTOM;	p = custom;	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),		      " Last beacon: %dms ago",		      jiffies_to_msecs(jiffies - network->last_scanned));	iwe.u.data.length = p - custom;	if (iwe.u.data.length)		start = iwe_stream_add_point(start, stop, &iwe, custom);	/* Add spectrum management information */	iwe.cmd = -1;	p = custom;	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");	if (ieee80211_get_channel_flags(ieee, network->channel) &	    IEEE80211_CH_INVALID) {		iwe.cmd = IWEVCUSTOM;		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");	}	if (ieee80211_get_channel_flags(ieee, network->channel) &	    IEEE80211_CH_RADAR_DETECT) {		iwe.cmd = IWEVCUSTOM;		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");	}	if (iwe.cmd == IWEVCUSTOM) {		iwe.u.data.length = p - custom;		start = iwe_stream_add_point(start, stop, &iwe, custom);	}	return start;}#define SCAN_ITEM_SIZE 128int ieee80211_wx_get_scan(struct ieee80211_device *ieee,			  struct iw_request_info *info,			  union iwreq_data *wrqu, char *extra){	struct ieee80211_network *network;	unsigned long flags;	int err = 0;	char *ev = extra;	char *stop = ev + wrqu->data.length;	int i = 0;	IEEE80211_DEBUG_WX("Getting scan\n");	spin_lock_irqsave(&ieee->lock, flags);	list_for_each_entry(network, &ieee->network_list, list) {		i++;		if (stop - ev < SCAN_ITEM_SIZE) {			err = -E2BIG;			break;		}		if (ieee->scan_age == 0 ||		    time_after(network->last_scanned + ieee->scan_age, jiffies))			ev = ieee80211_translate_scan(ieee, ev, stop, network);		else			IEEE80211_DEBUG_SCAN("Not showing network '%s ("					     MAC_FMT ")' due to age (%dms).\n",					     escape_essid(network->ssid,							  network->ssid_len),					     MAC_ARG(network->bssid),					     jiffies_to_msecs(jiffies -							      network->							      last_scanned));	}	spin_unlock_irqrestore(&ieee->lock, flags);	wrqu->data.length = ev - extra;	wrqu->data.flags = 0;	IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);	return err;}int ieee80211_wx_set_encode(struct ieee80211_device *ieee,			    struct iw_request_info *info,			    union iwreq_data *wrqu, char *keybuf){	struct iw_point *erq = &(wrqu->encoding);	struct net_device *dev = ieee->dev;	struct ieee80211_security sec = {		.flags = 0	};	int i, key, key_provided, len;	struct ieee80211_crypt_data **crypt;	int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;	IEEE80211_DEBUG_WX("SET_ENCODE\n");	key = erq->flags & IW_ENCODE_INDEX;	if (key) {		if (key > WEP_KEYS)			return -EINVAL;		key--;		key_provided = 1;	} else {		key_provided = 0;		key = ieee->tx_keyidx;	}	IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?			   "provided" : "default");	crypt = &ieee->crypt[key];	if (erq->flags & IW_ENCODE_DISABLED) {		if (key_provided && *crypt) {			IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",					   key);			ieee80211_crypt_delayed_deinit(ieee, crypt);		} else			IEEE80211_DEBUG_WX("Disabling encryption.\n");		/* Check all the keys to see if any are still configured,		 * and if no key index was provided, de-init them all */		for (i = 0; i < WEP_KEYS; i++) {			if (ieee->crypt[i] != NULL) {				if (key_provided)					break;				ieee80211_crypt_delayed_deinit(ieee,							       &ieee->crypt[i]);			}		}		if (i == WEP_KEYS) {			sec.enabled = 0;			sec.encrypt = 0;			sec.level = SEC_LEVEL_0;			sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;		}		goto done;	}	sec.enabled = 1;	sec.encrypt = 1;	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;	if (*crypt != NULL && (*crypt)->ops != NULL &&	    strcmp((*crypt)->ops->name, "WEP") != 0) {		/* changing to use WEP; deinit previously used algorithm		 * on this key */		ieee80211_crypt_delayed_deinit(ieee, crypt);	}	if (*crypt == NULL && host_crypto) {		struct ieee80211_crypt_data *new_crypt;		/* take WEP into use */		new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),				    GFP_KERNEL);		if (new_crypt == NULL)			return -ENOMEM;		new_crypt->ops = ieee80211_get_crypto_ops("WEP");		if (!new_crypt->ops) {			request_module("ieee80211_crypt_wep");			new_crypt->ops = ieee80211_get_crypto_ops("WEP");		}		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))			new_crypt->priv = new_crypt->ops->init(key);		if (!new_crypt->ops || !new_crypt->priv) {			kfree(new_crypt);			new_crypt = NULL;			printk(KERN_WARNING "%s: could not initialize WEP: "			       "load module ieee80211_crypt_wep\n", dev->name);			return -EOPNOTSUPP;		}		*crypt = new_crypt;	}	/* If a new key was provided, set it up */	if (erq->length > 0) {		len = erq->length <= 5 ? 5 : 13;		memcpy(sec.keys[key], keybuf, erq->length);		if (len > erq->length)			memset(sec.keys[key] + erq->length, 0,			       len - erq->length);		IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",				   key, escape_essid(sec.keys[key], len),				   erq->length, len);		sec.key_sizes[key] = len;		if (*crypt)			(*crypt)->ops->set_key(sec.keys[key], len, NULL,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -