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

📄 driver_wext.c

📁 一个Linux下无线网卡的设置工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * WPA Supplicant - driver interaction with generic Linux Wireless Extensions * Copyright (c) 2003-2006, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file implements a driver interface for the Linux Wireless Extensions. * When used with WE-18 or newer, this interface can be used as-is with number * of drivers. In addition to this, some of the common functions in this file * can be used by other driver interface implementations that use generic WE * ioctls, but require private ioctls for some of the functionality. */#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/ioctl.h>#include <errno.h>#include <net/if_arp.h>#include "wireless_copy.h"#include "common.h"#include "driver.h"#include "l2_packet.h"#include "eloop.h"#include "wpa_supplicant.h"#include "priv_netlink.h"#include "driver_wext.h"#include "wpa.h"struct wpa_driver_wext_data {	void *ctx;	int event_sock;	int ioctl_sock;	char ifname[IFNAMSIZ + 1];	int ifindex;	int ifindex2;	u8 *assoc_req_ies;	size_t assoc_req_ies_len;	u8 *assoc_resp_ies;	size_t assoc_resp_ies_len;	struct wpa_driver_capa capa;	int has_capability;	int we_version_compiled;	/* for set_auth_alg fallback */	int use_crypt;	int auth_alg_fallback;};static int wpa_driver_wext_flush_pmkid(void *priv);static int wpa_driver_wext_get_range(void *priv);static int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,					  int idx, u32 value){	struct iwreq iwr;	int ret = 0;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	iwr.u.param.flags = idx & IW_AUTH_INDEX;	iwr.u.param.value = value;	if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {		perror("ioctl[SIOCSIWAUTH]");		fprintf(stderr, "WEXT auth param %d value 0x%x - ",			idx, value);		ret = errno == EOPNOTSUPP ? -2 : -1;	}	return ret;}/** * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP * @priv: Pointer to private wext data from wpa_driver_wext_init() * @bssid: Buffer for BSSID * Returns: 0 on success, -1 on failure */int wpa_driver_wext_get_bssid(void *priv, u8 *bssid){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	int ret = 0;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {		perror("ioctl[SIOCGIWAP]");		ret = -1;	}	memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);	return ret;}/** * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP * @priv: Pointer to private wext data from wpa_driver_wext_init() * @bssid: BSSID * Returns: 0 on success, -1 on failure */int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	int ret = 0;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	iwr.u.ap_addr.sa_family = ARPHRD_ETHER;	if (bssid)		memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);	else		memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);	if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {		perror("ioctl[SIOCSIWAP]");		ret = -1;	}	return ret;}/** * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID * @priv: Pointer to private wext data from wpa_driver_wext_init() * @ssid: Buffer for the SSID; must be at least 32 bytes long * Returns: SSID length on success, -1 on failure */int wpa_driver_wext_get_ssid(void *priv, u8 *ssid){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	int ret = 0;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	iwr.u.essid.pointer = (caddr_t) ssid;	iwr.u.essid.length = 32;	if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {		perror("ioctl[SIOCGIWESSID]");		ret = -1;	} else {		ret = iwr.u.essid.length;		if (ret > 32)			ret = 32;		/* Some drivers include nul termination in the SSID, so let's		 * remove it here before further processing. WE-21 changes this		 * to explicitly require the length _not_ to include nul		 * termination. */		if (ret > 0 && ssid[ret - 1] == '\0' &&		    drv->we_version_compiled < 21)			ret--;	}	return ret;}/** * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID * @priv: Pointer to private wext data from wpa_driver_wext_init() * @ssid: SSID * @ssid_len: Length of SSID (0..32) * Returns: 0 on success, -1 on failure */int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	int ret = 0;	char buf[33];	if (ssid_len > 32)		return -1;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	/* flags: 1 = ESSID is active, 0 = not (promiscuous) */	iwr.u.essid.flags = (ssid_len != 0);	memset(buf, 0, sizeof(buf));	memcpy(buf, ssid, ssid_len);	iwr.u.essid.pointer = (caddr_t) buf;	if (drv->we_version_compiled < 21) {		/* For historic reasons, set SSID length to include one extra		 * character, C string nul termination, even though SSID is		 * really an octet string that should not be presented as a C		 * string. Some Linux drivers decrement the length by one and		 * can thus end up missing the last octet of the SSID if the		 * length is not incremented here. WE-21 changes this to		 * explicitly require the length _not_ to include nul		 * termination. */		if (ssid_len)			ssid_len++;	}	iwr.u.essid.length = ssid_len;	if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {		perror("ioctl[SIOCSIWESSID]");		ret = -1;	}	return ret;}/** * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ * @priv: Pointer to private wext data from wpa_driver_wext_init() * @freq: Frequency in MHz * Returns: 0 on success, -1 on failure */int wpa_driver_wext_set_freq(void *priv, int freq){	struct wpa_driver_wext_data *drv = priv;	struct iwreq iwr;	int ret = 0;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	iwr.u.freq.m = freq * 100000;	iwr.u.freq.e = 1;	if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {		perror("ioctl[SIOCSIWFREQ]");		ret = -1;	}	return ret;}static voidwpa_driver_wext_event_wireless_custom(struct wpa_driver_wext_data *drv,				      void *ctx, char *custom){	union wpa_event_data data;	wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);	memset(&data, 0, sizeof(data));	/* Host AP driver */	if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {		data.michael_mic_failure.unicast =			strstr(custom, " unicast ") != NULL;		/* TODO: parse parameters(?) */		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);	} else if (strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) {		char *spos;		int bytes;		spos = custom + 17;		bytes = strspn(spos, "0123456789abcdefABCDEF");		if (!bytes || (bytes & 1))			return;		bytes /= 2;		data.assoc_info.req_ies = malloc(bytes);		if (data.assoc_info.req_ies == NULL)			return;		data.assoc_info.req_ies_len = bytes;		hexstr2bin(spos, data.assoc_info.req_ies, bytes);		spos += bytes * 2;		data.assoc_info.resp_ies = NULL;		data.assoc_info.resp_ies_len = 0;		if (strncmp(spos, " RespIEs=", 9) == 0) {			spos += 9;			bytes = strspn(spos, "0123456789abcdefABCDEF");			if (!bytes || (bytes & 1))				goto done;			bytes /= 2;			data.assoc_info.resp_ies = malloc(bytes);			if (data.assoc_info.resp_ies == NULL)				goto done;			data.assoc_info.resp_ies_len = bytes;			hexstr2bin(spos, data.assoc_info.resp_ies, bytes);		}		wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);	done:		free(data.assoc_info.resp_ies);		free(data.assoc_info.req_ies);	}}static int wpa_driver_wext_event_wireless_michaelmicfailure(	struct wpa_driver_wext_data *drv, void *ctx, const char *ev, int len){	const struct iw_michaelmicfailure *mic;	union wpa_event_data data;	if (len < sizeof(*mic))		return -1;	mic = (const struct iw_michaelmicfailure *) ev;	wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: "		   "flags=0x%x src_addr=" MACSTR, mic->flags,		   MAC2STR(mic->src_addr.sa_data));	memset(&data, 0, sizeof(data));	data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP);	wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);	return 0;}static int wpa_driver_wext_event_wireless_pmkidcand(	struct wpa_driver_wext_data *drv, void *ctx, const char *ev, int len){	const struct iw_pmkid_cand *cand;	union wpa_event_data data;	const u8 *addr;	if (len < sizeof(*cand))		return -1;	cand = (const struct iw_pmkid_cand *) ev;	addr = (const u8 *) cand->bssid.sa_data;	wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: "		   "flags=0x%x index=%d bssid=" MACSTR, cand->flags,		   cand->index, MAC2STR(addr));	memset(&data, 0, sizeof(data));	memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN);	data.pmkid_candidate.index = cand->index;	data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH;	wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);	return 0;}static int wpa_driver_wext_event_wireless_assocreqie(	struct wpa_driver_wext_data *drv, void *ctx, const char *ev, int len){	if (len < 0)		return -1;	wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev,		    len);	free(drv->assoc_req_ies);	drv->assoc_req_ies = malloc(len);	if (drv->assoc_req_ies == NULL) {		drv->assoc_req_ies_len = 0;		return -1;	}	memcpy(drv->assoc_req_ies, ev, len);	drv->assoc_req_ies_len = len;	return 0;}static int wpa_driver_wext_event_wireless_assocrespie(	struct wpa_driver_wext_data *drv, void *ctx, const char *ev, int len){	if (len < 0)		return -1;	wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev,		    len);	free(drv->assoc_resp_ies);	drv->assoc_resp_ies = malloc(len);	if (drv->assoc_resp_ies == NULL) {		drv->assoc_resp_ies_len = 0;		return -1;	}	memcpy(drv->assoc_resp_ies, ev, len);	drv->assoc_resp_ies_len = len;	return 0;}static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv){	union wpa_event_data data;	if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL)		return;	memset(&data, 0, sizeof(data));	if (drv->assoc_req_ies) {		data.assoc_info.req_ies = drv->assoc_req_ies;		drv->assoc_req_ies = NULL;		data.assoc_info.req_ies_len = drv->assoc_req_ies_len;	}	if (drv->assoc_resp_ies) {		data.assoc_info.resp_ies = drv->assoc_resp_ies;		drv->assoc_resp_ies = NULL;		data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;	}	wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);	free(data.assoc_info.req_ies);	free(data.assoc_info.resp_ies);}static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,					   void *ctx, char *data, int len){	struct iw_event iwe_buf, *iwe = &iwe_buf;	char *pos, *end, *custom, *buf;	pos = data;	end = data + len;	while (pos + IW_EV_LCP_LEN <= end) {		/* Event data may be unaligned, so make a local, aligned copy		 * before processing. */		memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);		wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",			   iwe->cmd, iwe->len);		if (iwe->len <= IW_EV_LCP_LEN)			return;		custom = pos + IW_EV_POINT_LEN;		if (drv->we_version_compiled > 18 &&		    (iwe->cmd == IWEVMICHAELMICFAILURE ||		     iwe->cmd == IWEVCUSTOM ||		     iwe->cmd == IWEVASSOCREQIE ||		     iwe->cmd == IWEVASSOCRESPIE ||		     iwe->cmd == IWEVPMKIDCAND)) {			/* 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;

⌨️ 快捷键说明

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