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

📄 hostap.c

📁 IEEE 802.11a/b/g linux2.4/2.6 驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Host AP (software wireless LAN access point) driver for * Intersil Prism2/2.5/3 - hostap.o module, common routines * * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen * <jkmaline@cc.hut.fi> * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.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. See README and COPYING for * more details. */#ifndef EXPORT_SYMTAB#define EXPORT_SYMTAB#endif#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/if_arp.h>#include <linux/delay.h>#include <linux/random.h>#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44))#include <linux/tqueue.h>#else#include <linux/workqueue.h>#endif#include <linux/kmod.h>#include <linux/rtnetlink.h>#include "hostap_wext.h"#include <asm/uaccess.h>#include "hostap_wlan.h"#include "hostap_80211.h"#include "hostap_ap.h"#include "hostap.h"#include "hostap_crypt.h"#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))#error Host AP driver was added into Linux 2.6.14.#error The version used in the kernel tree should be used instead of this#error external release which is only maintained for old kernel versions.#endifMODULE_AUTHOR("Jouni Malinen");MODULE_DESCRIPTION("Host AP common routines");MODULE_LICENSE("GPL");#ifdef MODULE_VERSIONMODULE_VERSION(PRISM2_VERSION);#endif#ifndef HOSTAP_CRYPT_MODULE/* Old hostap_crypt module is now part of hostap module. */#include "hostap_crypt.c"#else /* HOSTAP_CRYPT_MODULE */#define hostap_crypto_init()#define hostap_crypto_deinit()#endif /* HOSTAP_CRYPT_MODULE */#define TX_TIMEOUT (2 * HZ)#define PRISM2_MAX_FRAME_SIZE 2304#define PRISM2_MIN_MTU 256/* FIX: */#define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 /* LLC */ + 8 /* WEP */))/* hostap.c */static int prism2_wds_add(local_info_t *local, u8 *remote_addr,			  int rtnl_locked);static int prism2_wds_del(local_info_t *local, u8 *remote_addr,			  int rtnl_locked, int do_not_remove);/* hostap_ap.c */static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],				  struct iw_quality qual[], int buf_size,				  int aplist);static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);static int prism2_hostapd(struct ap_data *ap,			  struct prism2_hostapd_param *param);static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,				struct prism2_crypt_data ***crypt);static void ap_control_kickall(struct ap_data *ap);#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMTstatic int ap_control_add_mac(struct mac_restrictions *mac_restrictions,			      u8 *mac);static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,			      u8 *mac);static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,			       u8 *mac);#endif /* !PRISM2_NO_KERNEL_IEEE80211_MGMT */static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,				  2447, 2452, 2457, 2462, 2467, 2472, 2484 };#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation *//* Ethernet-II snap header (RFC1042 for most EtherTypes) */static unsigned char rfc1042_header[] ={ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */static unsigned char bridge_tunnel_header[] ={ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };/* No encapsulation header if EtherType < 0x600 (=length) *//* FIX: these could be compiled separately and linked together to hostap.o */#include "hostap_ap.c"#include "hostap_info.c"#include "hostap_ioctl.c"#include "hostap_proc.c"#include "hostap_80211_rx.c"#include "hostap_80211_tx.c"struct net_device * hostap_add_interface(struct local_info *local,					 int type, int rtnl_locked,					 const char *prefix,					 const char *name){	struct net_device *dev, *mdev;	struct hostap_interface *iface;	int ret;	dev = alloc_etherdev(sizeof(struct hostap_interface));	if (dev == NULL)		return NULL;	iface = dev->priv;	iface->dev = dev;	iface->local = local;	iface->type = type;	list_add(&iface->list, &local->hostap_interfaces);	mdev = local->dev;	memcpy(dev->dev_addr, mdev->dev_addr, ETH_ALEN);	dev->base_addr = mdev->base_addr;	dev->irq = mdev->irq;	dev->mem_start = mdev->mem_start;	dev->mem_end = mdev->mem_end;	hostap_setup_dev(dev, local, 0);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))	dev->destructor = free_netdev;#else	/* Linux 2.4.x uses dev entry (reads dev->features) after	 * dev->destructor has returned, so must not free struct net_device	 * here. Set NETIF_F_DYNALLOC flag so that netdev_finish_unregister()	 * frees the entry. */	dev->features |= NETIF_F_DYNALLOC;#endif	sprintf(dev->name, "%s%s", prefix, name);	if (!rtnl_locked)		rtnl_lock();	ret = 0;	if (strchr(dev->name, '%'))		ret = dev_alloc_name(dev, dev->name);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))	SET_NETDEV_DEV(dev, mdev->class_dev.dev);#endif	if (ret >= 0)		ret = register_netdevice(dev);	if (!rtnl_locked)		rtnl_unlock();	if (ret < 0) {		printk(KERN_WARNING "%s: failed to add new netdevice!\n",		       dev->name);		free_netdev(dev);		return NULL;	}	printk(KERN_DEBUG "%s: registered netdevice %s\n",	       mdev->name, dev->name);	return dev;}void hostap_remove_interface(struct net_device *dev, int rtnl_locked,			     int remove_from_list){	struct hostap_interface *iface;	if (!dev)		return;	iface = dev->priv;	if (remove_from_list) {		list_del(&iface->list);	}	if (dev == iface->local->ddev)		iface->local->ddev = NULL;	else if (dev == iface->local->apdev)		iface->local->apdev = NULL;	else if (dev == iface->local->stadev)		iface->local->stadev = NULL;	if (rtnl_locked)		unregister_netdevice(dev);	else		unregister_netdev(dev);	/* dev->destructor = free_netdev() will free the device data, including	 * private data, when removing the device */}static inline int prism2_wds_special_addr(u8 *addr){	if (addr[0] || addr[1] || addr[2] || addr[3] || addr[4] || addr[5])		return 0;	return 1;}static int prism2_wds_add(local_info_t *local, u8 *remote_addr,			  int rtnl_locked){	struct net_device *dev;	struct list_head *ptr;	struct hostap_interface *iface, *empty, *match;	empty = match = NULL;	read_lock_bh(&local->iface_lock);	list_for_each(ptr, &local->hostap_interfaces) {		iface = list_entry(ptr, struct hostap_interface, list);		if (iface->type != HOSTAP_INTERFACE_WDS)			continue;		if (prism2_wds_special_addr(iface->u.wds.remote_addr))			empty = iface;		else if (memcmp(iface->u.wds.remote_addr, remote_addr,				ETH_ALEN) == 0) {			match = iface;			break;		}	}	if (!match && empty && !prism2_wds_special_addr(remote_addr)) {		/* take pre-allocated entry into use */		memcpy(empty->u.wds.remote_addr, remote_addr, ETH_ALEN);		read_unlock_bh(&local->iface_lock);		printk(KERN_DEBUG "%s: using pre-allocated WDS netdevice %s\n",		       local->dev->name, empty->dev->name);		return 0;	}	read_unlock_bh(&local->iface_lock);	if (!prism2_wds_special_addr(remote_addr)) {		if (match)			return -EEXIST;		hostap_add_sta(local->ap, remote_addr);	}	if (local->wds_connections >= local->wds_max_connections)		return -ENOBUFS;	/* verify that there is room for wds# postfix in the interface name */	if (strlen(local->dev->name) > IFNAMSIZ - 5) {		printk(KERN_DEBUG "'%s' too long base device name\n",		       local->dev->name);		return -EINVAL;	}	dev = hostap_add_interface(local, HOSTAP_INTERFACE_WDS, rtnl_locked,				   local->ddev->name, "wds%d");	if (dev == NULL)		return -ENOMEM;	iface = dev->priv;	memcpy(iface->u.wds.remote_addr, remote_addr, ETH_ALEN);	local->wds_connections++;	return 0;}static int prism2_wds_del(local_info_t *local, u8 *remote_addr,			  int rtnl_locked, int do_not_remove){	unsigned long flags;	struct list_head *ptr;	struct hostap_interface *iface, *selected = NULL;	write_lock_irqsave(&local->iface_lock, flags);	list_for_each(ptr, &local->hostap_interfaces) {		iface = list_entry(ptr, struct hostap_interface, list);		if (iface->type != HOSTAP_INTERFACE_WDS)			continue;		if (memcmp(iface->u.wds.remote_addr, remote_addr,			   ETH_ALEN) == 0) {			selected = iface;			break;		}	}	if (selected && !do_not_remove)		list_del(&selected->list);	write_unlock_irqrestore(&local->iface_lock, flags);	if (selected) {		if (do_not_remove)			memset(selected->u.wds.remote_addr, 0, ETH_ALEN);		else {			hostap_remove_interface(selected->dev, rtnl_locked, 0);			local->wds_connections--;		}	}	return selected ? 0 : -ENODEV;}u16 hostap_tx_callback_register(local_info_t *local,				void (*func)(struct sk_buff *, int ok, void *),				void *data){	unsigned long flags;	struct hostap_tx_callback_info *entry;	entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry),							   GFP_ATOMIC);	if (entry == NULL)		return 0;	entry->func = func;	entry->data = data;	spin_lock_irqsave(&local->lock, flags);	entry->idx = local->tx_callback ? local->tx_callback->idx + 1 : 1;	entry->next = local->tx_callback;	local->tx_callback = entry;	spin_unlock_irqrestore(&local->lock, flags);	return entry->idx;}int hostap_tx_callback_unregister(local_info_t *local, u16 idx){	unsigned long flags;	struct hostap_tx_callback_info *cb, *prev = NULL;	spin_lock_irqsave(&local->lock, flags);	cb = local->tx_callback;	while (cb != NULL && cb->idx != idx) {		prev = cb;		cb = cb->next;	}	if (cb) {		if (prev == NULL)			local->tx_callback = cb->next;		else			prev->next = cb->next;		kfree(cb);	}	spin_unlock_irqrestore(&local->lock, flags);	return cb ? 0 : -1;}/* val is in host byte order */int hostap_set_word(struct net_device *dev, int rid, u16 val){	struct hostap_interface *iface = dev->priv;	u16 tmp = cpu_to_le16(val);	return iface->local->func->set_rid(dev, rid, &tmp, 2);}int hostap_set_string(struct net_device *dev, int rid, const char *val){	struct hostap_interface *iface = dev->priv;	char buf[MAX_SSID_LEN + 2];	int len;	len = strlen(val);	if (len > MAX_SSID_LEN)		return -1;	memset(buf, 0, sizeof(buf));	buf[0] = len; /* little endian 16 bit word */	memcpy(buf + 2, val, len);	return iface->local->func->set_rid(dev, rid, &buf, MAX_SSID_LEN + 2);}u16 hostap_get_porttype(local_info_t *local){	if (local->iw_mode == IW_MODE_ADHOC && local->pseudo_adhoc)		return HFA384X_PORTTYPE_PSEUDO_IBSS;	if (local->iw_mode == IW_MODE_ADHOC)		return HFA384X_PORTTYPE_IBSS;	if (local->iw_mode == IW_MODE_INFRA)

⌨️ 快捷键说明

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