Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-rftap.c
Line
Count
Source
1
/*
2
 *  packet-rftap.c
3
 *  Decode packets with a RFtap header
4
 *  Copyright 2016, Jonathan Brucker <jonathan.brucke@gmail.com>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
/*
14
 * The RFtap header is a simple meta-data header designed to provide
15
 * RF (Radio Frequency) meta-data about frames, such as:
16
 * - Accurate signal and noise power
17
 * - Accurate timing and phase information
18
 * - Accurate carrier and Doppler frequencies, and more.
19
 * The RFtap protocol can be used to encapsulate any type of frame.
20
 *
21
 * Official specification:
22
 * https://rftap.github.io
23
 */
24
25
#include <config.h>
26
27
#include <epan/packet.h>
28
#include <epan/unit_strings.h>
29
#include <epan/expert.h>
30
#include <epan/proto_data.h>
31
32
#include <wsutil/array.h>
33
34
/* Prototypes */
35
/* (Required to prevent [-Wmissing-prototypes] warnings */
36
void proto_reg_handoff_rftap(void);
37
void proto_register_rftap(void);
38
39
/* protocols */
40
static int proto_rftap;
41
42
/* rftap fixed fields */
43
static int hf_rftap_fixed_header;
44
static int hf_rftap_magic;
45
static int hf_rftap_len;    /* length in bytes */
46
static int hf_rftap_flags;
47
48
/* rftap flags bit-field (16 bits) */
49
static int hf_rftap_present_dlt;
50
static int hf_rftap_present_freq;
51
static int hf_rftap_present_nomfreq;
52
static int hf_rftap_present_freqofs;
53
static int hf_rftap_power_is_in_dbm;
54
static int hf_rftap_present_signal_power;
55
static int hf_rftap_present_noise_power;
56
static int hf_rftap_present_snr;
57
static int hf_rftap_present_signal_quality;
58
static int hf_rftap_time_is_unix_time;
59
static int hf_rftap_present_time;
60
static int hf_rftap_present_duration;
61
static int hf_rftap_present_location;
62
static int hf_rftap_present_reserved_field_13;
63
static int hf_rftap_present_reserved_field_14;
64
static int hf_rftap_present_reserved_field_15;
65
66
/* rftap optional fields */
67
static int hf_rftap_dlt;
68
static int hf_rftap_freq;
69
static int hf_rftap_nomfreq;
70
static int hf_rftap_freqofs;
71
static int hf_rftap_signal_power;
72
static int hf_rftap_noise_power;
73
static int hf_rftap_snr;
74
static int hf_rftap_signal_quality;
75
static int hf_rftap_time_int;
76
static int hf_rftap_time_frac;
77
static int hf_rftap_time;
78
static int hf_rftap_duration;
79
static int hf_rftap_latitude;
80
static int hf_rftap_longitude;
81
static int hf_rftap_altitude;
82
83
/* rftap tag IDs >= 16 */
84
static int hf_rftap_subdissector_name;
85
86
static expert_field ei_rftap_nesting;
87
88
0
#define RFTAP_MAX_NESTING 8
89
90
/* subtree pointers */
91
static int ett_rftap;
92
static int ett_rftap_fixed_header;
93
static int ett_rftap_flags;
94
95
static dissector_handle_t pcap_pktdata_handle;
96
97
531
#define RFTAP_MAGIC 0x61744652UL  /* "RFta" */
98
99
enum rftap_tag_id {
100
    RFTAP_TAG_DLT = 0,
101
    RFTAP_TAG_FREQ = 1,
102
    RFTAP_TAG_NOM_FREQ = 2,
103
    RFTAP_TAG_FREQ_OFS = 3,
104
    RFTAP_TAG_POWER_IS_IN_DBM = 4,
105
    RFTAP_TAG_SIGNAL_POWER = 5,
106
    RFTAP_TAG_NOISE_POWER = 6,
107
    RFTAP_TAG_SNR = 7,
108
    RFTAP_TAG_SIGNAL_QUALITY = 8,
109
    RFTAP_TAG_TIME_IS_UNIX_TIME = 9,
110
    RFTAP_TAG_TIME = 10,
111
    RFTAP_TAG_DURATION = 11,
112
    RFTAP_TAG_LOCATION = 12,
113
    RFTAP_TAG_RESERVED_13 = 13,
114
    RFTAP_TAG_RESERVED_14 = 14,
115
    RFTAP_TAG_RESERVED_15 = 15,
116
    RFTAP_TAG_DISSECTOR_NAME = 16
117
};
118
119
/* This is the header as it is used by rftap-generating software.
120
 * It is not used by the wireshark dissector and provided for reference only.
121
struct rftap_hdr {
122
    le32 magic;  // "RFta"
123
    le16 len32;  // sizeof(rftap_hdr) / sizeof(le32)
124
    le16 flags;  // bitfield indicating presence of parameters
125
    le32 data[];
126
} __attribute__((packed));
127
 */
128
129
/* dissect the rftap header part of the packet
130
 * returns Data Link Type (dlt) and subdissector name
131
 */
132
static void
133
dissect_rftap_header(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t *dlt, const char **subdissector_name)
134
287
{
135
287
    proto_item *ti_header;
136
287
    proto_tree *header_tree;
137
287
    int32_t offset;
138
287
    int32_t len;
139
287
    uint64_t flags;
140
287
    uint32_t flag_bit;
141
287
    uint32_t tag_id;
142
287
    int32_t tag_len;
143
287
    uint32_t tag_flags;
144
287
    double double_val;
145
287
    float   float_val;
146
287
    char    *power_units;
147
148
287
    static int * const flag_fields[] = {
149
287
        &hf_rftap_present_dlt,
150
287
        &hf_rftap_present_freq,
151
287
        &hf_rftap_present_nomfreq,
152
287
        &hf_rftap_present_freqofs,
153
287
        &hf_rftap_power_is_in_dbm,
154
287
        &hf_rftap_present_signal_power,
155
287
        &hf_rftap_present_noise_power,
156
287
        &hf_rftap_present_snr,
157
287
        &hf_rftap_present_signal_quality,
158
287
        &hf_rftap_time_is_unix_time,
159
287
        &hf_rftap_present_time,
160
287
        &hf_rftap_present_duration,
161
287
        &hf_rftap_present_location,
162
287
        &hf_rftap_present_reserved_field_13,
163
287
        &hf_rftap_present_reserved_field_14,
164
287
        &hf_rftap_present_reserved_field_15,
165
287
        NULL
166
287
    };
167
168
287
    *dlt = 0xffffffff;
169
287
    *subdissector_name = NULL;
170
171
    /* rftap fixed header sub-tree */
172
173
287
    ti_header = proto_tree_add_item(tree, hf_rftap_fixed_header, tvb, 0, 8, ENC_NA);
174
287
    header_tree = proto_item_add_subtree(ti_header, ett_rftap_fixed_header);
175
176
287
    proto_tree_add_item(header_tree, hf_rftap_magic, tvb, 0, 4, ENC_LITTLE_ENDIAN);
177
287
    len = 4 * (int32_t) tvb_get_letohs(tvb, 4);  /* convert to length in bytes */
178
287
    proto_tree_add_uint(header_tree, hf_rftap_len, tvb, 4, 2, len);  /* show length in bytes */
179
287
    proto_tree_add_bitmask_ret_uint64(header_tree, tvb, 6, hf_rftap_flags,
180
287
        ett_rftap_flags, flag_fields, ENC_LITTLE_ENDIAN, &flags);
181
182
    /* rftap parameter fields */
183
184
287
    power_units = (flags & (1 << RFTAP_TAG_POWER_IS_IN_DBM)) ? "dBm" : "dB";
185
186
287
    offset = 8;
187
287
    flag_bit = 1;
188
4.14k
    for (tag_id = 0; tag_id < 16; tag_id++, flag_bit<<=1) {
189
190
4.10k
        if (!(flags & flag_bit))
191
2.42k
            continue;  /* parameter is not present, skip */
192
193
1.67k
        switch (tag_id) {
194
287
        case RFTAP_TAG_DLT:
195
287
            proto_tree_add_item_ret_uint(tree, hf_rftap_dlt, tvb, offset, 4, ENC_LITTLE_ENDIAN, dlt);
196
287
            offset += 4;
197
287
            break;
198
21
        case RFTAP_TAG_FREQ:
199
21
            proto_tree_add_item(tree, hf_rftap_freq, tvb, offset, 8, ENC_LITTLE_ENDIAN);
200
21
            offset += 8;
201
21
            break;
202
242
        case RFTAP_TAG_NOM_FREQ:
203
242
            proto_tree_add_item(tree, hf_rftap_nomfreq, tvb, offset, 8, ENC_LITTLE_ENDIAN);
204
242
            offset += 8;
205
242
            break;
206
3
        case RFTAP_TAG_FREQ_OFS:
207
3
            proto_tree_add_item(tree, hf_rftap_freqofs, tvb, offset, 8, ENC_LITTLE_ENDIAN);
208
3
            offset += 8;
209
3
            break;
210
236
        case RFTAP_TAG_POWER_IS_IN_DBM:
211
            /* do nothing, it's already decoded in flags bit-field */
212
236
            break;
213
239
        case RFTAP_TAG_SIGNAL_POWER:
214
239
            float_val = tvb_get_letohieee_float(tvb, offset);
215
239
            proto_tree_add_float_format_value(tree, hf_rftap_signal_power, tvb, offset, 4, float_val, "%.2f %s", float_val, power_units);
216
239
            offset += 4;
217
239
            break;
218
0
        case RFTAP_TAG_NOISE_POWER:
219
0
            float_val = tvb_get_letohieee_float(tvb, offset);
220
0
            proto_tree_add_float_format_value(tree, hf_rftap_noise_power, tvb, offset, 4, float_val, "%.2f %s", float_val, power_units);
221
0
            offset += 4;
222
0
            break;
223
268
        case RFTAP_TAG_SNR:
224
268
            float_val = tvb_get_letohieee_float(tvb, offset);
225
268
            proto_tree_add_float_format_value(tree, hf_rftap_snr, tvb, offset, 4, float_val, "%.2f dB", float_val);
226
268
            offset += 4;
227
268
            break;
228
83
        case RFTAP_TAG_SIGNAL_QUALITY:
229
83
            proto_tree_add_item(tree, hf_rftap_signal_quality, tvb, offset, 4, ENC_LITTLE_ENDIAN);
230
83
            offset += 4;
231
83
            break;
232
28
        case RFTAP_TAG_TIME_IS_UNIX_TIME:
233
            /* do nothing, it's already decoded in flags bit-field */
234
28
            break;
235
21
        case RFTAP_TAG_TIME:
236
21
            double_val = tvb_get_letohieee_double(tvb, offset);
237
21
            proto_tree_add_double_format_value(tree, hf_rftap_time_int, tvb, offset, 8, double_val, "%.0f seconds", double_val);
238
21
            double_val = tvb_get_letohieee_double(tvb, offset + 8);
239
21
            proto_tree_add_double_format_value(tree, hf_rftap_time_frac, tvb, offset+8, 8, double_val, "%.9f seconds", double_val);
240
            /* compute combined time: (not accurate, error is > 300 nanoseconds) */
241
21
            double_val += tvb_get_letohieee_double(tvb, offset);
242
21
            proto_tree_add_double_format_value(tree, hf_rftap_time, tvb, offset, 16, double_val, "%.6f seconds", double_val);
243
21
            offset += 16;
244
21
            break;
245
0
        case RFTAP_TAG_DURATION:
246
0
            proto_tree_add_item(tree, hf_rftap_duration, tvb, offset, 8, ENC_LITTLE_ENDIAN);
247
0
            offset += 8;
248
0
            break;
249
0
        case RFTAP_TAG_LOCATION:
250
0
            proto_tree_add_item(tree, hf_rftap_latitude, tvb, offset, 8, ENC_LITTLE_ENDIAN);
251
0
            proto_tree_add_item(tree, hf_rftap_longitude, tvb, offset+8, 8, ENC_LITTLE_ENDIAN);
252
0
            proto_tree_add_item(tree, hf_rftap_altitude, tvb, offset+16, 8, ENC_LITTLE_ENDIAN);
253
0
            offset += 24;
254
0
            break;
255
248
        default:
256
248
            return;  /* we've hit a parameter we can't decode, abort */
257
1.67k
        }
258
1.67k
    }
259
260
39
    if (offset >= len)
261
2
        return;  /* there are no tagged parameters to decode, goodbye */
262
263
    /* rftap tagged parameter fields */
264
265
37
    tag_id = tvb_get_letohs(tvb, offset);
266
37
    tag_len = tvb_get_uint8(tvb, offset+2);
267
37
    tag_flags = tvb_get_uint8(tvb, offset+3);
268
269
37
    if ((tag_id != RFTAP_TAG_DISSECTOR_NAME) || (tag_len == 0) || (tag_len == 255) || (tag_flags != 255))
270
37
        return;  /* we've hit a tagged parameter we can't decode, abort */
271
272
0
    proto_tree_add_item_ret_string(tree, hf_rftap_subdissector_name, tvb,
273
0
        offset+4, tag_len, ENC_ASCII, pinfo->pool, (const uint8_t**)subdissector_name);
274
0
}
275
276
/* Main entry point to dissect the packets.
277
 *
278
 * Each packet consists of two parts:
279
 * - The rftap header, containing all the RF metadata.
280
 * - The encapsulated data packet, decoded by a sub-dissector.
281
 */
282
static int
283
dissect_rftap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
284
        void *data _U_)
285
543
{
286
543
    proto_item *ti;
287
543
    proto_tree *rftap_tree;
288
289
543
    tvbuff_t   *rftap_tvb;  /* the first part of the packet */
290
543
    tvbuff_t   *subdissector_tvb;  /* the second part of the packet */
291
292
543
    int32_t     rftap_len;  /* length in bytes */
293
543
    dissector_handle_t subdissector_handle;
294
543
    uint32_t    subdissector_dlt;
295
543
    const char *subdissector_name;
296
297
    /* heuristics */
298
299
543
    if (tvb_captured_length(tvb) < 8)  /* 4 magic + 2 len + 2 flags = 8 bytes */
300
12
        return 0;
301
302
531
    if (tvb_get_letohl(tvb, 0) != RFTAP_MAGIC)
303
244
        return 0;
304
305
    /* column info */
306
307
287
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFTAP");
308
287
    col_clear(pinfo->cinfo, COL_INFO);
309
287
    clear_address(&pinfo->src);
310
287
    clear_address(&pinfo->dst);
311
312
    /* dissect part 1: rftap header */
313
314
287
    rftap_len = 4 * (int32_t) tvb_get_letohs(tvb, 4);
315
287
    rftap_tvb = tvb_new_subset_length(tvb, 0, rftap_len);
316
317
287
    ti = proto_tree_add_protocol_format(tree, proto_rftap, rftap_tvb, 0, -1,
318
287
        "RFtap Protocol (%d bytes)", rftap_len);
319
287
    rftap_tree = proto_item_add_subtree(ti, ett_rftap);
320
321
287
    dissect_rftap_header(rftap_tvb, rftap_tree, pinfo, &subdissector_dlt, &subdissector_name);
322
323
    /* dissect part 2: data packet */
324
325
287
    subdissector_tvb = tvb_new_subset_remaining(tvb, rftap_len);
326
327
    /* try using data link type (DLT) */
328
287
    if (subdissector_dlt != 0xffffffff) {
329
287
        call_dissector_with_data(pcap_pktdata_handle, subdissector_tvb, pinfo, tree, &subdissector_dlt);
330
287
        return tvb_captured_length(tvb);
331
287
    }
332
333
    /* try using dissector name */
334
0
    if (subdissector_name) {
335
0
        subdissector_handle = find_dissector(subdissector_name);
336
0
        if (subdissector_handle) {
337
0
            unsigned depth = p_get_proto_depth(pinfo, proto_rftap);
338
0
            if (depth >= RFTAP_MAX_NESTING) {
339
0
                proto_tree_add_expert(rftap_tree, pinfo, &ei_rftap_nesting, subdissector_tvb, 0, 0);
340
0
                return tvb_captured_length(tvb);
341
0
            }
342
0
            p_set_proto_depth(pinfo, proto_rftap, depth + 1);
343
0
            increment_dissection_depth(pinfo);
344
0
            call_dissector_with_data(subdissector_handle, subdissector_tvb, pinfo, tree, NULL);
345
0
            decrement_dissection_depth(pinfo);
346
0
            p_set_proto_depth(pinfo, proto_rftap, depth);
347
0
            return tvb_captured_length(tvb);
348
0
        }
349
0
    }
350
351
    /* fallback using plain data dissector */
352
0
    call_data_dissector(subdissector_tvb, pinfo, tree);
353
0
    return tvb_captured_length(tvb);
354
0
}
355
356
static bool
357
dissect_rftap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
358
543
{
359
543
    return dissect_rftap(tvb, pinfo, tree, data) != 0;
360
543
}
361
362
/* Register the protocol with Wireshark. */
363
void
364
proto_register_rftap(void)
365
16
{
366
    /* Setup protocol subtree array */
367
16
    static int *ett[] = {
368
16
        &ett_rftap,
369
16
        &ett_rftap_fixed_header,
370
16
        &ett_rftap_flags
371
16
    };
372
373
    /* Setup list of header fields */
374
16
    static hf_register_info hf[] = {
375
376
        /* rftap fixed header */
377
378
16
        { &hf_rftap_fixed_header, {
379
16
            "RFtap Fixed header",
380
16
            "rftap.fixedheader",
381
16
            FT_NONE, BASE_NONE, NULL, 0,
382
16
            "RFtap Fixed 8-byte Header", HFILL }},
383
384
16
        { &hf_rftap_magic, {
385
16
            "Magic",
386
16
            "rftap.magic",
387
16
            FT_UINT32, BASE_HEX, NULL, 0,
388
16
            "RFtap signature: wikipedia.org/wiki/File_format#Magic_number", HFILL }},
389
16
        { &hf_rftap_len, {
390
16
            "Length",
391
16
            "rftap.len",
392
16
            FT_UINT32, BASE_DEC, NULL, 0,
393
16
            "Length (in bytes) of entire rftap header, including tagged (optional) parameters", HFILL }},
394
16
        { &hf_rftap_flags, {
395
16
            "Flags",
396
16
            "rftap.flags",
397
16
            FT_UINT16, BASE_HEX, NULL, 0,
398
16
            "RFtap flags", HFILL }},
399
400
        /* flags bit-field */
401
402
16
        {&hf_rftap_present_dlt, {
403
16
            "DLT Present",
404
16
            "rftap.present.dlt",
405
16
            FT_BOOLEAN, 16, NULL, 0x0001,
406
16
            "Specifies if the DLT (Data Link Type) field is present", HFILL }},
407
16
        {&hf_rftap_present_freq, {
408
16
            "Frequency Present",
409
16
            "rftap.present.freq",
410
16
            FT_BOOLEAN, 16, NULL, 0x0002,
411
16
            "Specifies if the Frequency field is present", HFILL }},
412
16
        {&hf_rftap_present_nomfreq, {
413
16
            "Nominal Frequency Present",
414
16
            "rftap.present.nomfreq",
415
16
            FT_BOOLEAN, 16, NULL, 0x0004,
416
16
            "Specifies if the Nominal Frequency field is present", HFILL }},
417
16
        {&hf_rftap_present_freqofs, {
418
16
            "Frequency Offset Present",
419
16
            "rftap.present.freqofs",
420
16
            FT_BOOLEAN, 16, NULL, 0x0008,
421
16
            "Specifies if the Frequency Offset field is present", HFILL }},
422
16
        {&hf_rftap_power_is_in_dbm, {
423
16
            "Power is in dBm Units",
424
16
            "rftap.isdbm",
425
16
            FT_BOOLEAN, 16, NULL, 0x0010,
426
16
            "Specifies if the Power is specified in dBm units", HFILL }},
427
16
        {&hf_rftap_present_signal_power, {
428
16
            "Signal Power Present",
429
16
            "rftap.present.power",
430
16
            FT_BOOLEAN, 16, NULL, 0x0020,
431
16
            "Specifies if the Signal Power field is present", HFILL }},
432
16
        {&hf_rftap_present_noise_power, {
433
16
            "Noise Power Present",
434
16
            "rftap.present.noise",
435
16
            FT_BOOLEAN, 16, NULL, 0x0040,
436
16
            "Specifies if the Noise Power field is present", HFILL }},
437
16
        {&hf_rftap_present_snr, {
438
16
            "SNR Present",
439
16
            "rftap.present.snr",
440
16
            FT_BOOLEAN, 16, NULL, 0x0080,
441
16
            "Specifies if the SNR field is present", HFILL }},
442
16
        {&hf_rftap_present_signal_quality, {
443
16
            "Signal Quality Present",
444
16
            "rftap.present.qual",
445
16
            FT_BOOLEAN, 16, NULL, 0x0100,
446
16
            "Specifies if the Signal Quality field is present", HFILL }},
447
16
        {&hf_rftap_time_is_unix_time, {
448
16
            "Time standard is Unix Time",
449
16
            "rftap.isunixtime",
450
16
            FT_BOOLEAN, 16, NULL, 0x0200,
451
16
            "Specifies if the time standard is Unix Time: wikipedia.org/wiki/Unix_time", HFILL }},
452
16
        {&hf_rftap_present_time, {
453
16
            "Time Present",
454
16
            "rftap.present.time",
455
16
            FT_BOOLEAN, 16, NULL, 0x0400,
456
16
            "Specifies if the Time field is present", HFILL }},
457
16
        {&hf_rftap_present_duration, {
458
16
            "Duration Present",
459
16
            "rftap.present.duration",
460
16
            FT_BOOLEAN, 16, NULL, 0x0800,
461
16
            "Specifies if the Duration field is present", HFILL }},
462
16
        {&hf_rftap_present_location, {
463
16
            "Location Present",
464
16
            "rftap.present.location",
465
16
            FT_BOOLEAN, 16, NULL, 0x1000,
466
16
            "Specifies if the Location field is present", HFILL }},
467
16
        {&hf_rftap_present_reserved_field_13, {
468
16
            "Reserved Field 13 Present",
469
16
            "rftap.present.field13",
470
16
            FT_BOOLEAN, 16, NULL, 0x2000,
471
16
            "Specifies if the Reserved Field 13 is present", HFILL }},
472
16
        {&hf_rftap_present_reserved_field_14, {
473
16
            "Reserved Field 14 Present",
474
16
            "rftap.present.field14",
475
16
            FT_BOOLEAN, 16, NULL, 0x4000,
476
16
            "Specifies if the Reserved Field 14 is present", HFILL }},
477
16
        {&hf_rftap_present_reserved_field_15, {
478
16
            "Reserved Field 15 Present",
479
16
            "rftap.present.field15",
480
16
            FT_BOOLEAN, 16, NULL, 0x8000,
481
16
            "Specifies if the Reserved Field 15 is present", HFILL }},
482
483
        /* rftap parameters */
484
485
16
        { &hf_rftap_dlt, {
486
16
            "Data Link Type (DLT)",
487
16
            "rftap.dlt",
488
16
            FT_UINT32, BASE_DEC, NULL, 0,
489
16
            "Data Link Type (DLT) of the encapsulated packet: www.tcpdump.org/linktypes.html", HFILL }},
490
16
        { &hf_rftap_freq, {
491
16
            "Frequency",
492
16
            "rftap.freq",
493
16
            FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_hz), 0,
494
16
            "Actual (measured) carrier frequency, in Hertz (not necessarily center frequency)", HFILL }},
495
16
        { &hf_rftap_nomfreq, {
496
16
            "Nominal Frequency",
497
16
            "rftap.nomfreq",
498
16
            FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_hz), 0,
499
16
            "Nominal carrier frequency, in Hertz (the ideal frequency, ignoring freq errors)", HFILL }},
500
16
        { &hf_rftap_freqofs, {
501
16
            "Frequency Offset",
502
16
            "rftap.freqofs",
503
16
            FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_hz), 0,
504
16
            "Carrier frequency offset, in Hertz: wikipedia.org/wiki/Carrier_frequency_offset", HFILL }},
505
16
        { &hf_rftap_signal_power, {
506
16
            "Signal Power",
507
16
            "rftap.power",
508
16
            FT_FLOAT, BASE_NONE, NULL, 0,
509
16
            "Signal power, in dB or dBm units: wikipedia.org/wiki/DBm", HFILL }},
510
16
        { &hf_rftap_noise_power, {
511
16
            "Noise Power",
512
16
            "rftap.noise",
513
16
            FT_FLOAT, BASE_NONE, NULL, 0,
514
16
            "Noise power, in dB or dBm units: wikipedia.org/wiki/DBm", HFILL }},
515
16
        { &hf_rftap_snr, {
516
16
            "SNR",
517
16
            "rftap.snr",
518
16
            FT_FLOAT, BASE_NONE, NULL, 0,
519
16
            "Signal to Noise ratio (decibel units): wikipedia.org/wiki/Signal-to-noise_ratio", HFILL }},
520
16
        { &hf_rftap_signal_quality, {
521
16
            "Signal Quality",
522
16
            "rftap.qual",
523
16
            FT_FLOAT, BASE_NONE, NULL, 0,
524
16
            "Signal quality, arbitrary units from 0.0 (worst) to 1.0 (best)", HFILL }},
525
16
        { &hf_rftap_time_int, {
526
16
            "Time (integer part)",
527
16
            "rftap.timeint",
528
16
            FT_DOUBLE, BASE_NONE, NULL, 0,
529
16
            "The integer part of event time, in seconds, since epoch: wikipedia.org/wiki/Epoch_(reference_date)", HFILL }},
530
16
        { &hf_rftap_time_frac, {
531
16
            "Time (fractional part)",
532
16
            "rftap.timefrac",
533
16
            FT_DOUBLE, BASE_NONE, NULL, 0,
534
16
            "The fractional part of event time, in seconds, since epoch: wikipedia.org/wiki/Epoch_(reference_date)", HFILL }},
535
16
        { &hf_rftap_time, {
536
16
            "Time",
537
16
            "rftap.time",
538
16
            FT_DOUBLE, BASE_NONE, NULL, 0,
539
16
            "The event time, in seconds, since epoch: wikipedia.org/wiki/Epoch_(reference_date)", HFILL }},
540
16
        { &hf_rftap_duration, {
541
16
            "Duration",
542
16
            "rftap.duration",
543
16
            FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_second_seconds), 0,
544
16
            "The duration of the event (packet), in seconds", HFILL }},
545
16
        { &hf_rftap_latitude, {
546
16
            "Latitude",
547
16
            "rftap.lat",
548
16
            FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_degree_degrees), 0,
549
16
            "Latitude of receiver (-90..90 degrees), using WGS 84 datum: wikipedia.org/wiki/World_Geodetic_System", HFILL }},
550
16
        { &hf_rftap_longitude, {
551
16
            "Longitude",
552
16
            "rftap.lon",
553
16
            FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_degree_degrees), 0,
554
16
            "Longitude of receiver (-180..180 degrees), using WGS 84 datum: wikipedia.org/wiki/World_Geodetic_System", HFILL }},
555
16
        { &hf_rftap_altitude, {
556
16
            "Altitude",
557
16
            "rftap.alt",
558
16
            FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_meter_meters), 0,
559
16
            "Altitude of receiver, in meters, using WGS 84 datum: wikipedia.org/wiki/World_Geodetic_System", HFILL }},
560
561
        /* rftap tagged parameters */
562
563
16
        { &hf_rftap_subdissector_name, {
564
16
            "Dissector Name",
565
16
            "rftap.dissector",
566
16
            FT_STRING, BASE_NONE, NULL, 0,
567
16
            "Name of sub-dissector used for packet data (alternative to DLT field)", HFILL }}
568
16
    };
569
570
16
    static ei_register_info ei[] = {
571
16
        { &ei_rftap_nesting, { "rftap.nesting_too_deep", PI_MALFORMED, PI_ERROR,
572
16
            "Too many nested RFtap headers", EXPFILL }},
573
16
    };
574
575
    /* Register the protocol name and description */
576
16
    proto_rftap = proto_register_protocol("RFtap Protocol", "RFtap", "rftap");
577
578
    /* Register the header fields and subtrees */
579
16
    proto_register_field_array(proto_rftap, hf, array_length(hf));
580
16
    proto_register_subtree_array(ett, array_length(ett));
581
582
16
    expert_module_t *expert_rftap = expert_register_protocol(proto_rftap);
583
16
    expert_register_field_array(expert_rftap, ei, array_length(ei));
584
585
16
    register_dissector("rftap", dissect_rftap, proto_rftap);
586
16
}
587
588
589
/* Protocol registration routine. This function is also called by
590
 * Wireshark's preferences manager whenever "Apply" or "OK" are pressed.
591
 */
592
void
593
proto_reg_handoff_rftap(void)
594
16
{
595
16
    pcap_pktdata_handle = find_dissector_add_dependency("pcap_pktdata", proto_rftap);
596
16
    heur_dissector_add("udp", dissect_rftap_heur, "RFtap over UDP", "rftap", proto_rftap, HEURISTIC_ENABLE);
597
16
}
598
599
/*
600
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
601
 *
602
 * Local variables:
603
 * c-basic-offset: 4
604
 * tab-width: 8
605
 * indent-tabs-mode: nil
606
 * End:
607
 *
608
 * vi: set shiftwidth=4 tabstop=8 expandtab:
609
 * :indentSize=4:tabSize=8:noTabs=true:
610
 */