ieee80211_wireless.c

来自「madwifi上的atheros无线网卡驱动源码」· C语言 代码 · 共 2,347 行 · 第 1/5 页

C
2,347
字号
	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 intwaplist_cb(void *arg, const struct ieee80211_scan_entry *se){	struct waplistreq *req = arg;	int i = req->i;	if (i >= IW_MAX_AP)		return 0;	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, ATH_DEFAULT_NOISE);	req->i = i + 1;	return 0;}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 -ENETDOWN;	/* 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]);		bufsize -= 2;	}	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 intgiwscan_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;	char *last_ev;#if WIRELESS_EXT > 14#define MAX_IE_LENGTH 64 * 2 + 30	char buf[MAX_IE_LENGTH];#ifndef IWEVGENIE	static const char rsn_leader[] = "rsn_ie=";	static const char wpa_leader[] = "wpa_ie=";#endif#endif	struct iw_event iwe;	char *current_val;	int j;	if (current_ev >= end_buf)		return E2BIG;	/* WPA/!WPA sort criteria */	if ((req->mode != 0) ^ (se->se_wpa_ie != NULL))		return 0;	memset(&iwe, 0, sizeof(iwe));	last_ev = current_ev;	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);	/* We ran out of space in the buffer. */	if (last_ev == current_ev)	  return E2BIG;	memset(&iwe, 0, sizeof(iwe));	last_ev = current_ev;	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);	}	/* We ran out of space in the buffer. */	if (last_ev == current_ev)	  return E2BIG;	if (se->se_capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {		memset(&iwe, 0, sizeof(iwe));		last_ev = current_ev;		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);		/* We ran out of space in the buffer. */		if (last_ev == current_ev)		  return E2BIG;	}	memset(&iwe, 0, sizeof(iwe));	last_ev = current_ev;	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);	/* We ran out of space in the buffer. */	if (last_ev == current_ev)	  return E2BIG;	memset(&iwe, 0, sizeof(iwe));	last_ev = current_ev;	iwe.cmd = IWEVQUAL;	set_quality(&iwe.u.qual, se->se_rssi, ATH_DEFAULT_NOISE);	current_ev = iwe_stream_add_event(current_ev,		end_buf, &iwe, IW_EV_QUAL_LEN);	/* We ran out of space in the buffer */	if (last_ev == current_ev)	  return E2BIG;	memset(&iwe, 0, sizeof(iwe));	last_ev = current_ev;	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, "");	/* We ran out of space in the buffer. */	if (last_ev == current_ev)	  return E2BIG;	memset(&iwe, 0, sizeof(iwe));	last_ev = current_ev;	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;	} else {	  /* We ran out of space in the buffer. */	  if (last_ev == current_ev)	    return E2BIG;	}#if WIRELESS_EXT > 14	memset(&iwe, 0, sizeof(iwe));	last_ev = current_ev;	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);	/* We ran out of space in the buffer. */	if (last_ev == current_ev)	  return E2BIG;	if (se->se_rsn_ie != NULL) {	  last_ev = current_ev;#ifdef IWEVGENIE		memset(&iwe, 0, sizeof(iwe));		if ((se->se_rsn_ie[1] + 2) > MAX_IE_LENGTH)			return E2BIG;		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			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);						/* We ran out of space in the buffer */			if (last_ev == current_ev)			  return E2BIG;		}	}	if (se->se_wpa_ie != NULL) {	  last_ev = current_ev;#ifdef IWEVGENIE		memset(&iwe, 0, sizeof(iwe));		if ((se->se_wpa_ie[1] + 2) > MAX_IE_LENGTH)			return E2BIG;		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		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);						/* We ran out of space in the buffer. */			if (last_ev == current_ev)			  return E2BIG;		}	}	if (se->se_wme_ie != NULL) {		static const char wme_leader[] = "wme_ie=";		memset(&iwe, 0, sizeof(iwe));		last_ev = current_ev;		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);			/* We ran out of space in the buffer. */			if (last_ev == current_ev)			  return E2BIG;		}	}	if (se->se_ath_ie != NULL) {		static const char ath_leader[] = "ath_ie=";		memset(&iwe, 0, sizeof(iwe));		last_ev = current_ev;		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);			/* We ran out of space in the buffer. */			if (last_ev == current_ev)			  return E2BIG;		}	}#endif /* WIRELESS_EXT > 14 */	req->current_ev = current_ev;	return 0;}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;	int res = 0;	req.vap = vap;	req.current_ev = extra;	if (data->length == 0) {	  req.end_buf = extra + IW_SCAN_MAX_DATA;	} else {	  req.end_buf = extra + data->length;	}	/*	 * NB: This is no longer needed, as long as the caller supports	 * large scan results.	 *	 * 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;	res = ieee80211_scan_iterate(ic, giwscan_cb, &req);	if (res == 0) {	  req.mode = req.mode ? 0 : IEEE80211_F_WPA;	  res = ieee80211_scan_iterate(ic, giwscan_cb, &req);	}	data->length = req.current_ev - extra;	if (res != 0) {	  return -res;	}	return res;}#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 },

⌨️ 快捷键说明

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