Please note: This project is no longer active. The website is kept online for historic purposes only.
If you´re looking for a Linux driver for your Atheros WLAN device, you should continue here .

Radiotap Header Information

Background

The radiotap header format is a mechanism to supply additional information about frames, from the driver to userspace applications such as libpcap, and from a userspace application to the driver for transmission. Designed initially for NetBSD systems by David Young, the radiotap header format provides more flexibility than the PrismAVS header format and allows the driver developer to specify an arbitrary number of fields based on a bitmask presence field in the radiotap header.

Currently, the MADWIFI drivers support the radiotap header for the received frames when in monitor mode, as well as for frames being transmitted onto the network.

Why we need it

The radiotap header provides more flexibility for reporting the characteristics of frames than the legacy PrismAVS headers allow. For example, it is not currently possible to report the Frame Check Sequence (FCS) information in the PrismAVS header; adding the FCS information to the header would break other parsers that expect the PrismAVS header to be a consistent 144 bytes in length. Radiotap is flexible enough to accommodate the addition of new fields over time, without breaking existing parsers.

Detail

The radiotap capture format starts with a radiotap header:

struct ieee80211_radiotap_header {
        u_int8_t        it_version;     /* set to 0 */
        u_int8_t        it_pad;
        u_int16_t       it_len;         /* entire length */
        u_int32_t       it_present;     /* fields present */
} __attribute__((__packed__));

The it_version field indicates which major version of the radiotap header is in use. Currently, this is always 0. Adding support for additional radiotap fields does not change the version number.

The it_pad field is currently unused, it simply aligns the fields onto natural word boundaries.

The it_len field indicates the entire length of the radiotap data, including the radiotap header. This is valuable for the developer so they can consistently locate the beginning of the 802.11 frame that follows the radiotap data, even if their parser doesn't understand all of the data fields specified.

The it_present field is a bitmask of the radiotap data fields that follows the radiotap header. The currently supported list of radiotap header fields can be found in ieee80211_radiotap.h. Briefly, they are identified as follows:

enum ieee80211_radiotap_type {
        IEEE80211_RADIOTAP_TSFT = 0,
        IEEE80211_RADIOTAP_FLAGS = 1,
        IEEE80211_RADIOTAP_RATE = 2,
        IEEE80211_RADIOTAP_CHANNEL = 3,
        IEEE80211_RADIOTAP_FHSS = 4,
        IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
        IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
        IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
        IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
        IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
        IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
        IEEE80211_RADIOTAP_ANTENNA = 11,
        IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
        IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
        IEEE80211_RADIOTAP_EXT = 31,
};

Provided the IEEE80211_RADIOTAP_EXT bit is not set, the data for fields specified in the it_present bitmask immediately follow the radiotap header.

One of the advantages of radiotap is that new fields can be added to the end of the radiotap data without breaking existing parsers. If a parser identifies a bitmask value that is not recognized, it can skip to the end of the radiotap data by referencing the header it_len field.

Important Radiotap Characteristics

  • Fields are in strict-order; The developer can specify any combination of fields, but the data must appear following the radiotap header in the order they are specified in the it_present bitmask (or more accurately, in the order they are specified in the ieee80211_radiotap_type enum).
  • Data is specified in little endian byte-order; All data fields including the it_version, it_len and it_present fields in the radiotap header are to be specified in little endian byte-order. Developers should use make use of the cpu_to_leNN and leNN_to_cpu macros to convert appropriately.
  • Field lengths are implicit; The radiotap header format does not specify field lengths, it is expected that the developer knows the corresponding length based on the data field name;
  • Variable-length fields are not supported; Since field lengths are implicit, variable-length fields are not supported in the radiotap header format.
  • Support for extended bitmasks; If bit 31 of the it_present field is set, an extended it_present bitmask is present. Developers should check for the presence of bit 31 in the it_present field to identify if a second 32-bit bitmask follows the radiotap header instead of assuming the beginning of the radiotap data immediately follows the radiotap header. Note that additional bitmask may be chained to the end of extended bitmasks as well by setting bit 31.
  • Natural alignment field requirement; The radiotap manual page requires that 16-bit, 32-bit and 64-bit fields be naturally aligned on even-byte boundaries. See the section Alignment in Radiotap below for more information.

Alignment in Radiotap

The Radiotap Manual Page indicates that fields in the radiotap header aligned to natural boundaries:

Radiotap capture fields must be naturally aligned. That is, 16-, 32-, and 64-bit fields must begin on 16-, 32-, and 64-bit boundaries, respectively. In this way, drivers can avoid unaligned accesses to radiotap capture fields. radiotap-compliant drivers must insert padding before a capture field to ensure its natural alignment. radiotap-compliant packet dissectors, such as tcpdump(8), expect the padding.

Developers beware: all compilers may not pack structs alike. If a driver developer constructs their radiotap header with a packed structure, in order to ensure natural alignment, then it is important that they insert padding bytes by themselves.

This is in an effort to avoid the overhead of extracting bytes that fall on non-natural byte boundaries. For example, if the developer wants to construct a radiotap header as follows:

struct rtapdata {
    uint8_t foo;
    uint32_t bar;
    uint16_t oof;
    uint8_t rab;
} __attribute__ ((packed));

This would cause the fields "bar" and "oof" to be unnaturally aligned. Because the radiotap data fields are in a strict order with a fixed length, it is not always possible to get the alignment to fall on an natural boundary using only the radiotap data fields. Therefore, it is sometimes necessary to pad these fields. From the word of David Young:

To use your example, you have to pad it like this:

struct rtapdata {
    uint8_t foo;
    uint8_t pad[3];
    uint32_t bar;
    uint16_t oof;
    uint8_t rab;
} __attribute__ ((packed));

After the interpreter reads foo, it has to detect that its "cursor" is not at a 32-bit boundary, and skip 3 bytes until it is. Thus, it skips over the pad bytes.

David continues to comment that while the tcpdump parser does properly accommodate for the possible presence of padding between radiotap data fields, Ethereal does not properly implement this. Fortunately in the case of the MADWIFI drivers, all the fields we specify in the radiotap header fall on natural byte boundaries and we do not need to include padding.

One possible problem with David's cursor recommendation is how we can accommodate systems with processors that use different word sizes. It does not appear that tcpdump attempts to accommodate anything other than a 32-bit processor. --Josh

Support in MADWIFI

A monitor mode interface can be created and configured with radiotap support as follows:

# Must destroy all other managed mode interfaces before creating a monitor-mode interface
wlanconfig ath0 destroy
wlanconfig ath0 create wlandev wifi0 wlanmode monitor
echo 803 >/proc/sys/net/ath0/dev_type

As of release 0.9.2, the following fields are included in the radiotap data:

struct ath_rx_radiotap_header {
        struct ieee80211_radiotap_header wr_ihdr;
        u_int64_t wr_tsft;
        u_int8_t wr_flags;
        u_int8_t wr_rate;
        u_int16_t wr_chan_freq;
        u_int16_t wr_chan_flags;
        u_int8_t wr_antenna;
        u_int8_t wr_antsignal;
};
  • wr_ihdr - the radiotap header including version, length and bitmask;
  • wr_tsft - Specifies the value of the Timer Synchronisation Function, a value in microseconds indicating when the first bit of the MPDU was received by the MAC;
  • wr_flags - Flags defined in ieee80211_radiotap.h (short preamble, etc);
  • wr_rate - Specifies the data rate at the time the packet was received in a quantity of 500 Kb/s units;
  • wr_chan_freq - Specifies the frequency in MHz;
  • wr_chan_flags - Specifes modulation information and spectrum information, see ieee80211_radiotap.h, skip to "Channel flags";
  • wr_antenna - Specifies the antenna that received the frame in the case of diversified antennas;
  • wr_antsignal - Specifies the received signal strength of the frame at the indicated antenna, in dB above an arbitrary reference (In this case the reference value is the noise floor which is assumed to be a constant -95 dBm.);

References