[Click] [PATCH v2] Update radiotap parser

Roberto Riggio roberto.riggio at create-net.org
Thu Jul 14 12:38:19 EDT 2011


Hi,

this is a revised version of a previously submitted path.

Changes wrt the previous version:

* radiotap.o is now an ELEMENT_PROVIDES type, The radiotap{enca,decap} 
elements now depends on "radiotap"

This patch updates the click radiotap parser used by click. The code is 
taken directly from the upstream project and allows to parse radiotap 
header with extended bitmap presence field and with vendor extension.

The main advantage is that now the multi rate retry chain is supported
by both radiotap{encap, decap} elements (whose updates are included in 
this patch), so setting the rate{1,2,3} fields in the click_wifi_extra 
struct results in a properly formed radiotap header.

Signed-off-by: Roberto Riggio <roberto.riggio at create-net.org>

-- 

diff -urN click.old//elements/wifi/radiotap.c 
click//elements/wifi/radiotap.c
--- click.old//elements/wifi/radiotap.c	1970-01-01 01:00:00.000000000 +0100
+++ click//elements/wifi/radiotap.c	2011-07-14 17:54:14.727951938 +0200
@@ -0,0 +1,386 @@
+/*
+ * Radiotap parser
+ *
+ * Copyright 2007		Andy Green <andy at warmcat.com>
+ * Copyright 2009		Johannes Berg <johannes at sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See COPYING for more details.
+ */
+#include <click/config.h>
+#include <click/radiotap_iter.h>
+#include <click/platform.h>
+
+/* function prototypes and related defs are in radiotap_iter.h */
+
+static const struct radiotap_align_size rtap_namespace_sizes[] = {
+	[IEEE80211_RADIOTAP_TSFT] = { .align = 8, .size = 8, },
+	[IEEE80211_RADIOTAP_FLAGS] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_RATE] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_CHANNEL] = { .align = 2, .size = 4, },
+	[IEEE80211_RADIOTAP_FHSS] = { .align = 2, .size = 2, },
+	[IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_DBM_ANTNOISE] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_LOCK_QUALITY] = { .align = 2, .size = 2, },
+	[IEEE80211_RADIOTAP_TX_ATTENUATION] = { .align = 2, .size = 2, },
+	[IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = { .align = 2, .size = 2, },
+	[IEEE80211_RADIOTAP_DBM_TX_POWER] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_ANTENNA] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_DB_ANTSIGNAL] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_DB_ANTNOISE] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_RX_FLAGS] = { .align = 2, .size = 2, },
+	[IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, },
+	[IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
+	[IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, },
+	/*
+	 * add more here as they are defined in radiotap.h
+	 */
+};
+
+static const struct ieee80211_radiotap_namespace radiotap_ns = {
+	.n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]),
+	.align_size = rtap_namespace_sizes,
+};
+
+/**
+ * ieee80211_radiotap_iterator_init - radiotap parser iterator 
initialization
+ * @iterator: radiotap_iterator to initialize
+ * @radiotap_header: radiotap header to parse
+ * @max_length: total length we can parse into (eg, whole packet length)
+ *
+ * Returns: 0 or a negative error code if there is a problem.
+ *
+ * This function initializes an opaque iterator struct which can then
+ * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
+ * argument which is present in the header.  It knows about extended
+ * present headers and handles them.
+ *
+ * How to use:
+ * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
+ * struct ieee80211_radiotap_iterator (no need to init the struct 
beforehand)
+ * checking for a good 0 return code.  Then loop calling
+ * __ieee80211_radiotap_iterator_next()... it returns either 0,
+ * -ENOENT if there are no more args to parse, or -EINVAL if there is a 
problem.
+ * The iterator's @this_arg member points to the start of the argument
+ * associated with the current argument index that is present, which can be
+ * found in the iterator's @this_arg_index member.  This arg index 
corresponds
+ * to the IEEE80211_RADIOTAP_... defines.
+ *
+ * Radiotap header length:
+ * You can find the CPU-endian total radiotap header length in
+ * iterator->max_length after executing ieee80211_radiotap_iterator_init()
+ * successfully.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned.  Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ *
+ * Example code: parse.c
+ */
+
+int ieee80211_radiotap_iterator_init(
+	struct ieee80211_radiotap_iterator *iterator,
+	struct ieee80211_radiotap_header *radiotap_header,
+	int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
+{
+	/* Linux only supports version 0 radiotap format */
+	if (radiotap_header->it_version)
+		return -EINVAL;
+
+	/* sanity check for allowed length and radiotap length field */
+	if (max_length < get_unaligned_le16(&radiotap_header->it_len))
+		return -EINVAL;
+
+	iterator->_rtheader = radiotap_header;
+	iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
+	iterator->_arg_index = 0;
+	iterator->_bitmap_shifter = 
get_unaligned_le32(&radiotap_header->it_present);
+	iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header);
+	iterator->_reset_on_ext = 0;
+	iterator->_next_bitmap = &radiotap_header->it_present;
+	iterator->_next_bitmap++;
+	iterator->_vns = vns;
+	iterator->current_namespace = &radiotap_ns;
+	iterator->is_radiotap_ns = 1;
+#ifdef RADIOTAP_SUPPORT_OVERRIDES
+	iterator->n_overrides = 0;
+	iterator->overrides = NULL;
+#endif
+
+	/* find payload start allowing for extended bitmap(s) */
+
+	if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+		while (get_unaligned_le32(iterator->_arg) &
+					(1 << IEEE80211_RADIOTAP_EXT)) {
+			iterator->_arg += sizeof(uint32_t);
+
+			/*
+			 * check for insanity where the present bitmaps
+			 * keep claiming to extend up to or even beyond the
+			 * stated radiotap header length
+			 */
+
+			if ((unsigned long)iterator->_arg -
+			    (unsigned long)iterator->_rtheader >
+			    (unsigned long)iterator->_max_length)
+				return -EINVAL;
+		}
+
+		iterator->_arg += sizeof(uint32_t);
+
+		/*
+		 * no need to check again for blowing past stated radiotap
+		 * header length, because ieee80211_radiotap_iterator_next
+		 * checks it before it is dereferenced
+		 */
+	}
+
+	iterator->this_arg = iterator->_arg;
+
+	/* we are all initialized happily */
+
+	return 0;
+}
+
+static void find_ns(struct ieee80211_radiotap_iterator *iterator,
+		    uint32_t oui, uint8_t subns)
+{
+	int i;
+
+	iterator->current_namespace = NULL;
+
+	if (!iterator->_vns)
+		return;
+
+	for (i = 0; i < iterator->_vns->n_ns; i++) {
+		if (iterator->_vns->ns[i].oui != oui)
+			continue;
+		if (iterator->_vns->ns[i].subns != subns)
+			continue;
+
+		iterator->current_namespace = &iterator->_vns->ns[i];
+		break;
+	}
+}
+
+#ifdef RADIOTAP_SUPPORT_OVERRIDES
+static int find_override(struct ieee80211_radiotap_iterator *iterator,
+			 int *align, int *size)
+{
+	int i;
+
+	if (!iterator->overrides)
+		return 0;
+
+	for (i = 0; i < iterator->n_overrides; i++) {
+		if (iterator->_arg_index == iterator->overrides[i].field) {
+			*align = iterator->overrides[i].align;
+			*size = iterator->overrides[i].size;
+			if (!*align) /* erroneous override */
+				return 0;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+
+/**
+ * ieee80211_radiotap_iterator_next - return next radiotap parser 
iterator arg
+ * @iterator: radiotap_iterator to move to next arg (if any)
+ *
+ * Returns: 0 if there is an argument to handle,
+ * -ENOENT if there are no more args or -EINVAL
+ * if there is something else wrong.
+ *
+ * This function provides the next radiotap arg index 
(IEEE80211_RADIOTAP_*)
+ * in @this_arg_index and sets @this_arg to point to the
+ * payload for the field.  It takes care of alignment handling and extended
+ * present fields.  @this_arg can be changed by the caller (eg,
+ * incremented to move inside a compound argument like
+ * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
+ * little-endian format whatever the endianess of your CPU.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned.  Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ */
+
+int ieee80211_radiotap_iterator_next(
+	struct ieee80211_radiotap_iterator *iterator)
+{
+	while (1) {
+		int hit = 0;
+		int pad, align, size, subns;
+		uint32_t oui;
+
+		/* if no more EXT bits, that's it */
+		if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT &&
+		    !(iterator->_bitmap_shifter & 1))
+			return -ENOENT;
+
+		if (!(iterator->_bitmap_shifter & 1))
+			goto next_entry; /* arg not present */
+
+		/* get alignment/size of data */
+		switch (iterator->_arg_index % 32) {
+		case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
+		case IEEE80211_RADIOTAP_EXT:
+			align = 1;
+			size = 0;
+			break;
+		case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
+			align = 2;
+			size = 6;
+			break;
+		default:
+#ifdef RADIOTAP_SUPPORT_OVERRIDES
+			if (find_override(iterator, &align, &size)) {
+				/* all set */
+			} else
+#endif
+			if (!iterator->current_namespace ||
+			    iterator->_arg_index >= iterator->current_namespace->n_bits) {
+				if (iterator->current_namespace == &radiotap_ns)
+					return -ENOENT;
+				align = 0;
+			} else {
+				align = 
iterator->current_namespace->align_size[iterator->_arg_index].align;
+				size = 
iterator->current_namespace->align_size[iterator->_arg_index].size;
+			}
+			if (!align) {
+				/* skip all subsequent data */
+				iterator->_arg = iterator->_next_ns_data;
+				/* give up on this namespace */
+				iterator->current_namespace = NULL;
+				goto next_entry;
+			}
+			break;
+		}
+
+		/*
+		 * arg is present, account for alignment padding
+		 *
+		 * Note that these alignments are relative to the start
+		 * of the radiotap header.  There is no guarantee
+		 * that the radiotap header itself is aligned on any
+		 * kind of boundary.
+		 *
+		 * The above is why get_unaligned() is used to dereference
+		 * multibyte elements from the radiotap area.
+		 */
+
+		pad = ((unsigned long)iterator->_arg -
+		       (unsigned long)iterator->_rtheader) & (align - 1);
+
+		if (pad)
+			iterator->_arg += align - pad;
+
+		if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
+			int vnslen;
+
+			if ((unsigned long)iterator->_arg + size -
+			    (unsigned long)iterator->_rtheader >
+			    (unsigned long)iterator->_max_length)
+				return -EINVAL;
+
+			oui = (*iterator->_arg << 16) |
+				(*(iterator->_arg + 1) << 8) |
+				*(iterator->_arg + 2);
+			subns = *(iterator->_arg + 3);
+
+			find_ns(iterator, oui, subns);
+
+			vnslen = get_unaligned_le16(iterator->_arg + 4);
+			iterator->_next_ns_data = iterator->_arg + size + vnslen;
+			if (!iterator->current_namespace)
+				size += vnslen;
+		}
+
+		/*
+		 * this is what we will return to user, but we need to
+		 * move on first so next call has something fresh to test
+		 */
+		iterator->this_arg_index = iterator->_arg_index;
+		iterator->this_arg = iterator->_arg;
+		iterator->this_arg_size = size;
+
+		/* internally move on the size of this arg */
+		iterator->_arg += size;
+
+		/*
+		 * check for insanity where we are given a bitmap that
+		 * claims to have more arg content than the length of the
+		 * radiotap section.  We will normally end up equalling this
+		 * max_length on the last arg, never exceeding it.
+		 */
+
+		if ((unsigned long)iterator->_arg -
+		    (unsigned long)iterator->_rtheader >
+		    (unsigned long)iterator->_max_length)
+			return -EINVAL;
+
+		/* these special ones are valid in each bitmap word */
+		switch (iterator->_arg_index % 32) {
+		case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
+			iterator->_reset_on_ext = 1;
+
+			iterator->is_radiotap_ns = 0;
+			/*
+			 * If parser didn't register this vendor
+			 * namespace with us, allow it to show it
+			 * as 'raw. Do do that, set argument index
+			 * to vendor namespace.
+			 */
+			iterator->this_arg_index =
+				IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
+			if (!iterator->current_namespace)
+				hit = 1;
+			goto next_entry;
+		case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
+			iterator->_reset_on_ext = 1;
+			iterator->current_namespace = &radiotap_ns;
+			iterator->is_radiotap_ns = 1;
+			goto next_entry;
+		case IEEE80211_RADIOTAP_EXT:
+			/*
+			 * bit 31 was set, there is more
+			 * -- move to next u32 bitmap
+			 */
+			iterator->_bitmap_shifter =
+				get_unaligned_le32(iterator->_next_bitmap);
+			iterator->_next_bitmap++;
+			if (iterator->_reset_on_ext)
+				iterator->_arg_index = 0;
+			else
+				iterator->_arg_index++;
+			iterator->_reset_on_ext = 0;
+			break;
+		default:
+			/* we've got a hit! */
+			hit = 1;
+ next_entry:
+			iterator->_bitmap_shifter >>= 1;
+			iterator->_arg_index++;
+		}
+
+		/* if we found a valid arg earlier, return it now */
+		if (hit)
+			return 0;
+	}
+}
+
+ELEMENT_PROVIDES(radiotap)
diff -urN click.old//elements/wifi/radiotapdecap.cc 
click//elements/wifi/radiotapdecap.cc
--- click.old//elements/wifi/radiotapdecap.cc	2011-07-14 
17:57:39.459187566 +0200
+++ click//elements/wifi/radiotapdecap.cc	2011-07-14 17:55:10.468832791 
+0200
@@ -18,83 +18,16 @@
  #include <click/config.h>
  #include "radiotapdecap.hh"
  #include <click/etheraddress.hh>
-#include <click/args.hh>
  #include <click/error.hh>
  #include <click/glue.hh>
+#include <click/packet_anno.hh>
  #include <clicknet/wifi.h>
  #include <clicknet/radiotap.h>
-#include <click/packet_anno.hh>
  #include <clicknet/llc.h>
-CLICK_DECLS
-
-#define NUM_RADIOTAP_ELEMENTS 18
-
-static const int radiotap_elem_to_bytes[NUM_RADIOTAP_ELEMENTS] =
-	{8, /* IEEE80211_RADIOTAP_TSFT */
-	 1, /* IEEE80211_RADIOTAP_FLAGS */
-	 1, /* IEEE80211_RADIOTAP_RATE */
-	 4, /* IEEE80211_RADIOTAP_CHANNEL */
-	 2, /* IEEE80211_RADIOTAP_FHSS */
-	 1, /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
-	 1, /* IEEE80211_RADIOTAP_DBM_ANTNOISE */
-	 2, /* IEEE80211_RADIOTAP_LOCK_QUALITY */
-	 2, /* IEEE80211_RADIOTAP_TX_ATTENUATION */
-	 2, /* IEEE80211_RADIOTAP_DB_TX_ATTENUATION */
-	 1, /* IEEE80211_RADIOTAP_DBM_TX_POWER */
-	 1, /* IEEE80211_RADIOTAP_ANTENNA */
-	 1, /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */
-	 1, /* IEEE80211_RADIOTAP_DB_ANTNOISE */
-	 2, /* IEEE80211_RADIOTAP_RX_FLAGS */
-	 2, /* IEEE80211_RADIOTAP_TX_FLAGS */
-	 1, /* IEEE80211_RADIOTAP_RTS_RETRIES */
-	 1, /* IEEE80211_RADIOTAP_DATA_RETRIES */
-	};
-
-static int rt_el_present(struct ieee80211_radiotap_header *th, 
u_int32_t element)
-{
-	if (element > NUM_RADIOTAP_ELEMENTS)
-		return 0;
-	return le32_to_cpu(th->it_present) & (1 << element);
-}
-
-static int rt_check_header(struct ieee80211_radiotap_header *th, int len)
-{
-	int bytes = 0;
-	int x = 0;
-	if (th->it_version != 0) {
-		return 0;
-	}
-
-	if (le16_to_cpu(th->it_len) < sizeof(struct ieee80211_radiotap_header)) {
-		return 0;
-	}
-
-	for (x = 0; x < NUM_RADIOTAP_ELEMENTS; x++) {
-		if (rt_el_present(th, x))
-		    bytes += radiotap_elem_to_bytes[x];
-	}
-
-	if (le16_to_cpu(th->it_len) < sizeof(struct ieee80211_radiotap_header) 
+ bytes) {
-		return 0;
-	}
-
-	if (le16_to_cpu(th->it_len) > len) {
-		return 0;
-	}
-
-	return 1;
-}
-
-static u_int8_t *rt_el_offset(struct ieee80211_radiotap_header *th, 
u_int32_t element) {
-	unsigned int x = 0;
-	u_int8_t *offset = ((u_int8_t *) th) + sizeof(ieee80211_radiotap_header);
-	for (x = 0; x < NUM_RADIOTAP_ELEMENTS && x < element; x++) {
-		if (rt_el_present(th, x))
-			offset += radiotap_elem_to_bytes[x];
-	}
-
-	return offset;
+extern "C" {
+	#include <click/radiotap_iter.h>
  }
+CLICK_DECLS

  RadiotapDecap::RadiotapDecap()
  {
@@ -104,109 +37,87 @@
  {
  }

-int
-RadiotapDecap::configure(Vector<String> &conf, ErrorHandler *errh)
-{
-    _debug = false;
-    return Args(conf, this, errh).read("DEBUG", _debug).complete();
-}
-
  Packet *
-RadiotapDecap::simple_action(Packet *p)
-{
+RadiotapDecap::simple_action(Packet *p) {
+
  	struct ieee80211_radiotap_header *th = (struct 
ieee80211_radiotap_header *) p->data();
+	struct ieee80211_radiotap_iterator iter;
  	struct click_wifi_extra *ceh = WIFI_EXTRA_ANNO(p);
-	if (rt_check_header(th, p->length())) {
-		memset((void*)ceh, 0, sizeof(struct click_wifi_extra));
-		ceh->magic = WIFI_EXTRA_MAGIC;

-		if (rt_el_present(th, IEEE80211_RADIOTAP_FLAGS)) {
-			u_int8_t flags = *((u_int8_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_FLAGS));
+	int err = ieee80211_radiotap_iterator_init(&iter, th, p->length(), 0);
+
+	if (err) {
+		click_chatter("%{element} :: %s :: malformed radiotap header (init 
returns %d)", this, __func__, err);
+		goto drop;
+	}
+
+	memset((void*)ceh, 0, sizeof(struct click_wifi_extra));
+	ceh->magic = WIFI_EXTRA_MAGIC;
+
+	while (!(err = ieee80211_radiotap_iterator_next(&iter))) {
+		u_int16_t flags;
+		switch (iter.this_arg_index) {
+		case IEEE80211_RADIOTAP_FLAGS:
+			flags = le16_to_cpu(*(uint16_t *)iter.this_arg);
  			if (flags & IEEE80211_RADIOTAP_F_DATAPAD) {
  				ceh->pad = 1;
  			}
  			if (flags & IEEE80211_RADIOTAP_F_FCS) {
  				p->take(4);
  			}
-		}
-
-		if (rt_el_present(th, IEEE80211_RADIOTAP_RATE)) {
-			ceh->rate = *((u_int8_t *) rt_el_offset(th, IEEE80211_RADIOTAP_RATE));
-		}
-
-		if (rt_el_present(th, IEEE80211_RADIOTAP_DBM_ANTSIGNAL))
-			ceh->rssi = *((u_int8_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_DBM_ANTSIGNAL));
-
-		if (rt_el_present(th, IEEE80211_RADIOTAP_DBM_ANTNOISE))
-			ceh->silence = *((u_int8_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_DBM_ANTNOISE));
-
-		if (rt_el_present(th, IEEE80211_RADIOTAP_DB_ANTSIGNAL))
-			ceh->rssi = *((u_int8_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_DB_ANTSIGNAL));
-
-		if (rt_el_present(th, IEEE80211_RADIOTAP_DB_ANTNOISE))
-			ceh->silence = *((u_int8_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_DB_ANTNOISE));
-
-		if (rt_el_present(th, IEEE80211_RADIOTAP_RX_FLAGS)) {
-			u_int16_t flags = le16_to_cpu(*((u_int16_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_RX_FLAGS)));
-			if (flags & IEEE80211_RADIOTAP_F_RX_BADFCS)
+			break;
+		case IEEE80211_RADIOTAP_RATE:
+			ceh->rate = *iter.this_arg;
+			break;
+		case IEEE80211_RADIOTAP_DATA_RETRIES:
+			ceh->retries = *iter.this_arg;
+			break;
+		case IEEE80211_RADIOTAP_CHANNEL:
+			ceh->channel = le16_to_cpu(*(uint16_t *)iter.this_arg);
+			break;
+		case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+			ceh->rssi = *iter.this_arg;
+			break;
+		case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+			ceh->silence = *iter.this_arg;
+			break;
+		case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+			ceh->rssi = *iter.this_arg;
+			break;
+		case IEEE80211_RADIOTAP_DB_ANTNOISE:
+			ceh->silence = *iter.this_arg;
+			break;
+		case IEEE80211_RADIOTAP_RX_FLAGS:
+			flags = le16_to_cpu(*(uint16_t *)iter.this_arg);
+			if (flags & IEEE80211_RADIOTAP_F_BADFCS)
  				ceh->flags |= WIFI_EXTRA_RX_ERR;
-		}
-
-		if (rt_el_present(th, IEEE80211_RADIOTAP_TX_FLAGS)) {
-			u_int16_t flags = le16_to_cpu(*((u_int16_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_TX_FLAGS)));
+			break;
+		case IEEE80211_RADIOTAP_TX_FLAGS:
+			flags = le16_to_cpu(*(uint16_t *)iter.this_arg);
  			ceh->flags |= WIFI_EXTRA_TX;
  			if (flags & IEEE80211_RADIOTAP_F_TX_FAIL)
  				ceh->flags |= WIFI_EXTRA_TX_FAIL;
+			break;
  		}
+	}

-		if (rt_el_present(th, IEEE80211_RADIOTAP_DATA_RETRIES))
-			ceh->retries = *((u_int8_t *) rt_el_offset(th, 
IEEE80211_RADIOTAP_DATA_RETRIES));
-
-		p->pull(le16_to_cpu(th->it_len));
-		p->set_mac_header(p->data());  // reset mac-header pointer
+	if (err != -ENOENT) {
+		click_chatter("%{element} :: %s :: malformed radiotap data", this, 
__func__);
+		goto drop;
  	}

-  return p;
-}
+	p->pull(le16_to_cpu(th->it_len));
+	p->set_mac_header(p->data()); // reset mac-header pointer

+	return p;

-enum {H_DEBUG};
+  drop:

-static String
-RadiotapDecap_read_param(Element *e, void *thunk)
-{
-  RadiotapDecap *td = (RadiotapDecap *)e;
-    switch ((uintptr_t) thunk) {
-      case H_DEBUG:
-	return String(td->_debug) + "\n";
-    default:
-      return String();
-    }
-}
-static int
-RadiotapDecap_write_param(const String &in_s, Element *e, void *vparam,
-		      ErrorHandler *errh)
-{
-  RadiotapDecap *f = (RadiotapDecap *)e;
-  String s = cp_uncomment(in_s);
-  switch((intptr_t)vparam) {
-  case H_DEBUG: {    //debug
-    bool debug;
-    if (!BoolArg().parse(s, debug))
-      return errh->error("debug parameter must be boolean");
-    f->_debug = debug;
-    break;
-  }
-  }
-  return 0;
-}
+	p->kill();
+	return 0;

-void
-RadiotapDecap::add_handlers()
-{
-  add_read_handler("debug", RadiotapDecap_read_param, (void *) H_DEBUG);
-
-  add_write_handler("debug", RadiotapDecap_write_param, (void *) H_DEBUG);
  }
+
  CLICK_ENDDECLS
  EXPORT_ELEMENT(RadiotapDecap)
+ELEMENT_REQUIRES(radiotap)
diff -urN click.old//elements/wifi/radiotapdecap.hh 
click//elements/wifi/radiotapdecap.hh
--- click.old//elements/wifi/radiotapdecap.hh	2011-07-14 
17:57:39.459187566 +0200
+++ click//elements/wifi/radiotapdecap.hh	2011-07-09 23:32:01.082634786 
+0200
@@ -28,18 +28,10 @@
    const char *port_count() const	{ return PORTS_1_1; }
    const char *processing() const	{ return AGNOSTIC; }

-  int configure(Vector<String> &, ErrorHandler *);
    bool can_live_reconfigure() const	{ return true; }

    Packet *simple_action(Packet *);

-
-  void add_handlers();
-
-
-  bool _debug;
- private:
-
  };

  CLICK_ENDDECLS
diff -urN click.old//elements/wifi/radiotapencap.cc 
click//elements/wifi/radiotapencap.cc
--- click.old//elements/wifi/radiotapencap.cc	2011-07-14 
17:57:39.459187566 +0200
+++ click//elements/wifi/radiotapencap.cc	2011-07-14 17:55:09.720820969 
+0200
@@ -18,7 +18,6 @@
  #include <click/config.h>
  #include "radiotapencap.hh"
  #include <click/etheraddress.hh>
-#include <click/args.hh>
  #include <click/error.hh>
  #include <click/glue.hh>
  #include <clicknet/wifi.h>
@@ -27,116 +26,115 @@
  #include <clicknet/radiotap.h>
  CLICK_DECLS

-
-
-#define CLICK_RADIOTAP_PRESENT (		\
-	(1 << IEEE80211_RADIOTAP_RATE)		| \
-	(1 << IEEE80211_RADIOTAP_DBM_TX_POWER)	| \
-	(1 << IEEE80211_RADIOTAP_RTS_RETRIES)	| \
-	(1 << IEEE80211_RADIOTAP_DATA_RETRIES)	| \
+#define CLICK_RADIOTAP_PRESENT (			\
+	(1 << IEEE80211_RADIOTAP_RATE)			| \
+	(1 << IEEE80211_RADIOTAP_DBM_TX_POWER)		| \
+	(1 << IEEE80211_RADIOTAP_RTS_RETRIES)		| \
+	(1 << IEEE80211_RADIOTAP_DATA_RETRIES)		| \
+	(1 << IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE)	| \
+	(1 << IEEE80211_RADIOTAP_EXT)			| \
  	0)

  struct click_radiotap_header {
  	struct ieee80211_radiotap_header wt_ihdr;
+	u_int32_t	it_present1;
+	u_int32_t	it_present2;
+	u_int32_t	it_present3;
  	u_int8_t	wt_rate;
  	u_int8_t	wt_txpower;
-	u_int8_t        wt_rts_retries;
-	u_int8_t        wt_data_retries;
-};
-
-
-
-
-
+	u_int8_t	wt_rts_retries;
+	u_int8_t	wt_data_retries;
+	u_int8_t	wt_rate1;
+	u_int8_t	wt_data_retries1;
+	u_int8_t	wt_rate2;
+	u_int8_t	wt_data_retries2;
+	u_int8_t	wt_rate3;
+	u_int8_t	wt_data_retries3;
+} __attribute__((__packed__));

-RadiotapEncap::RadiotapEncap()
-{
+RadiotapEncap::RadiotapEncap() {
  }

-RadiotapEncap::~RadiotapEncap()
-{
-}
-
-int
-RadiotapEncap::configure(Vector<String> &conf, ErrorHandler *errh)
-{
-    _debug = false;
-    return Args(conf, this, errh).read("DEBUG", _debug).complete();
+RadiotapEncap::~RadiotapEncap() {
  }

  Packet *
-RadiotapEncap::simple_action(Packet *p)
-{
+RadiotapEncap::simple_action(Packet *p) {

-  WritablePacket *p_out = p->uniqueify();
-  if (!p_out) {
-    p->kill();
-    return 0;
-  }
-
-  p_out = p_out->push(sizeof(struct click_radiotap_header));
-
-  if (p_out) {
-	  struct click_radiotap_header *crh  = (struct click_radiotap_header 
*) p_out->data();
-	  click_wifi_extra *ceh = WIFI_EXTRA_ANNO(p);
-
-	  memset(crh, 0, sizeof(struct click_radiotap_header));
-
-	  crh->wt_ihdr.it_version = 0;
-	  crh->wt_ihdr.it_len = cpu_to_le16(sizeof(struct click_radiotap_header));
-	  crh->wt_ihdr.it_present = cpu_to_le32(CLICK_RADIOTAP_PRESENT);
-
-	  crh->wt_rate = ceh->rate;
-	  crh->wt_txpower = ceh->power;
-	  crh->wt_rts_retries = 0;
-	  if (ceh->max_tries > 0) {
-		  crh->wt_data_retries = ceh->max_tries - 1;
-	  } else {
-		  crh->wt_data_retries = WIFI_MAX_RETRIES + 1;
-	  }
-  }
-
-  return p_out;
-}
+	WritablePacket *p_out = p->uniqueify();
+	click_wifi_extra *ceh = WIFI_EXTRA_ANNO(p);

+	if (!p_out) {
+		p->kill();
+		return 0;
+	}
+
+	p_out = p_out->push(sizeof(struct click_radiotap_header));
+
+	if (!p_out) {
+		p->kill();
+		return 0;
+	}
+
+	struct click_radiotap_header *crh  = (struct click_radiotap_header *) 
p_out->data();
+
+	memset(crh, 0, sizeof(struct click_radiotap_header));
+
+	crh->wt_ihdr.it_version = 0;
+	crh->wt_ihdr.it_len = cpu_to_le16(sizeof(struct click_radiotap_header));
+
+	crh->wt_ihdr.it_present = cpu_to_le32(CLICK_RADIOTAP_PRESENT);
+
+	crh->wt_rate = ceh->rate;
+	crh->wt_txpower = ceh->power;
+	crh->wt_rts_retries = 0;
+
+	if (ceh->max_tries > 0) {
+		crh->wt_data_retries = ceh->max_tries;
+	} else {
+		crh->wt_data_retries = WIFI_MAX_RETRIES + 1;
+	}
+
+	crh->it_present1 |= cpu_to_le32(1 << 
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE);
+	crh->it_present1 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_EXT);
+	crh->it_present2 |= cpu_to_le32(1 << 
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE);
+	crh->it_present2 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_EXT);
+
+	if (ceh->rate1 != 0) {
+		crh->it_present1 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+		crh->it_present1 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_DATA_RETRIES);
+		crh->wt_rate1 = ceh->rate1;
+		if (ceh->max_tries1 > 0) {
+			crh->wt_data_retries1 = ceh->max_tries1;
+		} else {
+			crh->wt_data_retries1 = WIFI_MAX_RETRIES + 1;
+		}
+		if (ceh->rate2 != 0) {
+			crh->it_present2 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+			crh->it_present2 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_DATA_RETRIES);
+			crh->wt_rate2 = ceh->rate2;
+			if (ceh->max_tries2 > 0) {
+				crh->wt_data_retries2 = ceh->max_tries2;
+			} else {
+				crh->wt_data_retries2 = WIFI_MAX_RETRIES + 1;
+			}
+			if (ceh->rate3 != 0) {
+				crh->it_present3 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+				crh->it_present3 |= cpu_to_le32(1 << IEEE80211_RADIOTAP_DATA_RETRIES);
+				crh->wt_rate3 = ceh->rate3;
+				if (ceh->max_tries3 > 0) {
+					crh->wt_data_retries3 = ceh->max_tries3;
+				} else {
+					crh->wt_data_retries3 = WIFI_MAX_RETRIES + 1;
+				}
+			}
+		}
+	}

-enum {H_DEBUG};
+	return p_out;

-static String
-RadiotapEncap_read_param(Element *e, void *thunk)
-{
-  RadiotapEncap *td = (RadiotapEncap *)e;
-    switch ((uintptr_t) thunk) {
-      case H_DEBUG:
-	return String(td->_debug) + "\n";
-    default:
-      return String();
-    }
  }
-static int
-RadiotapEncap_write_param(const String &in_s, Element *e, void *vparam,
-		      ErrorHandler *errh)
-{
-  RadiotapEncap *f = (RadiotapEncap *)e;
-  String s = cp_uncomment(in_s);
-  switch((intptr_t)vparam) {
-  case H_DEBUG: {    //debug
-    bool debug;
-    if (!BoolArg().parse(s, debug))
-      return errh->error("debug parameter must be boolean");
-    f->_debug = debug;
-    break;
-  }
-  }
-  return 0;
-}
-
-void
-RadiotapEncap::add_handlers()
-{
-  add_read_handler("debug", RadiotapEncap_read_param, (void *) H_DEBUG);

-  add_write_handler("debug", RadiotapEncap_write_param, (void *) H_DEBUG);
-}
  CLICK_ENDDECLS
  EXPORT_ELEMENT(RadiotapEncap)
+ELEMENT_REQUIRES(radiotap)
diff -urN click.old//elements/wifi/radiotapencap.hh 
click//elements/wifi/radiotapencap.hh
--- click.old//elements/wifi/radiotapencap.hh	2011-07-14 
17:57:39.459187566 +0200
+++ click//elements/wifi/radiotapencap.hh	2011-07-09 23:32:01.082634786 
+0200
@@ -29,18 +29,10 @@
    const char *port_count() const	{ return PORTS_1_1; }
    const char *processing() const	{ return AGNOSTIC; }

-  int configure(Vector<String> &, ErrorHandler *);
    bool can_live_reconfigure() const	{ return true; }

    Packet *simple_action(Packet *);

-
-  void add_handlers();
-
-
-  bool _debug;
- private:
-
  };

  CLICK_ENDDECLS
diff -urN click.old//include/click/platform.h 
click//include/click/platform.h
--- click.old//include/click/platform.h	1970-01-01 01:00:00.000000000 +0100
+++ click//include/click/platform.h	2011-07-09 23:32:01.274637902 +0200
@@ -0,0 +1,19 @@
+#include <stddef.h>
+#include <errno.h>
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE
+#endif
+#include <endian.h>
+
+#define le16_to_cpu		le16toh
+#define le32_to_cpu		le32toh
+#define get_unaligned(p)					\
+({								\
+	struct packed_dummy_struct {				\
+		typeof(*(p)) __val;				\
+	} __attribute__((packed)) *__ptr = (void *) (p);	\
+								\
+	__ptr->__val;						\
+})
+#define get_unaligned_le16(p)	le16_to_cpu(get_unaligned((uint16_t *)(p)))
+#define get_unaligned_le32(p)	le32_to_cpu(get_unaligned((uint32_t *)(p)))
diff -urN click.old//include/click/radiotap_iter.h 
click//include/click/radiotap_iter.h
--- click.old//include/click/radiotap_iter.h	1970-01-01 
01:00:00.000000000 +0100
+++ click//include/click/radiotap_iter.h	2011-07-09 23:32:01.274637902 +0200
@@ -0,0 +1,96 @@
+#ifndef CLICK_RADIOTAP_ITER_H
+#define CLICK_RADIOTAP_ITER_H
+
+#include <stdint.h>
+#include <clicknet/radiotap.h>
+
+/* Radiotap header iteration
+ *   implemented in radiotap.c
+ */
+
+struct radiotap_override {
+	uint8_t field;
+	uint8_t align:4, size:4;
+};
+
+struct radiotap_align_size {
+	uint8_t align:4, size:4;
+};
+
+struct ieee80211_radiotap_namespace {
+	const struct radiotap_align_size *align_size;
+	int n_bits;
+	uint32_t oui;
+	uint8_t subns;
+};
+
+struct ieee80211_radiotap_vendor_namespaces {
+	const struct ieee80211_radiotap_namespace *ns;
+	int n_ns;
+};
+
+/**
+ * struct ieee80211_radiotap_iterator - tracks walk thru present 
radiotap args
+ * @this_arg_index: index of current arg, valid after each successful call
+ *	to ieee80211_radiotap_iterator_next()
+ * @this_arg: pointer to current radiotap arg; it is valid after each
+ *	call to ieee80211_radiotap_iterator_next() but also after
+ *	ieee80211_radiotap_iterator_init() where it will point to
+ *	the beginning of the actual data portion
+ * @this_arg_size: length of the current arg, for convenience
+ * @current_namespace: pointer to the current namespace definition
+ *	(or internally %NULL if the current namespace is unknown)
+ * @is_radiotap_ns: indicates whether the current namespace is the default
+ *	radiotap namespace or not
+ *
+ * @overrides: override standard radiotap fields
+ * @n_overrides: number of overrides
+ *
+ * @_rtheader: pointer to the radiotap header we are walking through
+ * @_max_length: length of radiotap header in cpu byte ordering
+ * @_arg_index: next argument index
+ * @_arg: next argument pointer
+ * @_next_bitmap: internal pointer to next present u32
+ * @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == 
arg present
+ * @_vns: vendor namespace definitions
+ * @_next_ns_data: beginning of the next namespace's data
+ * @_reset_on_ext: internal; reset the arg index to 0 when going to the
+ *	next bitmap word
+ *
+ * Describes the radiotap parser state. Fields prefixed with an underscore
+ * must not be used by users of the parser, only by the parser internally.
+ */
+
+struct ieee80211_radiotap_iterator {
+	struct ieee80211_radiotap_header *_rtheader;
+	const struct ieee80211_radiotap_vendor_namespaces *_vns;
+	const struct ieee80211_radiotap_namespace *current_namespace;
+
+	unsigned char *_arg, *_next_ns_data;
+	uint32_t *_next_bitmap;
+
+	unsigned char *this_arg;
+#ifdef RADIOTAP_SUPPORT_OVERRIDES
+	const struct radiotap_override *overrides;
+	int n_overrides;
+#endif
+	int this_arg_index;
+	int this_arg_size;
+
+	int is_radiotap_ns;
+
+	int _max_length;
+	int _arg_index;
+	uint32_t _bitmap_shifter;
+	int _reset_on_ext;
+};
+
+extern int ieee80211_radiotap_iterator_init(
+	struct ieee80211_radiotap_iterator *iterator,
+	struct ieee80211_radiotap_header *radiotap_header,
+	int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns);
+
+extern int ieee80211_radiotap_iterator_next(
+	struct ieee80211_radiotap_iterator *iterator);
+
+#endif /* CLICK_RADIOTAP_ITER_H */
diff -urN click.old//include/clicknet/radiotap.h 
click//include/clicknet/radiotap.h
--- click.old//include/clicknet/radiotap.h	2011-07-14 17:57:39.507188325 
+0200
+++ click//include/clicknet/radiotap.h	2011-07-09 23:32:01.278637966 +0200
@@ -1,6 +1,3 @@
-/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 
20:12:05 sam Exp $ */
-/* $NetBSD: ieee80211_radiotap.h,v 1.10 2005/01/04 00:34:58 dyoung Exp $ */
-
  /*-
   * Copyright (c) 2003, 2004 David Young.  All rights reserved.
   *
@@ -29,8 +26,19 @@
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
   * OF SUCH DAMAGE.
   */
-#ifndef _NET_IF_IEEE80211RADIOTAP_H_
-#define _NET_IF_IEEE80211RADIOTAP_H_
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn at kismetwireless.net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <stdint.h>
+
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION		0

  /* A generic radio capture format is desirable. There is one for
   * Linux, but it is neither rigidly defined (there were not even
@@ -46,135 +54,132 @@
   * function of...") that I cannot set false expectations for lawyerly
   * readers.
   */
-#if defined(__KERNEL__) || defined(_KERNEL)
-#ifndef DLT_IEEE802_11_RADIO
-#define	DLT_IEEE802_11_RADIO	127	/* 802.11 plus WLAN header */
-#endif
-#endif /* defined(__KERNEL__) || defined(_KERNEL) */

-/* XXX tcpdump/libpcap do not tolerate variable-length headers,
- * yet, so we pad every radiotap header to 64 bytes. Ugh.
+/* The radio capture header precedes the 802.11 header.
+ * All data in the header is little endian on all platforms.
   */
-#define IEEE80211_RADIOTAP_HDRLEN	64
-
-/* The radio capture header precedes the 802.11 header. */
  struct ieee80211_radiotap_header {
-	u_int8_t	it_version;	/* Version 0. Only increases
-					 * for drastic changes,
-					 * introduction of compatible
-					 * new fields does not count.
-					 */
-	u_int8_t	it_pad;
-	u_int16_t       it_len;         /* length of the whole
-					 * header in bytes, including
-					 * it_version, it_pad,
-					 * it_len, and data fields.
-					 */
-	u_int32_t       it_present;     /* A bitmap telling which
-					 * fields are present. Set bit 31
-					 * (0x80000000) to extend the
-					 * bitmap by another 32 bits.
-					 * Additional extensions are made
-					 * by setting bit 31.
-					 */
+	uint8_t it_version;	/* Version 0. Only increases
+				 * for drastic changes,
+				 * introduction of compatible
+				 * new fields does not count.
+				 */
+	uint8_t it_pad;
+	uint16_t it_len;	/* length of the whole
+				 * header in bytes, including
+				 * it_version, it_pad,
+				 * it_len, and data fields.
+				 */
+	uint32_t it_present;	/* A bitmap telling which
+				 * fields are present. Set bit 31
+				 * (0x80000000) to extend the
+				 * bitmap by another 32 bits.
+				 * Additional extensions are made
+				 * by setting bit 31.
+				 */
  } __attribute__((__packed__));

-/* Name                                 Data type       Units
- * ----                                 ---------       -----
+/* Name                                 Data type    Units
+ * ----                                 ---------    -----
   *
- * IEEE80211_RADIOTAP_TSFT              u_int64_t       microseconds
+ * IEEE80211_RADIOTAP_TSFT              __le64       microseconds
   *
   *      Value in microseconds of the MAC's 64-bit 802.11 Time
   *      Synchronization Function timer when the first bit of the
   *      MPDU arrived at the MAC. For received frames, only.
   *
- * IEEE80211_RADIOTAP_CHANNEL           2 x u_int16_t   MHz, bitmap
+ * IEEE80211_RADIOTAP_CHANNEL           2 x uint16_t   MHz, bitmap
   *
   *      Tx/Rx frequency in MHz, followed by flags (see below).
   *
- * IEEE80211_RADIOTAP_FHSS              u_int16_t       see below
+ * IEEE80211_RADIOTAP_FHSS              uint16_t       see below
   *
   *      For frequency-hopping radios, the hop set (first byte)
   *      and pattern (second byte).
   *
- * IEEE80211_RADIOTAP_RATE              u_int8_t        500kb/s
+ * IEEE80211_RADIOTAP_RATE              u8           500kb/s
   *
   *      Tx/Rx data rate
   *
- * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t          decibels from
- *                                                      one milliwatt (dBm)
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     s8           decibels from
+ *                                                   one milliwatt (dBm)
   *
   *      RF signal power at the antenna, decibel difference from
   *      one milliwatt.
   *
- * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t          decibels from
- *                                                      one milliwatt (dBm)
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE      s8           decibels from
+ *                                                   one milliwatt (dBm)
   *
   *      RF noise power at the antenna, decibel difference from one
   *      milliwatt.
   *
- * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u_int8_t        decibel (dB)
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8           decibel (dB)
   *
   *      RF signal power at the antenna, decibel difference from an
   *      arbitrary, fixed reference.
   *
- * IEEE80211_RADIOTAP_DB_ANTNOISE       u_int8_t        decibel (dB)
+ * IEEE80211_RADIOTAP_DB_ANTNOISE       u8           decibel (dB)
   *
   *      RF noise power at the antenna, decibel difference from an
   *      arbitrary, fixed reference point.
   *
- * IEEE80211_RADIOTAP_LOCK_QUALITY      u_int16_t       unitless
+ * IEEE80211_RADIOTAP_LOCK_QUALITY      uint16_t       unitless
   *
   *      Quality of Barker code lock. Unitless. Monotonically
   *      nondecreasing with "better" lock strength. Called "Signal
   *      Quality" in datasheets.  (Is there a standard way to measure
   *      this?)
   *
- * IEEE80211_RADIOTAP_TX_ATTENUATION    u_int16_t       unitless
+ * IEEE80211_RADIOTAP_TX_ATTENUATION    uint16_t       unitless
   *
   *      Transmit power expressed as unitless distance from max
   *      power set at factory calibration.  0 is max power.
   *      Monotonically nondecreasing with lower power levels.
   *
- * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u_int16_t       decibels (dB)
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t       decibels (dB)
   *
   *      Transmit power expressed as decibel distance from max power
   *      set at factory calibration.  0 is max power.  Monotonically
   *      nondecreasing with lower power levels.
   *
- * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t          decibels from
- *                                                      one milliwatt (dBm)
+ * IEEE80211_RADIOTAP_DBM_TX_POWER      s8           decibels from
+ *                                                   one milliwatt (dBm)
   *
   *      Transmit power expressed as dBm (decibels from a 1 milliwatt
   *      reference). This is the absolute power level measured at
   *      the antenna port.
   *
- * IEEE80211_RADIOTAP_FLAGS             u_int8_t        bitmap
+ * IEEE80211_RADIOTAP_FLAGS             u8           bitmap
   *
   *      Properties of transmitted and received frames. See flags
   *      defined below.
   *
- * IEEE80211_RADIOTAP_ANTENNA           u_int8_t        antenna index
+ * IEEE80211_RADIOTAP_ANTENNA           u8           antenna index
   *
   *      Unitless indication of the Rx/Tx antenna for this packet.
   *      The first antenna is antenna 0.
   *
- * IEEE80211_RADIOTAP_RX_FLAGS          u_int16_t       bitmap
+ * IEEE80211_RADIOTAP_RX_FLAGS          uint16_t       bitmap
   *
- *	Properties of received frames. See flags defined below.
+ *     Properties of received frames. See flags defined below.
   *
- * IEEE80211_RADIOTAP_TX_FLAGS          u_int16_t       bitmap
+ * IEEE80211_RADIOTAP_TX_FLAGS          uint16_t       bitmap
   *
- *	Properties of transmitted frames. See flags defined below.
+ *     Properties of transmitted frames. See flags defined below.
   *
- * IEEE80211_RADIOTAP_RTS_RETRIES       u_int8_t        data
+ * IEEE80211_RADIOTAP_RTS_RETRIES       u8           data
   *
- *	Number of rts retries a transmitted frame used.
- *
- * IEEE80211_RADIOTAP_DATA_RETRIES      u_int8_t        data
+ *     Number of rts retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_DATA_RETRIES      u8           data
+ *
+ *     Number of unicast retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_MCS	u8, u8, u8		unitless
+ *
+ *     Contains a bitmap of known fields/flags, the flags, and
+ *     the MCS index.
   *
- *	Number of unicast retries a transmitted frame used.
- *
   */
  enum ieee80211_radiotap_type {
  	IEEE80211_RADIOTAP_TSFT = 0,
@@ -195,20 +200,24 @@
  	IEEE80211_RADIOTAP_TX_FLAGS = 15,
  	IEEE80211_RADIOTAP_RTS_RETRIES = 16,
  	IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+
+	IEEE80211_RADIOTAP_MCS = 19,
+
+	/* valid in every it_present bitmap, even vendor namespaces */
+	IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
+	IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
  	IEEE80211_RADIOTAP_EXT = 31
  };

-#if !defined(__KERNEL__) && !defined(_KERNEL)
  /* Channel flags. */
-#define IEEE80211_CHAN_TURBO    0x0010  /* Turbo channel */
-#define IEEE80211_CHAN_CCK      0x0020  /* CCK channel */
-#define IEEE80211_CHAN_OFDM     0x0040  /* OFDM channel */
-#define IEEE80211_CHAN_2GHZ     0x0080  /* 2 GHz spectrum channel. */
-#define IEEE80211_CHAN_5GHZ     0x0100  /* 5 GHz spectrum channel */
-#define IEEE80211_CHAN_PASSIVE  0x0200  /* Only passive scan allowed */
+#define	IEEE80211_CHAN_TURBO	0x0010	/* Turbo channel */
+#define	IEEE80211_CHAN_CCK	0x0020	/* CCK channel */
+#define	IEEE80211_CHAN_OFDM	0x0040	/* OFDM channel */
+#define	IEEE80211_CHAN_2GHZ	0x0080	/* 2 GHz spectrum channel. */
+#define	IEEE80211_CHAN_5GHZ	0x0100	/* 5 GHz spectrum channel */
+#define	IEEE80211_CHAN_PASSIVE	0x0200	/* Only passive scan allowed */
  #define	IEEE80211_CHAN_DYN	0x0400	/* Dynamic CCK-OFDM channel */
  #define	IEEE80211_CHAN_GFSK	0x0800	/* GFSK channel (FHSS PHY) */
-#endif /* !defined(__KERNEL__) && !defined(_KERNEL) */

  /* For IEEE80211_RADIOTAP_FLAGS */
  #define	IEEE80211_RADIOTAP_F_CFP	0x01	/* sent/received
@@ -229,15 +238,32 @@
  						 * 802.11 header and payload
  						 * (to 32-bit boundary)
  						 */
+#define IEEE80211_RADIOTAP_F_BADFCS	0x40	/* frame failed FCS check */
+
  /* For IEEE80211_RADIOTAP_RX_FLAGS */
-#define	IEEE80211_RADIOTAP_F_RX_BADFCS	0x0001	/* frame failed crc check */
+#define IEEE80211_RADIOTAP_F_RX_BADPLCP	0x0002 /* bad PLCP */

  /* For IEEE80211_RADIOTAP_TX_FLAGS */
-#define	IEEE80211_RADIOTAP_F_TX_FAIL	0x0001	/* failed due to excessive
+#define IEEE80211_RADIOTAP_F_TX_FAIL	0x0001	/* failed due to excessive
  						 * retries */
-#define	IEEE80211_RADIOTAP_F_TX_CTS	0x0002	/* used cts 'protection' */
-#define	IEEE80211_RADIOTAP_F_TX_RTS	0x0004	/* used rts/cts handshake */
+#define IEEE80211_RADIOTAP_F_TX_CTS	0x0002	/* used cts 'protection' */
+#define IEEE80211_RADIOTAP_F_TX_RTS	0x0004	/* used rts/cts handshake */


+/* For IEEE80211_RADIOTAP_MCS */
+#define IEEE80211_RADIOTAP_MCS_HAVE_BW		0x01
+#define IEEE80211_RADIOTAP_MCS_HAVE_MCS		0x02
+#define IEEE80211_RADIOTAP_MCS_HAVE_GI		0x04
+#define IEEE80211_RADIOTAP_MCS_HAVE_FMT		0x08
+#define IEEE80211_RADIOTAP_MCS_HAVE_FEC		0x10
+
+#define IEEE80211_RADIOTAP_MCS_BW_MASK		0x03
+#define		IEEE80211_RADIOTAP_MCS_BW_20	0
+#define		IEEE80211_RADIOTAP_MCS_BW_40	1
+#define		IEEE80211_RADIOTAP_MCS_BW_20L	2
+#define		IEEE80211_RADIOTAP_MCS_BW_20U	3
+#define IEEE80211_RADIOTAP_MCS_SGI		0x04
+#define IEEE80211_RADIOTAP_MCS_FMT_GF		0x08
+#define IEEE80211_RADIOTAP_MCS_FEC_LDPC		0x10

-#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */
+#endif				/* IEEE80211_RADIOTAP_H */
diff -urN click.old//include/clicknet/wifi.h click//include/clicknet/wifi.h
--- click.old//include/clicknet/wifi.h	2011-07-14 17:57:39.507188325 +0200
+++ click//include/clicknet/wifi.h	2011-07-09 23:32:01.278637966 +0200
@@ -29,7 +29,9 @@

  struct click_wifi_extra {
    uint32_t magic;
-  uint32_t flags;
+
+  uint16_t flags;
+  uint16_t channel;

    uint8_t rssi;
    uint8_t silence;
@@ -48,7 +50,8 @@

    uint8_t virt_col;
    uint8_t retries;
-  uint16_t len;
+  uint8_t mcs;
+  uint8_t len;
  } CLICK_SIZE_PACKED_ATTRIBUTE;



More information about the click mailing list