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

📄 ieee80211_wireless.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
 			        vap->iv_bss->ni_txpower = 2 * rrq->value;				ic->ic_newtxpowlimit = 2 * rrq->value; 				ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; 			} else				return -EINVAL;		} else {			/*			 * No channel set yet			 */			if (ic->ic_txpowlimit/2 >= rrq->value) {				vap->iv_bss->ni_txpower = 2 * rrq->value;				ic->ic_newtxpowlimit = 2 * rrq->value;				ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;			}			else				return -EINVAL;		}	} else {		if (!fixed)		/* no change */			return 0;		ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED;	}done:	return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;}static intieee80211_ioctl_giwtxpow(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->value = vap->iv_bss->ni_txpower / 2;	rrq->fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) != 0;	rrq->disabled = (rrq->fixed && rrq->value == 0);	rrq->flags = IW_TXPOW_DBM;	return 0;}struct waplistreq {	/* XXX: not the right place for declaration? */	struct ieee80211vap *vap;	struct sockaddr addr[IW_MAX_AP];	struct iw_quality qual[IW_MAX_AP];	int i;};static voidwaplist_cb(void *arg, const struct ieee80211_scan_entry *se){	struct waplistreq *req = arg;	int i = req->i;	if (i >= IW_MAX_AP)		return;	req->addr[i].sa_family = ARPHRD_ETHER;	if (req->vap->iv_opmode == IEEE80211_M_HOSTAP)		IEEE80211_ADDR_COPY(req->addr[i].sa_data, se->se_macaddr);	else		IEEE80211_ADDR_COPY(req->addr[i].sa_data, se->se_bssid);	set_quality(&req->qual[i], se->se_rssi);	req->i = i + 1;}static intieee80211_ioctl_iwaplist(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 waplistreq req;		/* XXX off stack */	req.vap = vap;	req.i = 0;	ieee80211_scan_iterate(ic, waplist_cb, &req);	data->length = req.i;	memcpy(extra, &req.addr, req.i * sizeof(req.addr[0]));	data->flags = 1;		/* signal quality present (sort of) */	memcpy(extra + req.i * sizeof(req.addr[0]), &req.qual,		req.i * sizeof(req.qual[0]));	return 0;}#ifdef SIOCGIWSCANstatic intieee80211_ioctl_siwscan(struct net_device *dev,	struct iw_request_info *info,	struct iw_point *data, char *extra){	struct ieee80211vap *vap = dev->priv;	/*	 * XXX don't permit a scan to be started unless we	 * know the device is ready.  For the moment this means	 * the device is marked up as this is the required to	 * initialize the hardware.  It would be better to permit	 * scanning prior to being up but that'll require some	 * changes to the infrastructure.	 */	if (!IS_UP(vap->iv_dev))		return -EINVAL;		/* XXX */	/* XXX always manual... */	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,		"%s: active scan request\n", __func__);	preempt_scan(dev, 100, 100);#if WIRELESS_EXT > 17	if (data && (data->flags & IW_SCAN_THIS_ESSID)) {		struct iw_scan_req req;		struct ieee80211_scan_ssid ssid;		int copyLength;		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: SCAN_THIS_ESSID requested\n", __func__);		if (data->length > sizeof req) {			copyLength = sizeof req;		} else {			copyLength = data->length;		}		memset(&req, 0, sizeof req);		if (copy_from_user(&req, data->pointer, copyLength))			return -EFAULT;		memcpy(&ssid.ssid, req.essid, sizeof ssid.ssid);		ssid.len = req.essid_len;		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,				  "%s: requesting scan of essid '%s'\n", __func__, ssid.ssid);		(void) ieee80211_start_scan(vap,			IEEE80211_SCAN_ACTIVE |			IEEE80211_SCAN_NOPICK |			IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,			1, &ssid);		return 0;	}#endif		 	(void) ieee80211_start_scan(vap, IEEE80211_SCAN_ACTIVE |		IEEE80211_SCAN_NOPICK |	IEEE80211_SCAN_ONCE,		IEEE80211_SCAN_FOREVER,		/* XXX use ioctl params */		vap->iv_des_nssid, vap->iv_des_ssid);	return 0;}#if WIRELESS_EXT > 14/* * Encode a WPA or RSN information element as a custom * element using the hostap format. */static u_intencode_ie(void *buf, size_t bufsize, const u_int8_t *ie, size_t ielen,	const char *leader, size_t leader_len){	u_int8_t *p;	int i;	if (bufsize < leader_len)		return 0;	p = buf;	memcpy(p, leader, leader_len);	bufsize -= leader_len;	p += leader_len;	for (i = 0; i < ielen && bufsize > 2; i++)		p += sprintf(p, "%02x", ie[i]);	return (i == ielen ? p - (u_int8_t *)buf : 0);}#endif /* WIRELESS_EXT > 14 */struct iwscanreq {		/* XXX: right place for this declaration? */	struct ieee80211vap *vap;	char *current_ev;	char *end_buf;	int mode;};static voidgiwscan_cb(void *arg, const struct ieee80211_scan_entry *se){	struct iwscanreq *req = arg;	struct ieee80211vap *vap = req->vap;	char *current_ev = req->current_ev;	char *end_buf = req->end_buf;#if WIRELESS_EXT > 14	char buf[64 * 2 + 30];#endif	struct iw_event iwe;	char *current_val;	int j;	if (current_ev >= end_buf)		return;	/* WPA/!WPA sort criteria */	if ((req->mode != 0) ^ (se->se_wpa_ie != NULL))		return;	memset(&iwe, 0, sizeof(iwe));	iwe.cmd = SIOCGIWAP;	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;	if (vap->iv_opmode == IEEE80211_M_HOSTAP)		IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_macaddr);	else		IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_bssid);	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);	memset(&iwe, 0, sizeof(iwe));	iwe.cmd = SIOCGIWESSID;	iwe.u.data.flags = 1;	if (vap->iv_opmode == IEEE80211_M_HOSTAP) {		iwe.u.data.length = vap->iv_des_nssid > 0 ?			vap->iv_des_ssid[0].len : 0;		current_ev = iwe_stream_add_point(current_ev,			end_buf, &iwe, vap->iv_des_ssid[0].ssid);	} else {		iwe.u.data.length = se->se_ssid[1];		current_ev = iwe_stream_add_point(current_ev,			end_buf, &iwe, (char *) se->se_ssid+2);	}	if (se->se_capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {		memset(&iwe, 0, sizeof(iwe));		iwe.cmd = SIOCGIWMODE;		iwe.u.mode = se->se_capinfo & IEEE80211_CAPINFO_ESS ?			IW_MODE_MASTER : IW_MODE_ADHOC;		current_ev = iwe_stream_add_event(current_ev,			end_buf, &iwe, IW_EV_UINT_LEN);	}	memset(&iwe, 0, sizeof(iwe));	iwe.cmd = SIOCGIWFREQ;	iwe.u.freq.m = se->se_chan->ic_freq * 100000;	iwe.u.freq.e = 1;	current_ev = iwe_stream_add_event(current_ev,		end_buf, &iwe, IW_EV_FREQ_LEN);	memset(&iwe, 0, sizeof(iwe));	iwe.cmd = IWEVQUAL;	set_quality(&iwe.u.qual, se->se_rssi);	current_ev = iwe_stream_add_event(current_ev,		end_buf, &iwe, IW_EV_QUAL_LEN);	memset(&iwe, 0, sizeof(iwe));	iwe.cmd = SIOCGIWENCODE;	if (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY)		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;	else		iwe.u.data.flags = IW_ENCODE_DISABLED;	iwe.u.data.length = 0;	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");	memset(&iwe, 0, sizeof(iwe));	iwe.cmd = SIOCGIWRATE;	current_val = current_ev + IW_EV_LCP_LEN;	/* NB: not sorted, does it matter? */	for (j = 0; j < se->se_rates[1]; j++) {		int r = se->se_rates[2 + j] & IEEE80211_RATE_VAL;		if (r != 0) {			iwe.u.bitrate.value = r * (1000000 / 2);			current_val = iwe_stream_add_value(current_ev,				current_val, end_buf, &iwe,				IW_EV_PARAM_LEN);		}	}	for (j = 0; j < se->se_xrates[1]; j++) {		int r = se->se_xrates[2+j] & IEEE80211_RATE_VAL;		if (r != 0) {			iwe.u.bitrate.value = r * (1000000 / 2);			current_val = iwe_stream_add_value(current_ev,				current_val, end_buf, &iwe,				IW_EV_PARAM_LEN);		}	}	/* remove fixed header if no rates were added */	if ((current_val - current_ev) > IW_EV_LCP_LEN)		current_ev = current_val;#if WIRELESS_EXT > 14	memset(&iwe, 0, sizeof(iwe));	iwe.cmd = IWEVCUSTOM;	snprintf(buf, sizeof(buf), "bcn_int=%d", se->se_intval);	iwe.u.data.length = strlen(buf);	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf);	if (se->se_rsn_ie != NULL) {#ifdef IWEVGENIE		memset(&iwe, 0, sizeof(iwe));		memcpy(buf, se->se_rsn_ie, se->se_rsn_ie[1] + 2);		iwe.cmd = IWEVGENIE;		iwe.u.data.length = se->se_rsn_ie[1] + 2;#else			static const char rsn_leader[] = "rsn_ie=";		memset(&iwe, 0, sizeof(iwe));		iwe.cmd = IWEVCUSTOM;		if (se->se_rsn_ie[0] == IEEE80211_ELEMID_RSN)			iwe.u.data.length = encode_ie(buf, sizeof(buf),				se->se_rsn_ie, se->se_rsn_ie[1] + 2,				rsn_leader, sizeof(rsn_leader) - 1);#endif		if (iwe.u.data.length != 0)			current_ev = iwe_stream_add_point(current_ev, end_buf,				&iwe, buf);	}	if (se->se_wpa_ie != NULL) {#ifdef IWEVGENIE		memset(&iwe, 0, sizeof(iwe));		memcpy(buf, se->se_wpa_ie, se->se_wpa_ie[1] + 2);		iwe.cmd = IWEVGENIE;		iwe.u.data.length = se->se_wpa_ie[1] + 2;#else		static const char wpa_leader[] = "wpa_ie=";		memset(&iwe, 0, sizeof(iwe));		iwe.cmd = IWEVCUSTOM;		iwe.u.data.length = encode_ie(buf, sizeof(buf),			se->se_wpa_ie, se->se_wpa_ie[1] + 2,			wpa_leader, sizeof(wpa_leader) - 1);#endif		if (iwe.u.data.length != 0)			current_ev = iwe_stream_add_point(current_ev, end_buf,				&iwe, buf);	}	if (se->se_wme_ie != NULL) {		static const char wme_leader[] = "wme_ie=";		memset(&iwe, 0, sizeof(iwe));		iwe.cmd = IWEVCUSTOM;		iwe.u.data.length = encode_ie(buf, sizeof(buf),			se->se_wme_ie, se->se_wme_ie[1] + 2,			wme_leader, sizeof(wme_leader) - 1);		if (iwe.u.data.length != 0)			current_ev = iwe_stream_add_point(current_ev, end_buf,				&iwe, buf);	}	if (se->se_ath_ie != NULL) {		static const char ath_leader[] = "ath_ie=";		memset(&iwe, 0, sizeof(iwe));		iwe.cmd = IWEVCUSTOM;		iwe.u.data.length = encode_ie(buf, sizeof(buf),			se->se_ath_ie, se->se_ath_ie[1] + 2,			ath_leader, sizeof(ath_leader) - 1);		if (iwe.u.data.length != 0)			current_ev = iwe_stream_add_point(current_ev, end_buf,				&iwe, buf);	}#endif /* WIRELESS_EXT > 14 */	req->current_ev = current_ev;}static intieee80211_ioctl_giwscan(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 iwscanreq req;	req.vap = vap;	req.current_ev = extra;	req.end_buf = extra + IW_SCAN_MAX_DATA;	/*	 * Do two passes to ensure WPA/non-WPA scan candidates	 * are sorted to the front.  This is a hack to deal with	 * the wireless extensions capping scan results at	 * IW_SCAN_MAX_DATA bytes.  In densely populated environments	 * it's easy to overflow this buffer (especially with WPA/RSN	 * information elements).  Note this sorting hack does not	 * guarantee we won't overflow anyway.	 */	req.mode = vap->iv_flags & IEEE80211_F_WPA;	ieee80211_scan_iterate(ic, giwscan_cb, &req);	req.mode = req.mode ? 0 : IEEE80211_F_WPA;	ieee80211_scan_iterate(ic, giwscan_cb, &req);	data->length = req.current_ev - extra;	return 0;}#endif /* SIOCGIWSCAN */static intcipher2cap(int cipher){	switch (cipher) {	case IEEE80211_CIPHER_WEP:	return IEEE80211_C_WEP;	case IEEE80211_CIPHER_AES_OCB:	return IEEE80211_C_AES;	case IEEE80211_CIPHER_AES_CCM:	return IEEE80211_C_AES_CCM;	case IEEE80211_CIPHER_CKIP:	return IEEE80211_C_CKIP;	case IEEE80211_CIPHER_TKIP:	return IEEE80211_C_TKIP;	}	return 0;}#define	IEEE80211_MODE_TURBO_STATIC_A	IEEE80211_MODE_MAXstatic intieee80211_convert_mode(const char *mode){#define TOUPPER(c) ((((c) > 0x60) && ((c) < 0x7b)) ? ((c) - 0x20) : (c))	static const struct {		char *name;		int mode;	} mappings[] = {		/* NB: need to order longest strings first for overlaps */ 		{ "11AST" , IEEE80211_MODE_TURBO_STATIC_A },		{ "AUTO"  , IEEE80211_MODE_AUTO },		{ "11A"   , IEEE80211_MODE_11A },		{ "11B"   , IEEE80211_MODE_11B },		{ "11G"   , IEEE80211_MODE_11G },		{ "FH"    , IEEE80211_MODE_FH },		{ "0"     , IEEE80211_MODE_AUTO },		{ "1"     , IEEE80211_MODE_11A },		{ "2"     , IEEE80211_MODE_11B },		{ "3"     , IEEE80211_MODE_11G },		{ "4"     , IEEE80211_MODE_FH },		{ "5"     , IEEE80211_MODE_TURBO_STATIC_A },		{ NULL }	};	int i, j;	const char *cp;	for (i = 0; mappings[i].name != NULL; i++) {		cp = mappings[i].name;		for (j = 0; j < strlen(mode) + 1; j++) {			/* convert user-specified string to upper case */			if (TOUPPER(mode[j]) != cp[j])				break;			if (cp[j] == '\0')				return mappings[i].mode;		}	}	return -1;#undef TOUPPER}static intieee80211_ioctl_setmode(struct net_device *dev, struct iw_request_info *info,	struct iw_point *wri, char *extra){	struct ieee80211vap *vap = dev->priv;	struct ieee80211com *ic = vap->iv_ic;	struct ifreq ifr;	char s[6];		/* big enough for ``11adt'' */	int retv, mode, ifr_mode, itr_count;	if (ic->ic_media.ifm_cur == NULL)		return -EINVAL;	if (wri->length > sizeof(s))		/* silently truncate */		wri->length = sizeof(s);	if (copy_from_user(s, wri->pointer, wri->length))		return -EINVAL;	s[sizeof(s)-1] = '\0';			/* ensure null termination */	mode = ieee80211_convert_mode(s);	if (mode < 0)		return -EINVAL;	if(ieee80211_check_mode_consistency(ic,mode,vap->iv_des_chan)) { 		/*		 * error in AP mode.		 * overwrite channel selection in other modes.		 */		if (vap->iv_opmode == IEEE80211_M_HOSTAP)			return -EINVAL;		else			vap->iv_des_chan=IEEE80211_CHAN_ANYC;	}	ifr_mode = mode;	memset(&ifr, 0, sizeof(ifr));	ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media &~ IFM_MMASK;

⌨️ 快捷键说明

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