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

📄 ieee80211_linux.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 2003-2005 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id$ */#ifndef EXPORT_SYMTAB#define	EXPORT_SYMTAB#endif/* * IEEE 802.11 support (Linux-specific code) */#ifndef AUTOCONF_INCLUDED#include <linux/config.h>#endif#include <linux/version.h>#include <linux/module.h>#include <linux/kmod.h>#include <linux/init.h>#include <linux/skbuff.h>#include <linux/sysctl.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/if_vlan.h>#include <linux/vmalloc.h>#include <linux/proc_fs.h>#include <net/iw_handler.h>#include <linux/wireless.h>#include <linux/if_arp.h>		/* XXX for ARPHRD_* */#include <asm/uaccess.h>#include "if_media.h"#include "if_ethersubr.h"#include <net80211/ieee80211_var.h>#include <net80211/ieee80211_monitor.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)#include <linux/device.h>/* madwifi_name_type - device name type: * values:	0:	automatically assigned * 		1:	administratively assigned * 		else:	reserved			*/#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)static ssize_t show_madwifi_name_type(struct device *dev,		struct device_attribute *attr, char *buf)#elsestatic ssize_t show_madwifi_name_type(struct class_device *cdev,		char *buf)#endif{	ssize_t len = 0;	len = snprintf(buf, PAGE_SIZE, "1");	return len;}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)static DEVICE_ATTR(madwifi_name_type, S_IRUGO, show_madwifi_name_type, NULL);#elsestatic CLASS_DEVICE_ATTR(madwifi_name_type, S_IRUGO, show_madwifi_name_type, NULL);#endifstatic struct attribute *ieee80211_sysfs_attrs[] = {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)	&dev_attr_madwifi_name_type.attr,#else	&class_device_attr_madwifi_name_type.attr,#endif	NULL};static struct attribute_group ieee80211_attr_grp = {	.name	= NULL,	/* No seperate (sub-)directory */	.attrs	= ieee80211_sysfs_attrs};#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)#define proc_net init_net.proc_net#endif/* * Print a console message with the device name prepended. */voidif_printf(struct net_device *dev, const char *fmt, ...){	va_list ap;	char buf[512];		/* XXX */	va_start(ap, fmt);	vsnprintf(buf, sizeof(buf), fmt, ap);	va_end(ap);	printk("%s: %s", dev->name, buf);}/* * Allocate and setup a management frame of the specified * size.  We return the sk_buff and a pointer to the start * of the contiguous data area that's been reserved based * on the packet length.  The data area is forced to 32-bit * alignment and the buffer length to a multiple of 4 bytes. * This is done mainly so beacon frames (that require this) * can use this interface too. */struct sk_buff *#ifdef IEEE80211_DEBUG_REFCNTieee80211_getmgtframe_debug(u_int8_t **frm, u_int pktlen, 		const char *func, int line)#elseieee80211_getmgtframe(u_int8_t **frm, u_int pktlen)#endif{	const u_int align = sizeof(u_int32_t);	struct sk_buff *skb;	u_int len;	len = roundup(sizeof(struct ieee80211_frame) + pktlen, 4);#ifdef IEEE80211_DEBUG_REFCNT	skb = ieee80211_dev_alloc_skb_debug(len + align - 1, func, line);#else	skb = ieee80211_dev_alloc_skb(len + align - 1);#endif	if (skb != NULL) {		u_int off = ((unsigned long) skb->data) % align;		if (off != 0)			skb_reserve(skb, align - off);		SKB_NI(skb) = NULL;		SKB_CB(skb)->flags = 0;		skb_reserve(skb, sizeof(struct ieee80211_frame));		*frm = skb_put(skb, pktlen);	}	return skb;}#ifdef IEEE80211_DEBUG_REFCNTEXPORT_SYMBOL(ieee80211_getmgtframe_debug);#elseEXPORT_SYMBOL(ieee80211_getmgtframe);#endif #if IEEE80211_VLAN_TAG_USED/* * VLAN support. *//* * Register a vlan group. */static voidieee80211_vlan_register(struct net_device *dev, struct vlan_group *grp){	struct ieee80211vap *vap = netdev_priv(dev);	vap->iv_vlgrp = grp;}/* * Add an rx vlan identifier */static voidieee80211_vlan_add_vid(struct net_device *dev, unsigned short vid){	struct ieee80211vap *vap = netdev_priv(dev);	if (vap->iv_vlgrp != NULL)		vap->iv_bss->ni_vlan = vid;}/* * Kill (i.e. delete) a vlan identifier. */static voidieee80211_vlan_kill_vid(struct net_device *dev, unsigned short vid){	struct ieee80211vap *vap = netdev_priv(dev);	if (vap->iv_vlgrp != NULL)		vlan_group_set_device(vap->iv_vlgrp, vid, NULL);}#endif /* IEEE80211_VLAN_TAG_USED */voidieee80211_vlan_vattach(struct ieee80211vap *vap){#if IEEE80211_VLAN_TAG_USED	struct net_device *dev = vap->iv_dev;	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |			 NETIF_F_HW_VLAN_FILTER;	dev->vlan_rx_register = ieee80211_vlan_register;	dev->vlan_rx_add_vid = ieee80211_vlan_add_vid;	dev->vlan_rx_kill_vid = ieee80211_vlan_kill_vid;#endif /* IEEE80211_VLAN_TAG_USED */}voidieee80211_vlan_vdetach(struct ieee80211vap *vap){}voidieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc){	struct ieee80211vap *vap = ni->ni_vap;	struct net_device *dev = vap->iv_dev;	union iwreq_data wreq;	if (ni == vap->iv_bss) {		if (newassoc)			netif_carrier_on(dev);		memset(&wreq, 0, sizeof(wreq));		IEEE80211_ADDR_COPY(wreq.addr.sa_data, vap->iv_bssid);		wreq.addr.sa_family = ARPHRD_ETHER;#ifdef ATH_SUPERG_XR		if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)			dev = vap->iv_xrvap->iv_dev;#endif		wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);	} else {		memset(&wreq, 0, sizeof(wreq));		IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);		wreq.addr.sa_family = ARPHRD_ETHER;#ifdef ATH_SUPERG_XR		if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)			dev = vap->iv_xrvap->iv_dev;#endif		wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);	}}voidieee80211_notify_node_leave(struct ieee80211_node *ni){	struct ieee80211vap *vap = ni->ni_vap;	struct net_device *dev = vap->iv_dev;	union iwreq_data wreq;	if (ni == vap->iv_bss) {		netif_carrier_off(dev);		memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);		wreq.ap_addr.sa_family = ARPHRD_ETHER;		wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);	} else {		/* fire off wireless event station leaving */		memset(&wreq, 0, sizeof(wreq));		IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);		wreq.addr.sa_family = ARPHRD_ETHER;		wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);	}}voidieee80211_notify_sta_stats(struct ieee80211_node *ni){	struct ieee80211vap *vap = ni->ni_vap;	static const char *tag = "STA-TRAFFIC-STAT";	struct net_device *dev = vap->iv_dev;	union iwreq_data wreq;	char buf[1024];	snprintf(buf, sizeof(buf), "%s\nmac=" MAC_FMT "\nrx_packets=%u\nrx_bytes=%llu\n"			"tx_packets=%u\ntx_bytes=%llu\n", tag,			MAC_ADDR(ni->ni_macaddr), ni->ni_stats.ns_rx_data,			(unsigned long long)ni->ni_stats.ns_rx_bytes,			ni->ni_stats.ns_tx_data,			(unsigned long long)ni->ni_stats.ns_tx_bytes);	memset(&wreq, 0, sizeof(wreq));	wreq.data.length = strlen(buf);	wireless_send_event(dev, IWEVCUSTOM, &wreq, buf);}voidieee80211_notify_scan_done(struct ieee80211vap *vap){	struct net_device *dev = vap->iv_dev;	union iwreq_data wreq;	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s\n", "notify scan done");	/* dispatch wireless event indicating scan completed */	wreq.data.length = 0;	wreq.data.flags = 0;	wireless_send_event(dev, SIOCGIWSCAN, &wreq, NULL);}voidieee80211_notify_replay_failure(struct ieee80211vap *vap,	const struct ieee80211_frame *wh, const struct ieee80211_key *k,	u_int64_t rsc){	static const char *tag = "MLME-REPLAYFAILURE.indication";	struct net_device *dev = vap->iv_dev;	union iwreq_data wrqu;	char buf[128];		/* XXX */	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,		"%s replay detected <keyix %d, rsc %llu >",		k->wk_cipher->ic_name, k->wk_keyix,		(unsigned long long)rsc);	/* TODO: needed parameters: count, keyid, key type, src address, TSC */	snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,		k->wk_keyix,		IEEE80211_IS_MULTICAST(wh->i_addr2) ?  "broad" : "uni",		MAC_ADDR(wh->i_addr2));	memset(&wrqu, 0, sizeof(wrqu));	wrqu.data.length = strlen(buf);	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);}EXPORT_SYMBOL(ieee80211_notify_replay_failure);voidieee80211_notify_michael_failure(struct ieee80211vap *vap,	const struct ieee80211_frame *wh, ieee80211_keyix_t keyix){	static const char *tag = "MLME-MICHAELMICFAILURE.indication";	struct net_device *dev = vap->iv_dev;	union iwreq_data wrqu;	char buf[128];		/* XXX */	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,		"Michael MIC verification failed <keyix %d>", keyix);	vap->iv_stats.is_rx_tkipmic++;	/* TODO: needed parameters: count, keyid, key type, src address, TSC */	snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,		keyix, IEEE80211_IS_MULTICAST(wh->i_addr2) ?  "broad" : "uni",		MAC_ADDR(wh->i_addr2));	memset(&wrqu, 0, sizeof(wrqu));	wrqu.data.length = strlen(buf);	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);}EXPORT_SYMBOL(ieee80211_notify_michael_failure);/* This function might sleep. Therefore:  * Context: process * * Note that a successful call to this function does not guarantee that * the services provided by the requested module are available: * * "Note that a successful module load does not mean the module did not * then unload and exit on an error of its own. Callers must check that * the service they requested is now available not blindly invoke it." * http://kernelnewbies.org/documents/kdoc/kernel-api/r7338.html */intieee80211_load_module(const char *modname){#if defined(CONFIG_KMOD) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))	int rv;	rv = request_module("%s", modname);	if (rv < 0)		printk(KERN_ERR "failed to automatically load module: %s; " \			"errno: %d\n", modname, rv);	return rv;#else /* CONFIG_KMOD || 2.6.27+ */	printk(KERN_ERR "Unable to load needed module: %s; no support for " \			"automatic module loading\n", modname);	return -ENOSYS;#endif /* CONFIG_KMOD || 2.6.27+ */}static struct proc_dir_entry *proc_madwifi;static int proc_madwifi_count = 0;static intproc_read_nodes(struct ieee80211vap *vap, char *buf, int space){	char *p = buf;	struct ieee80211_node *ni;	struct ieee80211_node_table *nt =		(struct ieee80211_node_table *)&vap->iv_ic->ic_sta;	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {		struct timespec t;		/* Assume each node needs 500 bytes */		if (buf + space < p + 500)			break;		if ((ni->ni_vap == vap) && (memcmp(vap->iv_myaddr, 				ni->ni_macaddr, IEEE80211_ADDR_LEN) != 0)) {			jiffies_to_timespec(jiffies - ni->ni_last_rx, &t);			p += sprintf(p, "macaddr: <" MAC_FMT ">\n", 					MAC_ADDR(ni->ni_macaddr));			p += sprintf(p, " RSSI %d\n", ni->ni_rssi);			p += sprintf(p, " last_rx %ld.%06ld\n",				     t.tv_sec, t.tv_nsec / 1000);			p += sprintf(p, " ni_tstamp %10llu ni_rtsf %10llu\n",				     le64_to_cpu(ni->ni_tstamp.tsf), ni->ni_rtsf);		}        }	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);	return (p - buf);}static ssize_tproc_ieee80211_read(struct file *file, char __user *buf, size_t len, loff_t *offset){	loff_t pos = *offset;	struct proc_ieee80211_priv *pv =		(struct proc_ieee80211_priv *)file->private_data;	if (!pv->rbuf)		return -EINVAL;	if (pos < 0)		return -EINVAL;	if (pos > pv->rlen)		return -EFAULT;	if (len > pv->rlen - pos)		len = pv->rlen - pos;	if (copy_to_user(buf, pv->rbuf + pos, len))		return -EFAULT;	*offset = pos + len;	return len;}static intproc_ieee80211_open(struct inode *inode, struct file *file){	struct proc_ieee80211_priv *pv = NULL;	struct proc_dir_entry *dp = PDE(inode);	struct ieee80211vap *vap = dp->data;	if (!(file->private_data = kzalloc(sizeof(struct proc_ieee80211_priv), 			GFP_KERNEL)))		return -ENOMEM;	/* initially allocate both read and write buffers */	pv = (struct proc_ieee80211_priv *)file->private_data;	pv->rbuf = vmalloc(MAX_PROC_IEEE80211_SIZE);	if (!pv->rbuf) {		kfree(pv);		return -ENOMEM;	}	pv->wbuf = vmalloc(MAX_PROC_IEEE80211_SIZE);	if (!pv->wbuf) {		vfree(pv->rbuf);		kfree(pv);		return -ENOMEM;	}	memset(pv->wbuf, 0, MAX_PROC_IEEE80211_SIZE);	memset(pv->rbuf, 0, MAX_PROC_IEEE80211_SIZE);	pv->max_wlen = MAX_PROC_IEEE80211_SIZE;	pv->max_rlen = MAX_PROC_IEEE80211_SIZE;	/* now read the data into the buffer */	pv->rlen = proc_read_nodes(vap, pv->rbuf, MAX_PROC_IEEE80211_SIZE);	return 0;}static ssize_tproc_ieee80211_write(struct file *file, const char __user *buf, size_t len, loff_t *offset){	loff_t pos = *offset;	struct proc_ieee80211_priv *pv =		(struct proc_ieee80211_priv *)file->private_data;	if (!pv->wbuf)		return -EINVAL;	if (pos < 0)		return -EINVAL;	if (pos >= pv->max_wlen)		return 0;	if (len > pv->max_wlen - pos)		len = pv->max_wlen - pos;	if (copy_from_user(pv->wbuf + pos, buf, len))		return -EFAULT;	if (pos + len > pv->wlen)		pv->wlen = pos + len;	*offset = pos + len;	return len;}static intproc_ieee80211_close(struct inode *inode, struct file *file)

⌨️ 快捷键说明

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