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

📄 hostap_ioctl.c

📁 IEEE 802.11a/b/g linux2.4/2.6 驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */#ifdef in_atomic/* Get kernel_locked() for in_atomic() */#include <linux/smp_lock.h>#endif#include <linux/ethtool.h>static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	struct iw_statistics *wstats;#if WIRELESS_EXT > 16	/* Why are we doing that ? Jean II */	if (iface->type != HOSTAP_INTERFACE_MAIN)		return NULL;#endif /* WIRELESS_EXT > 16 */	wstats = &local->wstats;	wstats->status = 0;	wstats->discard.code =		local->comm_tallies.rx_discards_wep_undecryptable;	wstats->discard.misc =		local->comm_tallies.rx_fcs_errors +		local->comm_tallies.rx_discards_no_buffer +		local->comm_tallies.tx_discards_wrong_sa;	wstats->discard.retries =		local->comm_tallies.tx_retry_limit_exceeded;	wstats->discard.fragment =		local->comm_tallies.rx_message_in_bad_msg_fragments;	if (local->iw_mode != IW_MODE_MASTER &&	    local->iw_mode != IW_MODE_REPEAT) {		int update = 1;#ifdef in_atomic		/* RID reading might sleep and it must not be called in		 * interrupt context or while atomic. However, this		 * function seems to be called while atomic (at least in Linux		 * 2.5.59). Update signal quality values only if in suitable		 * context. Otherwise, previous values read from tick timer		 * will be used. */		if (in_atomic())			update = 0;#endif /* in_atomic */		if (update && prism2_update_comms_qual(dev) == 0)			wstats->qual.updated = IW_QUAL_ALL_UPDATED |				IW_QUAL_DBM;		wstats->qual.qual = local->comms_qual;		wstats->qual.level = local->avg_signal;		wstats->qual.noise = local->avg_noise;	} else {		wstats->qual.qual = 0;		wstats->qual.level = 0;		wstats->qual.noise = 0;		wstats->qual.updated = IW_QUAL_ALL_INVALID;	}	return wstats;}static int prism2_get_datarates(struct net_device *dev, u8 *rates){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	u8 buf[12];	int len;	u16 val;	len = local->func->get_rid(dev, HFA384X_RID_SUPPORTEDDATARATES, buf,				   sizeof(buf), 0);	if (len < 2)		return 0;	val = le16_to_cpu(*(u16 *) buf); /* string length */	if (len - 2 < val || val > 10)		return 0;	memcpy(rates, buf + 2, val);	return val;}static int prism2_get_name(struct net_device *dev,			   struct iw_request_info *info,			   char *name, char *extra){	u8 rates[10];	int len, i, over2 = 0;	len = prism2_get_datarates(dev, rates);	for (i = 0; i < len; i++) {		if (rates[i] == 0x0b || rates[i] == 0x16) {			over2 = 1;			break;		}	}	strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS");	return 0;}static void prism2_crypt_delayed_deinit(local_info_t *local,					struct prism2_crypt_data **crypt){	struct prism2_crypt_data *tmp;	unsigned long flags;	tmp = *crypt;	*crypt = NULL;	if (tmp == NULL)		return;	/* must not run ops->deinit() while there may be pending encrypt or	 * decrypt operations. Use a list of delayed deinits to avoid needing	 * locking. */	spin_lock_irqsave(&local->lock, flags);	list_add(&tmp->list, &local->crypt_deinit_list);	if (!timer_pending(&local->crypt_deinit_timer)) {		local->crypt_deinit_timer.expires = jiffies + HZ;		add_timer(&local->crypt_deinit_timer);	}	spin_unlock_irqrestore(&local->lock, flags);}static int prism2_ioctl_siwencode(struct net_device *dev,				  struct iw_request_info *info,				  struct iw_point *erq, char *keybuf){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	int i;	struct prism2_crypt_data **crypt;	i = erq->flags & IW_ENCODE_INDEX;	if (i < 1 || i > 4)		i = local->tx_keyidx;	else		i--;	if (i < 0 || i >= WEP_KEYS)		return -EINVAL;	crypt = &local->crypt[i];	if (erq->flags & IW_ENCODE_DISABLED) {		if (*crypt)			prism2_crypt_delayed_deinit(local, crypt);		goto done;	}	if (*crypt != NULL && (*crypt)->ops != NULL &&	    strcmp((*crypt)->ops->name, "WEP") != 0) {		/* changing to use WEP; deinit previously used algorithm */		prism2_crypt_delayed_deinit(local, crypt);	}	if (*crypt == NULL) {		struct prism2_crypt_data *new_crypt;		/* take WEP into use */		new_crypt = (struct prism2_crypt_data *)			kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL);		if (new_crypt == NULL)			return -ENOMEM;		memset(new_crypt, 0, sizeof(struct prism2_crypt_data));		new_crypt->ops = hostap_get_crypto_ops("WEP");		if (!new_crypt->ops) {			request_module("hostap_crypt_wep");			new_crypt->ops = hostap_get_crypto_ops("WEP");		}		if (new_crypt->ops)			new_crypt->priv = new_crypt->ops->init(i);		if (!new_crypt->ops || !new_crypt->priv) {			kfree(new_crypt);			new_crypt = NULL;			printk(KERN_WARNING "%s: could not initialize WEP: "			       "load module hostap_crypt_wep.o\n",			       dev->name);			return -EOPNOTSUPP;		}		*crypt = new_crypt;	}	if (erq->length > 0) {		int len = erq->length <= 5 ? 5 : 13;		int first = 1, j;		if (len > erq->length)			memset(keybuf + erq->length, 0, len - erq->length);		(*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv);		for (j = 0; j < WEP_KEYS; j++) {			if (j != i && local->crypt[j]) {				first = 0;				break;			}		}		if (first)			local->tx_keyidx = i;	} else {		/* No key data - just set the default TX key index */		local->tx_keyidx = i;	} done:	local->open_wep = erq->flags & IW_ENCODE_OPEN;	if (hostap_set_encryption(local)) {		printk(KERN_DEBUG "%s: set_encryption failed\n", dev->name);		return -EINVAL;	}	/* Do not reset port0 if card is in Managed mode since resetting will	 * generate new IEEE 802.11 authentication which may end up in looping	 * with IEEE 802.1X. Prism2 documentation seem to require port reset	 * after WEP configuration. However, keys are apparently changed at	 * least in Managed mode. */	if (local->iw_mode != IW_MODE_INFRA && local->func->reset_port(dev)) {		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);		return -EINVAL;	}	return 0;}static int prism2_ioctl_giwencode(struct net_device *dev,				  struct iw_request_info *info,				  struct iw_point *erq, char *key){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	int i, len;	u16 val;	struct prism2_crypt_data *crypt;	i = erq->flags & IW_ENCODE_INDEX;	if (i < 1 || i > 4)		i = local->tx_keyidx;	else		i--;	if (i < 0 || i >= WEP_KEYS)		return -EINVAL;	crypt = local->crypt[i];	erq->flags = i + 1;	if (crypt == NULL || crypt->ops == NULL) {		erq->length = 0;		erq->flags |= IW_ENCODE_DISABLED;		return 0;	}	if (strcmp(crypt->ops->name, "WEP") != 0) {		/* only WEP is supported with wireless extensions, so just		 * report that encryption is used */		erq->length = 0;		erq->flags |= IW_ENCODE_ENABLED;		return 0;	}	/* Reads from HFA384X_RID_CNFDEFAULTKEY* return bogus values, so show	 * the keys from driver buffer */	len = crypt->ops->get_key(key, WEP_KEY_LEN, NULL, crypt->priv);	erq->length = (len >= 0 ? len : 0);	if (local->func->get_rid(dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, 1) < 0)	{		printk("CNFWEPFLAGS reading failed\n");		return -EOPNOTSUPP;	}	le16_to_cpus(&val);	if (val & HFA384X_WEPFLAGS_PRIVACYINVOKED)		erq->flags |= IW_ENCODE_ENABLED;	else		erq->flags |= IW_ENCODE_DISABLED;	if (val & HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED)		erq->flags |= IW_ENCODE_RESTRICTED;	else		erq->flags |= IW_ENCODE_OPEN;	return 0;}#if WIRELESS_EXT <= 15static int prism2_ioctl_giwspy(struct net_device *dev,			       struct iw_request_info *info,			       struct iw_point *srq, char *extra){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	struct sockaddr addr[IW_MAX_SPY];	struct iw_quality qual[IW_MAX_SPY];	srq->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_SPY, 0);	memcpy(extra, &addr, sizeof(addr[0]) * srq->length);	memcpy(extra + sizeof(addr[0]) * srq->length, &qual,	       sizeof(qual[0]) * srq->length);	return 0;}static int prism2_ioctl_siwspy(struct net_device *dev,			       struct iw_request_info *info,			       struct iw_point *srq, char *extra){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	struct sockaddr *addr;	int i;	if (srq->length > IW_MAX_SPY)		return -E2BIG;	addr = (struct sockaddr *) extra;	for (i = 0; i < srq->length; i++, addr++) {		hostap_add_sta(local->ap, addr->sa_data);		/* TODO: how are these entries timed out? is the default		 * timeout suitable? probably not.. */	}	return 0;}#endif /* WIRELESS_EXT <= 15 */static int hostap_set_rate(struct net_device *dev){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	int ret, basic_rates;	basic_rates = local->basic_rates & local->tx_rate_control;	if (!basic_rates || basic_rates != local->basic_rates) {		printk(KERN_INFO "%s: updating basic rate set automatically "		       "to match with the new supported rate set\n",		       dev->name);		if (!basic_rates)			basic_rates = local->tx_rate_control;		local->basic_rates = basic_rates;		if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,				    basic_rates))			printk(KERN_WARNING "%s: failed to set "			       "cnfBasicRates\n", dev->name);	}	ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,			       local->tx_rate_control) ||	       hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,			       local->tx_rate_control) ||	       local->func->reset_port(dev));			if (ret) {		printk(KERN_WARNING "%s: TXRateControl/cnfSupportedRates "		       "setting to 0x%x failed\n",		       dev->name, local->tx_rate_control);	}	/* Update TX rate configuration for all STAs based on new operational	 * rate set. */	hostap_update_rates(local);	return ret;}static int prism2_ioctl_siwrate(struct net_device *dev,				struct iw_request_info *info,				struct iw_param *rrq, char *extra){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	if (rrq->fixed) {		switch (rrq->value) {		case 11000000:			local->tx_rate_control = HFA384X_RATES_11MBPS;			break;		case 5500000:			local->tx_rate_control = HFA384X_RATES_5MBPS;			break;		case 2000000:			local->tx_rate_control = HFA384X_RATES_2MBPS;			break;		case 1000000:			local->tx_rate_control = HFA384X_RATES_1MBPS;			break;		default:			local->tx_rate_control = HFA384X_RATES_1MBPS |				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |				HFA384X_RATES_11MBPS;			break;		}	} else {		switch (rrq->value) {		case 11000000:			local->tx_rate_control = HFA384X_RATES_1MBPS |				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |				HFA384X_RATES_11MBPS;			break;		case 5500000:			local->tx_rate_control = HFA384X_RATES_1MBPS |				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS;			break;		case 2000000:			local->tx_rate_control = HFA384X_RATES_1MBPS |				HFA384X_RATES_2MBPS;			break;		case 1000000:			local->tx_rate_control = HFA384X_RATES_1MBPS;			break;		default:			local->tx_rate_control = HFA384X_RATES_1MBPS |				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |				HFA384X_RATES_11MBPS;			break;		}	}	return hostap_set_rate(dev);}static int prism2_ioctl_giwrate(struct net_device *dev,				struct iw_request_info *info,				struct iw_param *rrq, char *extra){	u16 val;	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	int ret = 0;	if (local->func->get_rid(dev, HFA384X_RID_TXRATECONTROL, &val, 2, 1) <	    0)		return -EINVAL;	if ((val & 0x1) && (val > 1))		rrq->fixed = 0;	else		rrq->fixed = 1;	if (local->iw_mode == IW_MODE_MASTER && local->ap != NULL &&	    !local->fw_tx_rate_control) {		/* HFA384X_RID_CURRENTTXRATE seems to always be 2 Mbps in		 * Host AP mode, so use the recorded TX rate of the last sent		 * frame */		rrq->value = local->ap->last_tx_rate > 0 ?			local->ap->last_tx_rate * 100000 : 11000000;		return 0;	}

⌨️ 快捷键说明

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