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

📄 driver_wext.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 * @priv: Pointer to private wext data from wpa_driver_wext_init() * * Shut down driver interface and processing of driver events. Free * private data buffer if one was allocated in wpa_driver_wext_init(). */void wpa_driver_wext_deinit(void *priv){	struct wpa_driver_wext_data *drv = priv;	int flags;	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);	/*	 * Clear possibly configured driver parameters in order to make it	 * easier to use the driver after wpa_supplicant has been terminated.	 */	wpa_driver_wext_set_bssid(drv, (u8 *) "\x00\x00\x00\x00\x00\x00");	wpa_driver_wext_send_oper_ifla(priv, 0, IF_OPER_UP);	eloop_unregister_read_sock(drv->event_sock);	if (drv->mlme_sock >= 0)		eloop_unregister_read_sock(drv->mlme_sock);	if (wpa_driver_wext_get_ifflags(drv, &flags) == 0)		(void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);#ifdef CONFIG_CLIENT_MLME	if (drv->mlmedev[0] &&	    wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev, &flags) == 0)		(void) wpa_driver_wext_set_ifflags_ifname(drv, drv->mlmedev,							  flags & ~IFF_UP);#endif /* CONFIG_CLIENT_MLME */	close(drv->event_sock);	close(drv->ioctl_sock);	if (drv->mlme_sock >= 0)		close(drv->mlme_sock);	os_free(drv->assoc_req_ies);	os_free(drv->assoc_resp_ies);	os_free(drv);}/** * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion * @eloop_ctx: Unused * @timeout_ctx: ctx argument given to wpa_driver_wext_init() * * This function can be used as registered timeout when starting a scan to * generate a scan completed event if the driver does not report this. */void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx){	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);}/** * wpa_driver_wext_scan - Request the driver to initiate scan * @priv: Pointer to private wext data from wpa_driver_wext_init() * @ssid: Specific SSID to scan for (ProbeReq) or %NULL to scan for *	all SSIDs (either active scan with broadcast SSID or passive *	scan * @ssid_len: Length of the SSID * Returns: 0 on success, -1 on failure */int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	int ret = 0, timeout;	struct iw_scan_req req;	if (ssid_len > IW_ESSID_MAX_SIZE) {		wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",			   __FUNCTION__, (unsigned long) ssid_len);		return -1;	}	os_memset(&iwr, 0, sizeof(iwr));	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	if (ssid && ssid_len) {		os_memset(&req, 0, sizeof(req));		req.essid_len = ssid_len;		req.bssid.sa_family = ARPHRD_ETHER;		os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);		os_memcpy(req.essid, ssid, ssid_len);		iwr.u.data.pointer = (caddr_t) &req;		iwr.u.data.length = sizeof(req);		iwr.u.data.flags = IW_SCAN_THIS_ESSID;	}	if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {		perror("ioctl[SIOCSIWSCAN]");		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_wext_scan_timeout, drv, drv->ctx);	eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,			       drv->ctx);	return ret;}/* Compare function for sorting scan results. Return >0 if @b is considered * better. */static int wpa_scan_result_compar(const void *a, const void *b){	const struct wpa_scan_result *wa = a;	const struct wpa_scan_result *wb = b;	/* WPA/WPA2 support preferred */	if ((wb->wpa_ie_len || wb->rsn_ie_len) &&	    !(wa->wpa_ie_len || wa->rsn_ie_len))		return 1;	if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&	    (wa->wpa_ie_len || wa->rsn_ie_len))		return -1;	/* privacy support preferred */	if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&	    (wb->caps & IEEE80211_CAP_PRIVACY))		return 1;	if ((wa->caps & IEEE80211_CAP_PRIVACY) &&	    (wb->caps & IEEE80211_CAP_PRIVACY) == 0)		return -1;	/* best/max rate preferred if signal level close enough XXX */	if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)		return wb->maxrate - wa->maxrate;	/* use freq for channel preference */	/* all things being equal, use signal level; if signal levels are	 * identical, use quality values since some drivers may only report	 * that value and leave the signal level zero */	if (wb->level == wa->level)		return wb->qual - wa->qual;	return wb->level - wa->level;}/** * wpa_driver_wext_get_scan_results - Fetch the latest scan results * @priv: Pointer to private wext data from wpa_driver_wext_init() * @results: Pointer to buffer for scan results * @max_size: Maximum number of entries (buffer size) * Returns: Number of scan result entries used on success, -1 on * failure * * If scan results include more than max_size BSSes, max_size will be * returned and the remaining entries will not be included in the * buffer. */int wpa_driver_wext_get_scan_results(void *priv,				     struct wpa_scan_result *results,				     size_t max_size){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	size_t ap_num = 0;	int first, maxrate;	u8 *res_buf;	struct iw_event iwe_buf, *iwe = &iwe_buf;	char *pos, *end, *custom, *genie, *gpos, *gend;	struct iw_param p;	size_t len, clen, res_buf_len;	os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));	res_buf_len = IW_SCAN_MAX_DATA;	for (;;) {		res_buf = os_malloc(res_buf_len);		if (res_buf == NULL)			return -1;		os_memset(&iwr, 0, sizeof(iwr));		os_strncpy(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 -1;		}	}	len = iwr.u.data.length;	ap_num = 0;	first = 1;	pos = (char *) res_buf;	end = (char *) res_buf + len;	while (pos + IW_EV_LCP_LEN <= end) {		int ssid_len;		/* 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 (drv->we_version_compiled > 18 &&		    (iwe->cmd == SIOCGIWESSID ||		     iwe->cmd == SIOCGIWENCODE ||		     iwe->cmd == IWEVGENIE ||		     iwe->cmd == IWEVCUSTOM)) {			/* 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)				ap_num++;			first = 0;			if (ap_num < max_size) {				os_memcpy(results[ap_num].bssid,					  iwe->u.ap_addr.sa_data, ETH_ALEN);			}			break;		case SIOCGIWMODE:			if (ap_num >= max_size)				break;			if (iwe->u.mode == IW_MODE_ADHOC)				results[ap_num].caps |= IEEE80211_CAP_IBSS;			else if (iwe->u.mode == IW_MODE_MASTER ||				 iwe->u.mode == IW_MODE_INFRA)				results[ap_num].caps |= IEEE80211_CAP_ESS;			break;		case SIOCGIWESSID:			ssid_len = iwe->u.essid.length;			if (custom + ssid_len > end)				break;			if (iwe->u.essid.flags &&			    ssid_len > 0 &&			    ssid_len <= IW_ESSID_MAX_SIZE) {				if (ap_num < max_size) {					os_memcpy(results[ap_num].ssid, custom,						  ssid_len);					results[ap_num].ssid_len = ssid_len;				}			}			break;		case SIOCGIWFREQ:			if (ap_num < max_size) {				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.					 */					if (iwe->u.freq.m >= 1 &&					    iwe->u.freq.m <= 13) {						results[ap_num].freq =							2407 +							5 * iwe->u.freq.m;						break;					} else if (iwe->u.freq.m == 14) {						results[ap_num].freq = 2484;						break;					}				}				if (iwe->u.freq.e > 6) {					wpa_printf(						MSG_DEBUG, "Invalid freq "						"in scan results (BSSID="						MACSTR ": m=%d e=%d\n",						MAC2STR(results[ap_num].bssid),						iwe->u.freq.m, iwe->u.freq.e);					break;				}				for (i = 0; i < iwe->u.freq.e; i++)					divi /= 10;				results[ap_num].freq = iwe->u.freq.m / divi;			}			break;		case IWEVQUAL:			if (ap_num < max_size) {				results[ap_num].qual = iwe->u.qual.qual;				results[ap_num].noise = iwe->u.qual.noise;				results[ap_num].level = iwe->u.qual.level;			}			break;		case SIOCGIWENCODE:			if (ap_num < max_size &&			    !(iwe->u.data.flags & IW_ENCODE_DISABLED))				results[ap_num].caps |= IEEE80211_CAP_PRIVACY;			break;		case SIOCGIWRATE:			custom = pos + IW_EV_LCP_LEN;			clen = iwe->len;			if (custom + clen > end)				break;			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);			}			if (ap_num < max_size)				results[ap_num].maxrate = maxrate;			break;		case IWEVGENIE:			if (ap_num >= max_size)				break;			gpos = genie = custom;			gend = genie + iwe->u.data.length;			if (gend > end) {				wpa_printf(MSG_INFO, "IWEVGENIE overflow");				break;			}			while (gpos + 1 < gend &&			       gpos + 2 + (u8) gpos[1] <= gend) {				u8 ie = gpos[0], ielen = gpos[1] + 2;				if (ielen > SSID_MAX_WPA_IE_LEN) {					gpos += ielen;					continue;				}				switch (ie) {				case GENERIC_INFO_ELEM:					if (ielen < 2 + 4 ||					    os_memcmp(&gpos[2],						      "\x00\x50\xf2\x01", 4) !=					    0)						break;					os_memcpy(results[ap_num].wpa_ie, gpos,						  ielen);					results[ap_num].wpa_ie_len = ielen;					break;				case RSN_INFO_ELEM:					os_memcpy(results[ap_num].rsn_ie, gpos,						  ielen);					results[ap_num].rsn_ie_len = ielen;					break;				}				gpos += ielen;			}			break;		case IWEVCUSTOM:			clen = iwe->u.data.length;			if (custom + clen > end)				break;			if (clen > 7 &&			    os_strncmp(custom, "wpa_ie=", 7) == 0 &&			    ap_num < max_size) {				char *spos;				int bytes;				spos = custom + 7;				bytes = custom + clen - spos;				if (bytes & 1)					break;				bytes /= 2;				if (bytes > SSID_MAX_WPA_IE_LEN) {					wpa_printf(MSG_INFO, "Too long WPA IE "						   "(%d)", bytes);					break;				}				hexstr2bin(spos, results[ap_num].wpa_ie,					   bytes);				results[ap_num].wpa_ie_len = bytes;			} else if (clen > 7 &&				   os_strncmp(custom, "rsn_ie=", 7) == 0 &&				   ap_num < max_size) {				char *spos;				int bytes;				spos = custom + 7;				bytes = custom + clen - spos;				if (bytes & 1)					break;				bytes /= 2;				if (bytes > SSID_MAX_WPA_IE_LEN) {					wpa_printf(MSG_INFO, "Too long RSN IE "						   "(%d)", bytes);					break;				}				hexstr2bin(spos, results[ap_num].rsn_ie,					   bytes);				results[ap_num].rsn_ie_len = bytes;			}			break;		}		pos += iwe->len;	}	os_free(res_buf);	res_buf = NULL;	if (!first)		ap_num++;	if (ap_num > max_size) {		wpa_printf(MSG_DEBUG, "Too small scan result buffer - "			   "%lu BSSes but room only for %lu",			   (unsigned long) ap_num,			   (unsigned long) max_size);		ap_num = max_size;	}	qsort(results, ap_num, sizeof(struct wpa_scan_result),	      wpa_scan_result_compar);	wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",		   (unsigned long) len, (unsigned long) ap_num);	return ap_num;}static int wpa_driver_wext_get_range(void *priv){	struct wpa_driver_wext_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_strncpy(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]");

⌨️ 快捷键说明

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