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

📄 ieee80211_wireless.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	int i, r;	int step = 0;	data->length = sizeof(struct iw_range);	memset(range, 0, sizeof(struct iw_range));	/* txpower (128 values, but will print out only IW_MAX_TXPOWER) */#if WIRELESS_EXT >= 10	range->num_txpower = (ic->ic_txpowlimit >= 8) ? IW_MAX_TXPOWER : ic->ic_txpowlimit;	step = ic->ic_txpowlimit / (2 * (IW_MAX_TXPOWER - 1)); 	range->txpower[0] = 0;	for (i = 1; i < IW_MAX_TXPOWER; i++)		range->txpower[i] = (ic->ic_txpowlimit/2)			- (IW_MAX_TXPOWER - i - 1) * step;#endif	range->txpower_capa = IW_TXPOW_DBM;	if (vap->iv_opmode == IEEE80211_M_STA ||	    vap->iv_opmode == IEEE80211_M_IBSS) {		range->min_pmp = 1 * 1024;		range->max_pmp = 65535 * 1024;		range->min_pmt = 1 * 1024;		range->max_pmt = 1000 * 1024;		range->pmp_flags = IW_POWER_PERIOD;		range->pmt_flags = IW_POWER_TIMEOUT;		range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |			IW_POWER_UNICAST_R | IW_POWER_ALL_R;	}	range->we_version_compiled = WIRELESS_EXT;	range->we_version_source = 13;	range->retry_capa = IW_RETRY_LIMIT;	range->retry_flags = IW_RETRY_LIMIT;	range->min_retry = 0;	range->max_retry = 255;	range->num_channels = ic->ic_nchans;	range->num_frequency = 0;	memset(reported, 0, sizeof(reported));	for (i = 0; i < ic->ic_nchans; i++) {		const struct ieee80211_channel *c = &ic->ic_channels[i];		/* discard if previously reported (e.g. b/g) */		if (isclr(reported, c->ic_ieee)) {			setbit(reported, c->ic_ieee);			range->freq[range->num_frequency].i = c->ic_ieee;			range->freq[range->num_frequency].m =				ic->ic_channels[i].ic_freq * 100000;			range->freq[range->num_frequency].e = 1;			if (++range->num_frequency == IW_MAX_FREQUENCIES)				break;		}	}	/* Max quality is max field value minus noise floor */	range->max_qual.qual  = 0xff - 161;	/*	 * In order to use dBm measurements, 'level' must be lower	 * than any possible measurement (see iw_print_stats() in	 * wireless tools).  It's unclear how this is meant to be	 * done, but setting zero in these values forces dBm and	 * the actual numbers are not used.	 */	range->max_qual.level = 0;	range->max_qual.noise = 0;	range->sensitivity = 3;	range->max_encoding_tokens = IEEE80211_WEP_NKID;	/* XXX query driver to find out supported key sizes */	range->num_encoding_sizes = 3;	range->encoding_size[0] = 5;		/* 40-bit */	range->encoding_size[1] = 13;		/* 104-bit */	range->encoding_size[2] = 16;		/* 128-bit */	/* XXX this only works for station mode */	rs = &ni->ni_rates;	range->num_bitrates = rs->rs_nrates;	if (range->num_bitrates > IW_MAX_BITRATES)		range->num_bitrates = IW_MAX_BITRATES;	for (i = 0; i < range->num_bitrates; i++) {		r = rs->rs_rates[i] & IEEE80211_RATE_VAL;		range->bitrate[i] = (r * 1000000) / 2;	}	/* estimated maximum TCP throughput values (bps) */	range->throughput = 5500000;	range->min_rts = 0;	range->max_rts = 2347;	range->min_frag = 256;	range->max_frag = 2346;#if WIRELESS_EXT >= 17	/* Event capability (kernel) */	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);   	/* Event capability (driver) */	if (vap->iv_opmode == IEEE80211_M_STA ||		 vap->iv_opmode == IEEE80211_M_IBSS ||		 vap->iv_opmode == IEEE80211_M_AHDEMO) {		/* for now, only ibss, ahdemo, sta has this cap */		IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);	}	if (vap->iv_opmode == IEEE80211_M_STA) {		/* for sta only */		IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); 		IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);		IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);	}		/* this is used for reporting replay failure, which is used by the different encoding schemes */	IW_EVENT_CAPA_SET(range->event_capa, IWEVCUSTOM);#endif#if WIRELESS_EXT >= 18	/* report supported WPA/WPA2 capabilities to userspace */	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |               IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;#endif		return 0;}static intieee80211_ioctl_setspy(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *extra){	/* save the list of node addresses */	struct ieee80211vap *vap = dev->priv;	struct sockaddr address[IW_MAX_SPY];	unsigned int number = data->length;	int i;	if (number > IW_MAX_SPY)		return -E2BIG;		/* get the addresses into the driver */	if (data->pointer) {		if (copy_from_user(address, data->pointer,		    sizeof(struct sockaddr) * number))			return -EFAULT;        } else		return -EFAULT;	/* copy the MAC addresses into a list */	if (number > 0) {		/* extract the MAC addresses */		for (i = 0; i < number; i++)			memcpy(&vap->iv_spy.mac[i * IEEE80211_ADDR_LEN],				address[i].sa_data, IEEE80211_ADDR_LEN);	}	vap->iv_spy.num = number;	return 0;}static intieee80211_ioctl_getspy(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *extra){	/*	 * locate nodes by mac (ieee80211_find_node()),	 * copy out rssi, set updated flag appropriately	 */	struct ieee80211vap *vap = dev->priv;	struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;	struct ieee80211_node *ni;	struct sockaddr *address;	struct iw_quality *spy_stat;	unsigned int number = vap->iv_spy.num;	int i;	address = (struct sockaddr *) extra;	spy_stat = (struct iw_quality *) (extra + number * sizeof(struct sockaddr));	for (i = 0; i < number; i++) {		memcpy(address[i].sa_data, &vap->iv_spy.mac[i * IEEE80211_ADDR_LEN],			IEEE80211_ADDR_LEN);		address[i].sa_family = AF_PACKET;	}	/* locate a node, copy its rssi value, convert to dBm */	for (i = 0; i < number; i++) {		ni = ieee80211_find_node(nt, &vap->iv_spy.mac[i * IEEE80211_ADDR_LEN]);		/* TODO: free node ? */		/* check we are associated w/ this vap */		if (ni && (ni->ni_vap == vap))			set_quality(&spy_stat[i], ni->ni_rssi);		else 			spy_stat[i].updated = IW_QUAL_ALL_INVALID;	}	/* copy results to userspace */	data->length = number;	return 0;}/* Enhanced iwspy support */static intieee80211_ioctl_setthrspy(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *extra){	struct ieee80211vap *vap = dev->priv;	struct iw_thrspy threshold;	if (data->length != 1)		return -EINVAL;		/* get the threshold values into the driver */	if (data->pointer) {		if (copy_from_user(&threshold, data->pointer,		    sizeof(struct iw_thrspy)))			return -EFAULT;        } else		return -EINVAL;			if (threshold.low.level == 0) {		/* disable threshold */		vap->iv_spy.thr_low = 0;		vap->iv_spy.thr_high = 0;		IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG,			"%s: disabled iw_spy threshold\n", __func__);	} else {		/* calculate corresponding rssi values */		vap->iv_spy.thr_low = threshold.low.level - 161;		vap->iv_spy.thr_high = threshold.high.level - 161;		IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG,			"%s: enabled iw_spy threshold\n", __func__);	}	return 0;}static intieee80211_ioctl_getthrspy(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *extra){	struct ieee80211vap *vap = dev->priv;	struct iw_thrspy *threshold;			threshold = (struct iw_thrspy *) extra;	/* set threshold values */	set_quality(&(threshold->low), vap->iv_spy.thr_low);	set_quality(&(threshold->high), vap->iv_spy.thr_high);	/* copy results to userspace */	data->length = 1;		return 0;}static intieee80211_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info,	__u32 *mode, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ifmediareq imr;	int valid = 0;		memset(&imr, 0, sizeof(imr));	vap->iv_media.ifm_status(vap->iv_dev, &imr);		if (imr.ifm_active & IFM_IEEE80211_HOSTAP)		valid = (*mode == IW_MODE_MASTER);#if WIRELESS_EXT >= 15	else if (imr.ifm_active & IFM_IEEE80211_MONITOR)		valid = (*mode == IW_MODE_MONITOR);#endif	else if (imr.ifm_active & IFM_IEEE80211_ADHOC)		valid = (*mode == IW_MODE_ADHOC);	else if (imr.ifm_active & IFM_IEEE80211_WDS)		valid = (*mode == IW_MODE_REPEAT);	else		valid = (*mode == IW_MODE_INFRA);			return valid ? 0 : -EINVAL;	}static intieee80211_ioctl_giwmode(struct net_device *dev,	struct iw_request_info *info,	__u32 *mode, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ifmediareq imr;	memset(&imr, 0, sizeof(imr));	vap->iv_media.ifm_status(vap->iv_dev, &imr);	if (imr.ifm_active & IFM_IEEE80211_HOSTAP)		*mode = IW_MODE_MASTER;#if WIRELESS_EXT >= 15	else if (imr.ifm_active & IFM_IEEE80211_MONITOR)		*mode = IW_MODE_MONITOR;#endif	else if (imr.ifm_active & IFM_IEEE80211_ADHOC)		*mode = IW_MODE_ADHOC;	else if (imr.ifm_active & IFM_IEEE80211_WDS)		*mode = IW_MODE_REPEAT;	else		*mode = IW_MODE_INFRA;	return 0;}static intieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info,	struct iw_param *wrq, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	if (wrq->disabled) {		if (ic->ic_flags & IEEE80211_F_PMGTON) {			ic->ic_flags &= ~IEEE80211_F_PMGTON;			goto done;		}		return 0;	}	if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)		return -EOPNOTSUPP;	switch (wrq->flags & IW_POWER_MODE) {	case IW_POWER_UNICAST_R:	case IW_POWER_ALL_R:	case IW_POWER_ON:		ic->ic_flags |= IEEE80211_F_PMGTON;		break;	default:		return -EINVAL;	}	if (wrq->flags & IW_POWER_TIMEOUT) {		ic->ic_holdover = IEEE80211_MS_TO_TU(wrq->value);		ic->ic_flags |= IEEE80211_F_PMGTON;	}	if (wrq->flags & IW_POWER_PERIOD) {		ic->ic_lintval = IEEE80211_MS_TO_TU(wrq->value);		ic->ic_flags |= IEEE80211_F_PMGTON;	}done:	return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;}static intieee80211_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rrq, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	rrq->disabled = (ic->ic_flags & IEEE80211_F_PMGTON) == 0;	if (!rrq->disabled) {		switch (rrq->flags & IW_POWER_TYPE) {		case IW_POWER_TIMEOUT:			rrq->flags = IW_POWER_TIMEOUT;			rrq->value = IEEE80211_TU_TO_MS(ic->ic_holdover);			break;		case IW_POWER_PERIOD:			rrq->flags = IW_POWER_PERIOD;			rrq->value = IEEE80211_TU_TO_MS(ic->ic_lintval);			break;		}		rrq->flags |= IW_POWER_ALL_R;	}	return 0;}static intieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rrq, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	if (rrq->disabled) {		if (vap->iv_flags & IEEE80211_F_SWRETRY) {			vap->iv_flags &= ~IEEE80211_F_SWRETRY;			goto done;		}		return 0;	}	if ((vap->iv_caps & IEEE80211_C_SWRETRY) == 0)		return -EOPNOTSUPP;	if (rrq->flags == IW_RETRY_LIMIT) {		if (rrq->value >= 0) {			vap->iv_txmin = rrq->value;			vap->iv_txmax = rrq->value;	/* XXX */			vap->iv_txlifetime = 0;		/* XXX */			vap->iv_flags |= IEEE80211_F_SWRETRY;		} else {			vap->iv_flags &= ~IEEE80211_F_SWRETRY;		}		return 0;	}done:	return IS_UP(vap->iv_dev) ? ic->ic_reset(vap->iv_dev) : 0;}static intieee80211_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rrq, char *extra){	struct ieee80211vap *vap = dev->priv;	rrq->disabled = (vap->iv_flags & IEEE80211_F_SWRETRY) == 0;	if (!rrq->disabled) {		switch (rrq->flags & IW_RETRY_TYPE) {		case IW_RETRY_LIFETIME:			rrq->flags = IW_RETRY_LIFETIME;			rrq->value = IEEE80211_TU_TO_MS(vap->iv_txlifetime);			break;		case IW_RETRY_LIMIT:			rrq->flags = IW_RETRY_LIMIT;			switch (rrq->flags & IW_RETRY_MODIFIER) {			case IW_RETRY_MIN:				rrq->flags |= IW_RETRY_MAX;				rrq->value = vap->iv_txmin;				break;			case IW_RETRY_MAX:				rrq->flags |= IW_RETRY_MAX;				rrq->value = vap->iv_txmax;				break;			}			break;		}	}	return 0;}static intieee80211_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rrq, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	int fixed, disabled;	fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED);	disabled = (fixed && vap->iv_bss->ni_txpower == 0);	if (rrq->disabled) {		if (!disabled) {			if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)				return -EOPNOTSUPP;			ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;			vap->iv_bss->ni_txpower = 0;			goto done;		}		return 0;	}	if (rrq->fixed) {		if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)			return -EOPNOTSUPP;		if (rrq->flags != IW_TXPOW_DBM)			return -EOPNOTSUPP;		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) {			if (ic->ic_bsschan->ic_maxregpower >= rrq->value &&			    ic->ic_txpowlimit/2 >= rrq->value) {

⌨️ 快捷键说明

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