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

📄 driver_nl80211.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * WPA Supplicant - driver interaction with Linux nl80211/cfg80211 * Copyright (c) 2003-2008, 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. */#include "includes.h"#include <sys/ioctl.h>#include <net/if_arp.h>#include <netlink/genl/genl.h>#include <netlink/genl/family.h>#include <netlink/genl/ctrl.h>#include "nl80211_copy.h"#ifdef CONFIG_CLIENT_MLME#include <netpacket/packet.h>#include <linux/if_ether.h>#include "radiotap.h"#include "radiotap_iter.h"#endif /* CONFIG_CLIENT_MLME */#include "wireless_copy.h"#include "common.h"#include "driver.h"#include "eloop.h"#include "ieee802_11_defs.h"#ifndef IFF_LOWER_UP#define IFF_LOWER_UP   0x10000         /* driver signals L1 up         */#endif#ifndef IFF_DORMANT#define IFF_DORMANT    0x20000         /* driver signals dormant       */#endif#ifndef IF_OPER_DORMANT#define IF_OPER_DORMANT 5#endif#ifndef IF_OPER_UP#define IF_OPER_UP 6#endifstruct wpa_driver_nl80211_data {	void *ctx;	int wext_event_sock;	int ioctl_sock;	char ifname[IFNAMSIZ + 1];	int ifindex;	int if_removed;	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;	struct nl_handle *nl_handle;	struct nl_cache *nl_cache;	struct nl_cb *nl_cb;	struct genl_family *nl80211;#ifdef CONFIG_CLIENT_MLME	int monitor_sock; /* socket for monitor */	int monitor_ifidx;#endif /* CONFIG_CLIENT_MLME */};static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,					    void *timeout_ctx);static int wpa_driver_nl80211_set_mode(void *priv, int mode);static int wpa_driver_nl80211_flush_pmkid(void *priv);static int wpa_driver_nl80211_get_range(void *priv);static voidwpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv);/* nl80211 code */static int ack_handler(struct nl_msg *msg, void *arg){	int *err = arg;	*err = 0;	return NL_STOP;}static int finish_handler(struct nl_msg *msg, void *arg){	int *ret = arg;	*ret = 0;	return NL_SKIP;}static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,			 void *arg){	int *ret = arg;	*ret = err->error;	return NL_SKIP;}static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,			      struct nl_msg *msg,			      int (*valid_handler)(struct nl_msg *, void *),			      void *valid_data){	struct nl_cb *cb;	int err = -ENOMEM;	cb = nl_cb_clone(drv->nl_cb);	if (!cb)		goto out;	err = nl_send_auto_complete(drv->nl_handle, msg);	if (err < 0)		goto out;	err = 1;	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);	if (valid_handler)		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,			  valid_handler, valid_data);	while (err > 0)		nl_recvmsgs(drv->nl_handle, cb); out:	nl_cb_put(cb);	nlmsg_free(msg);	return err;}struct family_data {	const char *group;	int id;};static int family_handler(struct nl_msg *msg, void *arg){	struct family_data *res = arg;	struct nlattr *tb[CTRL_ATTR_MAX + 1];	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));	struct nlattr *mcgrp;	int i;	nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),		  genlmsg_attrlen(gnlh, 0), NULL);	if (!tb[CTRL_ATTR_MCAST_GROUPS])		return NL_SKIP;	nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {		struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];		nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),			  nla_len(mcgrp), NULL);		if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||		    !tb2[CTRL_ATTR_MCAST_GRP_ID] ||		    os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),			       res->group,			       nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)			continue;		res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);		break;	};	return NL_SKIP;}static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv,			       const char *family, const char *group){	struct nl_msg *msg;	int ret = -1;	struct family_data res = { group, -ENOENT };	msg = nlmsg_alloc();	if (!msg)		return -ENOMEM;	genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"),		    0, 0, CTRL_CMD_GETFAMILY, 0);	NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);	ret = send_and_recv_msgs(drv, msg, family_handler, &res);	msg = NULL;	if (ret == 0)		ret = res.id;nla_put_failure:	nlmsg_free(msg);	return ret;}static int wpa_driver_nl80211_send_oper_ifla(	struct wpa_driver_nl80211_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->wext_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_nl80211_set_auth_param(	struct wpa_driver_nl80211_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;}static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid){	struct wpa_driver_nl80211_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;}static int wpa_driver_nl80211_set_bssid(void *priv, const u8 *bssid){	struct wpa_driver_nl80211_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;}static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid){	struct wpa_driver_nl80211_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;}static int wpa_driver_nl80211_set_ssid(void *priv, const u8 *ssid,				       size_t ssid_len){	struct wpa_driver_nl80211_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;}static int wpa_driver_nl80211_set_freq(void *priv, int freq){	struct wpa_driver_nl80211_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_nl80211_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_nl80211_event_wireless_michaelmicfailure(	void *ctx, const char *ev, size_t len)

⌨️ 快捷键说明

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