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

📄 driver_nl80211.c

📁 IEEE802.11 a/b/g 客户端应用程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		ret = -1;	}	/* Not all drivers generate "scan completed" wireless event, so try to	 * read results after a timeout. */	timeout = 5;	if (drv->scan_complete_events) {		/*		 * The driver seems to deliver SIOCGIWSCAN events to notify		 * when scan is complete, so use longer timeout to avoid race		 * conditions with scanning and following association request.		 */		timeout = 30;	}	wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "		   "seconds", ret, timeout);	eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);	eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, drv,			       drv->ctx);	return ret;}static u8 * wpa_driver_nl80211_giwscan(struct wpa_driver_nl80211_data *drv,				    size_t *len){	struct iwreq iwr;	u8 *res_buf;	size_t res_buf_len;	res_buf_len = IW_SCAN_MAX_DATA;	for (;;) {		res_buf = os_malloc(res_buf_len);		if (res_buf == NULL)			return NULL;		os_memset(&iwr, 0, sizeof(iwr));		os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);		iwr.u.data.pointer = res_buf;		iwr.u.data.length = res_buf_len;		if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0)			break;		if (errno == E2BIG && res_buf_len < 100000) {			os_free(res_buf);			res_buf = NULL;			res_buf_len *= 2;			wpa_printf(MSG_DEBUG, "Scan results did not fit - "				   "trying larger buffer (%lu bytes)",				   (unsigned long) res_buf_len);		} else {			perror("ioctl[SIOCGIWSCAN]");			os_free(res_buf);			return NULL;		}	}	if (iwr.u.data.length > res_buf_len) {		os_free(res_buf);		return NULL;	}	*len = iwr.u.data.length;	return res_buf;}/* * Data structure for collecting WEXT scan results. This is needed to allow * the various methods of reporting IEs to be combined into a single IE buffer. */struct wext_scan_data {	struct wpa_scan_res res;	u8 *ie;	size_t ie_len;	u8 ssid[32];	size_t ssid_len;	int maxrate;};static void wext_get_scan_mode(struct iw_event *iwe,			       struct wext_scan_data *res){	if (iwe->u.mode == IW_MODE_ADHOC)		res->res.caps |= IEEE80211_CAP_IBSS;	else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA)		res->res.caps |= IEEE80211_CAP_ESS;}static void wext_get_scan_ssid(struct iw_event *iwe,			       struct wext_scan_data *res, char *custom,			       char *end){	int ssid_len = iwe->u.essid.length;	if (custom + ssid_len > end)		return;	if (iwe->u.essid.flags &&	    ssid_len > 0 &&	    ssid_len <= IW_ESSID_MAX_SIZE) {		os_memcpy(res->ssid, custom, ssid_len);		res->ssid_len = ssid_len;	}}static void wext_get_scan_freq(struct iw_event *iwe,			       struct wext_scan_data *res){	int divi = 1000000, i;	if (iwe->u.freq.e == 0) {		/*		 * Some drivers do not report frequency, but a channel.		 * Try to map this to frequency by assuming they are using		 * IEEE 802.11b/g.  But don't overwrite a previously parsed		 * frequency if the driver sends both frequency and channel,		 * since the driver may be sending an A-band channel that we		 * don't handle here.		 */		if (res->res.freq)			return;		if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) {			res->res.freq = 2407 + 5 * iwe->u.freq.m;			return;		} else if (iwe->u.freq.m == 14) {			res->res.freq = 2484;			return;		}	}	if (iwe->u.freq.e > 6) {		wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID="			   MACSTR " m=%d e=%d)",			   MAC2STR(res->res.bssid), iwe->u.freq.m,			   iwe->u.freq.e);		return;	}	for (i = 0; i < iwe->u.freq.e; i++)		divi /= 10;	res->res.freq = iwe->u.freq.m / divi;}static void wext_get_scan_qual(struct iw_event *iwe,			       struct wext_scan_data *res){	res->res.qual = iwe->u.qual.qual;	res->res.noise = iwe->u.qual.noise;	res->res.level = iwe->u.qual.level;}static void wext_get_scan_encode(struct iw_event *iwe,				 struct wext_scan_data *res){	if (!(iwe->u.data.flags & IW_ENCODE_DISABLED))		res->res.caps |= IEEE80211_CAP_PRIVACY;}static void wext_get_scan_rate(struct iw_event *iwe,			       struct wext_scan_data *res, char *pos,			       char *end){	int maxrate;	char *custom = pos + IW_EV_LCP_LEN;	struct iw_param p;	size_t clen;	clen = iwe->len;	if (custom + clen > end)		return;	maxrate = 0;	while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) {		/* Note: may be misaligned, make a local, aligned copy */		os_memcpy(&p, custom, sizeof(struct iw_param));		if (p.value > maxrate)			maxrate = p.value;		clen -= sizeof(struct iw_param);		custom += sizeof(struct iw_param);	}	/* Convert the maxrate from WE-style (b/s units) to	 * 802.11 rates (500000 b/s units).	 */	res->maxrate = maxrate / 500000;}static void wext_get_scan_iwevgenie(struct iw_event *iwe,				    struct wext_scan_data *res, char *custom,				    char *end){	char *genie, *gpos, *gend;	u8 *tmp;	gpos = genie = custom;	gend = genie + iwe->u.data.length;	if (gend > end) {		wpa_printf(MSG_INFO, "IWEVGENIE overflow");		return;	}	tmp = os_realloc(res->ie, res->ie_len + gend - gpos);	if (tmp == NULL)		return;	os_memcpy(tmp + res->ie_len, gpos, gend - gpos);	res->ie = tmp;	res->ie_len += gend - gpos;}static void wext_get_scan_custom(struct iw_event *iwe,				 struct wext_scan_data *res, char *custom,				 char *end){	size_t clen;	u8 *tmp;	clen = iwe->u.data.length;	if (custom + clen > end)		return;	if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) {		char *spos;		int bytes;		spos = custom + 7;		bytes = custom + clen - spos;		if (bytes & 1)			return;		bytes /= 2;		tmp = os_realloc(res->ie, res->ie_len + bytes);		if (tmp == NULL)			return;		hexstr2bin(spos, tmp + res->ie_len, bytes);		res->ie = tmp;		res->ie_len += bytes;	} else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) {		char *spos;		int bytes;		spos = custom + 7;		bytes = custom + clen - spos;		if (bytes & 1)			return;		bytes /= 2;		tmp = os_realloc(res->ie, res->ie_len + bytes);		if (tmp == NULL)			return;		hexstr2bin(spos, tmp + res->ie_len, bytes);		res->ie = tmp;		res->ie_len += bytes;	} else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) {		char *spos;		int bytes;		u8 bin[8];		spos = custom + 4;		bytes = custom + clen - spos;		if (bytes != 16) {			wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes);			return;		}		bytes /= 2;		hexstr2bin(spos, bin, bytes);		res->res.tsf += WPA_GET_BE64(bin);	}}static int wext_19_iw_point(struct wpa_driver_nl80211_data *drv, u16 cmd){	return drv->we_version_compiled > 18 &&		(cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE ||		 cmd == IWEVGENIE || cmd == IWEVCUSTOM);}static void wpa_driver_nl80211_add_scan_entry(struct wpa_scan_results *res,					   struct wext_scan_data *data){	struct wpa_scan_res **tmp;	struct wpa_scan_res *r;	size_t extra_len;	u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL;	/* Figure out whether we need to fake any IEs */	pos = data->ie;	end = pos + data->ie_len;	while (pos && pos + 1 < end) {		if (pos + 2 + pos[1] > end)			break;		if (pos[0] == WLAN_EID_SSID)			ssid_ie = pos;		else if (pos[0] == WLAN_EID_SUPP_RATES)			rate_ie = pos;		else if (pos[0] == WLAN_EID_EXT_SUPP_RATES)			rate_ie = pos;		pos += 2 + pos[1];	}	extra_len = 0;	if (ssid_ie == NULL)		extra_len += 2 + data->ssid_len;	if (rate_ie == NULL && data->maxrate)		extra_len += 3;	r = os_zalloc(sizeof(*r) + extra_len + data->ie_len);	if (r == NULL)		return;	os_memcpy(r, &data->res, sizeof(*r));	r->ie_len = extra_len + data->ie_len;	pos = (u8 *) (r + 1);	if (ssid_ie == NULL) {		/*		 * Generate a fake SSID IE since the driver did not report		 * a full IE list.		 */		*pos++ = WLAN_EID_SSID;		*pos++ = data->ssid_len;		os_memcpy(pos, data->ssid, data->ssid_len);		pos += data->ssid_len;	}	if (rate_ie == NULL && data->maxrate) {		/*		 * Generate a fake Supported Rates IE since the driver did not		 * report a full IE list.		 */		*pos++ = WLAN_EID_SUPP_RATES;		*pos++ = 1;		*pos++ = data->maxrate;	}	if (data->ie)		os_memcpy(pos, data->ie, data->ie_len);	tmp = os_realloc(res->res,			 (res->num + 1) * sizeof(struct wpa_scan_res *));	if (tmp == NULL) {		os_free(r);		return;	}	tmp[res->num++] = r;	res->res = tmp;}				      /** * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results * @priv: Pointer to private wext data from wpa_driver_nl80211_init() * Returns: Scan results on success, -1 on failure */struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv){	struct wpa_driver_nl80211_data *drv = priv;	size_t ap_num = 0, len;	int first;	u8 *res_buf;	struct iw_event iwe_buf, *iwe = &iwe_buf;	char *pos, *end, *custom;	struct wpa_scan_results *res;	struct wext_scan_data data;	res_buf = wpa_driver_nl80211_giwscan(drv, &len);	if (res_buf == NULL)		return NULL;	ap_num = 0;	first = 1;	res = os_zalloc(sizeof(*res));	if (res == NULL) {		os_free(res_buf);		return NULL;	}	pos = (char *) res_buf;	end = (char *) res_buf + len;	os_memset(&data, 0, sizeof(data));	while (pos + IW_EV_LCP_LEN <= end) {		/* Event data may be unaligned, so make a local, aligned copy		 * before processing. */		os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);		if (iwe->len <= IW_EV_LCP_LEN)			break;		custom = pos + IW_EV_POINT_LEN;		if (wext_19_iw_point(drv, iwe->cmd)) {			/* WE-19 removed the pointer from struct iw_point */			char *dpos = (char *) &iwe_buf.u.data.length;			int dlen = dpos - (char *) &iwe_buf;			os_memcpy(dpos, pos + IW_EV_LCP_LEN,				  sizeof(struct iw_event) - dlen);		} else {			os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));			custom += IW_EV_POINT_OFF;		}		switch (iwe->cmd) {		case SIOCGIWAP:			if (!first)				wpa_driver_nl80211_add_scan_entry(res, &data);			first = 0;			os_free(data.ie);			os_memset(&data, 0, sizeof(data));			os_memcpy(data.res.bssid,				  iwe->u.ap_addr.sa_data, ETH_ALEN);			break;		case SIOCGIWMODE:			wext_get_scan_mode(iwe, &data);			break;		case SIOCGIWESSID:			wext_get_scan_ssid(iwe, &data, custom, end);			break;		case SIOCGIWFREQ:			wext_get_scan_freq(iwe, &data);			break;		case IWEVQUAL:			wext_get_scan_qual(iwe, &data);			break;		case SIOCGIWENCODE:			wext_get_scan_encode(iwe, &data);			break;		case SIOCGIWRATE:			wext_get_scan_rate(iwe, &data, pos, end);			break;		case IWEVGENIE:			wext_get_scan_iwevgenie(iwe, &data, custom, end);			break;		case IWEVCUSTOM:			wext_get_scan_custom(iwe, &data, custom, end);			break;		}		pos += iwe->len;	}	os_free(res_buf);	res_buf = NULL;	if (!first)		wpa_driver_nl80211_add_scan_entry(res, &data);	os_free(data.ie);	wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",		   (unsigned long) len, (unsigned long) res->num);	return res;}static int wpa_driver_nl80211_get_range(void *priv){	struct wpa_driver_nl80211_data *drv = priv;	struct iw_range *range;	struct iwreq iwr;	int minlen;	size_t buflen;	/*	 * Use larger buffer than struct iw_range in order to allow the	 * structure to grow in the future.	 */	buflen = sizeof(struct iw_range) + 500;	range = os_zalloc(buflen);	if (range == NULL)		return -1;	os_memset(&iwr, 0, sizeof(iwr));	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	iwr.u.data.pointer = (caddr_t) range;	iwr.u.data.length = buflen;	minlen = ((char *) &range->enc_capa) - (char *) range +		sizeof(range->enc_capa);	if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {		perror("ioctl[SIOCGIWRANGE]");		os_free(range);		return -1;	} else if (iwr.u.data.length >= minlen &&		   range->we_version_compiled >= 18) {		wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "			   "WE(source)=%d enc_capa=0x%x",			   range->we_version_compiled,			   range->we_version_source,			   range->enc_capa);		drv->has_capability = 1;		drv->we_version_compiled = range->we_version_compiled;		if (range->enc_capa & IW_ENC_CAPA_WPA) {			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |				WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;		}		if (range->enc_capa & IW_ENC_CAPA_WPA2) {			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |				WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;		}		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |			WPA_DRIVER_CAPA_ENC_WEP104;		if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP)			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;		if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP)			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;		wpa_printf(MSG_DEBUG, "  capabilities: key_mgmt 0x%x enc 0x%x",			   drv->capa.key_mgmt, drv->capa.enc);	} else {		wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - "			   "assuming WPA is not supported");	}	os_free(range);	return 0;}static int wpa_driver_nl80211_set_wpa(void *priv, int enabled){	struct wpa_driver_nl80211_data *drv = priv;	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);	return wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_WPA_ENABLED,					      enabled);}

⌨️ 快捷键说明

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