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

📄 driver_wext.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * WPA Supplicant - driver interaction with generic Linux Wireless Extensions * Copyright (c) 2003-2007, Jouni Malinen <j@w1.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 "includes.h"#include <sys/ioctl.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"#ifdef CONFIG_CLIENT_MLME#include <netpacket/packet.h>#include <hostapd_ioctl.h>#include <ieee80211_common.h>/* from net/mac80211.h */enum {	MODE_IEEE80211A = 0 /* IEEE 802.11a */,	MODE_IEEE80211B = 1 /* IEEE 802.11b only */,	MODE_ATHEROS_TURBO = 2 /* Atheros Turbo mode (2x.11a at 5 GHz) */,	MODE_IEEE80211G = 3 /* IEEE 802.11g (and 802.11b compatibility) */,	MODE_ATHEROS_TURBOG = 4 /* Atheros Turbo mode (2x.11g at 2.4 GHz) */,	NUM_IEEE80211_MODES = 5};#include "mlme.h"#ifndef ETH_P_ALL#define ETH_P_ALL 0x0003#endif#endif /* CONFIG_CLIENT_MLME */struct wpa_driver_wext_data {	void *ctx;	int event_sock;	int ioctl_sock;	int mlme_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;	int operstate;	char mlmedev[IFNAMSIZ + 1];	int scan_complete_events;};static int wpa_driver_wext_flush_pmkid(void *priv);static int wpa_driver_wext_get_range(void *priv);static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,					  int linkmode, int operstate){	struct {		struct nlmsghdr hdr;		struct ifinfomsg ifinfo;		char opts[16];	} req;	struct rtattr *rta;	static int nl_seq;	ssize_t ret;	req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));	req.hdr.nlmsg_type = RTM_SETLINK;	req.hdr.nlmsg_flags = NLM_F_REQUEST;	req.hdr.nlmsg_seq = ++nl_seq;	req.hdr.nlmsg_pid = 0;	req.ifinfo.ifi_family = AF_UNSPEC;	req.ifinfo.ifi_type = 0;	req.ifinfo.ifi_index = drv->ifindex;	req.ifinfo.ifi_flags = 0;	req.ifinfo.ifi_change = 0;	if (linkmode != -1) {		rta = (struct rtattr *)			((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len));		rta->rta_type = IFLA_LINKMODE;		rta->rta_len = RTA_LENGTH(sizeof(char));		*((char *) RTA_DATA(rta)) = linkmode;		req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +			RTA_LENGTH(sizeof(char));	}	if (operstate != -1) {		rta = (struct rtattr *)			((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len));		rta->rta_type = IFLA_OPERSTATE;		rta->rta_len = RTA_LENGTH(sizeof(char));		*((char *) RTA_DATA(rta)) = operstate;		req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +			RTA_LENGTH(sizeof(char));	}	wpa_printf(MSG_DEBUG, "WEXT: Operstate: linkmode=%d, operstate=%d",		   linkmode, operstate);	ret = send(drv->event_sock, &req, req.hdr.nlmsg_len, 0);	if (ret < 0) {		wpa_printf(MSG_DEBUG, "WEXT: Sending operstate IFLA failed: "			   "%s (assume operstate is not supported)",			   strerror(errno));	}	return ret < 0 ? -1 : 0;}static int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,					  int idx, u32 value){	struct iwreq iwr;	int ret = 0;	os_memset(&iwr, 0, sizeof(iwr));	os_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;	os_memset(&iwr, 0, sizeof(iwr));	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {		perror("ioctl[SIOCGIWAP]");		ret = -1;	}	os_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;	os_memset(&iwr, 0, sizeof(iwr));	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	iwr.u.ap_addr.sa_family = ARPHRD_ETHER;	if (bssid)		os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);	else		os_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;	os_memset(&iwr, 0, sizeof(iwr));	os_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;	os_memset(&iwr, 0, sizeof(iwr));	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);	/* flags: 1 = ESSID is active, 0 = not (promiscuous) */	iwr.u.essid.flags = (ssid_len != 0);	os_memset(buf, 0, sizeof(buf));	os_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;	os_memset(&iwr, 0, sizeof(iwr));	os_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(void *ctx, char *custom){	union wpa_event_data data;	wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'",		   custom);	os_memset(&data, 0, sizeof(data));	/* Host AP driver */	if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {		data.michael_mic_failure.unicast =			os_strstr(custom, " unicast ") != NULL;		/* TODO: parse parameters(?) */		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);	} else if (os_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 = os_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 (os_strncmp(spos, " RespIEs=", 9) == 0) {			spos += 9;			bytes = strspn(spos, "0123456789abcdefABCDEF");			if (!bytes || (bytes & 1))				goto done;			bytes /= 2;			data.assoc_info.resp_ies = os_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:		os_free(data.assoc_info.resp_ies);		os_free(data.assoc_info.req_ies);#ifdef CONFIG_PEERKEY	} else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) {		if (hwaddr_aton(custom + 17, data.stkstart.peer)) {			wpa_printf(MSG_DEBUG, "WEXT: unrecognized "				   "STKSTART.request '%s'", custom + 17);			return;		}		wpa_supplicant_event(ctx, EVENT_STKSTART, &data);#endif /* CONFIG_PEERKEY */	}}static int wpa_driver_wext_event_wireless_michaelmicfailure(	void *ctx, const char *ev, size_t 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));	os_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, const char *ev, size_t 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));	os_memset(&data, 0, sizeof(data));	os_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, const char *ev, int len){	if (len < 0)		return -1;	wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev,		    len);	os_free(drv->assoc_req_ies);	drv->assoc_req_ies = os_malloc(len);	if (drv->assoc_req_ies == NULL) {		drv->assoc_req_ies_len = 0;		return -1;	}	os_memcpy(drv->assoc_req_ies, ev, len);	drv->assoc_req_ies_len = len;	return 0;}static int wpa_driver_wext_event_wireless_assocrespie(

⌨️ 快捷键说明

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