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

📄 driver_wext.c

📁 IEEE802.11 a/b/g 客户端应用程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return *i;}#endif /* CONFIG_CLIENT_MLME *//** * wpa_driver_wext_set_ifflags - Set interface flags (SIOCSIFFLAGS) * @drv: driver_wext private data * @flags: New value for flags * Returns: 0 on success, -1 on failure */int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags){	return wpa_driver_wext_set_ifflags_ifname(drv, drv->ifname, flags);}/** * wpa_driver_wext_init - Initialize WE driver interface * @ctx: context to be used when calling wpa_supplicant functions, * e.g., wpa_supplicant_event() * @ifname: interface name, e.g., wlan0 * Returns: Pointer to private data, %NULL on failure */void * wpa_driver_wext_init(void *ctx, const char *ifname){	int s;	struct sockaddr_nl local;	struct wpa_driver_wext_data *drv;	drv = os_zalloc(sizeof(*drv));	if (drv == NULL)		return NULL;	drv->ctx = ctx;	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);	if (drv->ioctl_sock < 0) {		perror("socket(PF_INET,SOCK_DGRAM)");		os_free(drv);		return NULL;	}	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);	if (s < 0) {		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");		close(drv->ioctl_sock);		os_free(drv);		return NULL;	}	os_memset(&local, 0, sizeof(local));	local.nl_family = AF_NETLINK;	local.nl_groups = RTMGRP_LINK;	if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {		perror("bind(netlink)");		close(s);		close(drv->ioctl_sock);		os_free(drv);		return NULL;	}	eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx);	drv->event_sock = s;	drv->mlme_sock = -1;	wpa_driver_wext_finish_drv_init(drv);	return drv;}static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv){	int flags;	if (wpa_driver_wext_get_ifflags(drv, &flags) != 0)		printf("Could not get interface '%s' flags\n", drv->ifname);	else if (!(flags & IFF_UP)) {		if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {			printf("Could not set interface '%s' UP\n",			       drv->ifname);		} else {			/*			 * Wait some time to allow driver to initialize before			 * starting configuring the driver. This seems to be			 * needed at least some drivers that load firmware etc.			 * when the interface is set up.			 */			wpa_printf(MSG_DEBUG, "Interface %s set UP - waiting "				   "a second for the driver to complete "				   "initialization", drv->ifname);			sleep(1);		}	}	/*	 * Make sure that the driver does not have any obsolete PMKID entries.	 */	wpa_driver_wext_flush_pmkid(drv);	if (wpa_driver_wext_set_mode(drv, 0) < 0) {		printf("Could not configure driver to use managed mode\n");	}	wpa_driver_wext_get_range(drv);	drv->ifindex = if_nametoindex(drv->ifname);	if (os_strncmp(drv->ifname, "wlan", 4) == 0) {		/*		 * Host AP driver may use both wlan# and wifi# interface in		 * wireless events. Since some of the versions included WE-18		 * support, let's add the alternative ifindex also from		 * driver_wext.c for the time being. This may be removed at		 * some point once it is believed that old versions of the		 * driver are not in use anymore.		 */		char ifname2[IFNAMSIZ + 1];		os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));		os_memcpy(ifname2, "wifi", 4);		wpa_driver_wext_alternative_ifindex(drv, ifname2);	}	wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);}/** * wpa_driver_wext_deinit - Deinitialize WE driver interface * @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.	 */	(void) 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]) {		if (wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev,						       &flags) == 0)			(void) wpa_driver_wext_set_ifflags_ifname(				drv, drv->mlmedev, flags & ~IFF_UP);		wpa_driver_prism2_param_set(drv, PRISM2_PARAM_MGMT_IF, 0);		wpa_driver_prism2_param_set(drv, PRISM2_PARAM_USER_SPACE_MLME,					    0);	}#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_strlcpy(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;}static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_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);	}

⌨️ 快捷键说明

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