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

📄 ieee80211_wireless.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 0;}static intieee80211_ioctl_giwrts(struct net_device *dev, struct iw_request_info *info,	struct iw_param *rts, char *extra){	struct ieee80211vap *vap = dev->priv;	rts->value = vap->iv_rtsthreshold;	rts->disabled = (rts->value == IEEE80211_RTS_MAX);	rts->fixed = 1;	return 0;}static intieee80211_ioctl_siwfrag(struct net_device *dev,	struct iw_request_info *info,	struct iw_param *rts, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	u16 val;	if (rts->disabled)		val = 2346;	else if (rts->value < 256 || rts->value > 2346)		return -EINVAL;	else		val = (rts->value & ~0x1);	if (val != vap->iv_fragthreshold) {		vap->iv_fragthreshold = val;		if (IS_UP(ic->ic_dev))			return ic->ic_reset(ic->ic_dev);	}	return 0;}static intieee80211_ioctl_giwfrag(struct net_device *dev,	struct iw_request_info *info,	struct iw_param *rts, char *extra){	struct ieee80211vap *vap = dev->priv;	rts->value = vap->iv_fragthreshold;	rts->disabled = (rts->value == 2346);	rts->fixed = 1;	return 0;}static intieee80211_ioctl_siwap(struct net_device *dev, struct iw_request_info *info,	struct sockaddr *ap_addr, char *extra){	static const u_int8_t zero_bssid[IEEE80211_ADDR_LEN];	static const u_int8_t broadcast_bssid[IEEE80211_ADDR_LEN] = 		"\xff\xff\xff\xff\xff\xff";	struct ieee80211vap *vap = dev->priv;	/* NB: should not be set when in AP mode */	if (vap->iv_opmode == IEEE80211_M_HOSTAP)		return -EINVAL;	/* 	 * zero address corresponds to 'iwconfig ath0 ap off', which means 	 * enable automatic choice of AP without actually forcing a	 * reassociation.  	 *	 * broadcast address corresponds to 'iwconfig ath0 ap any', which	 * means scan for the current best AP.	 *	 * anything else specifies a particular AP.	 */	if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zero_bssid)) 		vap->iv_flags &= ~IEEE80211_F_DESBSSID;	else {		IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data);		if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, broadcast_bssid))			vap->iv_flags &= ~IEEE80211_F_DESBSSID;		else 			vap->iv_flags |= IEEE80211_F_DESBSSID;		if (IS_UP_AUTO(vap))			ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);	}	return 0;}static intieee80211_ioctl_giwap(struct net_device *dev, struct iw_request_info *info,	struct sockaddr *ap_addr, char *extra){	struct ieee80211vap *vap = dev->priv;	if (vap->iv_flags & IEEE80211_F_DESBSSID)		IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_des_bssid);	else {		static const u_int8_t zero_bssid[IEEE80211_ADDR_LEN];		if (vap->iv_state == IEEE80211_S_RUN)			if (vap->iv_opmode != IEEE80211_M_WDS) 				IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_bss->ni_bssid);			else				IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->wds_mac);		else			IEEE80211_ADDR_COPY(&ap_addr->sa_data, zero_bssid);	}	ap_addr->sa_family = ARPHRD_ETHER;	return 0;}static intieee80211_ioctl_siwnickn(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *nickname){	struct ieee80211vap *vap = dev->priv;	if (data->length > IEEE80211_NWID_LEN)		return -EINVAL;	memset(vap->iv_nickname, 0, IEEE80211_NWID_LEN);	memcpy(vap->iv_nickname, nickname, data->length);	vap->iv_nicknamelen = data->length;	return 0;}static intieee80211_ioctl_giwnickn(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *nickname){	struct ieee80211vap *vap = dev->priv;	if (data->length > vap->iv_nicknamelen + 1)		data->length = vap->iv_nicknamelen + 1;	if (data->length > 0) {		memcpy(nickname, vap->iv_nickname, data->length - 1); /* XXX: strcpy? */		nickname[data->length-1] = '\0';	}	return 0;}static intfind11gchannel(struct ieee80211com *ic, int i, int freq){	for (; i < ic->ic_nchans; i++) {		const struct ieee80211_channel *c = &ic->ic_channels[i];		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))			return 1;	}	return 0;}static struct ieee80211_channel *findchannel(struct ieee80211com *ic, int ieee, int mode){	static const u_int chanflags[] = {		0,			/* IEEE80211_MODE_AUTO */		IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */		IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */		IEEE80211_CHAN_PUREG,	/* IEEE80211_MODE_11G */		IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */		IEEE80211_CHAN_108A,	/* IEEE80211_MODE_TURBO_A */		IEEE80211_CHAN_108G,	/* IEEE80211_MODE_TURBO_G */		IEEE80211_CHAN_ST,	/* IEEE80211_MODE_TURBO_STATIC_A */	};	u_int modeflags;	int i;	modeflags = chanflags[mode];	for (i = 0; i < ic->ic_nchans; i++) {		struct ieee80211_channel *c = &ic->ic_channels[i];		if (c->ic_ieee != ieee)			continue;		if (mode == IEEE80211_MODE_AUTO) {			/* ignore turbo channels for autoselect */			if (!(ic->ic_ath_cap & IEEE80211_ATHC_TURBOP) &&			    IEEE80211_IS_CHAN_TURBO(c))				continue;			/*			 * XXX special-case 11b/g channels so we			 *     always select the g channel if both			 *     are present.			 */			if (!IEEE80211_IS_CHAN_B(c) ||			    !find11gchannel(ic, i + 1, c->ic_freq))				return c;		} else {			if ((c->ic_flags & modeflags) == modeflags)				return c;		}	}	return NULL;}#define	IEEE80211_MODE_TURBO_STATIC_A	IEEE80211_MODE_MAXstatic intieee80211_check_mode_consistency(struct ieee80211com *ic, int mode,	struct ieee80211_channel *c){	if (c == IEEE80211_CHAN_ANYC)		return 0;	switch (mode) {	case IEEE80211_MODE_11B:		if (IEEE80211_IS_CHAN_B(c)) 			return 0;		else			return 1;		break;	case IEEE80211_MODE_11G:		if (IEEE80211_IS_CHAN_ANYG(c)) 			return 0;		else			return 1;		break;	case IEEE80211_MODE_11A:		if (IEEE80211_IS_CHAN_A(c)) 			return 0;		else			return 1;		break;	case IEEE80211_MODE_TURBO_STATIC_A:		if (IEEE80211_IS_CHAN_A(c) && IEEE80211_IS_CHAN_STURBO(c)) 			return 0;		else			return 1;		break;	case IEEE80211_MODE_AUTO:		return 0;		break;	}	return 1;}#undef	IEEE80211_MODE_TURBO_STATIC_Astatic intieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info,	struct iw_freq *freq, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	struct ieee80211_channel *c, *c2;	int i;		if (freq->e > 1)		return -EINVAL;	if (freq->e == 1)		i = (ic->ic_mhz2ieee)(ic, freq->m / 100000, 0);	else		i = freq->m;	if (i != 0) {		if (i > IEEE80211_CHAN_MAX)			return -EINVAL;		c = findchannel(ic, i, vap->iv_des_mode);		if (c == NULL) {			c = findchannel(ic, i, IEEE80211_MODE_AUTO);			if (c == NULL)			/* no channel */				return -EINVAL;		}		/*		 * Fine tune channel selection based on desired mode:		 *   if 11b is requested, find the 11b version of any		 *      11g channel returned,		 *   if static turbo, find the turbo version of any		 *	11a channel return,		 *   otherwise we should be ok with what we've got.		 */		switch (vap->iv_des_mode) {		case IEEE80211_MODE_11B:			if (IEEE80211_IS_CHAN_ANYG(c)) {				c2 = findchannel(ic, i, IEEE80211_MODE_11B);				/* NB: should not happen, =>'s 11g w/o 11b */				if (c2 != NULL)					c = c2;			}			break;		case IEEE80211_MODE_TURBO_A:			if (IEEE80211_IS_CHAN_A(c)) {				c2 = findchannel(ic, i, IEEE80211_MODE_TURBO_A);				if (c2 != NULL)					c = c2;			}			break;		default:		/* NB: no static turboG */			break;		}		if (ieee80211_check_mode_consistency(ic,vap->iv_des_mode,c)) {			if (vap->iv_opmode == IEEE80211_M_HOSTAP)				return -EINVAL;		}		if (vap->iv_state == IEEE80211_S_RUN && c == ic->ic_bsschan)			return 0;			/* no change, return */		/* Don't allow to change to channel with radar found */		if (c->ic_flags & IEEE80211_CHAN_RADAR)			return -EINVAL;		/*		 * Mark desired channel and if running force a		 * radio change.		 */		vap->iv_des_chan = c;	} else {		/*		 * Intepret channel 0 to mean "no desired channel";		 * otherwise there's no way to undo fixing the desired		 * channel.		 */		if (vap->iv_des_chan == IEEE80211_CHAN_ANYC)			return 0;		vap->iv_des_chan = IEEE80211_CHAN_ANYC;	}#if 0	if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) {		int mode = ieee80211_chan2mode(vap->iv_des_chan);		if (mode != ic->ic_curmode)			ieee80211_setmode(ic, mode);	}#endif	if ((vap->iv_opmode == IEEE80211_M_MONITOR ||	    vap->iv_opmode == IEEE80211_M_WDS) &&	    vap->iv_des_chan != IEEE80211_CHAN_ANYC) {		/*		 * Monitor and wds modes can switch directly.		 */		if (vap->iv_state == IEEE80211_S_RUN) {			ic->ic_curchan = vap->iv_des_chan;			ic->ic_set_channel(ic);		}	} else {		/*		 * Need to go through the state machine in case we need		 * to reassociate or the like.  The state machine will		 * pickup the desired channel and avoid scanning.		 */		if (IS_UP_AUTO(vap))			ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);	}	return 0;}static intieee80211_ioctl_giwfreq(struct net_device *dev, struct iw_request_info *info,	struct iw_freq *freq, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	if (vap->iv_state == IEEE80211_S_RUN &&	    vap->iv_opmode != IEEE80211_M_MONITOR) {		/*		 * NB: use curchan for monitor mode so you can see		 *     manual scanning by apps like kismet.		 */		KASSERT(ic->ic_bsschan != IEEE80211_CHAN_ANYC,			("bss channel not set"));		freq->m = ic->ic_bsschan->ic_freq;	} else if (vap->iv_state != IEEE80211_S_INIT)	/* e.g. when scanning */		freq->m = ic->ic_curchan->ic_freq;	else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC)		freq->m = vap->iv_des_chan->ic_freq;	else		freq->m = 0;	freq->m *= 100000;	freq->e = 1;	return 0;}#ifdef ATH_SUPERG_XR /* * Copy desired ssid state from one vap to another. */static voidcopy_des_ssid(struct ieee80211vap *dst, const struct ieee80211vap *src){	dst->iv_des_nssid = src->iv_des_nssid;	memcpy(dst->iv_des_ssid, src->iv_des_ssid,	    src->iv_des_nssid * sizeof(src->iv_des_ssid[0]));}#endif /* ATH_SUPERG_XR */static intieee80211_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *ssid){	struct ieee80211vap *vap = dev->priv;	if (vap->iv_opmode == IEEE80211_M_WDS)		return -EOPNOTSUPP;	if (data->flags == 0)		/* ANY */		vap->iv_des_nssid = 0;	else {		if (data->length > IEEE80211_NWID_LEN)			data->length = IEEE80211_NWID_LEN;		/* NB: always use entry 0 */		memcpy(vap->iv_des_ssid[0].ssid, ssid, data->length);		vap->iv_des_ssid[0].len = data->length;		vap->iv_des_nssid = 1;		/*		 * Deduct a trailing \0 since iwconfig passes a string		 * length that includes this.  Unfortunately this means		 * that specifying a string with multiple trailing \0's		 * won't be handled correctly.  Not sure there's a good		 * solution; the API is botched (the length should be		 * exactly those bytes that are meaningful and not include		 * extraneous stuff).		 */		if (data->length > 0 &&		    vap->iv_des_ssid[0].ssid[data->length - 1] == '\0')			vap->iv_des_ssid[0].len--;	}#ifdef ATH_SUPERG_XR 	if (vap->iv_xrvap != NULL && !(vap->iv_flags & IEEE80211_F_XR)) {		if (data->flags == 0)			vap->iv_des_nssid = 0;		else			copy_des_ssid(vap->iv_xrvap, vap);	}#endif	return IS_UP_AUTO(vap) ? ieee80211_init(vap->iv_dev, RESCAN) : 0;}static intieee80211_ioctl_giwessid(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *essid){	struct ieee80211vap *vap = dev->priv;	if (vap->iv_opmode == IEEE80211_M_WDS)		return -EOPNOTSUPP;	data->flags = 1;		/* active */	if (vap->iv_opmode == IEEE80211_M_HOSTAP) {		if (vap->iv_des_nssid > 0) {			if (data->length > vap->iv_des_ssid[0].len)				data->length = vap->iv_des_ssid[0].len;			memcpy(essid, vap->iv_des_ssid[0].ssid, data->length);		} else			data->length = 0;	} else {		if (vap->iv_des_nssid == 0) {			if (data->length > vap->iv_bss->ni_esslen)				data->length = vap->iv_bss->ni_esslen;			memcpy(essid, vap->iv_bss->ni_essid, data->length);		} else {			if (data->length > vap->iv_des_ssid[0].len)				data->length = vap->iv_des_ssid[0].len;			memcpy(essid, vap->iv_des_ssid[0].ssid, data->length);		}	}	return 0;}static intieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,	struct iw_point *data, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	struct ieee80211_node *ni = vap->iv_bss;	struct iw_range *range = (struct iw_range *) extra;	struct ieee80211_rateset *rs;	u_int8_t reported[IEEE80211_CHAN_BYTES];	/* XXX stack usage? */

⌨️ 快捷键说明

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