3 * Decode packets with a Radiotap header
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from README.developer
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include <epan/packet.h>
36 #include <epan/crc32.h>
37 #include <epan/frequency-utils.h>
38 #include "packet-ieee80211.h"
39 #include "packet-radiotap.h"
41 /* Written with info from:
43 * http://madwifi.org/wiki/DevDocs/RadiotapHeader
44 * NetBSD's ieee80211_radiotap.h file
47 struct ieee80211_radiotap_header {
48 guint8 it_version; /* Version 0. Only increases
49 * for drastic changes,
50 * introduction of compatible
51 * new fields does not count.
54 guint16 it_len; /* length of the whole
55 * header in bytes, including
57 * it_len, and data fields.
60 guint32 it_present[MAX_PRESENT]; /* A bitmap telling which
61 * fields are present. Set bit 31
62 * (0x80000000) to extend the
63 * bitmap by another 32 bits.
64 * Additional extensions are made
69 #define RADIOTAP_MIN_HEADER_LEN 8 /* minimum header length */
70 #define RADIOTAP_VERSION_OFFSET 0 /* offset of version field */
71 #define RADIOTAP_LENGTH_OFFSET 2 /* offset of length field */
72 #define RADIOTAP_PRESENT_OFFSET 4 /* offset of "present" field */
75 * AAAAAAAAAAAAAAAAAAAAAAAAAARGH.
77 * The current FreeBSD ieee80211_radiotap.h has IEEE80211_RADIOTAP_XCHANNEL
80 * The current NetBSD ieee80211_radiotap.h has IEEE80211_RADIOTAP_RX_FLAGS
83 * The current OpenBSD ieee80211_radiotap.h has IEEE80211_RADIOTAP_FCS as
86 * NetBSD and OpenBSD also differ on what comes *after* 14.
88 * They all use the same DLT_ value for "802.11+radiotap".
90 * This is all wonderfully appreciated by those of us who write code to
91 * read files containing packets with radiotap headers. I will see if
92 * I can apply a little cluebat-fu here.
94 enum ieee80211_radiotap_type {
95 IEEE80211_RADIOTAP_TSFT = 0,
96 IEEE80211_RADIOTAP_FLAGS = 1,
97 IEEE80211_RADIOTAP_RATE = 2,
98 IEEE80211_RADIOTAP_CHANNEL = 3,
99 IEEE80211_RADIOTAP_FHSS = 4,
100 IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
101 IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
102 IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
103 IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
104 IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
105 IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
106 IEEE80211_RADIOTAP_ANTENNA = 11,
107 IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
108 IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
109 /* XXX - IEEE80211_RADIOTAP_FCS is used by MadWifi and AirPcap, but
110 * was never officially assigned. */
111 IEEE80211_RADIOTAP_FCS = 14,
112 IEEE80211_RADIOTAP_EXT = 31
116 #define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
117 #define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
118 #define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
119 #define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
120 #define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
121 #define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
122 #define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
123 #define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
126 * Useful combinations of channel characteristics.
128 #define IEEE80211_CHAN_FHSS \
129 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
130 #define IEEE80211_CHAN_A \
131 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
132 #define IEEE80211_CHAN_B \
133 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
134 #define IEEE80211_CHAN_PUREG \
135 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
136 #define IEEE80211_CHAN_G \
137 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
138 #define IEEE80211_CHAN_T \
139 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
140 #define IEEE80211_CHAN_108G \
141 (IEEE80211_CHAN_G | IEEE80211_CHAN_TURBO)
142 #define IEEE80211_CHAN_108PUREG \
143 (IEEE80211_CHAN_PUREG | IEEE80211_CHAN_TURBO)
145 /* For IEEE80211_RADIOTAP_FLAGS */
146 #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
149 #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
153 #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
154 * with WEP encryption
156 #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
159 #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
160 #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
161 * 802.11 header and payload
162 * (to 32-bit boundary)
166 static int proto_radiotap = -1;
168 static int hf_radiotap_version = -1;
169 static int hf_radiotap_pad = -1;
170 static int hf_radiotap_length = -1;
171 static int hf_radiotap_present = -1;
172 static int hf_radiotap_mactime = -1;
173 static int hf_radiotap_channel = -1;
174 static int hf_radiotap_channel_frequency = -1;
175 static int hf_radiotap_channel_flags = -1;
176 static int hf_radiotap_channel_flags_turbo = -1;
177 static int hf_radiotap_channel_flags_cck = -1;
178 static int hf_radiotap_channel_flags_ofdm = -1;
179 static int hf_radiotap_channel_flags_2ghz = -1;
180 static int hf_radiotap_channel_flags_5ghz = -1;
181 static int hf_radiotap_channel_flags_passive = -1;
182 static int hf_radiotap_channel_flags_dynamic = -1;
183 static int hf_radiotap_channel_flags_gfsk = -1;
184 static int hf_radiotap_fhss_hopset = -1;
185 static int hf_radiotap_fhss_pattern = -1;
186 static int hf_radiotap_datarate = -1;
187 static int hf_radiotap_antenna = -1;
188 static int hf_radiotap_dbm_antsignal = -1;
189 static int hf_radiotap_db_antsignal = -1;
190 static int hf_radiotap_dbm_antnoise = -1;
191 static int hf_radiotap_db_antnoise = -1;
192 static int hf_radiotap_tx_attenuation = -1;
193 static int hf_radiotap_db_tx_attenuation = -1;
194 static int hf_radiotap_txpower = -1;
196 /* "Present" flags */
197 static int hf_radiotap_present_tsft = -1;
198 static int hf_radiotap_present_flags = -1;
199 static int hf_radiotap_present_rate = -1;
200 static int hf_radiotap_present_channel = -1;
201 static int hf_radiotap_present_fhss = -1;
202 static int hf_radiotap_present_dbm_antsignal = -1;
203 static int hf_radiotap_present_dbm_antnoise = -1;
204 static int hf_radiotap_present_lock_quality = -1;
205 static int hf_radiotap_present_tx_attenuation = -1;
206 static int hf_radiotap_present_db_tx_attenuation = -1;
207 static int hf_radiotap_present_dbm_tx_attenuation = -1;
208 static int hf_radiotap_present_antenna = -1;
209 static int hf_radiotap_present_db_antsignal = -1;
210 static int hf_radiotap_present_db_antnoise = -1;
211 static int hf_radiotap_present_fcs = -1;
212 static int hf_radiotap_present_ext = -1;
214 /* "present.flags" flags */
215 static int hf_radiotap_flags = -1;
216 static int hf_radiotap_flags_cfp = -1;
217 static int hf_radiotap_flags_preamble = -1;
218 static int hf_radiotap_flags_wep = -1;
219 static int hf_radiotap_flags_frag = -1;
220 static int hf_radiotap_flags_fcs = -1;
221 static int hf_radiotap_flags_datapad = -1;
223 static int hf_radiotap_quality = -1;
224 static int hf_radiotap_fcs = -1;
225 static int hf_radiotap_fcs_bad = -1;
227 static gint ett_radiotap = -1;
228 static gint ett_radiotap_present = -1;
229 static gint ett_radiotap_flags = -1;
230 static gint ett_radiotap_channel_flags = -1;
232 static dissector_handle_t ieee80211_handle;
233 static dissector_handle_t ieee80211_datapad_handle;
236 dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
238 #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
239 #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
240 #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
241 #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
242 #define BITNO_2(x) (((x) & 2) ? 1 : 0)
243 #define BIT(n) (1 << n)
246 * The NetBSD ieee80211_radiotap man page
247 * (http://netbsd.gw.com/cgi-bin/man-cgi?ieee80211_radiotap+9+NetBSD-current)
250 * Radiotap capture fields must be naturally aligned. That is, 16-, 32-,
251 * and 64-bit fields must begin on 16-, 32-, and 64-bit boundaries, respec-
252 * tively. In this way, drivers can avoid unaligned accesses to radiotap
253 * capture fields. radiotap-compliant drivers must insert padding before a
254 * capture field to ensure its natural alignment. radiotap-compliant packet
255 * dissectors, such as tcpdump(8), expect the padding.
259 * Returns the amount required to align "offset" with "width"
261 #define ALIGN_OFFSET(offset, width) \
262 ( (((offset) + ((width) - 1)) & (~((width) - 1))) - offset )
266 capture_radiotap(const guchar *pd, int offset, int len, packet_counts *ld)
272 if(!BYTES_ARE_IN_FRAME(offset, len, RADIOTAP_MIN_HEADER_LEN)) {
276 it_len = pletohs(&pd[RADIOTAP_LENGTH_OFFSET]);
277 if(!BYTES_ARE_IN_FRAME(offset, len, it_len)) {
283 /* Header length is bigger than total packet length */
288 if(it_len < RADIOTAP_MIN_HEADER_LEN) {
289 /* Header length is shorter than fixed-length portion of header */
294 present = pletohl(&pd[RADIOTAP_PRESENT_OFFSET]);
295 offset += RADIOTAP_MIN_HEADER_LEN;
296 it_len -= RADIOTAP_MIN_HEADER_LEN;
301 * IEEE80211_RADIOTAP_TSFT is the lowest-order bit.
303 if (present & BIT(IEEE80211_RADIOTAP_TSFT)) {
305 /* No room in header for this field. */
309 /* That field is present, and it's 8 bits long. */
315 * IEEE80211_RADIOTAP_FLAGS is the next bit.
317 if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) {
319 /* No room in header for this field. */
323 /* That field is present; fetch it. */
324 if(!BYTES_ARE_IN_FRAME(offset, len, 1)) {
331 /* 802.11 header follows */
332 if (rflags & IEEE80211_RADIOTAP_F_DATAPAD)
333 capture_ieee80211_datapad(pd, offset + it_len, len, ld);
335 capture_ieee80211(pd, offset + it_len, len, ld);
339 proto_register_radiotap(void)
341 static const value_string phy_type[] = {
343 { IEEE80211_CHAN_A, "802.11a" },
344 { IEEE80211_CHAN_B, "802.11b" },
345 { IEEE80211_CHAN_PUREG, "802.11g (pure-g)" },
346 { IEEE80211_CHAN_G, "802.11g" },
347 { IEEE80211_CHAN_T, "802.11a (turbo)" },
348 { IEEE80211_CHAN_108PUREG, "802.11g (pure-g, turbo)" },
349 { IEEE80211_CHAN_108G, "802.11g (turbo)" },
350 { IEEE80211_CHAN_FHSS, "FHSS" },
354 static const true_false_string preamble_type = {
359 static hf_register_info hf[] = {
360 { &hf_radiotap_version,
361 { "Header revision", "radiotap.version",
362 FT_UINT8, BASE_DEC, NULL, 0x0,
363 "Version of radiotap header format", HFILL } },
365 { "Header pad", "radiotap.pad",
366 FT_UINT8, BASE_DEC, NULL, 0x0,
367 "Padding", HFILL } },
368 { &hf_radiotap_length,
369 { "Header length", "radiotap.length",
370 FT_UINT16, BASE_DEC, NULL, 0x0,
371 "Length of header including version, pad, length and data fields", HFILL } },
372 { &hf_radiotap_present,
373 { "Present flags", "radiotap.present",
374 FT_UINT32, BASE_HEX, NULL, 0x0, "Bitmask indicating which fields are present", HFILL } },
376 #define RADIOTAP_MASK_TSFT 0x00000001
377 #define RADIOTAP_MASK_FLAGS 0x00000002
378 #define RADIOTAP_MASK_RATE 0x00000004
379 #define RADIOTAP_MASK_CHANNEL 0x00000008
380 #define RADIOTAP_MASK_FHSS 0x00000010
381 #define RADIOTAP_MASK_DBM_ANTSIGNAL 0x00000020
382 #define RADIOTAP_MASK_DBM_ANTNOISE 0x00000040
383 #define RADIOTAP_MASK_LOCK_QUALITY 0x00000080
384 #define RADIOTAP_MASK_TX_ATTENUATION 0x00000100
385 #define RADIOTAP_MASK_DB_TX_ATTENUATION 0x00000200
386 #define RADIOTAP_MASK_DBM_TX_ATTENUATION 0x00000400
387 #define RADIOTAP_MASK_ANTENNA 0x00000800
388 #define RADIOTAP_MASK_DB_ANTSIGNAL 0x00001000
389 #define RADIOTAP_MASK_DB_ANTNOISE 0x00002000
390 #define RADIOTAP_MASK_FCS 0x00004000
391 #define RADIOTAP_MASK_EXT 0x80000000
393 /* Boolean 'present' flags */
394 { &hf_radiotap_present_tsft,
395 { "TSFT", "radiotap.present.tsft",
396 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_TSFT,
397 "Specifies if the Time Synchronization Function Timer field is present", HFILL } },
399 { &hf_radiotap_present_flags,
400 { "Flags", "radiotap.present.flags",
401 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_FLAGS,
402 "Specifies if the channel flags field is present", HFILL } },
404 { &hf_radiotap_present_rate,
405 { "Rate", "radiotap.present.rate",
406 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_RATE,
407 "Specifies if the transmit/receive rate field is present", HFILL } },
409 { &hf_radiotap_present_channel,
410 { "Channel", "radiotap.present.channel",
411 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_CHANNEL,
412 "Specifies if the transmit/receive frequency field is present", HFILL } },
414 { &hf_radiotap_present_fhss,
415 { "FHSS", "radiotap.present.fhss",
416 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_FHSS,
417 "Specifies if the hop set and pattern is present for frequency hopping radios", HFILL } },
419 { &hf_radiotap_present_dbm_antsignal,
420 { "DBM Antenna Signal", "radiotap.present.dbm_antsignal",
421 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_DBM_ANTSIGNAL,
422 "Specifies if the antenna signal strength in dBm is present", HFILL } },
424 { &hf_radiotap_present_dbm_antnoise,
425 { "DBM Antenna Noise", "radiotap.present.dbm_antnoise",
426 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_DBM_ANTNOISE,
427 "Specifies if the RF noise power at antenna field is present", HFILL } },
429 { &hf_radiotap_present_lock_quality,
430 { "Lock Quality", "radiotap.present.lock_quality",
431 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_LOCK_QUALITY,
432 "Specifies if the signal quality field is present", HFILL } },
434 { &hf_radiotap_present_tx_attenuation,
435 { "TX Attenuation", "radiotap.present.tx_attenuation",
436 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_TX_ATTENUATION,
437 "Specifies if the transmit power from max power field is present", HFILL } },
439 { &hf_radiotap_present_db_tx_attenuation,
440 { "DB TX Attenuation", "radiotap.present.db_tx_attenuation",
441 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_DB_TX_ATTENUATION,
442 "Specifies if the transmit power from max power (in dB) field is present", HFILL } },
444 { &hf_radiotap_present_dbm_tx_attenuation,
445 { "DBM TX Attenuation", "radiotap.present.dbm_tx_attenuation",
446 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_DBM_TX_ATTENUATION,
447 "Specifies if the transmit power from max power (in dBm) field is present", HFILL } },
449 { &hf_radiotap_present_antenna,
450 { "Antenna", "radiotap.present.antenna",
451 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_ANTENNA,
452 "Specifies if the antenna number field is present", HFILL } },
454 { &hf_radiotap_present_db_antsignal,
455 { "DB Antenna Signal", "radiotap.present.db_antsignal",
456 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_DB_ANTSIGNAL,
457 "Specifies if the RF signal power at antenna in dB field is present", HFILL } },
459 { &hf_radiotap_present_db_antnoise,
460 { "DB Antenna Noise", "radiotap.present.db_antnoise",
461 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_DB_ANTNOISE,
462 "Specifies if the RF signal power at antenna in dBm field is present", HFILL } },
464 { &hf_radiotap_present_fcs,
465 { "FCS in header", "radiotap.present.fcs",
466 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_FCS,
467 "Specifies if the FCS field is present", HFILL } },
469 { &hf_radiotap_present_ext,
470 { "Ext", "radiotap.present.ext",
471 FT_BOOLEAN, 32, NULL, RADIOTAP_MASK_EXT,
472 "Specifies if there are any extensions to the header present", HFILL } },
474 /* Boolean 'present.flags' flags */
475 { &hf_radiotap_flags,
476 { "Flags", "radiotap.flags",
477 FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
479 { &hf_radiotap_flags_cfp,
480 { "CFP", "radiotap.flags.cfp",
481 FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_F_CFP,
482 "Sent/Received during CFP", HFILL } },
484 { &hf_radiotap_flags_preamble,
485 { "Preamble", "radiotap.flags.preamble",
486 FT_BOOLEAN, 8, TFS(&preamble_type), IEEE80211_RADIOTAP_F_SHORTPRE,
487 "Sent/Received with short preamble", HFILL } },
489 { &hf_radiotap_flags_wep,
490 { "WEP", "radiotap.flags.wep",
491 FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_F_WEP,
492 "Sent/Received with WEP encryption", HFILL } },
494 { &hf_radiotap_flags_frag,
495 { "Fragmentation", "radiotap.flags.frag",
496 FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_F_FRAG,
497 "Sent/Received with fragmentation", HFILL } },
499 { &hf_radiotap_flags_fcs,
500 { "FCS at end", "radiotap.flags.fcs",
501 FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_F_FCS,
502 "Frame includes FCS at end", HFILL } },
504 { &hf_radiotap_flags_datapad,
505 { "Data Pad", "radiotap.flags.datapad",
506 FT_BOOLEAN, 8, NULL, IEEE80211_RADIOTAP_F_DATAPAD,
507 "Frame has padding between 802.11 header and payload", HFILL } },
510 { &hf_radiotap_mactime,
511 { "MAC timestamp", "radiotap.mactime",
512 FT_UINT64, BASE_DEC, NULL, 0x0,
513 " Value in microseconds of the MAC's Time Synchronization Function timer when the first bit of the MPDU arrived at the MAC.", HFILL } },
515 { &hf_radiotap_quality,
516 { "Signal Quality", "radiotap.quality",
517 FT_UINT16, BASE_DEC, NULL, 0x0,
518 "Signal quality (unitless measure)", HFILL } },
521 { "802.11 FCS", "radiotap.fcs",
522 FT_UINT32, BASE_HEX, NULL, 0x0,
523 "Frame check sequence of this frame", HFILL } },
525 { &hf_radiotap_channel,
526 { "Channel", "radiotap.channel",
527 FT_UINT32, BASE_DEC, NULL, 0x0,
528 "802.11 channel number that this frame was sent/received on", HFILL } },
530 { &hf_radiotap_channel_frequency,
531 { "Channel frequency", "radiotap.channel.freq",
532 FT_UINT32, BASE_DEC, NULL, 0x0,
533 "Channel frequency in megahertz that this frame was sent/received on", HFILL } },
535 { &hf_radiotap_channel_flags,
536 { "Channel type", "radiotap.channel.type",
537 FT_UINT16, BASE_HEX, VALS(phy_type), 0x0,
538 "Channel type", HFILL } },
540 { &hf_radiotap_channel_flags_turbo,
541 { "Turbo", "radiotap.channel.type.turbo",
542 FT_BOOLEAN, 16, NULL, 0x0010, "Channel Type Turbo", HFILL } },
543 { &hf_radiotap_channel_flags_cck,
544 { "Complementary Code Keying (CCK)", "radiotap.channel.type.cck",
545 FT_BOOLEAN, 16, NULL, 0x0020, "Channel Type Complementary Code Keying (CCK) Modulation", HFILL } },
546 { &hf_radiotap_channel_flags_ofdm,
547 { "Orthogonal Frequency-Division Multiplexing (OFDM)", "radiotap.channel.type.ofdm",
548 FT_BOOLEAN, 16, NULL, 0x0040, "Channel Type Orthogonal Frequency-Division Multiplexing (OFDM)", HFILL } },
549 { &hf_radiotap_channel_flags_2ghz,
550 { "2 GHz spectrum", "radiotap.channel.type.2ghz",
551 FT_BOOLEAN, 16, NULL, 0x0080, "Channel Type 2 GHz spectrum", HFILL } },
552 { &hf_radiotap_channel_flags_5ghz,
553 { "5 GHz spectrum", "radiotap.channel.type.5ghz",
554 FT_BOOLEAN, 16, NULL, 0x0100, "Channel Type 5 GHz spectrum", HFILL } },
555 { &hf_radiotap_channel_flags_passive,
556 { "Passive", "radiotap.channel.type.passive",
557 FT_BOOLEAN, 16, NULL, 0x0200, "Channel Type Passive", HFILL } },
558 { &hf_radiotap_channel_flags_dynamic,
559 { "Dynamic CCK-OFDM", "radiotap.channel.type.dynamic",
560 FT_BOOLEAN, 16, NULL, 0x0400, "Channel Type Dynamic CCK-OFDM Channel", HFILL } },
561 { &hf_radiotap_channel_flags_gfsk,
562 { "Gaussian Frequency Shift Keying (GFSK)", "radiotap.channel.type.gfsk",
563 FT_BOOLEAN, 16, NULL, 0x0800, "Channel Type Gaussian Frequency Shift Keying (GFSK) Modulation", HFILL } },
565 { &hf_radiotap_fhss_hopset,
566 { "FHSS Hop Set", "radiotap.fhss.hopset",
567 FT_UINT8, BASE_DEC, NULL, 0x0,
568 "Frequency Hopping Spread Spectrum hopset", HFILL } },
570 { &hf_radiotap_fhss_pattern,
571 { "FHSS Pattern", "radiotap.fhss.pattern",
572 FT_UINT8, BASE_DEC, NULL, 0x0,
573 "Frequency Hopping Spread Spectrum hop pattern", HFILL } },
575 { &hf_radiotap_datarate,
576 { "Data rate", "radiotap.datarate",
577 FT_UINT32, BASE_DEC, NULL, 0x0,
578 "Speed this frame was sent/received at", HFILL } },
580 { &hf_radiotap_antenna,
581 { "Antenna", "radiotap.antenna",
582 FT_UINT32, BASE_DEC, NULL, 0x0,
583 "Antenna number this frame was sent/received over (starting at 0)", HFILL } },
585 { &hf_radiotap_dbm_antsignal,
586 { "SSI Signal (dBm)", "radiotap.dbm_antsignal",
587 FT_INT32, BASE_DEC, NULL, 0x0,
588 "RF signal power at the antenna from a fixed, arbitrary value in decibels from one milliwatt", HFILL } },
590 { &hf_radiotap_db_antsignal,
591 { "SSI Signal (dB)", "radiotap.db_antsignal",
592 FT_UINT32, BASE_DEC, NULL, 0x0,
593 "RF signal power at the antenna from a fixed, arbitrary value in decibels", HFILL } },
595 { &hf_radiotap_dbm_antnoise,
596 { "SSI Noise (dBm)", "radiotap.dbm_antnoise",
597 FT_INT32, BASE_DEC, NULL, 0x0,
598 "RF noise power at the antenna from a fixed, arbitrary value in decibels per one milliwatt", HFILL } },
600 { &hf_radiotap_db_antnoise,
601 { "SSI Noise (dB)", "radiotap.db_antnoise",
602 FT_UINT32, BASE_DEC, NULL, 0x0,
603 "RF noise power at the antenna from a fixed, arbitrary value in decibels", HFILL } },
605 { &hf_radiotap_tx_attenuation,
606 { "Transmit attenuation", "radiotap.txattenuation",
607 FT_UINT16, BASE_DEC, NULL, 0x0,
608 "Transmit power expressed as unitless distance from max power set at factory (0 is max power)", HFILL } },
610 { &hf_radiotap_db_tx_attenuation,
611 { "Transmit attenuation (dB)", "radiotap.db_txattenuation",
612 FT_UINT16, BASE_DEC, NULL, 0x0,
613 "Transmit power expressed as decibels from max power set at factory (0 is max power)", HFILL } },
615 { &hf_radiotap_txpower,
616 { "Transmit power", "radiotap.txpower",
617 FT_INT32, BASE_DEC, NULL, 0x0,
618 "Transmit power in decibels per one milliwatt (dBm)", HFILL } },
620 /* Special variables */
621 { &hf_radiotap_fcs_bad,
622 { "Bad FCS", "radiotap.fcs_bad",
623 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
624 "Specifies if this frame has a bad frame check sequence", HFILL } },
627 static gint *ett[] = {
629 &ett_radiotap_present,
631 &ett_radiotap_channel_flags
634 proto_radiotap = proto_register_protocol("IEEE 802.11 Radiotap Capture header", "802.11 Radiotap", "radiotap");
635 proto_register_field_array(proto_radiotap, hf, array_length(hf));
636 proto_register_subtree_array(ett, array_length(ett));
637 register_dissector("radiotap", dissect_radiotap, proto_radiotap);
642 dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
644 proto_tree *radiotap_tree = NULL;
645 proto_tree *pt, *present_tree = NULL;
646 proto_tree *ft, *flags_tree = NULL;
647 proto_item *ti = NULL;
648 proto_item *hdr_fcs_ti = NULL;
649 int hdr_fcs_offset = 0;
650 int align_offset, offset;
651 guint32 sent_fcs = 0;
655 guint length, length_remaining;
656 guint32 rate, freq, flags;
659 guint32 present, next_present;
662 if(check_col(pinfo->cinfo, COL_PROTOCOL))
663 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
664 if(check_col(pinfo->cinfo, COL_INFO))
665 col_clear(pinfo->cinfo, COL_INFO);
668 version = tvb_get_guint8(tvb, offset);
669 length = tvb_get_letohs(tvb, offset+2);
670 present = tvb_get_letohl(tvb, offset+4);
672 if(check_col(pinfo->cinfo, COL_INFO))
673 col_add_fstr(pinfo->cinfo, COL_INFO, "Radiotap Capture v%u, Length %u",
676 /* Dissect the packet */
678 ti = proto_tree_add_protocol_format(tree, proto_radiotap,
679 tvb, 0, length, "Radiotap Header v%u, Length %u", version, length);
680 radiotap_tree = proto_item_add_subtree(ti, ett_radiotap);
681 proto_tree_add_uint(radiotap_tree, hf_radiotap_version,
682 tvb, offset, 1, version);
683 proto_tree_add_item(radiotap_tree, hf_radiotap_pad,
684 tvb, offset + 1, 1, FALSE);
685 ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_length,
686 tvb, offset + 2, 2, length);
688 length_remaining = length;
691 * FIXME: This only works if there is exactly 1 it_present
692 * field in the header
694 if (length_remaining < RADIOTAP_MIN_HEADER_LEN) {
696 * Radiotap header is shorter than the fixed-length portion
697 * plus one "present" bitset.
700 proto_item_append_text(ti, " (bogus - minimum length is 8)");
703 /* Subtree for the "present flags" bitfield. */
705 pt = proto_tree_add_uint(radiotap_tree, hf_radiotap_present,
706 tvb, offset + 4, 4, present);
707 present_tree = proto_item_add_subtree(pt, ett_radiotap_present);
709 proto_tree_add_item(present_tree, hf_radiotap_present_tsft,
711 proto_tree_add_item(present_tree, hf_radiotap_present_flags,
713 proto_tree_add_item(present_tree, hf_radiotap_present_rate,
715 proto_tree_add_item(present_tree, hf_radiotap_present_channel,
717 proto_tree_add_item(present_tree, hf_radiotap_present_fhss,
719 proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antsignal,
721 proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antnoise,
723 proto_tree_add_item(present_tree, hf_radiotap_present_lock_quality,
725 proto_tree_add_item(present_tree, hf_radiotap_present_tx_attenuation,
727 proto_tree_add_item(present_tree, hf_radiotap_present_db_tx_attenuation,
729 proto_tree_add_item(present_tree, hf_radiotap_present_dbm_tx_attenuation,
731 proto_tree_add_item(present_tree, hf_radiotap_present_antenna,
733 proto_tree_add_item(present_tree, hf_radiotap_present_db_antsignal,
735 proto_tree_add_item(present_tree, hf_radiotap_present_db_antnoise,
737 proto_tree_add_item(present_tree, hf_radiotap_present_fcs,
739 proto_tree_add_item(present_tree, hf_radiotap_present_ext,
742 offset += RADIOTAP_MIN_HEADER_LEN;
743 length_remaining -= RADIOTAP_MIN_HEADER_LEN;
746 for (; present; present = next_present) {
747 /* clear the least significant bit that is set */
748 next_present = present & (present - 1);
750 /* extract the least significant bit that is set */
751 bit = BITNO_32(present ^ next_present);
754 case IEEE80211_RADIOTAP_FLAGS:
755 if (length_remaining < 1)
757 rflags = tvb_get_guint8(tvb, offset);
759 ft = proto_tree_add_item(radiotap_tree, hf_radiotap_flags,
760 tvb, offset, 1, FALSE);
761 flags_tree = proto_item_add_subtree(ft, ett_radiotap_flags);
763 proto_tree_add_item(flags_tree, hf_radiotap_flags_cfp,
764 tvb, offset, 1, FALSE);
765 proto_tree_add_item(flags_tree, hf_radiotap_flags_preamble,
766 tvb, offset, 1, FALSE);
767 proto_tree_add_item(flags_tree, hf_radiotap_flags_wep,
768 tvb, offset, 1, FALSE);
769 proto_tree_add_item(flags_tree, hf_radiotap_flags_frag,
770 tvb, offset, 1, FALSE);
771 proto_tree_add_item(flags_tree, hf_radiotap_flags_fcs,
772 tvb, offset, 1, FALSE);
773 proto_tree_add_item(flags_tree, hf_radiotap_flags_datapad,
774 tvb, offset, 1, FALSE);
780 case IEEE80211_RADIOTAP_RATE:
781 if (length_remaining < 1)
783 rate = tvb_get_guint8(tvb, offset) & 0x7f;
784 if (check_col(pinfo->cinfo, COL_TX_RATE)) {
785 col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%d.%d",
786 rate / 2, rate & 1 ? 5 : 0);
789 proto_tree_add_uint_format(radiotap_tree, hf_radiotap_datarate,
790 tvb, offset, 1, tvb_get_guint8(tvb, offset),
791 "Data Rate: %d.%d Mb/s", rate / 2, rate & 1 ? 5 : 0);
796 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
797 if (length_remaining < 1)
799 dbm = (gint8) tvb_get_guint8(tvb, offset);
800 if (check_col(pinfo->cinfo, COL_RSSI)) {
801 col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", dbm);
804 proto_tree_add_int_format(radiotap_tree,
805 hf_radiotap_dbm_antsignal,
807 "SSI Signal: %d dBm", dbm);
812 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
813 if (length_remaining < 1)
815 db = tvb_get_guint8(tvb, offset);
816 if (check_col(pinfo->cinfo, COL_RSSI)) {
817 col_add_fstr(pinfo->cinfo, COL_RSSI, "%u dB", db);
820 proto_tree_add_uint_format(radiotap_tree,
821 hf_radiotap_db_antsignal,
823 "SSI Signal: %u dB", db);
828 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
829 if (length_remaining < 1)
831 dbm = (gint8) tvb_get_guint8(tvb, offset);
833 proto_tree_add_int_format(radiotap_tree,
834 hf_radiotap_dbm_antnoise,
836 "SSI Noise: %d dBm", dbm);
841 case IEEE80211_RADIOTAP_DB_ANTNOISE:
842 if (length_remaining < 1)
844 db = tvb_get_guint8(tvb, offset);
846 proto_tree_add_uint_format(radiotap_tree,
847 hf_radiotap_db_antnoise,
849 "SSI Noise: %u dB", db);
854 case IEEE80211_RADIOTAP_ANTENNA:
855 if (length_remaining < 1)
858 proto_tree_add_uint(radiotap_tree, hf_radiotap_antenna,
859 tvb, offset, 1, tvb_get_guint8(tvb, offset));
864 case IEEE80211_RADIOTAP_DBM_TX_POWER:
865 if (length_remaining < 1)
868 proto_tree_add_int(radiotap_tree, hf_radiotap_txpower,
869 tvb, offset, 1, tvb_get_guint8(tvb, offset));
874 case IEEE80211_RADIOTAP_CHANNEL:
877 proto_tree *flags_tree;
880 align_offset = ALIGN_OFFSET(offset, 2);
881 offset += align_offset;
882 length_remaining -= align_offset;
883 if (length_remaining < 2)
886 freq = tvb_get_letohs(tvb, offset);
887 flags = tvb_get_letohs(tvb, offset+2);
888 chan_str = ieee80211_mhz_to_str(freq);
889 if (check_col(pinfo->cinfo, COL_FREQ_CHAN)) {
890 col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%s", chan_str);
892 proto_tree_add_uint_format(radiotap_tree, hf_radiotap_channel_frequency,
893 tvb, offset, 2, freq,
894 "Channel frequency: %s", chan_str);
896 /* We're already 2-byte aligned. */
897 it = proto_tree_add_uint(radiotap_tree, hf_radiotap_channel_flags,
898 tvb, offset+2, 2, flags);
899 flags_tree = proto_item_add_subtree(it, ett_radiotap_channel_flags);
900 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_turbo,
901 tvb, offset+2, 1, flags);
902 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_cck,
903 tvb, offset+2, 1, flags);
904 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_ofdm,
905 tvb, offset+2, 1, flags);
906 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_2ghz,
907 tvb, offset+2, 1, flags);
908 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_5ghz,
909 tvb, offset+3, 1, flags);
910 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_passive,
911 tvb, offset+3, 1, flags);
912 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_dynamic,
913 tvb, offset+3, 1, flags);
914 proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_gfsk,
915 tvb, offset+3, 1, flags);
917 offset+=4 /* Channel + flags */;
921 case IEEE80211_RADIOTAP_FHSS:
922 align_offset = ALIGN_OFFSET(offset, 2);
923 offset += align_offset;
924 length_remaining -= align_offset;
925 if (length_remaining < 2)
927 proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_hopset,
928 tvb, offset, 1, FALSE);
929 proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_pattern,
930 tvb, offset, 1, FALSE);
934 case IEEE80211_RADIOTAP_TX_ATTENUATION:
935 align_offset = ALIGN_OFFSET(offset, 2);
936 offset += align_offset;
937 length_remaining -= align_offset;
938 if (length_remaining < 2)
940 proto_tree_add_item(radiotap_tree, hf_radiotap_tx_attenuation,
941 tvb, offset, 2, FALSE);
945 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
946 align_offset = ALIGN_OFFSET(offset, 2);
947 offset += align_offset;
948 length_remaining -= align_offset;
949 if (length_remaining < 2)
951 proto_tree_add_item(radiotap_tree, hf_radiotap_db_tx_attenuation,
952 tvb, offset, 2, FALSE);
956 case IEEE80211_RADIOTAP_TSFT:
957 align_offset = ALIGN_OFFSET(offset, 8);
958 offset += align_offset;
959 length_remaining -= align_offset;
960 if (length_remaining < 8)
963 proto_tree_add_uint64(radiotap_tree, hf_radiotap_mactime,
964 tvb, offset, 8, tvb_get_letoh64(tvb, offset));
969 case IEEE80211_RADIOTAP_LOCK_QUALITY:
970 align_offset = ALIGN_OFFSET(offset, 2);
971 offset += align_offset;
972 length_remaining -= align_offset;
973 if (length_remaining < 2)
976 proto_tree_add_uint(radiotap_tree, hf_radiotap_quality,
977 tvb, offset, 2, tvb_get_letohs(tvb, offset));
982 case IEEE80211_RADIOTAP_FCS:
983 /* This handles the case of an FCS existing inside the radiotap header. */
984 align_offset = ALIGN_OFFSET(offset, 4);
985 offset += align_offset;
986 length_remaining -= align_offset;
987 if (length_remaining < 4)
990 sent_fcs = tvb_get_ntohl(tvb, offset);
991 hdr_fcs_ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_fcs,
992 tvb, offset, 4, sent_fcs);
993 hdr_fcs_offset = offset;
1000 * This indicates a field whose size we do not
1001 * know, so we cannot proceed.
1008 /* This handles the case of an FCS exiting at the end of the frame. */
1009 if (rflags & IEEE80211_RADIOTAP_F_FCS)
1010 pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
1012 pinfo->pseudo_header->ieee_802_11.fcs_len = 0;
1014 /* Grab the rest of the frame. */
1015 next_tvb = tvb_new_subset(tvb, length, -1, -1);
1017 /* If we had an in-header FCS, check it. */
1019 /* It would be very strange for the header to have an FCS for the
1020 * frame *and* the frame to have the FCS at the end, but it's possible, so
1021 * take that into account by using the FCS length recorded in pinfo. */
1023 /* Watch out for [erroneously] short frames */
1024 if (tvb_length(next_tvb) > (unsigned int) pinfo->pseudo_header->ieee_802_11.fcs_len) {
1025 calc_fcs = crc32_802_tvb(next_tvb,
1026 tvb_length(next_tvb) - pinfo->pseudo_header->ieee_802_11.fcs_len);
1028 /* By virtue of hdr_fcs_ti being set, we know that 'tree' is set,
1029 * so there's no need to check it here. */
1030 if (calc_fcs == sent_fcs) {
1031 proto_item_append_text(hdr_fcs_ti, " [correct]");
1034 proto_item_append_text(hdr_fcs_ti,
1035 " [incorrect, should be 0x%08x]", calc_fcs);
1036 proto_tree_add_boolean_hidden(radiotap_tree, hf_radiotap_fcs_bad,
1037 tvb, hdr_fcs_offset, 4, TRUE);
1041 proto_item_append_text(hdr_fcs_ti,
1042 " [cannot verify - not enough data]");
1046 /* dissect the 802.11 header next */
1047 call_dissector((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ?
1048 ieee80211_datapad_handle : ieee80211_handle,
1049 next_tvb, pinfo, tree);
1053 proto_reg_handoff_radiotap(void)
1055 dissector_handle_t radiotap_handle;
1057 /* handle for 802.11 dissector */
1058 ieee80211_handle = find_dissector("wlan");
1059 ieee80211_datapad_handle = find_dissector("wlan_datapad");
1061 radiotap_handle = create_dissector_handle(dissect_radiotap, proto_radiotap);
1063 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WLAN_RADIOTAP, radiotap_handle);