forked from osmocom/wireshark
![Dario Lombardo](/assets/img/avatar_default.png)
Change-Id: I92c94448e6641716d03158a5f332c8b53709423a Reviewed-on: https://code.wireshark.org/review/25756 Petri-Dish: Dario Lombardo <lomato@gmail.com> Reviewed-by: Anders Broman <a.broman58@gmail.com>
589 lines
22 KiB
C
589 lines
22 KiB
C
/*
|
|
* packet-rftap.c
|
|
* Decode packets with a RFtap header
|
|
* Copyright 2016, Jonathan Brucker <jonathan.brucke@gmail.com>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
/*
|
|
* The RFtap header is a simple meta-data header designed to provide
|
|
* RF (Radio Frequency) meta-data about frames, such as:
|
|
* - Accurate signal and noise power
|
|
* - Accurate timing and phase information
|
|
* - Accurate carrier and Doppler frequencies, and more.
|
|
* The RFtap protocol can be used to encapsulate any type of frame.
|
|
*
|
|
* Official specification:
|
|
* https://rftap.github.io
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <epan/packet.h>
|
|
#include <epan/prefs.h>
|
|
|
|
/* Prototypes */
|
|
/* (Required to prevent [-Wmissing-prototypes] warnings */
|
|
void proto_reg_handoff_rftap(void);
|
|
void proto_register_rftap(void);
|
|
|
|
/* protocols */
|
|
static int proto_rftap = -1;
|
|
|
|
/* rftap fixed fields */
|
|
static int hf_rftap_fixed_header = -1;
|
|
static int hf_rftap_magic = -1;
|
|
static int hf_rftap_len = -1; /* length in bytes */
|
|
static int hf_rftap_flags = -1;
|
|
|
|
/* rftap flags bit-field (16 bits) */
|
|
static int hf_rftap_present_dlt = -1;
|
|
static int hf_rftap_present_freq = -1;
|
|
static int hf_rftap_present_nomfreq = -1;
|
|
static int hf_rftap_present_freqofs = -1;
|
|
static int hf_rftap_power_is_in_dbm = -1;
|
|
static int hf_rftap_present_signal_power = -1;
|
|
static int hf_rftap_present_noise_power = -1;
|
|
static int hf_rftap_present_snr = -1;
|
|
static int hf_rftap_present_signal_quality = -1;
|
|
static int hf_rftap_time_is_unix_time = -1;
|
|
static int hf_rftap_present_time = -1;
|
|
static int hf_rftap_present_duration = -1;
|
|
static int hf_rftap_present_location = -1;
|
|
static int hf_rftap_present_reserved_field_13 = -1;
|
|
static int hf_rftap_present_reserved_field_14 = -1;
|
|
static int hf_rftap_present_reserved_field_15 = -1;
|
|
|
|
/* rftap optional fields */
|
|
static int hf_rftap_dlt = -1;
|
|
static int hf_rftap_freq = -1;
|
|
static int hf_rftap_nomfreq = -1;
|
|
static int hf_rftap_freqofs = -1;
|
|
static int hf_rftap_signal_power = -1;
|
|
static int hf_rftap_noise_power = -1;
|
|
static int hf_rftap_snr = -1;
|
|
static int hf_rftap_signal_quality = -1;
|
|
static int hf_rftap_time_int = -1;
|
|
static int hf_rftap_time_frac = -1;
|
|
static int hf_rftap_time = -1;
|
|
static int hf_rftap_duration = -1;
|
|
static int hf_rftap_latitude = -1;
|
|
static int hf_rftap_longitude = -1;
|
|
static int hf_rftap_altitude = -1;
|
|
|
|
/* rftap tag IDs >= 16 */
|
|
static int hf_rftap_subdissector_name = -1;
|
|
|
|
/* subtree pointers */
|
|
static gint ett_rftap = -1;
|
|
static gint ett_rftap_fixed_header = -1;
|
|
static gint ett_rftap_flags = -1;
|
|
|
|
static dissector_handle_t pcap_pktdata_handle;
|
|
|
|
#define RFTAP_MAGIC 0x61744652UL /* "RFta" */
|
|
|
|
enum rftap_tag_id {
|
|
RFTAP_TAG_DLT = 0,
|
|
RFTAP_TAG_FREQ = 1,
|
|
RFTAP_TAG_NOM_FREQ = 2,
|
|
RFTAP_TAG_FREQ_OFS = 3,
|
|
RFTAP_TAG_POWER_IS_IN_DBM = 4,
|
|
RFTAP_TAG_SIGNAL_POWER = 5,
|
|
RFTAP_TAG_NOISE_POWER = 6,
|
|
RFTAP_TAG_SNR = 7,
|
|
RFTAP_TAG_SIGNAL_QUALITY = 8,
|
|
RFTAP_TAG_TIME_IS_UNIX_TIME = 9,
|
|
RFTAP_TAG_TIME = 10,
|
|
RFTAP_TAG_DURATION = 11,
|
|
RFTAP_TAG_LOCATION = 12,
|
|
RFTAP_TAG_RESERVED_13 = 13,
|
|
RFTAP_TAG_RESERVED_14 = 14,
|
|
RFTAP_TAG_RESERVED_15 = 15,
|
|
RFTAP_TAG_DISSECTOR_NAME = 16
|
|
};
|
|
|
|
/* This is the header as it is used by rftap-generating software.
|
|
* It is not used by the wireshark dissector and provided for reference only.
|
|
struct rftap_hdr {
|
|
le32 magic; // "RFta"
|
|
le16 len32; // sizeof(rftap_hdr) / sizeof(le32)
|
|
le16 flags; // bitfield indicating presence of parameters
|
|
le32 data[];
|
|
} __attribute__((packed));
|
|
*/
|
|
|
|
/* dissect the rftap header part of the packet
|
|
* returns Data Link Type (dlt) and subdissector name
|
|
*/
|
|
static void
|
|
dissect_rftap_header(tvbuff_t *tvb, proto_tree *tree, guint32 *dlt, const guint8 **subdissector_name)
|
|
{
|
|
proto_item *ti_header;
|
|
proto_tree *header_tree;
|
|
gint32 offset;
|
|
gint32 len;
|
|
guint64 flags;
|
|
guint32 flag_bit;
|
|
guint32 tag_id;
|
|
gint32 tag_len;
|
|
guint32 tag_flags;
|
|
gdouble double_val;
|
|
gfloat float_val;
|
|
char *power_units;
|
|
|
|
static const int *flag_fields[] = {
|
|
&hf_rftap_present_dlt,
|
|
&hf_rftap_present_freq,
|
|
&hf_rftap_present_nomfreq,
|
|
&hf_rftap_present_freqofs,
|
|
&hf_rftap_power_is_in_dbm,
|
|
&hf_rftap_present_signal_power,
|
|
&hf_rftap_present_noise_power,
|
|
&hf_rftap_present_snr,
|
|
&hf_rftap_present_signal_quality,
|
|
&hf_rftap_time_is_unix_time,
|
|
&hf_rftap_present_time,
|
|
&hf_rftap_present_duration,
|
|
&hf_rftap_present_location,
|
|
&hf_rftap_present_reserved_field_13,
|
|
&hf_rftap_present_reserved_field_14,
|
|
&hf_rftap_present_reserved_field_15,
|
|
NULL
|
|
};
|
|
|
|
*dlt = 0xffffffff;
|
|
*subdissector_name = NULL;
|
|
|
|
/* rftap fixed header sub-tree */
|
|
|
|
ti_header = proto_tree_add_item(tree, hf_rftap_fixed_header, tvb, 0, 8, ENC_NA);
|
|
header_tree = proto_item_add_subtree(ti_header, ett_rftap_fixed_header);
|
|
|
|
proto_tree_add_item(header_tree, hf_rftap_magic, tvb, 0, 4, ENC_LITTLE_ENDIAN);
|
|
len = 4 * (gint32) tvb_get_letohs(tvb, 4); /* convert to length in bytes */
|
|
proto_tree_add_uint(header_tree, hf_rftap_len, tvb, 4, 2, len); /* show length in bytes */
|
|
proto_tree_add_bitmask_ret_uint64(header_tree, tvb, 6, hf_rftap_flags,
|
|
ett_rftap_flags, flag_fields, ENC_LITTLE_ENDIAN, &flags);
|
|
|
|
/* rftap parameter fields */
|
|
|
|
power_units = (flags & (1 << RFTAP_TAG_POWER_IS_IN_DBM)) ? "dBm" : "dB";
|
|
|
|
offset = 8;
|
|
flag_bit = 1;
|
|
for (tag_id = 0; tag_id < 16; tag_id++, flag_bit<<=1) {
|
|
|
|
if (!(flags & flag_bit))
|
|
continue; /* parameter is not present, skip */
|
|
|
|
switch (tag_id) {
|
|
case RFTAP_TAG_DLT:
|
|
proto_tree_add_item_ret_uint(tree, hf_rftap_dlt, tvb, offset, 4, ENC_LITTLE_ENDIAN, dlt);
|
|
offset += 4;
|
|
break;
|
|
case RFTAP_TAG_FREQ:
|
|
proto_tree_add_item(tree, hf_rftap_freq, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
break;
|
|
case RFTAP_TAG_NOM_FREQ:
|
|
proto_tree_add_item(tree, hf_rftap_nomfreq, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
break;
|
|
case RFTAP_TAG_FREQ_OFS:
|
|
proto_tree_add_item(tree, hf_rftap_freqofs, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
break;
|
|
case RFTAP_TAG_POWER_IS_IN_DBM:
|
|
/* do nothing, it's already decoded in flags bit-field */
|
|
break;
|
|
case RFTAP_TAG_SIGNAL_POWER:
|
|
float_val = tvb_get_letohieee_float(tvb, offset);
|
|
proto_tree_add_float_format_value(tree, hf_rftap_signal_power, tvb, offset, 4, float_val, "%.2f %s", float_val, power_units);
|
|
offset += 4;
|
|
break;
|
|
case RFTAP_TAG_NOISE_POWER:
|
|
float_val = tvb_get_letohieee_float(tvb, offset);
|
|
proto_tree_add_float_format_value(tree, hf_rftap_noise_power, tvb, offset, 4, float_val, "%.2f %s", float_val, power_units);
|
|
offset += 4;
|
|
break;
|
|
case RFTAP_TAG_SNR:
|
|
float_val = tvb_get_letohieee_float(tvb, offset);
|
|
proto_tree_add_float_format_value(tree, hf_rftap_snr, tvb, offset, 4, float_val, "%.2f dB", float_val);
|
|
offset += 4;
|
|
break;
|
|
case RFTAP_TAG_SIGNAL_QUALITY:
|
|
proto_tree_add_item(tree, hf_rftap_signal_quality, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
break;
|
|
case RFTAP_TAG_TIME_IS_UNIX_TIME:
|
|
/* do nothing, it's already decoded in flags bit-field */
|
|
break;
|
|
case RFTAP_TAG_TIME:
|
|
double_val = tvb_get_letohieee_double(tvb, offset);
|
|
proto_tree_add_double_format_value(tree, hf_rftap_time_int, tvb, offset, 8, double_val, "%.0f seconds", double_val);
|
|
double_val = tvb_get_letohieee_double(tvb, offset + 8);
|
|
proto_tree_add_double_format_value(tree, hf_rftap_time_frac, tvb, offset+8, 8, double_val, "%.9f seconds", double_val);
|
|
/* compute combined time: (not accurate, error is > 300 nanoseconds) */
|
|
double_val += tvb_get_letohieee_double(tvb, offset);
|
|
proto_tree_add_double_format_value(tree, hf_rftap_time, tvb, offset, 16, double_val, "%.6f seconds", double_val);
|
|
offset += 16;
|
|
break;
|
|
case RFTAP_TAG_DURATION:
|
|
proto_tree_add_item(tree, hf_rftap_duration, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
break;
|
|
case RFTAP_TAG_LOCATION:
|
|
proto_tree_add_item(tree, hf_rftap_latitude, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
proto_tree_add_item(tree, hf_rftap_longitude, tvb, offset+8, 8, ENC_LITTLE_ENDIAN);
|
|
proto_tree_add_item(tree, hf_rftap_altitude, tvb, offset+16, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 24;
|
|
break;
|
|
default:
|
|
return; /* we've hit a parameter we can't decode, abort */
|
|
}
|
|
}
|
|
|
|
if (offset >= len)
|
|
return; /* there are no tagged parameters to decode, goodbye */
|
|
|
|
/* rftap tagged parameter fields */
|
|
|
|
tag_id = tvb_get_letohs(tvb, offset);
|
|
tag_len = tvb_get_guint8(tvb, offset+2);
|
|
tag_flags = tvb_get_guint8(tvb, offset+3);
|
|
|
|
if ((tag_id != RFTAP_TAG_DISSECTOR_NAME) || (tag_len == 0) || (tag_len == 255) || (tag_flags != 255))
|
|
return; /* we've hit a tagged parameter we can't decode, abort */
|
|
|
|
proto_tree_add_item_ret_string(tree, hf_rftap_subdissector_name, tvb,
|
|
offset+4, tag_len, ENC_ASCII, wmem_packet_scope(), subdissector_name);
|
|
}
|
|
|
|
/* Main entry point to dissect the packets.
|
|
*
|
|
* Each packet consists of two parts:
|
|
* - The rftap header, containing all the RF metadata.
|
|
* - The encapsulated data packet, decoded by a sub-dissector.
|
|
*/
|
|
static int
|
|
dissect_rftap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
void *data _U_)
|
|
{
|
|
proto_item *ti;
|
|
proto_tree *rftap_tree;
|
|
|
|
tvbuff_t *rftap_tvb; /* the first part of the packet */
|
|
tvbuff_t *subdissector_tvb; /* the second part of the packet */
|
|
|
|
gint32 rftap_len; /* length in bytes */
|
|
dissector_handle_t subdissector_handle;
|
|
guint32 subdissector_dlt;
|
|
const guint8 *subdissector_name;
|
|
|
|
/* heuristics */
|
|
|
|
if (tvb_captured_length(tvb) < 8) /* 4 magic + 2 len + 2 flags = 8 bytes */
|
|
return 0;
|
|
|
|
if (tvb_get_letohl(tvb, 0) != RFTAP_MAGIC)
|
|
return 0;
|
|
|
|
/* column info */
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFTAP");
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
clear_address(&pinfo->src);
|
|
clear_address(&pinfo->dst);
|
|
|
|
/* dissect part 1: rftap header */
|
|
|
|
rftap_len = 4 * (gint32) tvb_get_letohs(tvb, 4);
|
|
rftap_tvb = tvb_new_subset_length_caplen(tvb, 0, rftap_len, rftap_len);
|
|
|
|
ti = proto_tree_add_protocol_format(tree, proto_rftap, rftap_tvb, 0, -1,
|
|
"RFtap Protocol (%d bytes)", rftap_len);
|
|
rftap_tree = proto_item_add_subtree(ti, ett_rftap);
|
|
|
|
dissect_rftap_header(rftap_tvb, rftap_tree, &subdissector_dlt, &subdissector_name);
|
|
|
|
/* dissect part 2: data packet */
|
|
|
|
subdissector_tvb = tvb_new_subset_remaining(tvb, rftap_len);
|
|
|
|
/* try using data link type (DLT) */
|
|
if (subdissector_dlt != 0xffffffff) {
|
|
call_dissector_with_data(pcap_pktdata_handle, subdissector_tvb, pinfo, tree, &subdissector_dlt);
|
|
return tvb_captured_length(tvb);
|
|
}
|
|
|
|
/* try using dissector name */
|
|
if (subdissector_name) {
|
|
subdissector_handle = find_dissector(subdissector_name);
|
|
if (subdissector_handle) {
|
|
call_dissector_with_data(subdissector_handle, subdissector_tvb, pinfo, tree, NULL);
|
|
return tvb_captured_length(tvb);
|
|
}
|
|
}
|
|
|
|
/* fallback using plain data dissector */
|
|
call_data_dissector(subdissector_tvb, pinfo, tree);
|
|
return tvb_captured_length(tvb);
|
|
}
|
|
|
|
static gboolean
|
|
dissect_rftap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
|
{
|
|
return dissect_rftap(tvb, pinfo, tree, data) != 0;
|
|
}
|
|
|
|
/* Register the protocol with Wireshark. */
|
|
void
|
|
proto_register_rftap(void)
|
|
{
|
|
/* Setup protocol subtree array */
|
|
static gint *ett[] = {
|
|
&ett_rftap,
|
|
&ett_rftap_fixed_header,
|
|
&ett_rftap_flags
|
|
};
|
|
|
|
/* Setup list of header fields */
|
|
static hf_register_info hf[] = {
|
|
|
|
/* rftap fixed header */
|
|
|
|
{ &hf_rftap_fixed_header, {
|
|
"RFtap Fixed header",
|
|
"rftap.fixedheader",
|
|
FT_NONE, BASE_NONE, NULL, 0,
|
|
"RFtap Fixed 8-byte Header", HFILL }},
|
|
|
|
{ &hf_rftap_magic, {
|
|
"Magic",
|
|
"rftap.magic",
|
|
FT_UINT32, BASE_HEX, NULL, 0,
|
|
"RFtap signature: wikipedia.org/wiki/File_format#Magic_number", HFILL }},
|
|
{ &hf_rftap_len, {
|
|
"Length",
|
|
"rftap.len",
|
|
FT_UINT32, BASE_DEC, NULL, 0,
|
|
"Length (in bytes) of entire rftap header, including tagged (optional) parameters", HFILL }},
|
|
{ &hf_rftap_flags, {
|
|
"Flags",
|
|
"rftap.flags",
|
|
FT_UINT16, BASE_HEX, NULL, 0,
|
|
"RFtap flags", HFILL }},
|
|
|
|
/* flags bit-field */
|
|
|
|
{&hf_rftap_present_dlt, {
|
|
"DLT Present",
|
|
"rftap.present.dlt",
|
|
FT_BOOLEAN, 16, NULL, 0x0001,
|
|
"Specifies if the DLT (Data Link Type) field is present", HFILL }},
|
|
{&hf_rftap_present_freq, {
|
|
"Frequency Present",
|
|
"rftap.present.freq",
|
|
FT_BOOLEAN, 16, NULL, 0x0002,
|
|
"Specifies if the Frequency field is present", HFILL }},
|
|
{&hf_rftap_present_nomfreq, {
|
|
"Nominal Frequency Present",
|
|
"rftap.present.nomfreq",
|
|
FT_BOOLEAN, 16, NULL, 0x0004,
|
|
"Specifies if the Nominal Frequency field is present", HFILL }},
|
|
{&hf_rftap_present_freqofs, {
|
|
"Frequency Offset Present",
|
|
"rftap.present.freqofs",
|
|
FT_BOOLEAN, 16, NULL, 0x0008,
|
|
"Specifies if the Frequency Offset field is present", HFILL }},
|
|
{&hf_rftap_power_is_in_dbm, {
|
|
"Power is in dBm Units",
|
|
"rftap.isdbm",
|
|
FT_BOOLEAN, 16, NULL, 0x0010,
|
|
"Specifies if the Power is specified in dBm units", HFILL }},
|
|
{&hf_rftap_present_signal_power, {
|
|
"Signal Power Present",
|
|
"rftap.present.power",
|
|
FT_BOOLEAN, 16, NULL, 0x0020,
|
|
"Specifies if the Signal Power field is present", HFILL }},
|
|
{&hf_rftap_present_noise_power, {
|
|
"Noise Power Present",
|
|
"rftap.present.noise",
|
|
FT_BOOLEAN, 16, NULL, 0x0040,
|
|
"Specifies if the Noise Power field is present", HFILL }},
|
|
{&hf_rftap_present_snr, {
|
|
"SNR Present",
|
|
"rftap.present.snr",
|
|
FT_BOOLEAN, 16, NULL, 0x0080,
|
|
"Specifies if the SNR field is present", HFILL }},
|
|
{&hf_rftap_present_signal_quality, {
|
|
"Signal Quality Present",
|
|
"rftap.present.qual",
|
|
FT_BOOLEAN, 16, NULL, 0x0100,
|
|
"Specifies if the Signal Quality field is present", HFILL }},
|
|
{&hf_rftap_time_is_unix_time, {
|
|
"Time standard is Unix Time",
|
|
"rftap.isunixtime",
|
|
FT_BOOLEAN, 16, NULL, 0x0200,
|
|
"Specifies if the time standard is Unix Time: wikipedia.org/wiki/Unix_time", HFILL }},
|
|
{&hf_rftap_present_time, {
|
|
"Time Present",
|
|
"rftap.present.time",
|
|
FT_BOOLEAN, 16, NULL, 0x0400,
|
|
"Specifies if the Time field is present", HFILL }},
|
|
{&hf_rftap_present_duration, {
|
|
"Duration Present",
|
|
"rftap.present.duration",
|
|
FT_BOOLEAN, 16, NULL, 0x0800,
|
|
"Specifies if the Duration field is present", HFILL }},
|
|
{&hf_rftap_present_location, {
|
|
"Location Present",
|
|
"rftap.present.location",
|
|
FT_BOOLEAN, 16, NULL, 0x1000,
|
|
"Specifies if the Location field is present", HFILL }},
|
|
{&hf_rftap_present_reserved_field_13, {
|
|
"Reserved Field 13 Present",
|
|
"rftap.present.field13",
|
|
FT_BOOLEAN, 16, NULL, 0x2000,
|
|
"Specifies if the Reserved Field 13 is present", HFILL }},
|
|
{&hf_rftap_present_reserved_field_14, {
|
|
"Reserved Field 14 Present",
|
|
"rftap.present.field14",
|
|
FT_BOOLEAN, 16, NULL, 0x4000,
|
|
"Specifies if the Reserved Field 14 is present", HFILL }},
|
|
{&hf_rftap_present_reserved_field_15, {
|
|
"Reserved Field 15 Present",
|
|
"rftap.present.field15",
|
|
FT_BOOLEAN, 16, NULL, 0x8000,
|
|
"Specifies if the Reserved Field 15 is present", HFILL }},
|
|
|
|
/* rftap parameters */
|
|
|
|
{ &hf_rftap_dlt, {
|
|
"Data Link Type (DLT)",
|
|
"rftap.dlt",
|
|
FT_UINT32, BASE_DEC, NULL, 0,
|
|
"Data Link Type (DLT) of the encapsulated packet: www.tcpdump.org/linktypes.html", HFILL }},
|
|
{ &hf_rftap_freq, {
|
|
"Frequency",
|
|
"rftap.freq",
|
|
FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_hz, 0,
|
|
"Actual (measured) carrier frequency, in Hertz (not necessarily center frequency)", HFILL }},
|
|
{ &hf_rftap_nomfreq, {
|
|
"Nominal Frequency",
|
|
"rftap.nomfreq",
|
|
FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_hz, 0,
|
|
"Nominal carrier frequency, in Hertz (the ideal frequency, ignoring freq errors)", HFILL }},
|
|
{ &hf_rftap_freqofs, {
|
|
"Frequency Offset",
|
|
"rftap.freqofs",
|
|
FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_hz, 0,
|
|
"Carrier frequency offset, in Hertz: wikipedia.org/wiki/Carrier_frequency_offset", HFILL }},
|
|
{ &hf_rftap_signal_power, {
|
|
"Signal Power",
|
|
"rftap.power",
|
|
FT_FLOAT, BASE_NONE, NULL, 0,
|
|
"Signal power, in dB or dBm units: wikipedia.org/wiki/DBm", HFILL }},
|
|
{ &hf_rftap_noise_power, {
|
|
"Noise Power",
|
|
"rftap.noise",
|
|
FT_FLOAT, BASE_NONE, NULL, 0,
|
|
"Noise power, in dB or dBm units: wikipedia.org/wiki/DBm", HFILL }},
|
|
{ &hf_rftap_snr, {
|
|
"SNR",
|
|
"rftap.snr",
|
|
FT_FLOAT, BASE_NONE, NULL, 0,
|
|
"Signal to Noise ratio (decibel units): wikipedia.org/wiki/Signal-to-noise_ratio", HFILL }},
|
|
{ &hf_rftap_signal_quality, {
|
|
"Signal Quality",
|
|
"rftap.qual",
|
|
FT_FLOAT, BASE_NONE, NULL, 0,
|
|
"Signal quality, arbitrary units from 0.0 (worst) to 1.0 (best)", HFILL }},
|
|
{ &hf_rftap_time_int, {
|
|
"Time (integer part)",
|
|
"rftap.timeint",
|
|
FT_DOUBLE, BASE_NONE, NULL, 0,
|
|
"The integer part of event time, in seconds, since epoch: wikipedia.org/wiki/Epoch_(reference_date)", HFILL }},
|
|
{ &hf_rftap_time_frac, {
|
|
"Time (fractional part)",
|
|
"rftap.timefrac",
|
|
FT_DOUBLE, BASE_NONE, NULL, 0,
|
|
"The fractional part of event time, in seconds, since epoch: wikipedia.org/wiki/Epoch_(reference_date)", HFILL }},
|
|
{ &hf_rftap_time, {
|
|
"Time",
|
|
"rftap.time",
|
|
FT_DOUBLE, BASE_NONE, NULL, 0,
|
|
"The event time, in seconds, since epoch: wikipedia.org/wiki/Epoch_(reference_date)", HFILL }},
|
|
{ &hf_rftap_duration, {
|
|
"Duration",
|
|
"rftap.duration",
|
|
FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_second_seconds, 0,
|
|
"The duration of the event (packet), in seconds", HFILL }},
|
|
{ &hf_rftap_latitude, {
|
|
"Latitude",
|
|
"rftap.lat",
|
|
FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_degree_degrees, 0,
|
|
"Latitude of receiver (-90..90 degrees), using WGS 84 datum: wikipedia.org/wiki/World_Geodetic_System", HFILL }},
|
|
{ &hf_rftap_longitude, {
|
|
"Longitude",
|
|
"rftap.lon",
|
|
FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_degree_degrees, 0,
|
|
"Longitude of receiver (-180..180 degrees), using WGS 84 datum: wikipedia.org/wiki/World_Geodetic_System", HFILL }},
|
|
{ &hf_rftap_altitude, {
|
|
"Altitude",
|
|
"rftap.alt",
|
|
FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_meter_meters, 0,
|
|
"Altitude of receiver, in meters, using WGS 84 datum: wikipedia.org/wiki/World_Geodetic_System", HFILL }},
|
|
|
|
/* rftap tagged parameters */
|
|
|
|
{ &hf_rftap_subdissector_name, {
|
|
"Dissector Name",
|
|
"rftap.dissector",
|
|
FT_STRING, BASE_NONE, NULL, 0,
|
|
"Name of sub-dissector used for packet data (alternative to DLT field)", HFILL }}
|
|
};
|
|
|
|
/* Register the protocol name and description */
|
|
proto_rftap = proto_register_protocol(
|
|
"RFtap Protocol", /* name */
|
|
"RFtap", /* short_name */
|
|
"rftap"); /* filter_name (used for display filter string) */
|
|
|
|
/* Register the header fields and subtrees */
|
|
proto_register_field_array(proto_rftap, hf, array_length(hf));
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
register_dissector("rftap", dissect_rftap, proto_rftap);
|
|
}
|
|
|
|
|
|
/* Protocol registration routine. This function is also called by
|
|
* Wireshark's preferences manager whenever "Apply" or "OK" are pressed.
|
|
*/
|
|
void
|
|
proto_reg_handoff_rftap(void)
|
|
{
|
|
pcap_pktdata_handle = find_dissector_add_dependency("pcap_pktdata", proto_rftap);
|
|
heur_dissector_add("udp", dissect_rftap_heur, "RFtap over UDP", "rftap", proto_rftap, HEURISTIC_ENABLE);
|
|
}
|
|
|
|
/*
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local variables:
|
|
* c-basic-offset: 4
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
*/
|