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

📄 driver_devicescape.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * hostapd / Kernel driver communication with Devicescape IEEE 802.11 stack * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> * Copyright (c) 2003-2004, Instant802 Networks, Inc. * Copyright (c) 2005-2006, Devicescape Software, Inc. * * 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>#ifdef USE_KERNEL_HEADERS#include <asm/types.h>#include <linux/if_packet.h>#include <linux/if_ether.h>   /* The L2 protocols */#include <linux/if_arp.h>#include <linux/wireless.h>#else /* USE_KERNEL_HEADERS */#include <net/if_arp.h>#include <netpacket/packet.h>#include "wireless_copy.h"#endif /* USE_KERNEL_HEADERS */#include "hostapd.h"#include "driver.h"#include "ieee802_1x.h"#include "eloop.h"#include "priv_netlink.h"#include "ieee802_11.h"#include "sta_info.h"#include "hw_features.h"#include <hostapd_ioctl.h>#include <net/d80211_common.h>#include <net/d80211_shared.h>/* from net/d80211.h */#define WLAN_FC_PVER		0x0003#define WLAN_FC_TODS		0x0100#define WLAN_FC_FROMDS		0x0200#define WLAN_FC_ISWEP		0x4000#define WLAN_FC_GET_TYPE(fc)	(((fc) & 0x000c) >> 2)#define WLAN_FC_GET_STYPE(fc)	(((fc) & 0x00f0) >> 4)#define WLAN_FC_TYPE_MGMT	0#define WLAN_FC_TYPE_CTRL	1#define WLAN_FC_TYPE_DATA	2#define WLAN_FC_STYPE_PROBE_REQ 4#define WLAN_FC_STYPE_BEACON		8#define WLAN_FC_STYPE_DISASSOC		10#define WLAN_FC_STYPE_DEAUTH		12#define WLAN_FC_STYPE_DATA		0#define WLAN_FC_STYPE_QOS_DATA		8/* from net/d80211_mgmt.h */#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7struct i802_driver_data {	struct driver_ops ops;	struct hostapd_data *hapd;	char iface[IFNAMSIZ + 1];	int sock; /* raw packet socket for driver access */	int ioctl_sock; /* socket for ioctl() use */	int wext_sock; /* socket for wireless events */	int we_version;};static const struct driver_ops devicescape_driver_ops;#define HAPD_DECL	struct hostapd_data *hapd = iface->bss[0]static int i802_sta_set_flags(void *priv, const u8 *addr,			      int flags_or, int flags_and);static int hostapd_set_iface_flags(struct i802_driver_data *drv, int dev_up){	struct ifreq ifr;	if (drv->ioctl_sock < 0)		return -1;	memset(&ifr, 0, sizeof(ifr));	snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface);	if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {		perror("ioctl[SIOCGIFFLAGS]");		return -1;	}	if (dev_up)		ifr.ifr_flags |= IFF_UP;	else		ifr.ifr_flags &= ~IFF_UP;	if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {		perror("ioctl[SIOCSIFFLAGS]");		return -1;	}	if (dev_up) {		memset(&ifr, 0, sizeof(ifr));		snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface);		ifr.ifr_mtu = HOSTAPD_MTU;		if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {			perror("ioctl[SIOCSIFMTU]");			printf("Setting MTU failed - trying to survive with "			       "current value\n");		}	}        memset(&ifr, 0, sizeof(ifr));	snprintf(ifr.ifr_name, IFNAMSIZ, "%s.11", drv->iface);	if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {		perror("ioctl[SIOCGIFFLAGS]");		return -1;	}	if (dev_up)		ifr.ifr_flags |= IFF_UP;	else		ifr.ifr_flags &= ~IFF_UP;	if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {		perror("ioctl[SIOCSIFFLAGS]");		return -1;	}	return 0;}static int hostapd_ioctl_iface(const char *iface, struct i802_driver_data *drv,			       struct prism2_hostapd_param *param, int len){	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, iface, IFNAMSIZ);	iwr.u.data.pointer = (caddr_t) param;	iwr.u.data.length = len;	if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {		/* perror("ioctl[PRISM2_IOCTL_HOSTAPD]"); */		return -1;	}	return 0;}static int hostapd_ioctl(struct i802_driver_data *drv,			 struct prism2_hostapd_param *param, int len){	return hostapd_ioctl_iface(drv->iface, drv, param, len);}static int i802_set_encryption(const char *iface, void *priv, const char *alg,			       const u8 *addr, int idx, const u8 *key,			       size_t key_len, int txkey){	struct i802_driver_data *drv = priv;	struct prism2_hostapd_param *param;	u8 *buf;	size_t blen;	int ret = 0;	blen = sizeof(*param) + key_len;	buf = wpa_zalloc(blen);	if (buf == NULL)		return -1;	param = (struct prism2_hostapd_param *) buf;	param->cmd = PRISM2_SET_ENCRYPTION;	if (addr == NULL)		memset(param->sta_addr, 0xff, ETH_ALEN);	else		memcpy(param->sta_addr, addr, ETH_ALEN);	strncpy((char *) param->u.crypt.alg, alg, HOSTAP_CRYPT_ALG_NAME_LEN);	param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;	param->u.crypt.idx = idx;	param->u.crypt.key_len = key_len;	memcpy(param->u.crypt.key, key, key_len);	if (hostapd_ioctl_iface(iface, drv, param, blen) && errno != ENOENT) {		printf("%s: Failed to set encryption to alg '%s' addr " MACSTR		       " errno=%d\n",		       iface, alg, MAC2STR(param->sta_addr), errno);		ret = -1;	}	free(buf);	return ret;}static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,			   int idx, u8 *seq){	struct i802_driver_data *drv = priv;	struct prism2_hostapd_param *param;	size_t param_len;	int ret;	param_len = sizeof(struct prism2_hostapd_param) + 32;	param = wpa_zalloc(param_len);	if (param == NULL)		return -1;	param->cmd = PRISM2_GET_ENCRYPTION;	if (addr == NULL)		memset(param->sta_addr, 0xff, ETH_ALEN);	else		memcpy(param->sta_addr, addr, ETH_ALEN);	param->u.crypt.idx = idx;	ret = hostapd_ioctl_iface(iface, drv, param, param_len);	if (ret == 0) {		memcpy(seq, param->u.crypt.seq_counter,		       HOSTAP_SEQ_COUNTER_SIZE);	}	free(param);	return ret;}static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates,			      int mode){	struct i802_driver_data *drv = priv;	struct prism2_hostapd_param *param;	u8 *buf;	u16 *pos;	size_t blen;	int ret = 0;	int i, num_supp = 0, num_basic = 0;	if (supp_rates)		for (i = 0; supp_rates[i] >= 0; i++)			num_supp++;	if (basic_rates)		for (i = 0; basic_rates[i] >= 0; i++)			num_basic++;	blen = sizeof(*param) + (num_supp + num_basic) * 2;	buf = wpa_zalloc(blen);	if (buf == NULL)		return -1;	param = (struct prism2_hostapd_param *) buf;	param->cmd = PRISM2_HOSTAPD_SET_RATE_SETS;	param->u.set_rate_sets.mode = mode;	param->u.set_rate_sets.num_supported_rates = num_supp;	param->u.set_rate_sets.num_basic_rates = num_basic;	pos = (u16 *) param->u.set_rate_sets.data;	for (i = 0; i < num_supp; i++)		*pos++ = supp_rates[i];	for (i = 0; i < num_basic; i++)		*pos++ = basic_rates[i];	if (hostapd_ioctl(drv, param, blen)) {		printf("Failed to set rate sets.\n");		ret = -1;	}	free(buf);	return ret;}static int hostap_ioctl_prism2param_iface(const char *iface,					  struct i802_driver_data *drv,					  int param, int value){	struct iwreq iwr;	int *i;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, iface, IFNAMSIZ);	i = (int *) iwr.u.name;	*i++ = param;	*i++ = value;	if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {		char buf[128];		snprintf(buf, sizeof(buf),			 "%s: ioctl[PRISM2_IOCTL_PRISM2_PARAM]", iface);		perror(buf);		return -1;	}	return 0;}static int hostap_ioctl_prism2param(struct i802_driver_data *drv, int param,				    int value){	return hostap_ioctl_prism2param_iface(drv->iface, drv, param, value);} static int i802_set_ssid(void *priv, const u8 *buf, int len){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ);	iwr.u.essid.flags = 1; /* SSID active */	iwr.u.essid.pointer = (caddr_t) buf;	iwr.u.essid.length = len;	if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {		perror("ioctl[SIOCSIWESSID]");		printf("len=%d\n", len);		return -1;	}	return 0;}static int i802_send_mgmt_frame(void *priv, const void *msg, size_t len,				int flags){	struct i802_driver_data *drv = priv;	return send(drv->sock, msg, len, flags);}/* Set kernel driver on given frequency (MHz) */static int i802_set_freq(void *priv, int mode, int freq){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	hostap_ioctl_prism2param(drv, PRISM2_PARAM_NEXT_MODE, mode);	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);	iwr.u.freq.m = freq;	iwr.u.freq.e = 6;	if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {		perror("ioctl[SIOCSIWFREQ]");		return -1;	}	return 0;}static int i802_set_rts(void *priv, int rts){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);	iwr.u.rts.value = rts;	iwr.u.rts.fixed = 1;	if (ioctl(drv->ioctl_sock, SIOCSIWRTS, &iwr) < 0) {		perror("ioctl[SIOCSIWRTS]");		return -1;	}	return 0;}static int i802_get_rts(void *priv, int *rts){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);	if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &iwr) < 0) {		perror("ioctl[SIOCGIWRTS]");		return -1;	}	*rts = iwr.u.rts.value;	return 0;}static int i802_set_frag(void *priv, int frag){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);	iwr.u.frag.value = frag;	iwr.u.frag.fixed = 1;	if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) {		perror("ioctl[SIOCSIWFRAG]");		return -1;	}	return 0;}static int i802_get_frag(void *priv, int *frag){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);	if (ioctl(drv->ioctl_sock, SIOCGIWFRAG, &iwr) < 0) {		perror("ioctl[SIOCGIWFRAG]");		return -1;	}	*frag = iwr.u.frag.value;	return 0;}static int i802_set_retry(void *priv, int short_retry, int long_retry){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);	iwr.u.retry.value = short_retry;	iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;	if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) {		perror("ioctl[SIOCSIWRETRY(short)]");		return -1;	}	iwr.u.retry.value = long_retry;	iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;	if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) {		perror("ioctl[SIOCSIWRETRY(long)]");		return -1;	}	return 0;}static int i802_get_retry(void *priv, int *short_retry, int *long_retry){	struct i802_driver_data *drv = priv;	struct iwreq iwr;	memset(&iwr, 0, sizeof(iwr));	strncpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);	iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;	if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) {		perror("ioctl[SIOCGIWFRAG(short)]");		return -1;	}	*short_retry = iwr.u.retry.value;	iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;	if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) {		perror("ioctl[SIOCGIWFRAG(long)]");		return -1;	}	*long_retry = iwr.u.retry.value;	return 0;}static int i802_flush(void *priv){	struct i802_driver_data *drv = priv;	struct prism2_hostapd_param param;	memset(&param, 0, sizeof(param));	param.cmd = PRISM2_HOSTAPD_FLUSH;	return hostapd_ioctl(drv, &param, sizeof(param));}static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,			      const u8 *addr){	struct i802_driver_data *drv = priv;	struct prism2_hostapd_param param;	memset(data, 0, sizeof(*data));	memset(&param, 0, sizeof(param));	param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;	memcpy(param.sta_addr, addr, ETH_ALEN);	if (hostapd_ioctl(drv, &param, sizeof(param))) {		printf("  Could not get station info from kernel driver.\n");		return -1;	}	data->inactive_msec = param.u.get_info_sta.inactive_msec;	data->rx_packets = param.u.get_info_sta.rx_packets;	data->tx_packets = param.u.get_info_sta.tx_packets;	data->rx_bytes = param.u.get_info_sta.rx_bytes;	data->tx_bytes = param.u.get_info_sta.tx_bytes;	data->current_tx_rate = param.u.get_info_sta.current_tx_rate;	data->flags = param.u.get_info_sta.flags;	data->num_ps_buf_frames = param.u.get_info_sta.num_ps_buf_frames;	data->tx_retry_failed = param.u.get_info_sta.tx_retry_failed;	data->tx_retry_count = param.u.get_info_sta.tx_retry_count;	data->last_rssi = param.u.get_info_sta.last_rssi;	data->last_ack_rssi = param.u.get_info_sta.last_ack_rssi;	return 0;}static int i802_send_eapol(void *priv, const u8 *addr, const u8 *data,			   size_t data_len, int encrypt){	struct i802_driver_data *drv = priv;	struct ieee80211_hdr *hdr;	size_t len;	u8 *pos;	int res;#if 0 /* FIX */	int qos = sta->flags & WLAN_STA_WME;#else	int qos = 0;#endif	len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +		data_len;	hdr = wpa_zalloc(len);	if (hdr == NULL) {		printf("malloc() failed for i802_send_data(len=%lu)\n",		       (unsigned long) len);		return -1;	}	hdr->frame_control =		IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);	hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);	/* Request TX callback */	hdr->frame_control |= host_to_le16(BIT(1));	if (encrypt)		hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);	if (qos) {		hdr->frame_control |=			host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);	}	memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);	memcpy(hdr->IEEE80211_BSSID_FROMDS, drv->hapd->own_addr, ETH_ALEN);	memcpy(hdr->IEEE80211_SA_FROMDS, drv->hapd->own_addr, ETH_ALEN);	pos = (u8 *) (hdr + 1);	if (qos) {		/* add an empty QoS header if needed */		pos[0] = 0;		pos[1] = 0;		pos += 2;	}	memcpy(pos, rfc1042_header, sizeof(rfc1042_header));	pos += sizeof(rfc1042_header);	/* Network order, i.e. big endian, or MSB first */	pos[0] = (ETH_P_PAE >> 8) & 0xff;	pos[1] = ETH_P_PAE & 0xff;	pos += 2;	memcpy(pos, data, data_len);	res = i802_send_mgmt_frame(drv, (u8 *) hdr, len, 0);	free(hdr);	if (res < 0) {		perror("i802_send_eapol: send");		printf("i802_send_eapol - packet len: %lu - failed\n",		       (unsigned long) len);	}	return res;

⌨️ 快捷键说明

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