[Click] [RFC] Update radiotap parser

Eddie Kohler kohler at cs.ucla.edu
Wed Jul 13 19:28:46 EDT 2011


Hi Roberto,

I'd like to merge something like this, but including radiotap.o in EVERY click 
build is a no go.  Why not make it an ELEMENT_PROVIDES() type library?  I also 
worry that this change might be disruptive to other users.

Eddie


On 4/11/11 6:16 AM, Roberto Riggio wrote:
> Hi,
>
> this patch updates the click radiotap parser. 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.
>
> I've also included a few warnings for wifi-related elements.
>
> R.
>
> --
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates
> click.upstream/elements/wifi/ap/associationresponder.cc
> click/elements/wifi/ap/associationresponder.cc
> --- click.upstream/elements/wifi/ap/associationresponder.cc
> 2011-04-11 11:52:49.785608001 +0200
> +++ click/elements/wifi/ap/associationresponder.cc    2011-03-24
> 20:50:55.691217001 +0100
> @@ -270,9 +270,10 @@
>      memcpy(w->i_addr2, bssid.data(), 6);
>      memcpy(w->i_addr3, bssid.data(), 6);
>
> -
> -  *(uint16_t *) w->i_dur = 0;
> -  *(uint16_t *) w->i_seq = 0;
> +  uint16_t * d16 = (uint16_t *) w->i_dur;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  *d16 = 0;
> +  *s16 = 0;
>
>      uint8_t *ptr = (uint8_t *) p->data() + sizeof(struct click_wifi);
>      int actual_length = sizeof(struct click_wifi);
> @@ -354,8 +355,10 @@
>      memcpy(w->i_addr3, bssid.data(), 6);
>
>
> -  *(uint16_t *) w->i_dur = 0;
> -  *(uint16_t *) w->i_seq = 0;
> +  uint16_t * d16 = (uint16_t *) w->i_dur;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  *d16 = 0;
> +  *s16 = 0;
>
>
>      uint8_t *ptr;
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/ap/beaconsource.cc
> click/elements/wifi/ap/beaconsource.cc
> --- click.upstream/elements/wifi/ap/beaconsource.cc    2011-04-11
> 11:52:49.785608001 +0200
> +++ click/elements/wifi/ap/beaconsource.cc    2011-03-24
> 20:50:55.691217001 +0100
> @@ -129,8 +129,10 @@
>      memcpy(w->i_addr2, bssid.data(), 6);
>      memcpy(w->i_addr3, bssid.data(), 6);
>
> -  *(uint16_t *) w->i_dur = 0;
> -  *(uint16_t *) w->i_seq = 0;
> +  uint16_t * d16 = (uint16_t *) w->i_dur;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  *d16 = 0;
> +  *s16 = 0;
>
>      uint8_t *ptr;
>
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates
> click.upstream/elements/wifi/ap/openauthresponder.cc
> click/elements/wifi/ap/openauthresponder.cc
> --- click.upstream/elements/wifi/ap/openauthresponder.cc    2011-04-11
> 11:52:49.785608001 +0200
> +++ click/elements/wifi/ap/openauthresponder.cc    2011-03-24
> 20:50:55.691217001 +0100
> @@ -169,8 +169,10 @@
>      memcpy(w->i_addr3, _winfo->_bssid.data(), 6);
>
>
> -  *(uint16_t *) w->i_dur = 0;
> -  *(uint16_t *) w->i_seq = 0;
> +  uint16_t * d16 = (uint16_t *) w->i_dur;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  *d16 = 0;
> +  *s16 = 0;
>
>      uint8_t *ptr;
>
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates
> click.upstream/elements/wifi/ap/proberesponder.cc
> click/elements/wifi/ap/proberesponder.cc
> --- click.upstream/elements/wifi/ap/proberesponder.cc    2011-04-11
> 11:52:49.785608001 +0200
> +++ click/elements/wifi/ap/proberesponder.cc    2011-03-24
> 20:50:55.691217001 +0100
> @@ -214,8 +214,10 @@
>      memcpy(w->i_addr3, _bssid.data(), 6);
>
>
> -  *(uint16_t *) w->i_dur = 0;
> -  *(uint16_t *) w->i_seq = 0;
> +  uint16_t * d16 = (uint16_t *) w->i_dur;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  *d16 = 0;
> +  *s16 = 0;
>
>      uint8_t *ptr;
>
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/printwifi.cc
> click/elements/wifi/printwifi.cc
> --- click.upstream/elements/wifi/printwifi.cc    2011-04-11
> 11:52:49.789608001 +0200
> +++ click/elements/wifi/printwifi.cc    2011-04-05 16:08:37.056939649 +0200
> @@ -308,7 +308,8 @@
>      struct click_wifi_extra *ceh = WIFI_EXTRA_ANNO(p);
>      int type = wh->i_fc[0]&  WIFI_FC0_TYPE_MASK;
>      int subtype = wh->i_fc[0]&  WIFI_FC0_SUBTYPE_MASK;
> -  int duration = cpu_to_le16(*(uint16_t *) wh->i_dur);
> +  uint16_t *d16 = (uint16_t *) wh->i_dur;
> +  int duration = cpu_to_le16(*d16);
>      EtherAddress src;
>      EtherAddress dst;
>      EtherAddress bssid;
> @@ -506,8 +507,9 @@
>      sa<<  " ";
>
>      if (p->length()>= sizeof(click_wifi)) {
> -    uint16_t seq = le16_to_cpu(*(u_int16_t *)wh->i_seq)>>
> WIFI_SEQ_SEQ_SHIFT;
> -    uint8_t frag = le16_to_cpu(*(u_int16_t *)wh->i_seq)&
> WIFI_SEQ_FRAG_MASK;
> +    uint16_t *s16 = (uint16_t *) wh->i_seq;
> +    uint16_t seq = le16_to_cpu(*s16)>>  WIFI_SEQ_SEQ_SHIFT;
> +    uint8_t frag = le16_to_cpu(*s16)&  WIFI_SEQ_FRAG_MASK;
>        sa<<  "seq "<<  (int) seq;
>        if (frag || wh->i_fc[1]&  WIFI_FC1_MORE_FRAG) {
>          sa<<  " frag "<<  (int) frag;
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/radiotapdecap.cc
> click/elements/wifi/radiotapdecap.cc
> --- click.upstream/elements/wifi/radiotapdecap.cc    2011-04-11
> 11:52:49.789608001 +0200
> +++ click/elements/wifi/radiotapdecap.cc    2011-04-05
> 16:08:29.380939649 +0200
> @@ -21,80 +21,14 @@
>    #include<click/confparse.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,114 +38,86 @@
>    {
>    }
>
> -int
> -RadiotapDecap::configure(Vector<String>  &conf, ErrorHandler *errh)
> -{
> -
> -  _debug = false;
> -  if (cp_va_kparse(conf, this, errh,
> -           "DEBUG", 0, cpBool,&_debug,
> -           cpEnd)<  0)
> -    return -1;
> -  return 0;
> -}
> -
>    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 (!cp_bool(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)
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/radiotapdecap.hh
> click/elements/wifi/radiotapdecap.hh
> --- click.upstream/elements/wifi/radiotapdecap.hh    2011-04-11
> 11:52:49.789608001 +0200
> +++ click/elements/wifi/radiotapdecap.hh    2011-03-31
> 16:53:52.929465001 +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 --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/radiotapencap.cc
> click/elements/wifi/radiotapencap.cc
> --- click.upstream/elements/wifi/radiotapencap.cc    2011-04-11
> 11:52:49.789608001 +0200
> +++ click/elements/wifi/radiotapencap.cc    2011-04-05
> 16:09:58.240939648 +0200
> @@ -27,121 +27,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;
> -  if (cp_va_kparse(conf, this, errh,
> -           "DEBUG", 0, cpBool,&_debug,
> -           cpEnd)<  0)
> -    return -1;
> -  return 0;
> +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 (!cp_bool(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)
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/radiotapencap.hh
> click/elements/wifi/radiotapencap.hh
> --- click.upstream/elements/wifi/radiotapencap.hh    2011-04-11
> 11:52:49.789608001 +0200
> +++ click/elements/wifi/radiotapencap.hh    2011-03-31
> 16:43:26.000000000 +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 --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates
> click.upstream/elements/wifi/station/beacontracker.cc
> click/elements/wifi/station/beacontracker.cc
> --- click.upstream/elements/wifi/station/beacontracker.cc    2011-04-11
> 11:52:49.793608001 +0200
> +++ click/elements/wifi/station/beacontracker.cc    2011-03-24
> 20:50:55.699217001 +0100
> @@ -117,7 +117,8 @@
>
>
>      struct beacon_t b;
> -  uint16_t seq = le16_to_cpu(*(uint16_t *) w->i_seq)>>  WIFI_SEQ_SEQ_SHIFT;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  uint16_t seq = le16_to_cpu(*s16)>>  WIFI_SEQ_SEQ_SHIFT;
>
>
>      b.rx = p->timestamp_anno();
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates
> click.upstream/elements/wifi/station/openauthrequester.cc
> click/elements/wifi/station/openauthrequester.cc
> --- click.upstream/elements/wifi/station/openauthrequester.cc
> 2011-04-11 11:52:49.793608001 +0200
> +++ click/elements/wifi/station/openauthrequester.cc    2011-03-24
> 20:50:55.699217001 +0100
> @@ -157,9 +157,10 @@
>      memcpy(w->i_addr2, _eth.data(), 6);
>      memcpy(w->i_addr3, bssid.data(), 6);
>
> -
> -  *(uint16_t *) w->i_dur = 0;
> -  *(uint16_t *) w->i_seq = 0;
> +  uint16_t * d16 = (uint16_t *) w->i_dur;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  *d16 = 0;
> +  *s16 = 0;
>
>      uint8_t *ptr;
>
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates
> click.upstream/elements/wifi/station/proberequester.cc
> click/elements/wifi/station/proberequester.cc
> --- click.upstream/elements/wifi/station/proberequester.cc    2011-04-11
> 11:52:49.793608001 +0200
> +++ click/elements/wifi/station/proberequester.cc    2011-03-24
> 20:50:55.699217001 +0100
> @@ -86,8 +86,10 @@
>      memset(w->i_addr3, 0xff, 6);
>
>
> -  *(uint16_t *) w->i_dur = 0;
> -  *(uint16_t *) w->i_seq = 0;
> +  uint16_t * d16 = (uint16_t *) w->i_dur;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  *d16 = 0;
> +  *s16 = 0;
>
>      uint8_t *ptr = (uint8_t *) p->data() + sizeof(struct click_wifi);
>      int actual_length = sizeof (struct click_wifi);
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/wepdecap.cc
> click/elements/wifi/wepdecap.cc
> --- click.upstream/elements/wifi/wepdecap.cc    2011-04-11
> 11:52:49.793608001 +0200
> +++ click/elements/wifi/wepdecap.cc    2011-03-31 11:00:25.000000000 +0200
> @@ -128,13 +128,14 @@
>      icv = payload + payload_len;
>      rc4_crypt_skip(&_rc4, icv, crcbuf, WIFI_WEP_CRCLEN, 0);
>
> -  if (crc != ~le32_to_cpu(*(u_int32_t *)crcbuf)) {
> +  u_int32_t * crc32 = (u_int32_t *) crcbuf;
> +  if (crc != ~le32_to_cpu(*crc32)) {
>        click_chatter("crc failed keyid %d iv %d %x wanted %x %x\n",
>              keyid,
>              iv,
>              crc,
> -          ~le32_to_cpu(*(u_int32_t *)crcbuf),
> -          *(u_int32_t *)crcbuf);
> +          ~le32_to_cpu(*crc32),
> +          *crc32);
>        /* packet failed decrypt */
>        return p;
>      }
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/wepencap.cc
> click/elements/wifi/wepencap.cc
> --- click.upstream/elements/wifi/wepencap.cc    2011-04-11
> 11:52:49.793608001 +0200
> +++ click/elements/wifi/wepencap.cc    2011-03-31 11:00:25.000000000 +0200
> @@ -139,7 +139,8 @@
>             p->length() - (sizeof(click_wifi) + WIFI_WEP_HEADERSIZE),
>             0);
>      /* tack on ICV */
> -  *(u_int32_t *)crcbuf = cpu_to_le32(~crc);
> +  u_int32_t * crc32 = (u_int32_t *) crcbuf;
> +  *crc32 = cpu_to_le32(~crc);
>      p = p->put(WIFI_WEP_CRCLEN);
>      icv = p->end_data() - WIFI_WEP_CRCLEN;
>      rc4_crypt_skip(&_rc4, crcbuf, icv, WIFI_WEP_CRCLEN, 0);
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/wifidefrag.cc
> click/elements/wifi/wifidefrag.cc
> --- click.upstream/elements/wifi/wifidefrag.cc    2011-04-11
> 11:52:49.793608001 +0200
> +++ click/elements/wifi/wifidefrag.cc    2011-03-31 11:00:25.000000000 +0200
> @@ -53,8 +53,9 @@
>
>      click_wifi *w = (click_wifi *) p->data();
>      EtherAddress src = EtherAddress(w->i_addr2);
> -  uint16_t seq = le16_to_cpu(*(uint16_t *) w->i_seq)>>  WIFI_SEQ_SEQ_SHIFT;
> -  uint8_t frag = le16_to_cpu(*(u_int16_t *)w->i_seq)&  WIFI_SEQ_FRAG_MASK;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  uint16_t seq = le16_to_cpu(*s16)>>  WIFI_SEQ_SEQ_SHIFT;
> +  uint8_t frag = le16_to_cpu(*s16)&  WIFI_SEQ_FRAG_MASK;
>      u_int8_t more_frag = w->i_fc[1]&  WIFI_FC1_MORE_FRAG;
>      PacketInfo *nfo = _packets.findp(src);
>
> @@ -139,7 +140,8 @@
>      }
>      p = nfo->p;
>      w = (click_wifi *) p->data();
> -  *((uint16_t *) w->i_seq) = cpu_to_le16(((u_int16_t) nfo->seq)<<
> WIFI_SEQ_SEQ_SHIFT);
> +  s16 = (uint16_t *) w->i_seq;
> +  *s16 = cpu_to_le16(((u_int16_t) nfo->seq)<<  WIFI_SEQ_SEQ_SHIFT);
>      w->i_fc[1] ^= WIFI_FC1_MORE_FRAG;
>
>      nfo->p = 0;
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/wifidupefilter.cc
> click/elements/wifi/wifidupefilter.cc
> --- click.upstream/elements/wifi/wifidupefilter.cc    2011-04-11
> 11:52:49.793608001 +0200
> +++ click/elements/wifi/wifidupefilter.cc    2011-03-31
> 11:00:25.000000000 +0200
> @@ -60,8 +60,9 @@
>
>      EtherAddress src = EtherAddress(w->i_addr2);
>      EtherAddress dst = EtherAddress(w->i_addr1);
> -  uint16_t seq = le16_to_cpu(*(uint16_t *) w->i_seq)>>  WIFI_SEQ_SEQ_SHIFT;
> -  uint8_t frag = le16_to_cpu(*(u_int16_t *)w->i_seq)&  WIFI_SEQ_FRAG_MASK;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  uint16_t seq = le16_to_cpu(*s16)>>  WIFI_SEQ_SEQ_SHIFT;
> +  uint8_t frag = le16_to_cpu(*s16)&  WIFI_SEQ_FRAG_MASK;
>      u_int8_t more_frag = w->i_fc[1]&  WIFI_FC1_MORE_FRAG;
>
>      bool is_frag = frag || more_frag;
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/elements/wifi/wififragment.cc
> click/elements/wifi/wififragment.cc
> --- click.upstream/elements/wifi/wififragment.cc    2011-04-11
> 11:52:49.793608001 +0200
> +++ click/elements/wifi/wififragment.cc    2011-03-31 11:00:25.000000000
> +0200
> @@ -55,7 +55,8 @@
>    {
>
>      click_wifi *w = (click_wifi *) p->data();
> -  uint16_t seq = le16_to_cpu(*(u_int16_t *)w->i_seq)>>  WIFI_SEQ_SEQ_SHIFT;
> +  uint16_t * s16 = (uint16_t *) w->i_seq;
> +  uint16_t seq = le16_to_cpu(*s16)>>  WIFI_SEQ_SEQ_SHIFT;
>      if (!_max_length ||
>          p->length()<= sizeof(click_wifi) + _max_length) {
>        if (_debug) {
> @@ -95,7 +96,8 @@
>           frag_len);
>        click_wifi *w_o = (click_wifi *) p_out->data();
>        uint16_t seq_o = (seq<<  WIFI_SEQ_SEQ_SHIFT) | (((u_int8_t) frag)
> &  WIFI_SEQ_FRAG_MASK);
> -    *((uint16_t *)w_o->i_seq) = cpu_to_le16(seq_o);
> +    uint16_t * s16 = (uint16_t *)w_o->i_seq;
> +    *s16 = cpu_to_le16(seq_o);
>        if (frag != num_frags - 1) {
>          w_o->i_fc[1] |= WIFI_FC1_MORE_FRAG;
>        }
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/include/click/platform.h
> click/include/click/platform.h
> --- click.upstream/include/click/platform.h    1970-01-01
> 01:00:00.000000000 +0100
> +++ click/include/click/platform.h    2011-04-07 16:54:32.000000000 +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 --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/include/click/radiotap_iter.h
> click/include/click/radiotap_iter.h
> --- click.upstream/include/click/radiotap_iter.h    1970-01-01
> 01:00:00.000000000 +0100
> +++ click/include/click/radiotap_iter.h    2011-03-24 20:50:55.739217001
> +0100
> @@ -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 --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/include/clicknet/platform.h
> click/include/clicknet/platform.h
> --- click.upstream/include/clicknet/platform.h    1970-01-01
> 01:00:00.000000000 +0100
> +++ click/include/clicknet/platform.h    2011-03-24 20:50:55.739217001 +0100
> @@ -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 --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/include/clicknet/radiotap.h
> click/include/clicknet/radiotap.h
> --- click.upstream/include/clicknet/radiotap.h    2011-04-11
> 11:52:49.841608001 +0200
> +++ click/include/clicknet/radiotap.h    2011-03-31 10:46:19.000000000 +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 --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/include/clicknet/wifi.h
> click/include/clicknet/wifi.h
> --- click.upstream/include/clicknet/wifi.h    2011-04-11
> 11:52:49.841608001 +0200
> +++ click/include/clicknet/wifi.h    2011-04-05 16:08:51.724939649 +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;
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/lib/radiotap.c click/lib/radiotap.c
> --- click.upstream/lib/radiotap.c    1970-01-01 01:00:00.000000000 +0100
> +++ click/lib/radiotap.c    2011-03-24 20:50:55.747217001 +0100
> @@ -0,0 +1,383 @@
> +/*
> + * 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/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;
> +    }
> +}
> diff -urN --exclude .git --exclude conf --exclude diffserv --exclude
> ethernet --exclude secaggr --exclude wing --exclude availablechannels
> --exclude availablerates click.upstream/userlevel/Makefile.in
> click/userlevel/Makefile.in
> --- click.upstream/userlevel/Makefile.in    2011-04-11
> 11:52:49.881608001 +0200
> +++ click/userlevel/Makefile.in    2011-03-31 16:56:55.457465001 +0200
> @@ -61,7 +61,7 @@
>        element.o \
>        confparse.o variableenv.o lexer.o elemfilter.o routervisitor.o \
>        routerthread.o router.o master.o handlercall.o notifier.o \
> -    integers.o md5.o crc32.o in_cksum.o iptable.o \
> +    integers.o md5.o radiotap.o crc32.o in_cksum.o iptable.o \
>        archive.o userutils.o driver.o \
>        $(EXTRA_DRIVER_OBJS)
>
>
>
> _______________________________________________
> click mailing list
> click at amsterdam.lcs.mit.edu
> https://amsterdam.lcs.mit.edu/mailman/listinfo/click


More information about the click mailing list