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

📄 driver_wext.c

📁 一个Linux下无线网卡的设置工具
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* 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 - wb->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;	int ap_num = 0, 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;	memset(results, 0, max_size * sizeof(struct wpa_scan_result));	res_buf_len = IW_SCAN_MAX_DATA;	for (;;) {		res_buf = malloc(res_buf_len);		if (res_buf == NULL)			return -1;		memset(&iwr, 0, sizeof(iwr));		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) {			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]");			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. */		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;			memcpy(dpos, pos + IW_EV_LCP_LEN,			       sizeof(struct iw_event) - dlen);		} else {			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) {				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) {					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 > 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) >= sizeof(struct iw_param)) {				/* Note: may be misaligned, make a local,				 * aligned copy */				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 ||					    memcmp(&gpos[2],						   "\x00\x50\xf2\x01", 4) != 0)						break;					memcpy(results[ap_num].wpa_ie, gpos,					       ielen);					results[ap_num].wpa_ie_len = ielen;					break;				case RSN_INFO_ELEM:					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 && 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 &&				   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;	}	free(res_buf);	res_buf = NULL;	if (!first)		ap_num++;	if (ap_num > max_size) {		wpa_printf(MSG_DEBUG, "Too small scan result buffer - %d BSSes"			   " but room only for %lu", 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 (%d BSSes)",		   (unsigned long) len, 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 = malloc(buflen);	if (range == NULL)		return -1;	memset(range, 0, buflen);	memset(&iwr, 0, sizeof(iwr));	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]");		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");	}	free(range);	return 0;}static int wpa_driver_wext_set_wpa(void *priv, int enabled){	struct wpa_driver_wext_data *drv = priv;	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);	return wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED,					      enabled);}static int wpa_driver_wext_set_key_ext(void *priv, wpa_alg alg,				       const u8 *addr, int key_idx,				       int set_tx, const u8 *seq,				       size_t seq_len,				       const u8 *key, size_t key_len){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	int ret = 0;	struct iw_encode_ext *ext;	if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) {		wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu",			   __FUNCTION__, (unsigned long) seq_len);		return -1;	}	ext = malloc(sizeof(*ext) + key_len);	if (ext == NULL)		return -1;	memset(ext, 0, sizeof(*ext) + key_len);	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	iwr.u.encoding.flags = key_idx + 1;	if (alg == WPA_ALG_NONE)		iwr.u.encoding.flags |= IW_ENCODE_DISABLED;	iwr.u.encoding.pointer = (caddr_t) ext;	iwr.u.encoding.length = sizeof(*ext) + key_len;	if (addr == NULL ||	    memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)		ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;	if (set_tx)		ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;	ext->addr.sa_family = ARPHRD_ETHER;	if (addr)		memcpy(ext->addr.sa_data, addr, ETH_ALEN);	else		memset(ext->addr.sa_data, 0xff, ETH_ALEN);	if (key && key_len) {		memcpy(ext + 1, key, key_len);		ext->key_len = key_len;	}	switch (alg) {	case WPA_ALG_NONE:		ext->alg = IW_ENCODE_ALG_NONE;		break;	case WPA_ALG_WEP:		ext->alg = IW_ENCODE_ALG_WEP;		break;	case WPA_ALG_TKIP:		ext->alg = IW_ENCODE_ALG_TKIP;		break;	case WPA_ALG_CCMP:		ext->alg = IW_ENCODE_ALG_CCMP;		break;	default:		wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d",			   __FUNCTION__, alg);		free(ext);		return -1;	}	if (seq && seq_len) {		ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID;		memcpy(ext->rx_seq, seq, seq_len);	}	if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) {		ret = errno == EOPNOTSUPP ? -2 : -1;		if (errno == ENODEV) {			/*			 * ndiswrapper seems to be returning incorrect error			 * code.. */			ret = -2;		}		perror("ioctl[SIOCSIWENCODEEXT]");	}	free(ext);	return ret;}/** * wpa_driver_wext_set_key - Configure encryption key * @priv: Pointer to private wext data from wpa_driver_wext_init() * @priv: Private driver interface data * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, *	%WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key. * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for *	broadcast/default keys * @key_idx: key index (0..3), usually 0 for unicast keys * @set_tx: Configure this key as the default Tx key (only used when *	driver does not support separate unicast/individual key * @seq: Sequence number/packet number, seq_len octets, the next *	packet number to be used for in replay protection; configured *	for Rx keys (in most cases, this is only used with broadcast *	keys and set to zero for unicast keys) * @seq_len: Length of the seq, depends on the algorithm: *	TKIP: 6 octets, CCMP: 6 octets * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, *	8-byte Rx Mic Key * @key_len: Length of the key buffer in octets (WEP: 5 or 13, *	TKIP: 32, CCMP: 16) * Returns: 0 on success, -1 on failure *

⌨️ 快捷键说明

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