Skip to contentSkip to conversation

ieee80211 subsystem

PATCH Applied James Ketrenos 6 participants 17 messages Feb 4, 2005 – Feb 11, 2005

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ieee80211 subsystem

Attached is the patch against 2.6.11-rc3-mm1 that adds the ieee80211 subsystem used by the ipw2100 and ipw2200 projects.

I'll be sending out the patches for ipw2100-1.0.0 and ipw2200-1.0.0 that use thist stack to the list on Monday.

In terms of what the stack currently does:

* HW independent -- it only knows about 802.11 data and structures
* Performs an 802.3 <-> 802.11 transform for data Tx/Rx
* Host based support for fragmentation, WEP, and WPA using the kernel's crypto functions
* Beacon and probe response collection and parsing
* Default implementation of some of the WE handlers that can be managed without hardware knowledge

We are working to merge in Dave Miller's p80211 code into the ieee80211 subsystem so that it hooks into the kernel as a true network layer as opposed to a mutated offspring of ethernet.

Once that is done, hopefully the skb to txb code can be reworked and 802.11 fragments can be treated either as normal skbs, or skbs can be modified to directly support them (ideally so that encrypted 802.11 frames in support of IP packets can be cached by the stack instead of having to be re-encrypted on TCP retries)

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

Anyway, please let me know what you think. Hopefully I built the patch right...

Thanks,
James

drivers/net/wireless/Kconfig +2 -0
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/drivers/net/wireless/Kconfig netdev-2.6-ipw/drivers/net/wireless/Kconfig
@@ -28,6 +28,8 @@
 	  special kernel support are available from
 	  <ftp://shadow.cabi.net/pub/Linux/>.
 
+source "drivers/net/wireless/ieee80211/Kconfig"
+
 # Note : the cards are obsolete (can't buy them anymore), but the drivers
 # are not, as people are still using them...
 comment "Obsolete Wireless cards support (pre-802.11)"
drivers/net/wireless/ieee80211/Kconfig +72 -0

72 lines not on this page · raw message

drivers/net/wireless/ieee80211/Makefile +11 -0
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/drivers/net/wireless/ieee80211/Makefile netdev-2.6-ipw/drivers/net/wireless/ieee80211/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_IEEE80211) += ieee80211.o 
+obj-$(CONFIG_IEEE80211_CRYPT) += ieee80211_crypt.o
+obj-$(CONFIG_IEEE80211_CRYPT) += ieee80211_crypt_wep.o
+obj-$(CONFIG_IEEE80211_CRYPT_WPA) += ieee80211_crypt_ccmp.o
+obj-$(CONFIG_IEEE80211_CRYPT_WPA) += ieee80211_crypt_tkip.o
+ieee80211-objs := \
+	ieee80211_module.o \
+	ieee80211_tx.o \
+	ieee80211_rx.o \
+	ieee80211_wx.o
+
drivers/net/wireless/ieee80211/ieee80211_crypt.c +253 -0

253 lines not on this page · raw message

drivers/net/wireless/ieee80211/ieee80211_crypt_ccmp.c +477 -0

477 lines not on this page · raw message

drivers/net/wireless/ieee80211/ieee80211_crypt_tkip.c +714 -0

714 lines not on this page · raw message

drivers/net/wireless/ieee80211/ieee80211_crypt_wep.c +277 -0

277 lines not on this page · raw message

drivers/net/wireless/ieee80211/ieee80211_rx.c +1215 -0

1,188 lines not on this page · raw message

drivers/net/wireless/ieee80211/ieee80211_tx.c +464 -0

464 lines not on this page · raw message

drivers/net/wireless/ieee80211/ieee80211_wx.c +526 -0

526 lines not on this page · raw message

drivers/net/wireless/ieee80211.h +888 -0

888 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

#1 lore raw
Quoted 6 lines · James Ketrenos

Attached is the patch against 2.6.11-rc3-mm1 that adds the ieee80211 subsystem used by the ipw2100 and ipw2200 projects.

I'll be sending out the patches for ipw2100-1.0.0 and ipw2200-1.0.0 that use thist stack to the list on Monday.

In terms of what the stack currently does:

Quoted 8 lines

* HW independent -- it only knows about 802.11 data and structures
* Performs an 802.3 <-> 802.11 transform for data Tx/Rx
* Host based support for fragmentation, WEP, and WPA using the kernel's crypto functions
* Beacon and probe response collection and parsing
* Default implementation of some of the WE handlers that can be managed without hardware knowledge

We are working to merge in Dave Miller's p80211 code into the ieee80211 subsystem so that it hooks into the kernel as a true network layer as opposed to a mutated offspring of ethernet.
Once that is done, hopefully the skb to txb code can be reworked and 802.11 fragments can be treated either as normal skbs, or skbs can be modified to directly support them (ideally so that encrypted 802.11 frames in support of IP packets can be cached by the stack instead of having to be re-encrypted on TCP retries)

All this sounds great. I (and others) will be reviewing, and hope to get this into netdev-2.6 very soon.

Thanks much,

Jeff

#2 lore raw
In reply to James Ketrenos
Quoted 12 lines · James Ketrenos

Attached is the patch against 2.6.11-rc3-mm1 that adds the ieee80211 subsystem used by the ipw2100 and ipw2200 projects.

I'll be sending out the patches for ipw2100-1.0.0 and ipw2200-1.0.0 that use thist stack to the list on Monday.

In terms of what the stack currently does:

* HW independent -- it only knows about 802.11 data and structures
* Performs an 802.3 <-> 802.11 transform for data Tx/Rx
* Host based support for fragmentation, WEP, and WPA using the kernel's crypto functions
* Beacon and probe response collection and parsing
* Default implementation of some of the WE handlers that can be managed without hardware knowledge

Quoted 8 lines

We are working to merge in Dave Miller's p80211 code into the ieee80211 subsystem so that it hooks into the kernel as a true network layer as opposed to a mutated offspring of ethernet.
Once that is done, hopefully the skb to txb code can be reworked and 802.11 fragments can be treated either as normal skbs, or skbs can be modified to directly support them (ideally so that encrypted 802.11 frames in support of IP packets can be cached by the stack instead of having to be re-encrypted on TCP retries)

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

Anyway, please let me know what you think. Hopefully I built the patch right...

It applies fine.

A few comments:

1. config IEEE80211_DEBUG
bool "Enable full debugging output"
depends on IEEE80211

+ /proc/net/ieee80211/debug_level
+
+ For example:
+
+ % echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level

I get the impression that one of these file names is incorrect:
/proc vs. /sys.....

+ % . idvals
+
+ From within drivers/net/wireless/ipw2200

Is there some good place for this other than in
drivers/net/wireless? I don't know.

+	  If you are not trying to debug or develop the IPW2200 driver,
+	  you
+	  most likely want to say N here.

Combine those last 2 lines.

2. This can be compiled as a modules and it will be called
+ "ieee80211_crypt.ko".

Don't use the ".ko" suffix at all (anywhere).

3. +static int __init ieee80211_crypto_init(void)
+ (void) ieee80211_register_crypto_ops(&ieee80211_crypt_null);

That register call can fail, so I'd rather see it checked, as in all of the other similar register calls.

4. +static void * ieee80211_ccmp_init(int key_idx)
+ if (priv == NULL) {
+ goto fail;
+ }

Lose the braces. Same for:
ieee80211_ccmp_init()

5. +static void ccmp_init_blocks()

+ /* CCM Initial Block:
+ * Flag (Include authentication header, M=3 (8-octet MIC),
+ * L=1 (2-octet Dlen))
+ * Nonce: 0x00 | A2 | PN
+ * Dlen */

Kernel long comment style begins with "/*" by itself and ends with "*/" by itself.

6. +struct ieee80211_ccmp_data {

+ u32 dot11RSNAStatsCCMPFormatErrors;
+ u32 dot11RSNAStatsCCMPReplays;
+ u32 dot11RSNAStatsCCMPDecryptErrors;

Are these MIB-mandated names? otherwise the studlyCaps should go.

7. +static int ieee80211_ccmp_decrypt()

Does anything care about the various negative/error case return values?

8. What calls the .print_stats functions?
static char * ieee80211_ccmp_print_stats()

Is it possible to use seq_file there instead of sprintf(), or is this in /sysfs (so seq_file is not possible)? Are there any overflow possibilities?

Enough for tonight...

Signature · 1 line
~Randy
#3 lore raw
Quoted 7 lines · Randy.Dunlap

6. +struct ieee80211_ccmp_data {

drivers/net/wireless/ieee80211/ieee80211_crypt_ccmp.c +3 -0
+	u32 dot11RSNAStatsCCMPFormatErrors;
+	u32 dot11RSNAStatsCCMPReplays;
+	u32 dot11RSNAStatsCCMPDecryptErrors;

Are these MIB-mandated names? otherwise the studlyCaps should go.

Well, I don't know whether it would be fair to say these are mandated as variable names here, but yes, these are indeed the exact names used in IEEE 802.11i MIB definition which is the reason for the variable names here.

Quoted 5 lines

8. What calls the .print_stats functions?
static char * ieee80211_ccmp_print_stats()

Is it possible to use seq_file there instead of sprintf(), or is this in /sysfs (so seq_file is not possible)?

I used these for getting key information into procfs files. Conversion to seq_file should be possible for procfs. This is of course assuming that someone else has not used these for something else than procfs.

Quoted 1 line

Are there any overflow possibilities?

Should not be, these are used to create a procfs file of less than 500 bytes and the available buffer is at least a page. I did not yet look how these are used in this patch or ipw2100/ipw2200 drivers, so this is based on how I implemented this with Host AP driver.

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#4 lore raw
Quoted 10 lines · Jouni Malinen
Quoted 6 lines · Randy.Dunlap

6. +struct ieee80211_ccmp_data {

drivers/net/wireless/ieee80211/ieee80211_crypt_ccmp.c +3 -0
+	u32 dot11RSNAStatsCCMPFormatErrors;
+	u32 dot11RSNAStatsCCMPReplays;
+	u32 dot11RSNAStatsCCMPDecryptErrors;
Quoted 10 lines
Quoted 3 lines

Are these MIB-mandated names? otherwise the studlyCaps should go.

Well, I don't know whether it would be fair to say these are mandated as variable names here, but yes, these are indeed the exact names used in IEEE 802.11i MIB definition which is the reason for the variable names here.

A thought that has been at the back of my mind is if we will ever want to fully export the MIBs for 802.11, and if so, are there any minimal overhead ways of doing so from kernel drivers?

Quoted 13 lines
Quoted 7 lines

8. What calls the .print_stats functions?
static char * ieee80211_ccmp_print_stats()

Is it possible to use seq_file there instead of sprintf(), or is this in /sysfs (so seq_file is not possible)?

I used these for getting key information into procfs files. Conversion to seq_file should be possible for procfs. This is of course assuming that someone else has not used these for something else than procfs.

Quoted 9 lines
Quoted 3 lines

Are there any overflow possibilities?

Should not be, these are used to create a procfs file of less than 500 bytes and the available buffer is at least a page. I did not yet look how these are used in this patch or ipw2100/ipw2200 drivers, so this is based on how I implemented this with Host AP driver.

The ipw* drivers currently don't use the print_stats callbacks.

Do we want to maintain this capability of the ciphers to be able to output freeform data, or should this be incorporated into a more defined output structure for use by user space tools and exported by the ieee80211 subsystem?

James

#6 lore raw
In reply to James Ketrenos
Quoted 12 lines · James Ketrenos

Attached is the patch against 2.6.11-rc3-mm1 that adds the ieee80211 subsystem used by the ipw2100 and ipw2200 projects.

I'll be sending out the patches for ipw2100-1.0.0 and ipw2200-1.0.0 that use thist stack to the list on Monday.

In terms of what the stack currently does:

* HW independent -- it only knows about 802.11 data and structures
* Performs an 802.3 <-> 802.11 transform for data Tx/Rx
* Host based support for fragmentation, WEP, and WPA using the kernel's crypto functions
* Beacon and probe response collection and parsing
* Default implementation of some of the WE handlers that can be managed without hardware knowledge

Quoted 8 lines

We are working to merge in Dave Miller's p80211 code into the ieee80211 subsystem so that it hooks into the kernel as a true network layer as opposed to a mutated offspring of ethernet.
Once that is done, hopefully the skb to txb code can be reworked and 802.11 fragments can be treated either as normal skbs, or skbs can be modified to directly support them (ideally so that encrypted 802.11 frames in support of IP packets can be cached by the stack instead of having to be re-encrypted on TCP retries)

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

Anyway, please let me know what you think. Hopefully I built the patch right...

James,
Can you post a patch that will build? or did you just want feedback on the current state of the patch?

Thanks,

Signature · 20 lines
~Randy


a.  in ieee80211/Makefile, there is nothing for ieee80211_module.o:

ieee80211-objs := \
	ieee80211_module.o \

b.  in wireless/Makefile, it needs to pull in ieee80211, e.g.:

--- Makefile~80211_netstack     2004-12-24 13:35:50.000000000 -0800
+++ Makefile    2005-02-07 18:37:49.000000000 -0800
@@ -2,6 +2,8 @@
 # Makefile for the Linux Wireless network device drivers.
 #

+obj-$(CONFIG_IEEE80211) += ieee80211/
+
 obj-$(CONFIG_STRIP) += strip.o
 obj-$(CONFIG_ARLAN) += arlan.o
#7 lore raw
Quoted 19 lines · Randy.Dunlap
Quoted 17 lines · James Ketrenos

Attached is the patch against 2.6.11-rc3-mm1 that adds the ieee80211 subsystem used by the ipw2100 and ipw2200 projects.

I'll be sending out the patches for ipw2100-1.0.0 and ipw2200-1.0.0 that use thist stack to the list on Monday.

In terms of what the stack currently does:

* HW independent -- it only knows about 802.11 data and structures
* Performs an 802.3 <-> 802.11 transform for data Tx/Rx
* Host based support for fragmentation, WEP, and WPA using the kernel's crypto functions
* Beacon and probe response collection and parsing
* Default implementation of some of the WE handlers that can be managed without hardware knowledge

We are working to merge in Dave Miller's p80211 code into the ieee80211 subsystem so that it hooks into the kernel as a true network layer as opposed to a mutated offspring of ethernet.
Once that is done, hopefully the skb to txb code can be reworked and 802.11 fragments can be treated either as normal skbs, or skbs can be modified to directly support them (ideally so that encrypted 802.11 frames in support of IP packets can be cached by the stack instead of having to be re-encrypted on TCP retries)

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

Quoted 8 lines
Quoted 3 lines

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

Anyway, please let me know what you think. Hopefully I built the patch right...

James,
Can you post a patch that will build? or did you just want feedback on the current state of the patch?

Ah; I see my tree that I did the diff on was missing the wireless/Makefile and the ieee80211/ieee80211_module.c to create the patch against... sigh. Attached is ieee80211_module.c; you have the change for the Makefile to include ieee80211.

Later {hopefully today} I'll send a full patch that includes several of the corrections you called out in your prior patch.

Thanks,
James

Quoted 2 lines

Thanks,

/*******************************************************************************

Copyright(c) 2004 Intel Corporation. All rights reserved.

Portions of this file are based on the WEP enablement code provided by the Host AP project hostap-drivers v0.1.3
Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen <[email protected]>
Copyright (c) 2002-2003, Jouni Malinen <[email protected]>

This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

The full GNU General Public License is included in this distribution in the file called LICENSE.

Contact Information:
James P. Ketrenos <[email protected]>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497

*******************************************************************************/

#include <linux/compiler.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in6.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
#include <net/arp.h>

#include "ieee80211.h"

MODULE_DESCRIPTION("802.11 data/management/control stack"); MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <[email protected]>"); MODULE_LICENSE("GPL");

#define DRV_NAME "ieee80211"

static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)

{
	if (ieee->networks)
		return 0;

	ieee->networks = kmalloc(
		MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
		GFP_KERNEL);
	if (!ieee->networks) {
		printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
		       ieee->dev->name);
		return -ENOMEM;
	}

	memset(ieee->networks, 0,
	       MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));

	return 0;
}

static inline void ieee80211_networks_free(struct ieee80211_device *ieee)

{
	if (!ieee->networks)
		return;
	kfree(ieee->networks);
	ieee->networks = NULL;
}

static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)

{
	int i;

	INIT_LIST_HEAD(&ieee->network_free_list);
	INIT_LIST_HEAD(&ieee->network_list);
	for (i = 0; i < MAX_NETWORK_COUNT; i++)
		list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
}

struct net_device *alloc_ieee80211(int sizeof_priv)

{
	struct ieee80211_device *ieee;
	struct net_device *dev;
	int err;

	IEEE80211_DEBUG_INFO("Initializing...\n");

	dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
	if (!dev) {
		IEEE80211_ERROR("Unable to network device.\n");
		goto failed;
	}
	ieee = netdev_priv(dev);
	dev->hard_start_xmit = ieee80211_xmit;

	ieee->dev = dev;

	err = ieee80211_networks_allocate(ieee);
	if (err) {
		IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
				err);
		goto failed;
	}
	ieee80211_networks_initialize(ieee);

	/* Default fragmentation threshold is maximum payload size */
	ieee->fts = DEFAULT_FTS;
	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
	ieee->open_wep = 1;
#ifdef CONFIG_IEEE80211_CRYPT
	/* Default to enabling full open WEP with host based encrypt/decrypt */
	ieee->host_encrypt = 1;
	ieee->host_decrypt = 1;
	ieee->ieee802_1x = 1; /* Default to supporting 802.1x */

	INIT_LIST_HEAD(&ieee->crypt_deinit_list);
	init_timer(&ieee->crypt_deinit_timer);
	ieee->crypt_deinit_timer.data = (unsigned long)ieee;
	ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;

#endif

	spin_lock_init(&ieee->lock);

#ifdef CONFIG_IEEE80211_WPA
ieee->wpa_enabled = 0;
ieee->tkip_countermeasures = 0;
ieee->drop_unencrypted = 0;
ieee->privacy_invoked = 0;
ieee->ieee802_1x = 1;
#endif /* CONFIG_IEEE80211_WPA */

	return dev;

failed:

	if (dev)
		free_netdev(dev);
	return NULL;
}

void free_ieee80211(struct net_device *dev)

{
	struct ieee80211_device *ieee = netdev_priv(dev);
#ifdef CONFIG_IEEE80211_CRYPT
	int i;

	del_timer_sync(&ieee->crypt_deinit_timer);
	ieee80211_crypt_deinit_entries(ieee, 1);

	for (i = 0; i < WEP_KEYS; i++) {
		struct ieee80211_crypt_data *crypt = ieee->crypt[i];
		if (crypt) {
			if (crypt->ops) {
				crypt->ops->deinit(crypt->priv);
				module_put(crypt->ops->owner);
			}
			kfree(crypt);
			ieee->crypt[i] = NULL;
		}
	}

#endif

	ieee80211_networks_free(ieee);
	free_netdev(dev);
}

#ifdef CONFIG_IEEE80211_DEBUG

static int debug = 0;
u32 ieee80211_debug_level = 0;
struct proc_dir_entry *ieee80211_proc = NULL;

static int show_debug_level(char *page, char **start, off_t offset,
int count, int *eof, void *data)

{
	return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
}

static int store_debug_level(struct file *file, const char *buffer,
unsigned long count, void *data)

{
	char buf[] = "0x00000000";
	unsigned long len = min(sizeof(buf) - 1, (u32)count);
	char *p = (char *)buf;
	unsigned long val;

	if (copy_from_user(buf, buffer, len))
		return count;
	buf[len] = 0;
	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
		p++;
		if (p[0] == 'x' || p[0] == 'X')
			p++;
		val = simple_strtoul(p, &p, 16);
	} else
		val = simple_strtoul(p, &p, 10);
	if (p == buf)
		printk(KERN_INFO DRV_NAME
		       ": %s is not in hex or decimal form.\n", buf);
	else
		ieee80211_debug_level = val;

	return strnlen(buf, count);
}

static int __init ieee80211_init(void)

{
	struct proc_dir_entry *e;

	ieee80211_debug_level = debug;
	ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
	if (ieee80211_proc == NULL) {
		IEEE80211_ERROR("Unable to create " DRV_NAME
				" proc directory\n");
		return -EIO;
	}
	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
			      ieee80211_proc);
	if (!e) {
		remove_proc_entry(DRV_NAME, proc_net);
		ieee80211_proc = NULL;
		return -EIO;
	}
	e->read_proc = show_debug_level;
	e->write_proc = store_debug_level;
	e->data = NULL;

	return 0;
}

static void __exit ieee80211_exit(void)

{
	if (ieee80211_proc) {
		remove_proc_entry("debug_level", ieee80211_proc);
		remove_proc_entry(DRV_NAME, proc_net);
		ieee80211_proc = NULL;
	}
}

#include <linux/moduleparam.h>
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask");

module_exit(ieee80211_exit);
module_init(ieee80211_init);
#endif

EXPORT_SYMBOL(alloc_ieee80211);
EXPORT_SYMBOL(free_ieee80211);

#8 lore raw
Quoted 27 lines · James Ketrenos
Quoted 25 lines · Randy.Dunlap
Quoted 20 lines · James Ketrenos

Attached is the patch against 2.6.11-rc3-mm1 that adds the ieee80211 subsystem used by the ipw2100 and ipw2200 projects.

I'll be sending out the patches for ipw2100-1.0.0 and ipw2200-1.0.0 that use thist stack to the list on Monday.

In terms of what the stack currently does:

* HW independent -- it only knows about 802.11 data and structures
* Performs an 802.3 <-> 802.11 transform for data Tx/Rx
* Host based support for fragmentation, WEP, and WPA using the kernel's crypto functions
* Beacon and probe response collection and parsing
* Default implementation of some of the WE handlers that can be managed without hardware knowledge

We are working to merge in Dave Miller's p80211 code into the ieee80211 subsystem so that it hooks into the kernel as a true network layer as opposed to a mutated offspring of ethernet.
Once that is done, hopefully the skb to txb code can be reworked and 802.11 fragments can be treated either as normal skbs, or skbs can be modified to directly support them (ideally so that encrypted 802.11 frames in support of IP packets can be cached by the stack instead of having to be re-encrypted on TCP retries)

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

Anyway, please let me know what you think. Hopefully I built the patch right...

Quoted 7 lines
Quoted 3 lines

James,
Can you post a patch that will build? or did you just want feedback on the current state of the patch?

Ah; I see my tree that I did the diff on was missing the wireless/Makefile and the ieee80211/ieee80211_module.c to create the patch against... sigh. Attached is ieee80211_module.c; you have the change for the Makefile to include ieee80211. Later {hopefully today} I'll send a full patch that includes several of the corrections you called out in your prior patch.

Now missing ieee80211_crypt.h (#included in the new ieee80211.h). Apparently still needing a complete diff.

+ /* Add the ESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ if (network->flags & NETWORK_EMPTY_ESSID) {

Lines 2-3 above use spaces (e.g.) -- please use tabs.

Signature · 1 line
~Randy
#9 lore raw
In reply to James Ketrenos
Quoted 2 lines · James Ketrenos

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

Do you already have some detailed plans on how to implement this? There are number of different implementations of TKIP hardware acceleration and it would be nice to support all of them. For example, some cards expect to get Ethernet 802.3 frames and take care of everything, others take IEEE 802.11 frames with possible padding between header and payload, some can take care of TKIP encryption part, but leave Michael MIC to software, some can take care of both for some packets, but not all (e.g., fragmentented frames), and so on..

Quoted 8 lines

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

We will need to take care of these areas in order to be able to call this "generic IEEE 802.11 networking stack".. I would like to be able to test replacing the upper level code in Host AP driver with this and verify that all functionality is still available. Another useful test case would be to go through what needs to be done to make this work with the madwifi driver (i.e., merge some parts of net80211 code with this and make the low-level parts of the driver use the combination for IEEE 802.11 processing).

drivers/net/wireless/Kconfig line 31

Quoted 8 lines

diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/drivers/net/wireless/Kconfig netdev-2.6-ipw/drivers/net/wireless/Kconfig

drivers/net/wireless/Kconfig +1 -0
@@ -28,6 +28,8 @@
 	  special kernel support are available from
 	  <ftp://shadow.cabi.net/pub/Linux/>.
 
+source "drivers/net/wireless/ieee80211/Kconfig"

The generic IEEE 802.11 implementatio should go to net/ieee80211 or net/80211 etc. like mentioned before.

drivers/net/wireless/Kconfig

Quoted 5 lines
drivers/net/wireless/Kconfig +4 -0
+config IEEE80211_DEBUG
+	  This option will enable debug tracing output for the 
+	  ieee80211 network stack.  
 
+	  % echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level

Generic IEEE 802.11 code should not refer to specific driver.. Should there be a per network device option for setting debug level or is a global one enough?

drivers/net/wireless/Kconfig

Quoted 10 lines
drivers/net/wireless/Kconfig +10 -0
+	  For a list of values you can assign to debug_level, simply 
+   	  perform:
+
+	  % . idvals
+	  
+	  From within drivers/net/wireless/ipw2200
+
+	  If you are not trying to debug or develop the IPW2200 driver, 
+	  you 
+	  most likely want to say N here.

This sounds like something that should be moved to ipw2200 specific configuration option.

drivers/net/wireless/Kconfig

Quoted 6 lines
drivers/net/wireless/Kconfig +6 -0
+config IEEE80211_WPA
+	tristate "IEEE 802.11 WPA"
+	depends on IEEE80211_CRYPT
+	---help---
+	Software implementation of IEEE 802.11 WPA.  You will need
+	to select the WPA algorithms you wish to use.

Software implementation? Is there a hardware implementation of WPA? ;-) "WPA algorithms" should be replaced with cipher suites or something like that since WPA uses number of algorithms for key management and authentication and those are not included in the kernel code.

Is this configuration option needed or should WPA support be included by default? If this remains, we should at least included WPA2 and IEEE 802.11i in the description, since this code is not only for WPA.

drivers/net/wireless/Kconfig

Quoted 4 lines
drivers/net/wireless/Kconfig +4 -0
+config IEEE80211_CRYPT_CCMP
+	tristate "IEEE 802.11 CCMP encryption"
+	depends on IEEE80211_WPA
+	select CRYPTO_AES_586

Is CRYPTO_AES_586 the proper way of selecting this? 586 sounds like x86-specific optimization, but I would like to use this on, say, xscale.

Quoted 3 lines

+++ netdev-2.6-ipw/drivers/net/wireless/ieee80211/ieee80211_crypt.c 2005-02-04 10:20:03 -06:00

+#include "../ieee80211.h"

Should that be moved to include/net/ieee80211.h? I.e., this would be #include <net/ieee80211.h>.

drivers/net/wireless/Kconfig

Quoted 5 lines

+++ netdev-2.6-ipw/drivers/net/wireless/ieee80211/ieee80211_crypt_ccmp.c 2005-02-04 10:20:03 -06:00

drivers/net/wireless/Kconfig +3 -0
+#ifndef CONFIG_CRYPTO
+#error CONFIG_CRYPTO is required to build this module.
+#endif

This can be removed, IEEE80211_CRYPT had "select CRYPTO" in Kconfig.

drivers/net/wireless/Kconfig

Quoted 5 lines
drivers/net/wireless/Kconfig +5 -0
+static void * ieee80211_ccmp_init(int key_idx)
+{
+	struct ieee80211_ccmp_data *priv;
+
+	priv = kmalloc(sizeof(*priv), GFP_ATOMIC);

You do not seem to include try_module_get(THIS_MODULE) here (and matching module_put in deinit) like the version in Host AP driver is using. What is protecting the CCMP/TKIP modules from being unloaded when they are still used?

That's for the first 1840 lines of the patch and enough for today.. I'll try to continue later this week.

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#10 lore raw
Quoted 8 lines · Jouni Malinen
Quoted 3 lines · James Ketrenos

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

Quoted 10 lines

Do you already have some detailed plans on how to implement this? There are number of different implementations of TKIP hardware acceleration and it would be nice to support all of them. For example, some cards expect to get Ethernet 802.3 frames and take care of everything, others take IEEE 802.11 frames with possible padding between header and payload, some can take care of TKIP encryption part, but leave Michael MIC to software, some can take care of both for some packets, but not all (e.g., fragmentented frames), and so on..

I don't have any detailed planning on this currently. I agree it should be done in a way to support as much hardware as possible -- the most difficult will likely be support of adapters that require 802.3 frames since all thinking to this point has been to make the stack such that wireless drivers never need to know about 802.3.

Is it only for the data Tx/Rx that the 802.11/802.3 transform is handled by the device? Or does the device internalize all 802.11 features such that 802.11 frames are never exposed externally? The ipw2100 is similar in some regard to this -- although it doesn't take either 802.3 or 802.11; it takes a raw data payload and a data structure that contains the dest addr, etc.

Quoted 4 lines
Quoted 3 lines

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

Quoted 10 lines

We will need to take care of these areas in order to be able to call this "generic IEEE 802.11 networking stack".. I would like to be able to test replacing the upper level code in Host AP driver with this and verify that all functionality is still available. Another useful test case would be to go through what needs to be done to make this work with the madwifi driver (i.e., merge some parts of net80211 code with this and make the low-level parts of the driver use the combination for IEEE 802.11 processing).

Agreed. Hopefully as more folks start seeing these patches others will be encouraged to try and help out, pulling the best of all the existing drivers together.

Quoted 7 lines
Quoted 7 lines

diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/drivers/net/wireless/Kconfig netdev-2.6-ipw/drivers/net/wireless/Kconfig

drivers/net/wireless/Kconfig +0 -0
@@ -28,6 +28,8 @@
 	  special kernel support are available from
 	  <ftp://shadow.cabi.net/pub/Linux/>.
 
Quoted 8 lines

drivers/net/wireless/Kconfig line 33

Quoted 3 lines
drivers/net/wireless/Kconfig +1 -0
+source "drivers/net/wireless/ieee80211/Kconfig"
 
 

The generic IEEE 802.11 implementatio should go to net/ieee80211 or net/80211 etc. like mentioned before.

I'll rework it into net/ieee80211.

Quoted 8 lines
Quoted 5 lines
drivers/net/wireless/Kconfig +3 -0
+config IEEE80211_DEBUG
+	  This option will enable debug tracing output for the 
+	  ieee80211 network stack.  
Quoted 9 lines

drivers/net/wireless/Kconfig

Quoted 3 lines
drivers/net/wireless/Kconfig +1 -0
+	  % echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level

Generic IEEE 802.11 code should not refer to specific driver.. Should there be a per network device option for setting debug level or is a global one enough?

This was an oversite when last I updated the Kconfig for the ieee80211 components. The debug level for ieee80211 is configured in /proc/net/ieee80211/debug_level.

Currently there is a script provided in the ipw2100 and ipw2200 projects that greps the various debug levels supported for ieee80211 and dumps them to the console so the user doesn't have to manually look in ieee80211.h to try and figure out what bit masks in the debug_level correspond to what aspects.

That script should be provided in a utility pacakge for the ieee80211 stack -- a question is if it should simply grep on the running kernel's ieee80211.h to find the debug levels, or if the ieee80211 subsystem should contain in it the strings to export to the utility its internal debug levels via sysfs.

Having the debug flexibility in the module has been extremely useful in tracking issues and resolving bugs, while not flooding everyone's kernel logs with unneeded messages.

Quoted 7 lines
Quoted 7 lines
drivers/net/wireless/Kconfig +7 -0
+	  For a list of values you can assign to debug_level, simply 
+   	  perform:
+
+	  % . idvals
+	  
+	  From within drivers/net/wireless/ipw2200
+
Quoted 10 lines

drivers/net/wireless/Kconfig

Quoted 5 lines
drivers/net/wireless/Kconfig +3 -0
+	  If you are not trying to debug or develop the IPW2200 driver, 
+	  you 
+	  most likely want to say N here.

This sounds like something that should be moved to ipw2200 specific configuration option.

Same oversite as above -- it should change to:

----
For a list of values you can assign to debug_level, you can need to use the ieee80211 utility package available at <URL>. Once installed, you can then run:

% ieee80211_dvals

To obtain a list of supported debug masks. You can also read/write the debug mask via

/proc/net/ieee80211/debug_level

If you are not trying to debug or develop the ieee80211 subsystem, you most likely want to say N here.

---

and then I need to put up an ieee80211 utility package somewhere...

Quoted 15 lines

drivers/net/wireless/Kconfig

Quoted 8 lines
drivers/net/wireless/Kconfig +6 -0
+config IEEE80211_WPA
+	tristate "IEEE 802.11 WPA"
+	depends on IEEE80211_CRYPT
+	---help---
+	Software implementation of IEEE 802.11 WPA.  You will need
+	to select the WPA algorithms you wish to use.

Software implementation? Is there a hardware implementation of WPA? ;-) "WPA algorithms" should be replaced with cipher suites or something like that since WPA uses number of algorithms for key management and authentication and those are not included in the kernel code.

Quoted 5 lines

Is this configuration option needed or should WPA support be included by default? If this remains, we should at least included WPA2 and IEEE 802.11i in the description, since this code is not only for WPA.

802.11i should be provided by default (it currently isn't). If we provide the option for selecting the cipher suites, any issues with this text?:

CONFIG_IEEE80211_WEP
Include software based cipher suites in support of IEEE 802.11's WEP. This is needed for WEP as well as 802.1x. This selects ARC4 under kernel crypto libraries, and CRC32 under kernel libraries.

CONFIG_IEEE80211_CCMP
Include software based cipher suites in support of IEEE 802.11i (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled networks. This selects AES support under kernel crypto libraries.

CONFIG_IEEE80211_TKIP
Include software based cipher suites in support of IEEE 802.11i (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled networks. This selects Michael Mic support under kernel crypto libraries.
...

All of the above should default to 'Y'.

Quoted 11 lines

drivers/net/wireless/Kconfig

Quoted 6 lines
drivers/net/wireless/Kconfig +4 -0
+config IEEE80211_CRYPT_CCMP
+	tristate "IEEE 802.11 CCMP encryption"
+	depends on IEEE80211_WPA
+	select CRYPTO_AES_586

Is CRYPTO_AES_586 the proper way of selecting this? 586 sounds like x86-specific optimization, but I would like to use this on, say, xscale.

How do you set up a dependency to be "one of"?

depends on CRYPTO_AES or CRYPTO_AES_586

?

Quoted 6 lines
Quoted 3 lines

+++ netdev-2.6-ipw/drivers/net/wireless/ieee80211/ieee80211_crypt.c 2005-02-04 10:20:03 -06:00

Quoted 8 lines
Quoted 3 lines

+#include "../ieee80211.h"

Should that be moved to include/net/ieee80211.h? I.e., this would be #include <net/ieee80211.h>.

Will do.

Quoted 6 lines
Quoted 3 lines

+++ netdev-2.6-ipw/drivers/net/wireless/ieee80211/ieee80211_crypt_ccmp.c 2005-02-04 10:20:03 -06:00

Quoted 9 lines

drivers/net/wireless/Kconfig

Quoted 5 lines
drivers/net/wireless/Kconfig +3 -0
+#ifndef CONFIG_CRYPTO
+#error CONFIG_CRYPTO is required to build this module.
+#endif

This can be removed, IEEE80211_CRYPT had "select CRYPTO" in Kconfig.

Removed.

Quoted 4 lines
Quoted 4 lines
drivers/net/wireless/Kconfig +4 -0
+static void * ieee80211_ccmp_init(int key_idx)
+{
+	struct ieee80211_ccmp_data *priv;
+
Quoted 10 lines

drivers/net/wireless/Kconfig

Quoted 3 lines
drivers/net/wireless/Kconfig +1 -0
+	priv = kmalloc(sizeof(*priv), GFP_ATOMIC);

You do not seem to include try_module_get(THIS_MODULE) here (and matching module_put in deinit) like the version in Host AP driver is using. What is protecting the CCMP/TKIP modules from being unloaded when they are still used?

The handler that loads the crypto module performs a try_module_get(). Currently that code isn't contained in ieee80211_wx.c and is in drivers loading the ciphers for WPA -- it needs to be moved to the ieee80211_wx.

Which raises the question -- should we continue to support dynamically loading cipher suite handlers, or just statically compile them in if the user has requested them to be included? Originally, the cipher suites contained all the crypto code within them, which increased their size and complexity. Now, however, the suites are essentially shims that wrap the kernel crypto libraries.

There is the obvious aspect of flexibility that arises from supporting arbitrary and dynamic loading of crypto shims, but it does complicate the code somewhat.

Thoughts?

Quoted 4 lines

That's for the first 1840 lines of the patch and enough for today.. I'll try to continue later this week.

Thanks,
James

#11 lore raw

Just to keep everything moving, my recommendation would be to move the code to net/*, and resend the patch (with whatever changes you have made to date).

That way you, and others, can review and work on the tree in parallel.

I'm worried that your list of todo items (based on responses so far) is already so long that I won't hear from you for another year ;-) We need to get the wireless-2.6 tree active again, and avoid bottlenecks. We need "release early, release often."

Jeff

#12 lore raw
Quoted 5 lines · Jeff Garzik

Just to keep everything moving, my recommendation would be to move the code to net/*, and resend the patch (with whatever changes you have made to date).

That way you, and others, can review and work on the tree in parallel.

I'm worried that your list of todo items (based on responses so far) is already so long that I won't hear from you for another year ;-) We need to get the wireless-2.6 tree active again, and avoid bottlenecks. We need "release early, release often."

I've allocated a couple hours tomorrow to merge in all the comments to date and get them pushed to my bk tree (bk://ipw.bkbits.net/ipw-2.6 is where I've been staging all of the ipw work)

So, I'll send a new patch out tomorrow with what I have to date.

James

#13 lore raw
In reply to Jeff Garzik
Quoted 1 line · Jeff Garzik

Just to keep everything moving, my recommendation would be to move the code to net/*, and resend the patch (with whatever changes you have made to date).

Alrighty... attached is the latest diff against netdev-2.6.

Changes since last version:

* Includes previously missing files
* Lots of whitespace cleanups
* Various syntactical cleanups
* Moved to net/ieee80211 from drivers/net/wireless/ieee80211
-- I wasn't sure what people's thoughts were for how Wireless is currently leveled under menuconfig.
* Moved ieee80211.h and ieee80211_crypt.h to include/net
* Updated descriptions of WEP, TKIP, and CCMP software cipher suites and reworked Makefile to match
* Verified that the patch applies, can be configured via menuconfig, and builds successfully
* Changed AES_586 selection to just AES

Also attached is the list of items folks have sent me that I have not resolved (if anyone wants to throw me a patch that hits any of these, feel free)

I've pushed the above changes to bk://ipw.bkbits.net/ipw-2.6 if anyone wants to use them on conjunction w/ the current development snapshots of the ipw* drivers.

James

include/net/ieee80211.h +883 -0
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/include/net/ieee80211.h netdev-2.6-ipw/include/net/ieee80211.h
@@ -0,0 +1,883 @@
+/*
+ * Merged with mainline ieee80211.h in Aug 2004.  Original ieee802_11
+ * remains copyright by the original authors
+ *
+ * Portions of the merged code are based on Host AP (software wireless
+ * LAN access point) driver for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <[email protected]>
+ * Copyright (c) 2002-2003, Jouni Malinen <[email protected]>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <[email protected]>
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * 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 IEEE80211_H
+#define IEEE80211_H
+#include <linux/if_ether.h> /* ETH_ALEN */
+#include <linux/kernel.h>   /* ARRAY_SIZE */
+
+#if WIRELESS_EXT < 17
+#define IW_QUAL_QUAL_INVALID   0x10
+#define IW_QUAL_LEVEL_INVALID  0x20
+#define IW_QUAL_NOISE_INVALID  0x40
+#define IW_QUAL_QUAL_UPDATED   0x1
+#define IW_QUAL_LEVEL_UPDATED  0x2
+#define IW_QUAL_NOISE_UPDATED  0x4
+#endif
+
+#define IEEE80211_DATA_LEN		2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+   6.2.1.1.2.
+
+   The figure in section 7.1.2 suggests a body size of up to 2312
+   bytes is allowed, which is a bit confusing, I suspect this
+   represents the 2304 bytes of real data, plus a possible 8 bytes of
+   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
+
+
+#define IEEE80211_HLEN			30
+#define IEEE80211_FRAME_LEN		(IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct ieee80211_hdr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_3addr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+} __attribute__ ((packed));
+
+static const char *eap_types[] = {
+	"EAP-Packet", "EAPOL-Start", "EAPOL-Logoff", "EAPOL-Key",
+	"EAPOL-Encap-ASF-Alert", "Unknown"
+};
+
+static inline const char *eap_get_type(int type)
+{
+	if (type > ARRAY_SIZE(eap_types))
+		type = ARRAY_SIZE(eap_types) - 1;
+	return eap_types[type];
+}
+
+struct eapol {
+	u8 snap[6];
+	u16 ethertype;
+	u8 version;
+	u8 type;
+	u16 length;
+} __attribute__ ((packed));
+
+#define IEEE80211_3ADDR_LEN 24
+#define IEEE80211_4ADDR_LEN 30
+#define IEEE80211_FCS_LEN    4
+
+#define MIN_FRAG_THRESHOLD     256U
+#define	MAX_FRAG_THRESHOLD     2346U
+
+/* Frame control field constants */
+#define IEEE80211_FCTL_VERS		0x0002
+#define IEEE80211_FCTL_FTYPE		0x000c
+#define IEEE80211_FCTL_STYPE		0x00f0
+#define IEEE80211_FCTL_TODS		0x0100
+#define IEEE80211_FCTL_FROMDS		0x0200
+#define IEEE80211_FCTL_MOREFRAGS	0x0400
+#define IEEE80211_FCTL_RETRY		0x0800
+#define IEEE80211_FCTL_PM		0x1000
+#define IEEE80211_FCTL_MOREDATA	0x2000
+#define IEEE80211_FCTL_WEP		0x4000
+#define IEEE80211_FCTL_ORDER		0x8000
+
+#define IEEE80211_FTYPE_MGMT		0x0000
+#define IEEE80211_FTYPE_CTL		0x0004
+#define IEEE80211_FTYPE_DATA		0x0008
+
+/* management */
+#define IEEE80211_STYPE_ASSOC_REQ	0x0000
+#define IEEE80211_STYPE_ASSOC_RESP 	0x0010
+#define IEEE80211_STYPE_REASSOC_REQ	0x0020
+#define IEEE80211_STYPE_REASSOC_RESP	0x0030
+#define IEEE80211_STYPE_PROBE_REQ	0x0040
+#define IEEE80211_STYPE_PROBE_RESP	0x0050
+#define IEEE80211_STYPE_BEACON		0x0080
+#define IEEE80211_STYPE_ATIM		0x0090
+#define IEEE80211_STYPE_DISASSOC	0x00A0
+#define IEEE80211_STYPE_AUTH		0x00B0
+#define IEEE80211_STYPE_DEAUTH		0x00C0
+
+/* control */
+#define IEEE80211_STYPE_PSPOLL		0x00A0
+#define IEEE80211_STYPE_RTS		0x00B0
+#define IEEE80211_STYPE_CTS		0x00C0
+#define IEEE80211_STYPE_ACK		0x00D0
+#define IEEE80211_STYPE_CFEND		0x00E0
+#define IEEE80211_STYPE_CFENDACK	0x00F0
+
+/* data */
+#define IEEE80211_STYPE_DATA		0x0000
+#define IEEE80211_STYPE_DATA_CFACK	0x0010
+#define IEEE80211_STYPE_DATA_CFPOLL	0x0020
+#define IEEE80211_STYPE_DATA_CFACKPOLL	0x0030
+#define IEEE80211_STYPE_NULLFUNC	0x0040
+#define IEEE80211_STYPE_CFACK		0x0050
+#define IEEE80211_STYPE_CFPOLL		0x0060
+#define IEEE80211_STYPE_CFACKPOLL	0x0070
+
+#define IEEE80211_SCTL_FRAG		0x000F
+#define IEEE80211_SCTL_SEQ		0xFFF0
+
+
+/* debug macros */
+
+#ifdef CONFIG_IEEE80211_DEBUG
+extern u32 ieee80211_debug_level;
+#define IEEE80211_DEBUG(level, fmt, args...) \
+do { if (ieee80211_debug_level & (level)) \
+  printk(KERN_DEBUG "ieee80211: %c %s " fmt, \
+         in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+#else
+#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
+#endif	/* CONFIG_IEEE80211_DEBUG */
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define IEEE80211_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry.  xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your
+ * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw/debug_level
+ *
+ * you simply need to add your entry to the ipw_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/ipw then you do not have
+ * CONFIG_IEEE80211_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define IEEE80211_DL_INFO          (1<<0)
+#define IEEE80211_DL_WX            (1<<1)
+#define IEEE80211_DL_SCAN          (1<<2)
+#define IEEE80211_DL_STATE         (1<<3)
+#define IEEE80211_DL_MGMT          (1<<4)
+#define IEEE80211_DL_FRAG          (1<<5)
+#define IEEE80211_DL_EAP           (1<<6)
+#define IEEE80211_DL_DROP          (1<<7)
+
+#define IEEE80211_DL_TX            (1<<8)
+#define IEEE80211_DL_RX            (1<<9)
+
+#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
+#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
+#define IEEE80211_DEBUG_INFO(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a)
+
+#define IEEE80211_DEBUG_WX(f, a...)     IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a)
+#define IEEE80211_DEBUG_SCAN(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a)
+#define IEEE80211_DEBUG_STATE(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
+#define IEEE80211_DEBUG_MGMT(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
+#define IEEE80211_DEBUG_FRAG(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
+#define IEEE80211_DEBUG_EAP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
+#define IEEE80211_DEBUG_DROP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
+#define IEEE80211_DEBUG_TX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
+#define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/if_arp.h> /* ARPHRD_ETHER */
+
+#ifndef WIRELESS_SPY
+#define WIRELESS_SPY		// enable iwspy support
+#endif
+#include <net/iw_handler.h>	// new driver API
+
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+
+#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+#endif
+
+/* IEEE 802.11 defines */
+
+#define P80211_OUI_LEN 3
+
+struct ieee80211_snap_hdr {
+
+        u8    dsap;   /* always 0xAA */
+        u8    ssap;   /* always 0xAA */
+        u8    ctrl;   /* always 0x03 */
+        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
+
+} __attribute__ ((packed));
+
+#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
+
+#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
+#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
+
+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
+#define WLAN_GET_SEQ_SEQ(seq)  ((seq) & IEEE80211_SCTL_SEQ)
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_BSS (1<<0)
+#define WLAN_CAPABILITY_IBSS (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
+#define WLAN_CAPABILITY_PRIVACY (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
+
+/* Status codes */
+#define WLAN_STATUS_SUCCESS 0
+#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
+#define WLAN_STATUS_CAPS_UNSUPPORTED 10
+#define WLAN_STATUS_REASSOC_NO_ASSOC 11
+#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
+#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
+#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
+#define WLAN_STATUS_CHALLENGE_FAIL 15
+#define WLAN_STATUS_AUTH_TIMEOUT 16
+#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
+#define WLAN_STATUS_ASSOC_DENIED_RATES 18
+/* 802.11b */
+#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
+#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
+#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
+
+/* Reason codes */
+#define WLAN_REASON_UNSPECIFIED 1
+#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define WLAN_REASON_DEAUTH_LEAVING 3
+#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define WLAN_REASON_DISASSOC_AP_BUSY 5
+#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
+#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
+#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+
+
+/* Information Element IDs */
+#define WLAN_EID_SSID 0
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_FH_PARAMS 2
+#define WLAN_EID_DS_PARAMS 3
+#define WLAN_EID_CF_PARAMS 4
+#define WLAN_EID_TIM 5
+#define WLAN_EID_IBSS_PARAMS 6
+#define WLAN_EID_CHALLENGE 16
+#define WLAN_EID_RSN 48
+#define WLAN_EID_GENERIC 221
+
+#define IEEE80211_MGMT_HDR_LEN 24
+#define IEEE80211_DATA_HDR3_LEN 24
+#define IEEE80211_DATA_HDR4_LEN 30
+
+
+#define IEEE80211_STATMASK_SIGNAL (1<<0)
+#define IEEE80211_STATMASK_RSSI (1<<1)
+#define IEEE80211_STATMASK_NOISE (1<<2)
+#define IEEE80211_STATMASK_RATE (1<<3)
+#define IEEE80211_STATMASK_WEMASK 0x7
+
+
+#define IEEE80211_CCK_MODULATION    (1<<0)
+#define IEEE80211_OFDM_MODULATION   (1<<1)
+
+#define IEEE80211_24GHZ_BAND     (1<<0)
+#define IEEE80211_52GHZ_BAND     (1<<1)
+
+#define IEEE80211_CCK_RATE_1MB		        0x02
+#define IEEE80211_CCK_RATE_2MB		        0x04
+#define IEEE80211_CCK_RATE_5MB		        0x0B
+#define IEEE80211_CCK_RATE_11MB		        0x16
+#define IEEE80211_OFDM_RATE_6MB		        0x0C
+#define IEEE80211_OFDM_RATE_9MB		        0x12
+#define IEEE80211_OFDM_RATE_12MB		0x18
+#define IEEE80211_OFDM_RATE_18MB		0x24
+#define IEEE80211_OFDM_RATE_24MB		0x30
+#define IEEE80211_OFDM_RATE_36MB		0x48
+#define IEEE80211_OFDM_RATE_48MB		0x60
+#define IEEE80211_OFDM_RATE_54MB		0x6C
+#define IEEE80211_BASIC_RATE_MASK		0x80
+
+#define IEEE80211_CCK_RATE_1MB_MASK		(1<<0)
+#define IEEE80211_CCK_RATE_2MB_MASK		(1<<1)
+#define IEEE80211_CCK_RATE_5MB_MASK		(1<<2)
+#define IEEE80211_CCK_RATE_11MB_MASK		(1<<3)
+#define IEEE80211_OFDM_RATE_6MB_MASK		(1<<4)
+#define IEEE80211_OFDM_RATE_9MB_MASK		(1<<5)
+#define IEEE80211_OFDM_RATE_12MB_MASK		(1<<6)
+#define IEEE80211_OFDM_RATE_18MB_MASK		(1<<7)
+#define IEEE80211_OFDM_RATE_24MB_MASK		(1<<8)
+#define IEEE80211_OFDM_RATE_36MB_MASK		(1<<9)
+#define IEEE80211_OFDM_RATE_48MB_MASK		(1<<10)
+#define IEEE80211_OFDM_RATE_54MB_MASK		(1<<11)
+
+#define IEEE80211_CCK_RATES_MASK	        0x0000000F
+#define IEEE80211_CCK_BASIC_RATES_MASK	(IEEE80211_CCK_RATE_1MB_MASK | \
+	IEEE80211_CCK_RATE_2MB_MASK)
+#define IEEE80211_CCK_DEFAULT_RATES_MASK	(IEEE80211_CCK_BASIC_RATES_MASK | \
+        IEEE80211_CCK_RATE_5MB_MASK | \
+        IEEE80211_CCK_RATE_11MB_MASK)
+
+#define IEEE80211_OFDM_RATES_MASK		0x00000FF0
+#define IEEE80211_OFDM_BASIC_RATES_MASK	(IEEE80211_OFDM_RATE_6MB_MASK | \
+	IEEE80211_OFDM_RATE_12MB_MASK | \
+	IEEE80211_OFDM_RATE_24MB_MASK)
+#define IEEE80211_OFDM_DEFAULT_RATES_MASK	(IEEE80211_OFDM_BASIC_RATES_MASK | \
+	IEEE80211_OFDM_RATE_9MB_MASK  | \
+	IEEE80211_OFDM_RATE_18MB_MASK | \
+	IEEE80211_OFDM_RATE_36MB_MASK | \
+	IEEE80211_OFDM_RATE_48MB_MASK | \
+	IEEE80211_OFDM_RATE_54MB_MASK)
+#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
+                                IEEE80211_CCK_DEFAULT_RATES_MASK)
+
+#define IEEE80211_NUM_OFDM_RATES	    8
+#define IEEE80211_NUM_CCK_RATES	            4
+#define IEEE80211_OFDM_SHIFT_MASK_A         4
+
+
+
+
+/* NOTE: This data is for statistical purposes; not all hardware provides this
+ *       information for frames received.  Not setting these will not cause
+ *       any adverse affects. */
+struct ieee80211_rx_stats {
+	u32 mac_time;
+	s8 rssi;
+	u8 signal;
+	u8 noise;
+	u16 rate; /* in 100 kbps */
+	u8 received_channel;
+	u8 control;
+	u8 mask;
+	u8 freq;
+	u16 len;
+};
+
+/* IEEE 802.11 requires that STA supports concurrent reception of at least
+ * three fragmented frames. This define can be increased to support more
+ * concurrent frames, but it should be noted that each entry can consume about
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
+#define IEEE80211_FRAG_CACHE_LEN 4
+
+struct ieee80211_frag_entry {
+	unsigned long first_frag_time;
+	unsigned int seq;
+	unsigned int last_frag;
+	struct sk_buff *skb;
+	u8 src_addr[ETH_ALEN];
+	u8 dst_addr[ETH_ALEN];
+};
+
+struct ieee80211_stats {
+	unsigned int tx_unicast_frames;
+	unsigned int tx_multicast_frames;
+	unsigned int tx_fragments;
+	unsigned int tx_unicast_octets;
+	unsigned int tx_multicast_octets;
+	unsigned int tx_deferred_transmissions;
+	unsigned int tx_single_retry_frames;
+	unsigned int tx_multiple_retry_frames;
+	unsigned int tx_retry_limit_exceeded;
+	unsigned int tx_discards;
+	unsigned int rx_unicast_frames;
+	unsigned int rx_multicast_frames;
+	unsigned int rx_fragments;
+	unsigned int rx_unicast_octets;
+	unsigned int rx_multicast_octets;
+	unsigned int rx_fcs_errors;
+	unsigned int rx_discards_no_buffer;
+	unsigned int tx_discards_wrong_sa;
+	unsigned int rx_discards_undecryptable;
+	unsigned int rx_message_in_msg_fragments;
+	unsigned int rx_message_in_bad_msg_fragments;
+};
+
+struct ieee80211_device;
+
+#include "ieee80211_crypt.h"
+
+#define SEC_KEY_1         (1<<0)
+#define SEC_KEY_2         (1<<1)
+#define SEC_KEY_3         (1<<2)
+#define SEC_KEY_4         (1<<3)
+#define SEC_ACTIVE_KEY    (1<<4)
+#define SEC_AUTH_MODE     (1<<5)
+#define SEC_UNICAST_GROUP (1<<6)
+#define SEC_LEVEL         (1<<7)
+#define SEC_ENABLED       (1<<8)
+
+#define SEC_LEVEL_0      0 /* None */
+#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
+#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
+#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
+
+#define WEP_KEYS 4
+#define WEP_KEY_LEN 13
+
+struct ieee80211_security {
+	u16 active_key:2,
+            enabled:1,
+	    auth_mode:2,
+            auth_algo:4,
+            unicast_uses_group:1;
+	u8 key_sizes[WEP_KEYS];
+	u8 keys[WEP_KEYS][WEP_KEY_LEN];
+	u8 level;
+	u16 flags;
+} __attribute__ ((packed));
+
+
+/*
+
+ 802.11 data frame from AP
+
+      ,-------------------------------------------------------------------.
+Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
+      |------|------|---------|---------|---------|------|---------|------|
+Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
+      |      | tion | (BSSID) |         |         | ence |  data   |      |
+      `-------------------------------------------------------------------'
+
+Total: 28-2340 bytes
+
+*/
+
+struct ieee80211_header_data {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[6];
+	u8 addr2[6];
+	u8 addr3[6];
+	u16 seq_ctrl;
+};
+
+#define BEACON_PROBE_SSID_ID_POSITION 12
+
+/* Management Frame Information Element Types */
+#define MFIE_TYPE_SSID       0
+#define MFIE_TYPE_RATES      1
+#define MFIE_TYPE_FH_SET     2
+#define MFIE_TYPE_DS_SET     3
+#define MFIE_TYPE_CF_SET     4
+#define MFIE_TYPE_TIM        5
+#define MFIE_TYPE_IBSS_SET   6
+#define MFIE_TYPE_CHALLENGE  16
+#define MFIE_TYPE_RSN	     48
+#define MFIE_TYPE_RATES_EX   50
+#define MFIE_TYPE_GENERIC    221
+
+struct ieee80211_info_element_hdr {
+	u8 id;
+	u8 len;
+} __attribute__ ((packed));
+
+struct ieee80211_info_element {
+	u8 id;
+	u8 len;
+	u8 data[0];
+} __attribute__ ((packed));
+
+/*
+ * These are the data types that can make up management packets
+ *
+	u16 auth_algorithm;
+	u16 auth_sequence;
+	u16 beacon_interval;
+	u16 capability;
+	u8 current_ap[ETH_ALEN];
+	u16 listen_interval;
+	struct {
+		u16 association_id:14, reserved:2;
+	} __attribute__ ((packed));
+	u32 time_stamp[2];
+	u16 reason;
+	u16 status;
+*/
+
+struct ieee80211_authentication {
+	struct ieee80211_header_data header;
+	u16 algorithm;
+	u16 transaction;
+	u16 status;
+	struct ieee80211_info_element info_element;
+} __attribute__ ((packed));
+
+
+struct ieee80211_probe_response {
+	struct ieee80211_header_data header;
+	u32 time_stamp[2];
+	u16 beacon_interval;
+	u16 capability;
+	struct ieee80211_info_element info_element;
+} __attribute__ ((packed));
+
+struct ieee80211_assoc_request_frame {
+	u16 capability;
+	u16 listen_interval;
+	u8 current_ap[ETH_ALEN];
+	struct ieee80211_info_element info_element;
+} __attribute__ ((packed));
+
+struct ieee80211_assoc_response_frame {
+	struct ieee80211_hdr_3addr header;
+	u16 capability;
+	u16 status;
+	u16 aid;
+	struct ieee80211_info_element info_element; /* supported rates */
+} __attribute__ ((packed));
+
+
+struct ieee80211_txb {
+	u8 nr_frags;
+	u8 encrypted;
+	u16 reserved;
+	u16 frag_size;
+	u16 payload_size;
+	struct sk_buff *fragments[0];
+};
+
+
+/* SWEEP TABLE ENTRIES NUMBER*/
+#define MAX_SWEEP_TAB_ENTRIES		  42
+#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET  7
+/* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
+ * only use 8, and then use extended rates for the remaining supported
+ * rates.  Other APs, however, stick all of their supported rates on the
+ * main rates information element... */
+#define MAX_RATES_LENGTH                  ((u8)12)
+#define MAX_RATES_EX_LENGTH               ((u8)16)
+#define MAX_NETWORK_COUNT                  128
+
+#define CRC_LENGTH                 4U
+
+#define MAX_WPA_IE_LEN 64
+
+#define NETWORK_EMPTY_ESSID (1<<0)
+#define NETWORK_HAS_OFDM    (1<<1)
+#define NETWORK_HAS_CCK     (1<<2)
+
+struct ieee80211_network {
+	/* These entries are used to identify a unique network */
+	u8 bssid[ETH_ALEN];
+	u8 channel;
+	/* Ensure null-terminated for any debug msgs */
+	u8 ssid[IW_ESSID_MAX_SIZE + 1];
+	u8 ssid_len;
+
+	/* These are network statistics */
+	struct ieee80211_rx_stats stats;
+	u16 capability;
+	u8 rates[MAX_RATES_LENGTH];
+	u8 rates_len;
+	u8 rates_ex[MAX_RATES_EX_LENGTH];
+	u8 rates_ex_len;
+	unsigned long last_scanned;
+	u8 mode;
+	u8 flags;
+	u32 last_associate;
+	u32 time_stamp[2];
+	u16 beacon_interval;
+	u16 listen_interval;
+	u16 atim_window;
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	size_t wpa_ie_len;
+	u8 rsn_ie[MAX_WPA_IE_LEN];
+	size_t rsn_ie_len;
+	struct list_head list;
+};
+
+enum ieee80211_state {
+	IEEE80211_UNINITIALIZED = 0,
+	IEEE80211_INITIALIZED,
+	IEEE80211_ASSOCIATING,
+	IEEE80211_ASSOCIATED,
+	IEEE80211_AUTHENTICATING,
+	IEEE80211_AUTHENTICATED,
+	IEEE80211_SHUTDOWN
+};
+
+#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
+#define DEFAULT_FTS 2346
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
+
+
+extern inline int is_multicast_ether_addr(const u8 *addr)
+{
+	return ((addr[0] != 0xff) && (0x01 & addr[0]));
+}
+
+extern inline int is_broadcast_ether_addr(const u8 *addr)
+{
+	return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&   \
+		(addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
+}
+
+#define CFG_IEEE80211_RESERVE_FCS (1<<0)
+#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
+
+struct ieee80211_device {
+	struct net_device *dev;
+
+	/* Bookkeeping structures */
+	struct net_device_stats stats;
+	struct ieee80211_stats ieee_stats;
+
+	/* Probe / Beacon management */
+	struct list_head network_free_list;
+	struct list_head network_list;
+	struct ieee80211_network *networks;
+	int scans;
+	int scan_age;
+
+	int iw_mode; /* operating mode (IW_MODE_*) */
+
+	spinlock_t lock;
+
+	int tx_headroom; /* Set to size of any additional room needed at front
+			  * of allocated Tx SKBs */
+	u32 config;
+
+	/* WEP and other encryption related settings at the device level */
+	int open_wep; /* Set to 1 to allow unencrypted frames */
+
+	int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
+				 * WEP key changes */
+
+	/* If the host performs {en,de}cryption, then set to 1 */
+	int host_encrypt;
+	int host_decrypt;
+	int ieee802_1x; /* is IEEE 802.1X used */
+
+	/* WPA data */
+	int wpa_enabled;
+	int drop_unencrypted;
+	int tkip_countermeasures;
+	int privacy_invoked;
+	size_t wpa_ie_len;
+	u8 *wpa_ie;
+
+	struct list_head crypt_deinit_list;
+	struct ieee80211_crypt_data *crypt[WEP_KEYS];
+	int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+	struct timer_list crypt_deinit_timer;
+
+	int bcrx_sta_key; /* use individual keys to override default keys even
+			   * with RX of broad/multicast frames */
+
+	/* Fragmentation structures */
+	struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN];
+	unsigned int frag_next_idx;
+	u16 fts; /* Fragmentation Threshold */
+
+	/* Association info */
+	u8 bssid[ETH_ALEN];
+
+	enum ieee80211_state state;
+
+	int mode;       /* A, B, G */
+	int modulation; /* CCK, OFDM */
+	int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
+	int abg_ture;   /* ABG flag              */
+
+	/* Callback functions */
+	void (*set_security)(struct net_device *dev,
+			     struct ieee80211_security *sec);
+	int (*hard_start_xmit)(struct ieee80211_txb *txb,
+			       struct net_device *dev);
+	int (*reset_port)(struct net_device *dev);
+
+	/* This must be the last item so that it points to the data
+	 * allocated beyond this structure by alloc_ieee80211 */
+	u8 priv[0];
+};
+
+#define IEEE_A            (1<<0)
+#define IEEE_B            (1<<1)
+#define IEEE_G            (1<<2)
+#define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
+
+extern inline void *ieee80211_priv(struct net_device *dev)
+{
+	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
+}
+
+extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+{
+	/* Single white space is for Linksys APs */
+	if (essid_len == 1 && essid[0] == ' ')
+		return 1;
+
+	/* Otherwise, if the entire essid is 0, we assume it is hidden */
+	while (essid_len) {
+		essid_len--;
+		if (essid[essid_len] != '\0')
+			return 0;
+	}
+
+	return 1;
+}
+
+extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
+{
+	/*
+	 * It is possible for both access points and our device to support
+	 * combinations of modes, so as long as there is one valid combination
+	 * of ap/device supported modes, then return success
+	 *
+	 */
+	if ((mode & IEEE_A) &&
+	    (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
+	    (ieee->freq_band & IEEE80211_52GHZ_BAND))
+		return 1;
+
+	if ((mode & IEEE_G) &&
+	    (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
+	    (ieee->freq_band & IEEE80211_24GHZ_BAND))
+		return 1;
+
+	if ((mode & IEEE_B) &&
+	    (ieee->modulation & IEEE80211_CCK_MODULATION) &&
+	    (ieee->freq_band & IEEE80211_24GHZ_BAND))
+		return 1;
+
+	return 0;
+}
+
+extern inline int ieee80211_get_hdrlen(u16 fc)
+{
+	int hdrlen = 24;
+
+	switch (WLAN_FC_GET_TYPE(fc)) {
+	case IEEE80211_FTYPE_DATA:
+		if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
+			hdrlen = 30; /* Addr4 */
+		break;
+	case IEEE80211_FTYPE_CTL:
+		switch (WLAN_FC_GET_STYPE(fc)) {
+		case IEEE80211_STYPE_CTS:
+		case IEEE80211_STYPE_ACK:
+			hdrlen = 10;
+			break;
+		default:
+			hdrlen = 16;
+			break;
+		}
+		break;
+	}
+
+	return hdrlen;
+}
+
+
+
+/* ieee80211.c */
+extern void free_ieee80211(struct net_device *dev);
+extern struct net_device *alloc_ieee80211(int sizeof_priv);
+
+extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
+
+/* ieee80211_tx.c */
+
+
+extern int ieee80211_xmit(struct sk_buff *skb,
+			  struct net_device *dev);
+extern void ieee80211_txb_free(struct ieee80211_txb *);
+
+
+/* ieee80211_rx.c */
+extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+			struct ieee80211_rx_stats *rx_stats);
+extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
+			     struct ieee80211_hdr *header,
+			     struct ieee80211_rx_stats *stats);
+
+/* iee80211_wx.c */
+extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *key);
+extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *key);
+extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *key);
+
+
+extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
+{
+	ieee->scans++;
+}
+
+extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
+{
+	return ieee->scans;
+}
+
+static inline const char *escape_essid(const char *essid, u8 essid_len) {
+	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+	const char *s = essid;
+	char *d = escaped;
+
+	if (ieee80211_is_empty_essid(essid, essid_len)) {
+		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
+		return escaped;
+	}
+
+	essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
+	while (essid_len--) {
+		if (*s == '\0') {
+			*d++ = '\\';
+			*d++ = '0';
+			s++;
+		} else {
+			*d++ = *s++;
+		}
+	}
+	*d = '\0';
+	return escaped;
+}
+
+#ifndef offset_in_page
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+#endif
+
+#endif /* IEEE80211_H */
include/net/ieee80211_crypt.h +86 -0

86 lines not on this page · raw message

net/Kconfig +2 -0
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/net/Kconfig netdev-2.6-ipw/net/Kconfig
@@ -653,6 +653,8 @@
 
 source "net/bluetooth/Kconfig"
 
+source "net/ieee80211/Kconfig"
+
 source "drivers/net/Kconfig"
 
 endmenu
net/Makefile +1 -0
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/net/Makefile netdev-2.6-ipw/net/Makefile
@@ -42,6 +42,7 @@
 obj-$(CONFIG_ECONET)		+= econet/
 obj-$(CONFIG_VLAN_8021Q)	+= 8021q/
 obj-$(CONFIG_IP_SCTP)		+= sctp/
+obj-$(CONFIG_IEEE80211)		+= ieee80211/
 
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)		+= sysctl_net.o
net/ieee80211/Kconfig +71 -0

71 lines not on this page · raw message

net/ieee80211/Makefile +11 -0
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet netdev-2.6/net/ieee80211/Makefile netdev-2.6-ipw/net/ieee80211/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_IEEE80211) += ieee80211.o 
+obj-$(CONFIG_IEEE80211) += ieee80211_crypt.o
+obj-$(CONFIG_IEEE80211_CRYPT_WEP) += ieee80211_crypt_wep.o
+obj-$(CONFIG_IEEE80211_CRYPT_CCMP) += ieee80211_crypt_ccmp.o
+obj-$(CONFIG_IEEE80211_CRYPT_TKIP) += ieee80211_crypt_tkip.o
+ieee80211-objs := \
+	ieee80211_module.o \
+	ieee80211_tx.o \
+	ieee80211_rx.o \
+	ieee80211_wx.o
+
net/ieee80211/ieee80211_crypt.c +253 -0

253 lines not on this page · raw message

net/ieee80211/ieee80211_crypt_ccmp.c +473 -0

473 lines not on this page · raw message

net/ieee80211/ieee80211_crypt_tkip.c +711 -0

711 lines not on this page · raw message

net/ieee80211/ieee80211_crypt_wep.c +275 -0

275 lines not on this page · raw message

net/ieee80211/ieee80211_module.c +268 -0

222 lines not on this page · raw message

net/ieee80211/ieee80211_rx.c +1206 -0

1,206 lines not on this page · raw message

net/ieee80211/ieee80211_tx.c +448 -0

448 lines not on this page · raw message

net/ieee80211/ieee80211_wx.c +471 -0

471 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

-------

Quoted 1 line

From Randy Dunlap:

3. +static int __init ieee80211_crypto_init(void)
+ (void) ieee80211_register_crypto_ops(&ieee80211_crypt_null);

That register call can fail, so I'd rather see it checked, as in all of the other similar register calls.

6. +struct ieee80211_ccmp_data {

+    u32 dot11RSNAStatsCCMPFormatErrors;
+    u32 dot11RSNAStatsCCMPReplays;
+    u32 dot11RSNAStatsCCMPDecryptErrors;

Are these MIB-mandated names? otherwise the studlyCaps should go.

7. +static int ieee80211_ccmp_decrypt()

Does anything care about the various negative/error case return values?

8. What calls the .print_stats functions?
static char * ieee80211_ccmp_print_stats()

Is it possible to use seq_file there instead of sprintf(), or is this in /sysfs (so seq_file is not possible)? Are there any overflow possibilities?

Enough for tonight...
Here are a few more comments.

1. No need to check ptr for NULL before kfree(ptr), so several places like this can be simplified:

+fail:
+ if (priv) {
+ if (priv->tfm)
+ crypto_free_tfm(priv->tfm);
+ kfree(priv);
+ }

3. +static inline int ieee80211_network_init()
is more than 200 lines. Somebody likes huge inline functions.

-------------------------

Quoted 1 line

From Stephen Hemminger

1. You can get rid of the /proc interface altogether since now with sysfs module parameters can be made accessible via module_param

2. Include files need to be moved and factored better:
include/linux/ieee80211.h for anything exposed to utilities and
general API related
include/net/ieee80211.h for interfaces other drivers would use. drivers/net/wireless/iee80211/iee80211_xxx.h for stuff that
only gets used internally.

4. Don't put data in .h files like eap_types[]
Maybe just move eap_get_type() to .c fle

5. Use C99 initializers for tags arrays like eap_types[]

 i.e static const char *eap_types[] = {
	[EAP_PACKET] = "EAP-Packet",

...

5. Move is_broadcast_addr and is_multicast_addr to etherdevice.h besides is_muliticast_addr(x) has extra uneeded test.

6. Don't put format type stuff in .h file MAC_FMT, MAC_ARG, etc...

8. Patch if_ether.h rather than stuff like:
#ifndef ETH_P_80211_RAW

 	#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
	#endif

9. Isn't SNAP generic and not part of just wireless, LLC and other places like ATM have the similar stuff, maybe one set of routines and definitions?

10. Do we really need another set of statistics? Already have ethtool, net_stats, wireless, ...?

11. Does ieee->scans need to be atomic?

12. offset_in_page() shouldn't be here and is defined elsewhere.

The basic philosophy changes as this gets incorporated in mailine kernel. You need to feel free to patch in several existing header files rather than standing alone as required in an out of tree driver.

----

Quoted 10 lines

From Jouni Malinen

When you look through the patch you'll likely notice the #ifdef

Quoted 7 lines

NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

We will need to take care of these areas in order to be able to call this "generic IEEE 802.11 networking stack".. I would like to be able to test replacing the upper level code in Host AP driver with this and verify that all functionality is still available. Another useful test case would be to go through what needs to be done to make this work with the madwifi driver (i.e., merge some parts of net80211 code with this and make the low-level parts of the driver use the combination for IEEE 802.11 processing).

Quoted 5 lines

+static void * ieee80211_ccmp_init(int key_idx)

Review

Quoted 4 lines
(quoted diff) +4 -0

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

You do not seem to include try_module_get(THIS_MODULE) here (and matching module_put in deinit) like the version in Host AP driver is using. What is protecting the CCMP/TKIP modules from being unloaded when they are still used?

Part of the diff is not shown here. View the raw message.

#15 lore raw
In reply to James Ketrenos
Quoted 12 lines · James Ketrenos

Attached is the patch against 2.6.11-rc3-mm1 that adds the ieee80211 subsystem used by the ipw2100 and ipw2200 projects.

I'll be sending out the patches for ipw2100-1.0.0 and ipw2200-1.0.0 that use thist stack to the list on Monday.

In terms of what the stack currently does:

* HW independent -- it only knows about 802.11 data and structures
* Performs an 802.3 <-> 802.11 transform for data Tx/Rx
* Host based support for fragmentation, WEP, and WPA using the kernel's crypto functions
* Beacon and probe response collection and parsing
* Default implementation of some of the WE handlers that can be managed without hardware knowledge

Quoted 8 lines

We are working to merge in Dave Miller's p80211 code into the ieee80211 subsystem so that it hooks into the kernel as a true network layer as opposed to a mutated offspring of ethernet.
Once that is done, hopefully the skb to txb code can be reworked and 802.11 fragments can be treated either as normal skbs, or skbs can be modified to directly support them (ideally so that encrypted 802.11 frames in support of IP packets can be cached by the stack instead of having to be re-encrypted on TCP retries)

Support for HW/FW crypto and fragmentation offload, in a HW independent fashion, is also on the short-term list.

When you look through the patch you'll likely notice the #ifdef NOTYET/#endif sequences surrounding portions of code from the hostap project. Portions of this subsystem were based on an earlier version of the hostap project. Those areas that weren't directly supported by the ipw* projects weren't ported to be completely hardware independent (since I don't have the hardware to test it), and so are still wrapped in the ifdefs. These sections mainly cover support for MASTER and WDS modes.

Anyway, please let me know what you think. Hopefully I built the patch right...

Here are a few more comments.

1. No need to check ptr for NULL before kfree(ptr), so several places like this can be simplified:

+fail:
+ if (priv) {
+ if (priv->tfm)
+ crypto_free_tfm(priv->tfm);
+ kfree(priv);
+ }

2. drivers/net/wireless/ieee80211/ieee80211_rx.c
includes: +#include "ieee80211.h"
Should that be ../ieee80211.h (which I dislike), or should the Makefile specify -I to the parent directory, or what? IOW, I don't see how it finds the header file, but the "able to build request" will fix this one.

3. +static inline int ieee80211_network_init()
is more than 200 lines. Somebody likes huge inline functions.

(wow, 1/2 thru a 4900 line patch :)

Signature · 1 line
~Randy
#16 lore raw

A couple of observations:

1. You can get rid of the /proc interface altogether since now with sysfs module parameters can be made accessible via module_param

2. Include files need to be moved and factored better:
include/linux/ieee80211.h for anything exposed to utilities and
general API related
include/net/ieee80211.h for interfaces other drivers would use. drivers/net/wireless/iee80211/iee80211_xxx.h for stuff that
only gets used internally.

3. Remove the BIT() macro and instead show the shift. My preference would be to change to something like:

enum ieee80211_rate {
	IEEE80211_CCK_RATE_1MB_MASK	= 1<<0,
	IEEE80211_CCK_RATE_2MB_MASK	= 1<<1,

...

4. Don't put data in .h files like eap_types[]
Maybe just move eap_get_type() to .c fle

5. Use C99 initializers for tags arrays like eap_types[]

 i.e static const char *eap_types[] = {
	[EAP_PACKET] = "EAP-Packet",

...

5. Move is_broadcast_addr and is_multicast_addr to etherdevice.h besides is_muliticast_addr(x) has extra uneeded test.

6. Don't put format type stuff in .h file MAC_FMT, MAC_ARG, etc...

7. Don't need () around simple integers in #define's

	#define IEEE80211_3ADDR_LEN (24)

8. Patch if_ether.h rather than stuff like:
#ifndef ETH_P_80211_RAW

 	#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
	#endif

9. Isn't SNAP generic and not part of just wireless, LLC and other places like ATM have the similar stuff, maybe one set of routines and definitions?

10. Do we really need another set of statistics? Already have ethtool, net_stats, wireless, ...?

11. Does ieee->scans need to be atomic?

12. offset_in_page() shouldn't be here and is defined elsewhere.

The basic philosophy changes as this gets incorporated in mailine kernel. You need to feel free to patch in several existing header files rather than standing alone as required in an out of tree driver.