I have attached the header file (ieee802_11_radio.h) defining an improved
(IMHO) generic 802.11 radio capture format. I have also attached patches
containing my implementation for tcpdump. Please consider this format
for adoption by tcpdump.
The idea behind this capture format is that
* it is generic: it suits radios parts by Cisco/Aironet, ADMtek,
AMD 79c930, Prism 2.x, TI, Atheros, Atmel, and Realtek.
* it is extensible: if new hardware provides useful new radio
information, you can add them to this capture format without breaking
existing parsers for the capture format.
* it conserves bandwidth: the capture header length can vary
with the content of the header; drivers can take advantage when
libpcap finally groks variable-length headers.
* it is more informative than previous radio headers: the units and
meaning for each field are rigidly specified; fields can be left out
which are meaningless in context (e.g., Rx signal strength can be left
out of transmitted frames)
* it supports advanced wireless applications: existing sniffer
apps (dsniffer, kismet) can be adapted to use this format, for universal
radio support; wireless routers algorithms can monitor a link and assign
costs based on S/N ratio or on peers' data rate; stations can share
S/N information with each other to support improved rate adaptation;
and so on.
Here is an example capture:
> sudo ./tcpdump -ne -y ieee802_11_radio -s 256 -i wi0
Password:
tcpdump: data link type ieee802_11_radio
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wi0, link-type 127, capture size 256 bytes
01:17:58.503262 2.0 Mb/s -64dB signal -73dB noise 2762646109us mactime
BSSID:00:05:5d:da:ac:a8 DA:00:05:5d:da:ac:a8 SA:00:30:65:15:46:38 Authentication (Open
System)-1: Succesful
01:17:58.503292 2.0 Mb/s BSSID:00:05:5d:da:ac:a8 DA:00:30:65:15:46:38
SA:00:05:5d:da:ac:a8 Authentication (Open System)-2:
01:17:58.505034 2.0 Mb/s -64dB signal -73dB noise 2876613213us mactime
BSSID:00:05:5d:da:ac:a8 DA:00:05:5d:da:ac:a8 SA:00:30:65:15:46:38 Assoc Request (ojc)
[1.0 2.0 5.5 11.0 Mbit]
01:17:58.505051 2.0 Mb/s BSSID:00:05:5d:da:ac:a8 DA:00:30:65:15:46:38
SA:00:05:5d:da:ac:a8 Assoc Response AID(1) :: Succesful
01:17:59.033918 2.0 Mb/s -64dB signal -73dB noise 3153437285us mactime
BSSID:00:05:5d:da:ac:a8 SA:00:30:65:15:46:38 DA:00:05:5d:da:ac:a8 LLC, dsap 0xaa, ssap
0xaa, cmd 0x03, IP 192.168.1.109 > 192.168.1.1: icmp 64: echo request seq 2660
01:17:59.034024 2.0 Mb/s DA:00:30:65:15:46:38 BSSID:00:05:5d:da:ac:a8
SA:00:05:5d:da:ac:a8 LLC, dsap 0xaa, ssap 0xaa, cmd 0x03, IP 192.168.1.1 >
192.168.1.109: icmp 64: echo reply seq 2660
01:17:59.627226 2.0 Mb/s -64dB signal -73dB noise 3309281902us mactime
BSSID:00:05:5d:da:ac:a8 SA:00:30:65:15:46:38 DA:ff:ff:ff:ff:ff:ff LLC, dsap 0xaa, ssap
0xaa, cmd 0x03, IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from
00:30:65:15:46:38, length: 303
01:17:59.630303 2.0 Mb/s DA:00:30:65:15:46:38 BSSID:00:05:5d:da:ac:a8
SA:00:05:5d:da:ac:a8 LLC, dsap 0xaa, ssap 0xaa, cmd 0x03, IP 192.168.1.1.67 >
192.168.1.109.68: BOOTP/DHCP, Reply, length: 300
01:18:00.034279 2.0 Mb/s -64dB signal -73dB noise 4287079028us mactime
BSSID:00:05:5d:da:ac:a8 SA:00:30:65:15:46:38 DA:00:05:5d:da:ac:a8 LLC, dsap 0xaa, ssap
0xaa, cmd 0x03, IP 192.168.1.109 > 192.168.1.1: icmp 64: echo request seq 2661
01:18:00.034373 2.0 Mb/s DA:00:30:65:15:46:38 BSSID:00:05:5d:da:ac:a8
SA:00:05:5d:da:ac:a8 LLC, dsap 0xaa, ssap 0xaa, cmd 0x03, IP 192.168.1.1 >
192.168.1.109: icmp 64: echo reply seq 2661
Dave
--
David Young OJC Technologies
[EMAIL PROTECTED] Urbana, IL * (217) 278-3933
? ieee802_11_radio.h
Index: extract.h
===================================================================
RCS file: /tcpdump/master/tcpdump/extract.h,v
retrieving revision 1.19
diff -u -r1.19 extract.h
--- extract.h 11 Dec 2002 07:13:51 -0000 1.19
+++ extract.h 2 Aug 2003 21:46:00 -0000
@@ -96,3 +96,12 @@
(u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \
(u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
(u_int32_t)*((const u_int8_t *)(p) + 0)))
+#define EXTRACT_LE_64BITS(p) \
+ ((u_int64_t)((u_int64_t)*((const u_int8_t *)(p) + 7) << 56 | \
+ (u_int64_t)*((const u_int8_t *)(p) + 6) << 48 | \
+ (u_int64_t)*((const u_int8_t *)(p) + 5) << 40 | \
+ (u_int64_t)*((const u_int8_t *)(p) + 4) << 32 | \
+ (u_int64_t)*((const u_int8_t *)(p) + 3) << 24 | \
+ (u_int64_t)*((const u_int8_t *)(p) + 2) << 16 | \
+ (u_int64_t)*((const u_int8_t *)(p) + 1) << 8 | \
+ (u_int64_t)*((const u_int8_t *)(p) + 0)))
Index: print-802_11.c
===================================================================
RCS file: /tcpdump/master/tcpdump/print-802_11.c,v
retrieving revision 1.22
diff -u -r1.22 print-802_11.c
--- print-802_11.c 22 Jul 2003 17:36:57 -0000 1.22
+++ print-802_11.c 2 Aug 2003 21:46:00 -0000
@@ -42,6 +42,11 @@
#include "extract.h"
#include "ieee802_11.h"
+#ifdef HAVE_IEEE80211RADIOTAP_H
+#include <net/if_ieee80211radiotap.h>
+#else
+#include "ieee802_11_radio.h"
+#endif
#define PRINT_RATES(p) \
do { \
@@ -927,6 +932,155 @@
static u_int
ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
{
+#define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
+#define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
+#define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
+#define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
+#define BITNO_2(x) (((x) & 2) ? 1 : 0)
+#define BIT(n) (1 << n)
+
+ union {
+ int16_t i16;
+ u_int16_t u16;
+ u_int32_t u32;
+ u_int64_t u64;
+ } u;
+ struct ieee80211_radiotap_header *hdr;
+ u_int32_t present, next_present;
+ u_int32_t *presentp, *last_presentp;
+ enum ieee80211_radiotap_type bit;
+ int bit0;
+ const u_char *iter;
+
+ if (caplen < sizeof(*hdr)) {
+ printf("[|802.11]");
+ return caplen;
+ }
+
+ hdr = (struct ieee80211_radiotap_header *)p;
+
+ if (caplen < hdr->it_len) {
+ printf("[|802.11]");
+ return caplen;
+ }
+
+ for (last_presentp = &hdr->it_present;
+ (*last_presentp & BIT(IEEE80211_RADIOTAP_EXT)) != 0 &&
+ (u_char*)(last_presentp + 1) <= p + hdr->it_len;
+ last_presentp++);
+
+ /* are there more bitmap extensions than bytes in header? */
+ if ((*last_presentp & BIT(IEEE80211_RADIOTAP_EXT)) != 0) {
+ printf("[|802.11]");
+ return caplen;
+ }
+
+ iter = (u_char*)(last_presentp + 1);
+
+ for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
+ presentp++, bit0 += 32) {
+ for (present = *presentp; present; present = next_present) {
+ /* clear the least significant bit that is set */
+ next_present = present & (present - 1);
+
+ /* extract the least significant bit that is set */
+ bit = bit0 + BITNO_32(present ^ next_present);
+
+ switch (bit) {
+ case IEEE80211_RADIOTAP_RATE:
+ case IEEE80211_RADIOTAP_CHANNEL:
+ case IEEE80211_RADIOTAP_FHSS:
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ case IEEE80211_RADIOTAP_DB_ANTNOISE:
+ case IEEE80211_RADIOTAP_LOCK_QUALITY:
+ case IEEE80211_RADIOTAP_TX_ATTENUATION:
+ case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ case IEEE80211_RADIOTAP_FLAGS:
+ case IEEE80211_RADIOTAP_ANTENNA:
+ u.u16 = EXTRACT_LE_16BITS(iter);
+ iter += sizeof(u.u16);
+ break;
+ case IEEE80211_RADIOTAP_TIME:
+ u.u32 = EXTRACT_LE_32BITS(iter);
+ iter += sizeof(u.u32);
+ break;
+ case IEEE80211_RADIOTAP_TSFT:
+ u.u64 = EXTRACT_LE_64BITS(iter);
+ iter += sizeof(u.u64);
+ break;
+ default:
+ continue;
+ }
+
+ switch (bit) {
+ case IEEE80211_RADIOTAP_CHANNEL:
+ printf("ch %d ", u.u16);
+ break;
+ case IEEE80211_RADIOTAP_FHSS:
+ printf("fhset %d fhpat %d ", u.u16 & 0xff,
+ (u.u16 >> 8) & 0xff);
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ printf("%d.%d Mb/s ", u.u16 / 2,
+ (u.u16 * 5) % 10);
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ printf("%ddB signal ", u.i16);
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTNOISE:
+ printf("%ddB noise ", u.i16);
+ break;
+ case IEEE80211_RADIOTAP_LOCK_QUALITY:
+ printf("%u sq ", u.u16);
+ break;
+ case IEEE80211_RADIOTAP_TX_ATTENUATION:
+ printf("%d tx power ", -(int)u.u16);
+ break;
+ case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
+ printf("%ddB tx power ", -(int)u.u16);
+ break;
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ printf("%ddBm tx power ", u.u16);
+ break;
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (u.u16 & IEEE80211_RADIOTAP_F_CFP)
+ printf("cfp ");
+ if (u.u16 & IEEE80211_RADIOTAP_F_SHORTPRE)
+ printf("short preamble ");
+ if (u.u16 & IEEE80211_RADIOTAP_F_WEP)
+ printf("wep ");
+ if (u.u16 & IEEE80211_RADIOTAP_F_FRAG)
+ printf("fragmented ");
+ break;
+ case IEEE80211_RADIOTAP_ANTENNA:
+ printf("antenna %d ", u.u16);
+ break;
+ case IEEE80211_RADIOTAP_TIME:
+ printf("%uus mactime ", u.u32);
+ break;
+ case IEEE80211_RADIOTAP_TSFT:
+ printf("%" PRIu64 "us tsft ", u.u64);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return hdr->it_len + ieee802_11_print(p + hdr->it_len,
+ length - hdr->it_len, caplen - hdr->it_len);
+#undef BITNO_32
+#undef BITNO_16
+#undef BITNO_8
+#undef BITNO_4
+#undef BITNO_2
+#undef BIT
+}
+
+static u_int
+ieee802_11_linux_radio_print(const u_char *p, u_int length, u_int caplen)
+{
u_int32_t caphdr_len;
caphdr_len = EXTRACT_32BITS(p + 4);
@@ -977,7 +1131,7 @@
}
if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
- return ieee802_11_radio_print(p, length, caplen);
+ return ieee802_11_linux_radio_print(p, length, caplen);
if (caplen < PRISM_HDR_LEN) {
printf("[|802.11]");
/* $Header: $ */
/*-
* Copyright (c) 2003, 2004 David Young. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
* YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/* A generic radio capture format is desirable. There is one for
* Linux, but it is neither rigidly defined (there were not even
* units given for some fields) nor easily extensible.
*
* I suggest the following extensible radio capture format. It is
* based on a bitmap indicating which fields are present.
*
* I am trying to describe precisely what the application programmer
* should expect in the following, and for that reason I tell the
* units and origin of each measurement (where it applies), or else I
* use sufficiently weaselly language ("is a monotonically nondecreasing
* function of...") that I cannot set false expectations for lawyerly
* readers.
*/
#ifndef _IEEE802_11_RADIO_H_
#define _IEEE802_11_RADIO_H_
/* 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 LTVs 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 LTVs.
*/
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.
*/
};
/* Name Data type Units
* ---- --------- -----
*
* IEEE80211_RADIOTAP_CHANNEL u_int16_t MHz
*
* Tx/Rx channel number (for DSSS/OFDM/PBCC PHY)
*
* IEEE80211_RADIOTAP_FHSS u_int16_t see below
*
* For frequency-hopping radios, the hop set (first byte)
* and pattern (second byte).
*
* IEEE80211_RADIOTAP_RATE u_int16_t 100kb/s
*
* Tx/Rx data rate
*
* IEEE80211_RADIOTAP_DB_ANTSIGNAL int16_t decibel (dB)
*
* RF signal power at the antenna, measured from a fixed,
* arbitrary reference point.
*
* IEEE80211_RADIOTAP_DB_ANTNOISE int16_t decibel (dB)
*
* RF noise power at the antenna in decibels from an arbitrary,
* fixed reference point.
*
* IEEE80211_RADIOTAP_BARKER_CODE_LOCK u_int16_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
*
* 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)
*
* 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 u_int16_t decibels from
* 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_TSFT u_int64_t 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.
* Little-endian byte order.
*
* IEEE80211_RADIOTAP_FLAGS u_int16_t bitmap
*
* Properties of transmitted and received frames. See flags
* defined below.
*
* IEEE80211_RADIOTAP_TIME u_int32_t microseconds
*
* For radios that provide it: packet arrival time in
* microseconds. Prism hardware will provide this, but it is
* not known whether it marks the first or the last bit of
* the frame. Nor is it known where that bit has arrived
* (antenna, modem, MAC?) when the time is measured.
*
* IEEE80211_RADIOTAP_ANTENNA u_int16_t antenna index
*
* Unitless indication of the Rx/Tx antenna for this packet.
* The first antenna is antenna 0.
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_PAD = 0,
IEEE80211_RADIOTAP_FLAGS = 1,
IEEE80211_RADIOTAP_RATE = 2,
IEEE80211_RADIOTAP_CHANNEL = 3,
IEEE80211_RADIOTAP_FHSS = 4,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 5,
IEEE80211_RADIOTAP_DB_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_TSFT = 12,
IEEE80211_RADIOTAP_EXT = 31,
IEEE80211_RADIOTAP_TIME = 32
};
/* For IEEE80211_RADIOTAP_FLAGS */
#define IEEE80211_RADIOTAP_F_CFP 0x0001 /* sent/received
* during CFP
*/
#define IEEE80211_RADIOTAP_F_SHORTPRE 0x0002 /* sent/received
* with short
* preamble
*/
#define IEEE80211_RADIOTAP_F_WEP 0x0004 /* sent/received
* with WEP encryption
*/
#define IEEE80211_RADIOTAP_F_FRAG 0x0008 /* sent/received
* with fragmentation
*/
#endif /* _IEEE802_11_RADIO_H_ */