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

📄 driver_wext.c

📁 IEEE802.11 a/b/g 客户端应用程序源代码
💻 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 "eloop.h"#include "priv_netlink.h"#include "driver_wext.h"#include "ieee802_11_defs.h"#include "wpa_common.h"#ifdef CONFIG_CLIENT_MLME#include <netpacket/packet.h>/* old definitions from net/mac80211 */typedef u32 __bitwise __be32;typedef u64 __bitwise __be64;#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)#define PRISM2_PARAM_USER_SPACE_MLME 1045#define PRISM2_PARAM_MGMT_IF		1046#define PRISM2_HOSTAPD_ADD_STA 2#define PRISM2_HOSTAPD_REMOVE_STA 3#define PRISM2_HOSTAPD_GET_HW_FEATURES	1002#define PRISM2_HOSTAPD_MAX_BUF_SIZE	2048#ifndef ALIGNED#define ALIGNED __attribute__ ((aligned))#endifstruct prism2_hostapd_param {	u32 cmd;	u8 sta_addr[ETH_ALEN];	u8 pad[2];	union {		struct {			u16 aid;			u16 capability;			u8 supp_rates[32];			u8 wds_flags;#define IEEE80211_STA_DYNAMIC_ENC BIT(0)			u8 enc_flags;			u16 listen_interval;		} add_sta;		struct {			u16 num_modes;			u16 flags;			u8 data[0] ALIGNED; /* num_modes * feature data */		} hw_features;		struct {			u16 mode; /* MODE_* */			u16 num_supported_rates;			u16 num_basic_rates;			u8 data[0] ALIGNED; /* num_supported_rates * u16 +					     * num_basic_rates * u16 */		} set_rate_sets;		struct {			u16 mode; /* MODE_* */			u16 chan;			u32 flag;			u8 power_level; /* regulatory limit in dBm */			u8 antenna_max;		} set_channel_flag;		struct {			u32 rd;		} set_regulatory_domain;		struct {			u32 queue;			s32 aifs;			u32 cw_min;			u32 cw_max;			u32 burst_time; /* maximum burst time in 0.1 ms, i.e.,					 * 10 = 1 ms */		} tx_queue_params;	} u;};struct hostapd_ioctl_hw_modes_hdr {	int mode;	int num_channels;	int num_rates;};/* * frame format for the management interface that is slated * to be replaced by "cooked monitor" with radiotap */#define IEEE80211_FI_VERSION 0x80211001struct ieee80211_frame_info {	__be32 version;	__be32 length;	__be64 mactime;	__be64 hosttime;	__be32 phytype;	__be32 channel;	__be32 datarate;	__be32 antenna;	__be32 priority;	__be32 ssi_type;	__be32 ssi_signal;	__be32 ssi_noise;	__be32 preamble;	__be32 encoding;	/* Note: this structure is otherwise identical to capture format used	 * in linux-wlan-ng, but this additional field is used to provide meta	 * data about the frame to hostapd. This was the easiest method for	 * providing this information, but this might change in the future. */	__be32 msg_type;} __attribute__ ((packed));/* old mode definitions */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};#ifndef ETH_P_ALL#define ETH_P_ALL 0x0003#endif#endif /* CONFIG_CLIENT_MLME */static int wpa_driver_wext_flush_pmkid(void *priv);static int wpa_driver_wext_get_range(void *priv);static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);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;	os_memset(&req, 0, sizeof(req));	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;}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_strlcpy(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) {		if (errno != EOPNOTSUPP) {			wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d "				   "value 0x%x) failed: %s)",				   idx, value, strerror(errno));		}		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_strlcpy(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_strlcpy(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_strlcpy(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_strlcpy(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_strlcpy(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;

⌨️ 快捷键说明

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