diff options
-rw-r--r-- | docbook/release-notes.asciidoc | 7 | ||||
-rw-r--r-- | epan/CMakeLists.txt | 2 | ||||
-rw-r--r-- | epan/dissectors/Makefile.common | 2 | ||||
-rw-r--r-- | epan/dissectors/file-pcap.c | 545 | ||||
-rw-r--r-- | epan/dissectors/file-pcapng.c | 1943 | ||||
-rw-r--r-- | wiretap/mime_file.c | 20 |
6 files changed, 2516 insertions, 3 deletions
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc index a5050c9230..1230e0821f 100644 --- a/docbook/release-notes.asciidoc +++ b/docbook/release-notes.asciidoc @@ -167,6 +167,13 @@ available in the Qt UI yet. //=== Removed Dissectors +=== New File Format Support + +--sort-and-group-- +BTSNOOP +PCAP +PCAPNG +--sort-and-group-- === New Protocol Support diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index cbf752def1..908544be05 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -317,6 +317,8 @@ set(DISSECTOR_SRC dissectors/file-gif.c dissectors/file-jpeg.c dissectors/file-mp4.c + dissectors/file-pcap.c + dissectors/file-pcapng.c dissectors/file-png.c dissectors/packet-2dparityfec.c dissectors/packet-3com-njack.c diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 7fbcbc0363..1b7c164395 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -229,6 +229,8 @@ FILE_DISSECTOR_SRC = \ file-gif.c \ file-jpeg.c \ file-mp4.c \ + file-pcap.c \ + file.pcapng.c \ file-png.c # # Dissectors without warnings. diff --git a/epan/dissectors/file-pcap.c b/epan/dissectors/file-pcap.c new file mode 100644 index 0000000000..0d229721aa --- /dev/null +++ b/epan/dissectors/file-pcap.c @@ -0,0 +1,545 @@ +/* file-pcap.c + * Routines for PCAP File Format + * https://wiki.wireshark.org/Development/LibpcapFileFormat + * + * Copyright 2015, Michal Labedzki for Tieto Corporation + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/expert.h> +#include <epan/wmem/wmem.h> + +#include <wiretap/wtap.h> +#include <wiretap/pcap-encap.h> + +static int proto_pcap = -1; + +static dissector_handle_t pcap_handle; +dissector_handle_t pcap_pseudoheader_handle; + +static int hf_pcap_header = -1; +static int hf_pcap_header_magic_number = -1; +static int hf_pcap_header_version_major = -1; +static int hf_pcap_header_version_minor = -1; +static int hf_pcap_header_this_zone = -1; +static int hf_pcap_header_sigfigs = -1; +static int hf_pcap_header_snapshot_length = -1; +static int hf_pcap_header_link_type = -1; +static int hf_pcap_packet = -1; +static int hf_pcap_packet_timestamp = -1; +static int hf_pcap_packet_timestamp_sec = -1; +static int hf_pcap_packet_timestamp_usec = -1; +static int hf_pcap_packet_included_length = -1; +static int hf_pcap_packet_origin_length = -1; +static int hf_pcap_packet_data = -1; +static int hf_pcap_packet_data_pseudoheader = -1; +static int hf_pcap_packet_data_pseudoheader_bluetooth_direction = -1; +static int hf_pcap_packet_data_data = -1; + +static expert_field ei_unknown_encoding = EI_INIT; + +static gint ett_pcap = -1; +static gint ett_pcap_header = -1; +static gint ett_pcap_packet = -1; +static gint ett_pcap_packet_data = -1; +static gint ett_pcap_pseudoheader = -1; +static gint ett_pcap_timestamp = -1; + +static dissector_table_t wtap_encap_table; + +static gboolean pref_dissect_next_layer = FALSE; + +static const value_string magic_number_vals[] = { + { 0xA1B2C3D4, "Little-endian" }, + { 0xD4C3B2A1, "Big-endian" }, + { 0, NULL } +}; + +static const value_string link_type_vals[] = { + { 0, "NULL" }, + { 1, "ETHERNET" }, + { 3, "AX25" }, + { 6, "IEEE802_5" }, + { 7, "ARCNET_BSD" }, + { 8, "SLIP" }, + { 9, "PPP" }, + { 10, "FDDI" }, + { 50, "PPP_HDLC" }, + { 51, "PPP_ETHER" }, + { 100, "ATM_RFC1483" }, + { 101, "RAW" }, + { 104, "C_HDLC" }, + { 105, "IEEE802_11" }, + { 107, "FRELAY" }, + { 108, "LOOP" }, + { 113, "LINUX_SLL" }, + { 114, "LTALK" }, + { 117, "PFLOG" }, + { 119, "IEEE802_11_PRISM" }, + { 122, "IP_OVER_FC" }, + { 123, "SUNATM" }, + { 127, "IEEE802_11_RADIOTAP" }, + { 129, "ARCNET_LINUX" }, + { 138, "APPLE_IP_OVER_IEEE1394" }, + { 139, "MTP2_WITH_PHDR" }, + { 140, "MTP2" }, + { 141, "MTP3" }, + { 142, "SCCP" }, + { 143, "DOCSIS" }, + { 144, "LINUX_IRDA" }, + { 147, "USER_0" }, + { 148, "USER_1" }, + { 149, "USER_2" }, + { 150, "USER_3" }, + { 151, "USER_4" }, + { 152, "USER_5" }, + { 153, "USER_6" }, + { 154, "USER_7" }, + { 155, "USER_8" }, + { 156, "USER_9" }, + { 157, "USER_10" }, + { 158, "USER_11" }, + { 159, "USER_12" }, + { 160, "USER_13" }, + { 161, "USER_14" }, + { 162, "USER_15" }, + { 163, "IEEE802_11_AVS" }, + { 165, "BACNET_MS_TP" }, + { 166, "PPP_PPPD" }, + { 169, "GPRS_LLC" }, + { 177, "LINUX_LAPD" }, + { 187, "BLUETOOTH_HCI_H4" }, + { 189, "USB_LINUX" }, + { 192, "PPI" }, + { 195, "IEEE802_15_4" }, + { 196, "SITA" }, + { 197, "ERF" }, + { 201, "BLUETOOTH_HCI_H4_WITH_PHDR" }, + { 202, "AX25_KISS" }, + { 203, "LAPD" }, + { 204, "PPP_WITH_DIR" }, + { 205, "C_HDLC_WITH_DIR" }, + { 206, "FRELAY_WITH_DIR" }, + { 209, "IPMB_LINUX" }, + { 215, "IEEE802_15_4_NONASK_PHY" }, + { 220, "USB_LINUX_MMAPPED" }, + { 224, "FC_2" }, + { 225, "FC_2_WITH_FRAME_DELIMS" }, + { 226, "IPNET" }, + { 227, "CAN_SOCKETCAN" }, + { 228, "IPV4" }, + { 229, "IPV6" }, + { 230, "IEEE802_15_4_NOFCS" }, + { 231, "DBUS" }, + { 235, "DVB_CI" }, + { 236, "MUX27010" }, + { 237, "STANAG_5066_D_PDU" }, + { 239, "NFLOG" }, + { 240, "NETANALYZER" }, + { 241, "NETANALYZER_TRANSPARENT" }, + { 242, "IPOIB" }, + { 243, "MPEG_2_TS" }, + { 244, "NG40" }, + { 245, "NFC_LLCP" }, + { 247, "INFINIBAND" }, + { 248, "SCTP" }, + { 249, "USBPCAP" }, + { 250, "RTAC_SERIAL" }, + { 251, "BLUETOOTH_LE_LL" }, + { 253, "NETLINK" }, + { 254, "BLUETOOTH_LINUX_MONITOR" }, + { 255, "BLUETOOTH_BREDR_BB" }, + { 256, "BLUETOOTH_LE_LL_WITH_PHDR" }, + { 257, "PROFIBUS_DL" }, + { 258, "PKTAP" }, + { 259, "EPON" }, + { 260, "IPMI_HPM_2" }, + { 261, "ZWAVE_R1_R2" }, + { 262, "ZWAVE_R3" }, + { 263, "WATTSTOPPER_DLM" }, + { 0, NULL } +}; + +static const value_string pseudoheader_bluetooth_direction_vals[] = { + { 0, "Sent" }, + { 1, "Recv" }, + { 0, NULL } +}; + + +void proto_register_file_pcap(void); +void proto_reg_handoff_file_pcap(void); + +static int +dissect_pcap_pseudoheader(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + gint offset = 0; + guint32 *link_type; + guint32 length; + tvbuff_t *next_tvb; + proto_item *pseudoheader_item; + proto_tree *pseudoheader_tree = NULL; + proto_item *packet_item; + proto_tree *packet_tree; + + DISSECTOR_ASSERT(data); + + link_type = (guint32 *) data; + pinfo->phdr->pkt_encap = wtap_pcap_encap_to_wtap_encap(*link_type); + + switch (*link_type) { + case 139: +/* TODO no description for pseudoheader at http://www.tcpdump.org/linktypes.html */ + break; + case 196: + length = 5; + break; + case 197: +/* TODO no description for pseudoheader at http://www.tcpdump.org/linktypes.html */ + break; + case 201: + length = 4; + break; + case 204: + length = 1; + break; + case 205: + length = 1; + break; + case 206: + length = 1; + break; + case 209: + length = 6; + break; + case 226: + length = 24; + break; + case 227: +/* TODO no description for pseudoheader at http://www.tcpdump.org/linktypes.html */ + break; + case 240: + case 241: + length = 4; + break; + case 244: + length = 20; + break; + case 245: + length = 20; + break; + } + + if (length > 0) { + pseudoheader_item = proto_tree_add_item(tree, hf_pcap_packet_data_pseudoheader, tvb, offset, length, ENC_NA); + pseudoheader_tree = proto_item_add_subtree(pseudoheader_item, ett_pcap_pseudoheader); + } + + switch (*link_type) { + case 201: + proto_tree_add_item(pseudoheader_tree, hf_pcap_packet_data_pseudoheader_bluetooth_direction, tvb, offset, 4, ENC_BIG_ENDIAN); + if (tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN) == 0) + pinfo->p2p_dir = P2P_DIR_SENT; + else if (tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN) == 1) + pinfo->p2p_dir = P2P_DIR_RECV; + else + pinfo->p2p_dir = P2P_DIR_UNKNOWN; + offset += 4; + break; + default: + offset += length; + } + + next_tvb = tvb_new_subset_remaining(tvb, offset); + + packet_item = proto_tree_add_item(tree, hf_pcap_packet_data_data, tvb, offset, tvb_reported_length(next_tvb), ENC_NA); + packet_tree = proto_item_add_subtree(packet_item, ett_pcap_packet_data); + + offset = dissector_try_uint_new(wtap_encap_table, pinfo->phdr->pkt_encap, next_tvb, pinfo, packet_tree, TRUE, NULL); + + return offset; +} + +static int +dissect_pcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + static const guint8 pcap_magic[] = { 0xA1, 0xB2, 0xC3, 0xD4 }; + static const guint8 pcap_swapped_magic[] = { 0xD4, 0xC3, 0xB2, 0xA1 }; + gint offset = 0; + proto_tree *main_tree; + proto_item *main_item; + proto_tree *header_tree; + proto_item *header_item; + proto_tree *packet_tree; + proto_item *packet_item; + proto_tree *timestamp_tree; + proto_item *timestamp_item; + proto_tree *packet_data_tree; + proto_item *packet_data_item; + guint32 encoding; + guint32 length; + guint32 link_type; + guint32 frame_number = 1; + nstime_t timestamp; + + if (tvb_memeql(tvb, 0, pcap_magic, sizeof(pcap_magic)) && + tvb_memeql(tvb, 0, pcap_swapped_magic, sizeof(pcap_swapped_magic))) + return 0; + + main_item = proto_tree_add_item(tree, proto_pcap, tvb, offset, -1, ENC_NA); + main_tree = proto_item_add_subtree(main_item, ett_pcap); + + header_item = proto_tree_add_item(main_tree, hf_pcap_header , tvb, offset, 24, ENC_NA); + header_tree = proto_item_add_subtree(header_item, ett_pcap_header); + + proto_tree_add_item(header_tree, hf_pcap_header_magic_number, tvb, offset, 4, ENC_HOST_ENDIAN); + encoding = tvb_get_guint32(tvb, offset, ENC_HOST_ENDIAN); + if (encoding == 0xA1B2C3D4) { + encoding = ENC_LITTLE_ENDIAN; + } else if (encoding == 0xD4C3B2A1) { + encoding = ENC_BIG_ENDIAN; + } else { + expert_add_info(pinfo, main_item, &ei_unknown_encoding); + return offset; + } + offset += 4; + + proto_tree_add_item(header_tree, hf_pcap_header_version_major, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(header_tree, hf_pcap_header_version_minor, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(header_tree, hf_pcap_header_this_zone, tvb, offset, 4, encoding); + offset += 4; + + proto_tree_add_item(header_tree, hf_pcap_header_sigfigs, tvb, offset, 4, encoding); + offset += 4; + + proto_tree_add_item(header_tree, hf_pcap_header_snapshot_length, tvb, offset, 4, encoding); + offset += 4; + + proto_tree_add_item(header_tree, hf_pcap_header_link_type, tvb, offset, 4, encoding); + link_type = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + + while (offset < (gint) tvb_reported_length(tvb)) { + packet_item = proto_tree_add_item(main_tree, hf_pcap_packet, tvb, offset, 4 * 4, ENC_NA); + packet_tree = proto_item_add_subtree(packet_item, ett_pcap_packet); + proto_item_append_text(packet_item, " %u", frame_number); + + timestamp.secs = tvb_get_guint32(tvb, offset, encoding); + timestamp.nsecs = tvb_get_guint32(tvb, offset + 4, encoding) * 1000; + + timestamp_item = proto_tree_add_time(packet_tree, hf_pcap_packet_timestamp, tvb, offset, 8, ×tamp); + timestamp_tree = proto_item_add_subtree(timestamp_item, ett_pcap_timestamp); + + proto_tree_add_item(timestamp_tree, hf_pcap_packet_timestamp_sec, tvb, offset, 4, encoding); + offset += 4; + + proto_tree_add_item(timestamp_tree, hf_pcap_packet_timestamp_usec, tvb, offset, 4, encoding); + offset += 4; + + proto_tree_add_item(packet_tree, hf_pcap_packet_included_length, tvb, offset, 4, encoding); + length = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + + proto_tree_add_item(packet_tree, hf_pcap_packet_origin_length, tvb, offset, 4, encoding); + offset += 4; + + packet_data_item = proto_tree_add_item(packet_tree, hf_pcap_packet_data, tvb, offset, length, ENC_NA); + packet_data_tree = proto_item_add_subtree(packet_data_item, ett_pcap_packet_data); + + pinfo->fd->num = frame_number; + pinfo->fd->abs_ts = timestamp; + + if (pref_dissect_next_layer) + call_dissector_with_data(pcap_pseudoheader_handle, tvb_new_subset_length(tvb, offset, length), pinfo, packet_data_tree, &link_type); + offset += length; + + proto_item_set_len(packet_item, 4 * 4 + length); + frame_number += 1; + } + + return offset; +} + +static gboolean +dissect_pcap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + return dissect_pcap(tvb, pinfo, tree, NULL) > 0; +} + +void +proto_register_file_pcap(void) +{ + module_t *module; + expert_module_t *expert_module; + + static hf_register_info hf[] = { + { &hf_pcap_header, + { "Header", "pcap.header", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_header_magic_number, + { "Magic Bytes", "pcap.header.magic_bytes", + FT_UINT32, BASE_HEX, VALS(magic_number_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcap_header_version_major, + { "Version Major", "pcap.header.version.major", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_header_version_minor, + { "Version Minor", "pcap.header.version.minor", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_header_this_zone, + { "This Zone", "pcap.header.this_zone", + FT_INT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_header_sigfigs, + { "Sigfigs", "pcap.header.sigfigs", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_header_snapshot_length, + { "Snapshot Length", "pcap.header.snapshot_length", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_header_link_type, + { "Link Type", "pcap.header.link_type", + FT_UINT32, BASE_DEC_HEX, VALS(link_type_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet, + { "Packet", "pcap.packet", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_timestamp, + { "Timestamp", "pcap.packet.timestamp", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_timestamp_sec, + { "Timestamp sec", "pcap.packet.timestamp.sec", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_timestamp_usec, + { "Timestamp usec", "pcap.packet.timestamp.usec", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_included_length, + { "Included Length", "pcap.packet.included_length", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_origin_length, + { "Origin Length", "pcap.packet.origin_length", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_data, + { "Data", "pcap.packet.data", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_data_pseudoheader, + { "Pseudoheader", "pcap.packet.data.pseudoheader", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_data_pseudoheader_bluetooth_direction, + { "Direction", "pcap.packet.data.pseudoheader.bluetooth.direction", + FT_UINT32, BASE_HEX, VALS(pseudoheader_bluetooth_direction_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcap_packet_data_data, + { "Data", "pcap.packet.data.data", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + }; + + static ei_register_info ei[] = { + { &ei_unknown_encoding, { "pcap.unknown_encoding", PI_PROTOCOL, PI_ERROR, "Unknown Encoding", EXPFILL }} + }; + + static gint *ett[] = { + &ett_pcap, + &ett_pcap_header, + &ett_pcap_packet, + &ett_pcap_packet_data, + &ett_pcap_pseudoheader, + &ett_pcap_timestamp + }; + + proto_pcap = proto_register_protocol("PCAP File Format", "File-PCAP", "file-pcap"); + proto_register_field_array(proto_pcap, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + pcap_handle = new_register_dissector("file-pcap", dissect_pcap, proto_pcap); + pcap_pseudoheader_handle = new_create_dissector_handle(dissect_pcap_pseudoheader, proto_pcap); + + module = prefs_register_protocol(proto_pcap, NULL); + prefs_register_static_text_preference(module, "version", + "PCAP version: >=2.4", + "Version of file-format supported by this dissector."); + + prefs_register_bool_preference(module, "dissect_next_layer", + "Dissect next layer", + "Dissect next layer", + &pref_dissect_next_layer); + + expert_module = expert_register_protocol(proto_pcap); + expert_register_field_array(expert_module, ei, array_length(ei)); +} + +void +proto_reg_handoff_file_pcap(void) +{ + heur_dissector_add("wtap_file", dissect_pcap_heur, "PCAP File", "pcap_wtap", proto_pcap, HEURISTIC_ENABLE); + wtap_encap_table = find_dissector_table("wtap_encap"); +} + +/* + * Editor modelines - http://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: + */ diff --git a/epan/dissectors/file-pcapng.c b/epan/dissectors/file-pcapng.c new file mode 100644 index 0000000000..dcff37c465 --- /dev/null +++ b/epan/dissectors/file-pcapng.c @@ -0,0 +1,1943 @@ +/* file-pcapng.c + * Routines for PCAPNG File Format + * http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html + * + * Copyright 2015, Michal Labedzki for Tieto Corporation + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/expert.h> +#include <epan/addr_resolv.h> +#include <epan/wmem/wmem.h> + +#include <wiretap/wtap.h> + +static int proto_pcapng = -1; + +static dissector_handle_t pcapng_handle; +extern dissector_handle_t pcap_pseudoheader_handle; + +static int hf_pcapng_block = -1; + +static int hf_pcapng_block_type = -1; +static int hf_pcapng_block_type_vendor = -1; +static int hf_pcapng_block_type_value = -1; +static int hf_pcapng_block_length = -1; +static int hf_pcapng_block_data = -1; + +static int hf_pcapng_section_header_byte_order_magic = -1; +static int hf_pcapng_section_header_major_version = -1; +static int hf_pcapng_section_header_minor_version = -1; +static int hf_pcapng_section_header_section_length = -1; +static int hf_pcapng_options = -1; +static int hf_pcapng_option = -1; +static int hf_pcapng_option_code = -1; +static int hf_pcapng_option_code_section_header = -1; +static int hf_pcapng_option_code_interface_description = -1; +static int hf_pcapng_option_code_enhanced_packet = -1; +static int hf_pcapng_option_code_packet = -1; +static int hf_pcapng_option_code_interface_statistics = -1; +static int hf_pcapng_option_code_name_resolution = -1; +static int hf_pcapng_option_length = -1; +static int hf_pcapng_option_data = -1; +static int hf_pcapng_option_data_comment = -1; +static int hf_pcapng_option_data_section_header_hardware = -1; +static int hf_pcapng_option_data_section_header_os = -1; +static int hf_pcapng_option_data_section_header_user_application = -1; +static int hf_pcapng_option_data_interface_description_name = -1; +static int hf_pcapng_option_data_interface_description_description = -1; +static int hf_pcapng_option_data_ipv4 = -1; +static int hf_pcapng_option_data_ipv4_mask = -1; +static int hf_pcapng_option_data_ipv6 = -1; +static int hf_pcapng_option_data_ipv6_mask = -1; +static int hf_pcapng_option_data_mac_address = -1; +static int hf_pcapng_option_data_eui_address = -1; +static int hf_pcapng_option_data_interface_speed = -1; +static int hf_pcapng_option_data_interface_timestamp_resolution = -1; +static int hf_pcapng_option_data_interface_timestamp_resolution_base = -1; +static int hf_pcapng_option_data_interface_timestamp_resolution_value = -1; +static int hf_pcapng_option_data_interface_timezone = -1; +static int hf_pcapng_option_data_interface_filter = -1; +static int hf_pcapng_option_data_interface_os = -1; +static int hf_pcapng_option_data_interface_fcs_length = -1; +static int hf_pcapng_option_data_interface_timestamp_offset = -1; +static int hf_pcapng_option_data_packet_drop_count = -1; +static int hf_pcapng_option_data_packet_hash_algorithm = -1; +static int hf_pcapng_option_data_packet_hash_data = -1; +static int hf_pcapng_option_data_packet_flags = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_symbol = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_preamble = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_start_frame_delimiter = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_unaligned_frame = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_wrong_inter_frame_gap = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_packet_too_short = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_packet_too_long = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_crc_error = -1; +static int hf_pcapng_option_data_packet_flags_link_layer_errors_reserved = -1; +static int hf_pcapng_option_data_packet_flags_reserved = -1; +static int hf_pcapng_option_data_packet_flags_fcs_length = -1; +static int hf_pcapng_option_data_packet_flags_reception_type = -1; +static int hf_pcapng_option_data_packet_flags_direction = -1; +static int hf_pcapng_option_data_dns_name = -1; +static int hf_pcapng_option_data_start_time = -1; +static int hf_pcapng_option_data_end_time = -1; +static int hf_pcapng_option_data_interface_received = -1; +static int hf_pcapng_option_data_interface_dropped = -1; +static int hf_pcapng_option_data_interface_accepted_by_filter = -1; +static int hf_pcapng_option_data_interface_dropped_by_os = -1; +static int hf_pcapng_option_data_interface_delivered_to_user = -1; +static int hf_pcapng_option_padding = -1; +static int hf_pcapng_interface_description_link_type = -1; +static int hf_pcapng_interface_description_reserved = -1; +static int hf_pcapng_interface_description_snap_length = -1; +static int hf_pcapng_packet_block_interface_id = -1; +static int hf_pcapng_packet_block_drops_count = -1; +static int hf_pcapng_captured_length = -1; +static int hf_pcapng_packet_length = -1; +static int hf_pcapng_packet_data = -1; +static int hf_pcapng_packet_padding = -1; +static int hf_pcapng_interface_id = -1; +static int hf_pcapng_timestamp = -1; +static int hf_pcapng_timestamp_data = -1; +static int hf_pcapng_records = -1; +static int hf_pcapng_record = -1; +static int hf_pcapng_record_code = -1; +static int hf_pcapng_record_length = -1; +static int hf_pcapng_record_data = -1; +static int hf_pcapng_record_ipv4 = -1; +static int hf_pcapng_record_ipv6 = -1; +static int hf_pcapng_record_name = -1; +static int hf_pcapng_record_padding = -1; + +static expert_field ei_invalid_option_length = EI_INIT; +static expert_field ei_invalid_record_length = EI_INIT; +static expert_field ei_unknown_encoding = EI_INIT; + +static gint ett_pcapng = -1; +static gint ett_pcapng_section_header_block = -1; +static gint ett_pcapng_block_data = -1; +static gint ett_pcapng_options = -1; +static gint ett_pcapng_option = -1; +static gint ett_pcapng_records = -1; +static gint ett_pcapng_record = -1; +static gint ett_pcapng_packet_data = -1; + +static const int *hfx_pcapng_option_data_interface_timestamp_resolution[] = { + &hf_pcapng_option_data_interface_timestamp_resolution_base, + &hf_pcapng_option_data_interface_timestamp_resolution_value, + NULL +}; + +static const int *hfx_pcapng_option_data_packet_flags_link_layer_errors[] = { + &hf_pcapng_option_data_packet_flags_link_layer_errors_symbol, + &hf_pcapng_option_data_packet_flags_link_layer_errors_preamble, + &hf_pcapng_option_data_packet_flags_link_layer_errors_start_frame_delimiter, + &hf_pcapng_option_data_packet_flags_link_layer_errors_unaligned_frame, + &hf_pcapng_option_data_packet_flags_link_layer_errors_wrong_inter_frame_gap, + &hf_pcapng_option_data_packet_flags_link_layer_errors_packet_too_short, + &hf_pcapng_option_data_packet_flags_link_layer_errors_packet_too_long, + &hf_pcapng_option_data_packet_flags_link_layer_errors_crc_error, + &hf_pcapng_option_data_packet_flags_link_layer_errors_reserved, + NULL +}; + +static const int *hfx_pcapng_option_data_packet_flags[] = { + &hf_pcapng_option_data_packet_flags_reserved, + &hf_pcapng_option_data_packet_flags_fcs_length, + &hf_pcapng_option_data_packet_flags_reception_type, + &hf_pcapng_option_data_packet_flags_direction, + NULL +}; + +static const int *hfx_pcapng_block_type[] = { + &hf_pcapng_block_type_vendor, + &hf_pcapng_block_type_value, + NULL +}; + +struct info { + guint32 file_number; + guint32 interface_number; + guint32 frame_number; + wmem_array_t *interfaces; +}; + +struct interface_description { + guint32 link_type; + guint8 timestamp_resolution; + guint64 timestamp_offset; +}; + + +static gboolean pref_dissect_next_layer = FALSE; + +#define BLOCK_INTERFACE_DESCRIPTION 0x00000001 +#define BLOCK_PACKET 0x00000002 +#define BLOCK_SIMPLE_PACKET 0x00000003 +#define BLOCK_NAME_RESOLUTION 0x00000004 +#define BLOCK_INTERFACE_STATISTICS 0x00000005 +#define BLOCK_ENHANCED_PACKET 0x00000006 +#define BLOCK_IRIG_TIMESTAMP 0x00000007 +#define BLOCK_ARINC_429 0x00000008 +#define BLOCK_SECTION_HEADER 0x0A0D0D0A + +static const value_string block_type_vals[] = { + { 0x00000001, "Interface Description Block" }, + { 0x00000002, "Packet Block" }, + { 0x00000003, "Simple Packet Block" }, + { 0x00000004, "Name Resolution Block" }, + { 0x00000005, "Interface Statistics Block" }, + { 0x00000006, "Enhanced Packet Block" }, + { 0x00000007, "IRIG Timestamp Block" }, + { 0x00000008, "Arinc 429 in AFDX Encapsulation Information Block " }, + { 0x0A0D0D0A, "Section Header Block" }, + { 0, NULL } +}; + +static const value_string byte_order_magic_vals[] = { + { 0x1A2B3C4D, "Big-endian" }, + { 0x4D3C2B1A, "Little-endian" }, + { 0, NULL } +}; + +static const value_string option_code_section_header_vals[] = { + { 0x0000, "End of Options" }, + { 0x0001, "Comment" }, + + { 0x0002, "Hardware Description" }, + { 0x0003, "OS Description" }, + { 0x0004, "User Application" }, + { 0, NULL } +}; + +static const value_string option_code_interface_description_vals[] = { + { 0x0000, "End of Options" }, + { 0x0001, "Comment" }, + + { 0x0002, "Interface Name" }, + { 0x0003, "Interface Description" }, + { 0x0004, "IPv4 Address" }, + { 0x0005, "IPv6 Address" }, + { 0x0006, "MAC Address" }, + { 0x0007, "EUI Address" }, + { 0x0008, "Speed" }, + { 0x0009, "Timestamp Resolution" }, + { 0x000A, "Timezone" }, + { 0x000B, "Filter" }, + { 0x000C, "OS" }, + { 0x000D, "FCS Length" }, + { 0x000E, "Timestamo Offset" }, + { 0, NULL } +}; + +static const value_string option_code_enhanced_packet_vals[] = { + { 0x0000, "End of Options" }, + { 0x0001, "Comment" }, + + { 0x0002, "Flags" }, + { 0x0003, "Hash" }, + { 0x0004, "Drop Count" }, + { 0, NULL } +}; + +static const value_string option_code_packet_vals[] = { + { 0x0000, "End of Options" }, + { 0x0001, "Comment" }, + + { 0x0002, "Flags" }, + { 0x0003, "Hash" }, + { 0, NULL } +}; + + +static const value_string option_code_name_resolution_vals[] = { + { 0x0000, "End of Options" }, + { 0x0001, "Comment" }, + + { 0x0002, "DNS Name" }, + { 0x0003, "DNS IPv4 Address" }, + { 0x0004, "DNS IPv6 Address" }, + { 0, NULL } +}; + + +static const value_string option_code_interface_statistics_vals[] = { + { 0x0000, "End of Options" }, + { 0x0001, "Comment" }, + + { 0x0002, "Start Time" }, + { 0x0003, "End Time" }, + { 0x0004, "Number of Rx Packets" }, + { 0x0005, "Number of Dropped Packets" }, + { 0x0006, "Number of Accepted Packets" }, + { 0x0007, "Number of Packets Dropped by OS" }, + { 0x0008, "Number of Packets Delivered to the User" }, + { 0, NULL } +}; + +static const value_string record_code_vals[] = { + { 0x0000, "End of Records" }, + { 0x0001, "IPv4 Record" }, + { 0x0002, "IPv6 Record" }, + { 0, NULL } +}; + + +static const value_string timestamp_resolution_base_vals[] = { + { 0x0000, "Power of 10" }, + { 0x0001, "Power of 2" }, + { 0, NULL } +}; + +static const value_string packet_hash_algorithm_vals[] = { + { 0x00, "2's complement" }, + { 0x01, "XOR" }, + { 0x02, "CRC32" }, + { 0x03, "MD5" }, + { 0x04, "SHA1" }, + { 0, NULL } +}; + +static const value_string packet_flags_direction_vals[] = { + { 0x00, "Information Not Available" }, + { 0x01, "Inbound" }, + { 0x02, "Outbound" }, + { 0, NULL } +}; + +static const value_string flags_reception_type_vals[] = { + { 0x00, "Not Specified" }, + { 0x01, "Unicast" }, + { 0x02, "Multicast" }, + { 0x03, "Broadcast" }, + { 0x04, "Promiscuous" }, + { 0, NULL } +}; + +/* Mostly PCAP, but add also link type found in wiretap code */ +static const value_string link_type_vals[] = { + { 0, "NULL" }, + { 1, "ETHERNET" }, + { 3, "AX25" }, + { 6, "IEEE802_5" }, + { 7, "ARCNET_BSD" }, + { 8, "SLIP" }, + { 9, "PPP" }, + { 10, "FDDI/FDDI_BITSWAPPED" }, + { 32, "REDBACK" }, + { 50, "PPP_HDLC" }, + { 51, "PPP_ETHER" }, + { 99, "SYMANTEC" }, + { 100, "ATM_RFC1483" }, + { 101, "RAW" }, + { 104, "C_HDLC" }, + { 105, "IEEE802_11" }, + { 106, "LINUX_ATM_CLIP" }, + { 107, "FRELAY" }, + { 108, "LOOP" }, + { 109, "ENC" }, + { 112, "CHDLC" }, + { 113, "LINUX_SLL" }, + { 114, "LTALK" }, + { 117, "PFLOG" }, + { 118, "CISCO_IOS" }, + { 119, "IEEE802_11_PRISM" }, + { 121, "HHDLC" }, + { 122, "IP_OVER_FC" }, + { 123, "SUNATM" }, + { 127, "IEEE802_11_RADIOTAP" }, + { 128, "TZSP" }, + { 129, "ARCNET_LINUX" }, + { 130, "JUNIPER_MLPPP" }, + { 131, "JUNIPER_MLFR" }, + { 133, "JUNIPER_GGSN" }, + { 135, "JUNIPER_ATM2" }, + { 136, "JUNIPER_SVCS" }, + { 137, "JUNIPER_ATM1" }, + { 138, "APPLE_IP_OVER_IEEE1394" }, + { 139, "MTP2_WITH_PHDR" }, + { 140, "MTP2" }, + { 141, "MTP3" }, + { 142, "SCCP" }, + { 143, "DOCSIS" }, + { 144, "LINUX_IRDA" }, + { 147, "USER_0" }, + { 148, "USER_1" }, + { 149, "USER_2" }, + { 150, "USER_3" }, + { 151, "USER_4" }, + { 152, "USER_5" }, + { 153, "USER_6" }, + { 154, "USER_7" }, + { 155, "USER_8" }, + { 156, "USER_9" }, + { 157, "USER_10" }, + { 158, "USER_11" }, + { 159, "USER_12" }, + { 160, "USER_13" }, + { 161, "USER_14" }, + { 162, "USER_15" }, + { 163, "IEEE802_11_AVS" }, + { 165, "BACNET_MS_TP" }, + { 166, "PPP_PPPD" }, + { 167, "JUNIPER_PPPOE" }, + { 169, "GPRS_LLC" }, + { 172, "GCOM_TIE1" }, + { 173, "GCOM_SERIAL" }, + { 177, "LINUX_LAPD" }, + { 178, "JUNIPER_ETHER" }, + { 179, "JUNIPER_PPP" }, + { 180, "JUNIPER_FRELAY" }, + { 181, "JUNIPER_CHDLC" }, + { 183, "JUNIPER_VP" }, + { 186, "USB" }, + { 187, "BLUETOOTH_HCI_H4" }, + { 188, "IEEE802_16_MAC_CPS" }, + { 189, "USB_LINUX" }, + { 190, "CAN20B" }, + { 192, "PPI" }, + { 195, "IEEE802_15_4" }, + { 196, "SITA" }, + { 197, "ERF" }, + { 199, "IPMB" }, + { 201, "BLUETOOTH_HCI_H4_WITH_PHDR" }, + { 202, "AX25_KISS" }, + { 203, "LAPD" }, + { 204, "PPP_WITH_DIR" }, + { 205, "C_HDLC_WITH_DIR" }, + { 206, "FRELAY_WITH_DIR" }, + { 209, "IPMB_LINUX" }, + { 210, "FLEXRAY" }, + { 211, "MOST" }, + { 212, "LIN" }, + { 213, "X2E_SERIAL" }, + { 214, "X2E_XORAYA" }, + { 215, "IEEE802_15_4_NONASK_PHY" }, + { 220, "USB_LINUX_MMAPPED" }, + { 224, "FC_2" }, + { 225, "FC_2_WITH_FRAME_DELIMS" }, + { 226, "IPNET" }, + { 227, "CAN_SOCKETCAN" }, + { 228, "IPV4" }, + { 229, "IPV6" }, + { 230, "IEEE802_15_4_NOFCS" }, + { 231, "DBUS" }, + { 235, "DVB_CI" }, + { 236, "MUX27010" }, + { 237, "STANAG_5066_D_PDU" }, + { 239, "NFLOG" }, + { 240, "NETANALYZER" }, + { 241, "NETANALYZER_TRANSPARENT" }, + { 242, "IPOIB" }, + { 243, "MPEG_2_TS" }, + { 244, "NG40" }, + { 245, "NFC_LLCP" }, + { 247, "INFINIBAND" }, + { 248, "SCTP" }, + { 249, "USBPCAP" }, + { 250, "RTAC_SERIAL" }, + { 251, "BLUETOOTH_LE_LL" }, + { 252, "WIRESHARK_UPPER_PDU" }, + { 253, "NETLINK" }, + { 254, "BLUETOOTH_LINUX_MONITOR" }, + { 255, "BLUETOOTH_BREDR_BB" }, + { 256, "BLUETOOTH_LE_LL_WITH_PHDR" }, + { 257, "PROFIBUS_DL" }, + { 258, "PKTAP" }, + { 259, "EPON" }, + { 260, "IPMI_HPM_2" }, + { 261, "ZWAVE_R1_R2" }, + { 262, "ZWAVE_R3" }, + { 263, "WATTSTOPPER_DLM" }, + { 0, NULL } +}; + + +void proto_register_pcapng(void); +void proto_reg_handoff_pcapng(void); + +static gint dissect_options(proto_tree *tree, packet_info *pinfo, + guint32 block_type, tvbuff_t *tvb, guint encoding, void *user_data) +{ + proto_tree *options_tree; + proto_item *options_item; + proto_tree *option_tree; + proto_item *option_item; + proto_item *p_item; + gint offset = 0; + gint offset_option_start; + guint16 option_code; + gint option_length; + gint hfj_pcapng_option_code; + const gchar *str = NULL; + address addr; + address addr_mask; + const value_string *vals = NULL; + union value { + guint32 u32; + guint64 u64; + guint8 u8; + } value; + + if (tvb_reported_length(tvb) <= 0) + return 0; + + options_item = proto_tree_add_item(tree, hf_pcapng_options, tvb, offset, -1, ENC_NA); + options_tree = proto_item_add_subtree(options_item, ett_pcapng_options); + + offset_option_start = offset; + while (tvb_reported_length(tvb) - (offset_option_start - offset) > 0) { + str = NULL; + option_code = tvb_get_guint16(tvb, offset, encoding); + option_length = tvb_get_guint16(tvb, offset + 2, encoding); + + option_item = proto_tree_add_item(options_tree, hf_pcapng_option, tvb, offset, option_length + 2 * 2, ENC_NA); + option_tree = proto_item_add_subtree(option_item, ett_pcapng_option); + + switch (block_type) { + case BLOCK_SECTION_HEADER: + hfj_pcapng_option_code = hf_pcapng_option_code_section_header; + vals = option_code_section_header_vals; + break; + case BLOCK_INTERFACE_DESCRIPTION: + hfj_pcapng_option_code = hf_pcapng_option_code_interface_description; + vals = option_code_interface_description_vals; + break; + case BLOCK_ENHANCED_PACKET: + hfj_pcapng_option_code = hf_pcapng_option_code_enhanced_packet; + vals = option_code_enhanced_packet_vals; + break; + case BLOCK_PACKET: + hfj_pcapng_option_code = hf_pcapng_option_code_packet; + vals = option_code_packet_vals; + break; + case BLOCK_NAME_RESOLUTION: + hfj_pcapng_option_code = hf_pcapng_option_code_name_resolution; + vals = option_code_name_resolution_vals; + break; + case BLOCK_INTERFACE_STATISTICS: + hfj_pcapng_option_code = hf_pcapng_option_code_interface_statistics; + vals = option_code_interface_statistics_vals; + break; + default: + hfj_pcapng_option_code = hf_pcapng_option_code; + } + + if (vals) + proto_item_append_text(option_item, ": %s", val_to_str_const(option_code, vals, "Unknown")); + + proto_tree_add_item(option_tree, hfj_pcapng_option_code, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(option_tree, hf_pcapng_option_length, tvb, offset, 2, encoding); + offset += 2; + + if (option_code == 0 && option_length == 0) { + break; + } else if (option_code == 1) { + proto_tree_add_item(option_tree, hf_pcapng_option_data_comment, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + } else switch (block_type) { + case BLOCK_SECTION_HEADER: + switch (option_code) { + case 0x0002: + proto_tree_add_item(option_tree, hf_pcapng_option_data_section_header_hardware, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + break; + case 0x0003: + proto_tree_add_item(option_tree, hf_pcapng_option_data_section_header_os, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + break; + case 0x0004: + proto_tree_add_item(option_tree, hf_pcapng_option_data_section_header_user_application, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + break; + default: + proto_tree_add_item(option_tree, hf_pcapng_option_data, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + break; + case BLOCK_INTERFACE_DESCRIPTION: { + struct interface_description *interface_description = (struct interface_description *) user_data; + + switch (option_code) { + case 0x0002: + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_description_name, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + + break; + case 0x0003: + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_description_description, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + + break; + case 0x0004: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + proto_tree_add_item(option_tree, hf_pcapng_option_data_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); + TVB_SET_ADDRESS(&addr, AT_IPv4, tvb, offset, 4); + offset += 4; + + proto_tree_add_item(option_tree, hf_pcapng_option_data_ipv4_mask, tvb, offset, 4, ENC_BIG_ENDIAN); + TVB_SET_ADDRESS(&addr_mask, AT_IPv4, tvb, offset, 4); + offset += 4; + + str = wmem_strdup_printf(wmem_packet_scope(), "%s/%s", + address_to_display(wmem_packet_scope(), &addr), + address_to_display(wmem_packet_scope(), &addr_mask)); + break; + case 0x0005: + if (option_length != 17) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_ipv6, tvb, offset, 16, ENC_NA); + TVB_SET_ADDRESS(&addr, AT_IPv6, tvb, offset, 16); + offset += 16; + + proto_tree_add_item(option_tree, hf_pcapng_option_data_ipv6_mask, tvb, offset, 1, ENC_NA); + offset += 1; + + str = wmem_strdup_printf(wmem_packet_scope(), "%s/%u", + address_to_display(wmem_packet_scope(), &addr), (unsigned int) tvb_get_guint8(tvb, offset - 1)); + + break;; + case 0x0006: + if (option_length != 6) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_mac_address, tvb, offset, 6, encoding); + str = tvb_get_ether_name(tvb, offset); + offset += 6; + + break; + case 0x0007: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_eui_address, tvb, offset, 8, encoding); + TVB_SET_ADDRESS(&addr, AT_EUI64, tvb, offset, 8); + offset += 8; + + str = address_to_display(wmem_packet_scope(), &addr); + + break; + case 0x0008: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + p_item = proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_speed, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + if (value.u64 == 10000000) { + str = "10 Mbps"; + proto_item_append_text(p_item, "%s", str); + } else if (value.u64 == 100000000) { + str = "100 Mbps"; + proto_item_append_text(p_item, "%s", str); + } else if (value.u64 == 1000000000) { + str = "1 Gbps"; + proto_item_append_text(p_item, "%s", str); + } else { + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + } + offset += 8; + + break; + case 0x0009: + if (option_length != 1) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_bitmask(option_tree, tvb, offset, hf_pcapng_option_data_interface_timestamp_resolution, ett_pcapng_option, hfx_pcapng_option_data_interface_timestamp_resolution, ENC_NA); + value.u8 = tvb_get_guint8(tvb, offset); + offset += 1; + + if (interface_description) { + interface_description->timestamp_resolution = value.u8; + } + + str = wmem_strdup_printf(wmem_packet_scope(), "%s^-%u%s", + (value.u8 & 0x80) ? "2" : "10", + (guint32) (value.u8 & 0x7F), + (!(value.u8 & 0x80) && value.u8 == 6) ? " (microseconds)" : ((!(value.u8 & 0x80) && value.u8 == 9) ? " (nanoseconds)" : "")); + + break; + case 0x000A: + if (option_length != 4) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + +/* TODO: Better timezone decoding */ + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_timezone, tvb, offset, 4, encoding); + value.u32 = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + + str = wmem_strdup_printf(wmem_packet_scope(), "%u", value.u32); + + break; + case 0x000B: + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_filter, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + + break; + case 0x000C: + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_os, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + + break; + case 0x000D: + if (option_length != 1) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_fcs_length, tvb, offset, 1, ENC_NA); + value.u8 = tvb_get_guint8(tvb, offset); + str = wmem_strdup_printf(wmem_packet_scope(), "%u", (guint32) value.u8); + offset += 1; + + break; + case 0x000E: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_timestamp_offset, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + offset += 8; + + if (interface_description) { + interface_description->timestamp_offset = value.u64; + } + + break; + default: + proto_tree_add_item(option_tree, hf_pcapng_option_data, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + } + break; + case BLOCK_PACKET: + switch (option_code) { + case 0x0002: + if (option_length != 4) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + if (encoding == ENC_LITTLE_ENDIAN) { + proto_tree_add_bitmask(option_tree, tvb, offset, hf_pcapng_option_data_packet_flags, ett_pcapng_option, hfx_pcapng_option_data_packet_flags, encoding); + offset += 2; + + proto_tree_add_bitmask(option_tree, tvb, offset, hf_pcapng_option_data_packet_flags_link_layer_errors, ett_pcapng_option, hfx_pcapng_option_data_packet_flags_link_layer_errors, encoding); + offset += 2; + } else { + proto_tree_add_bitmask(option_tree, tvb, offset, hf_pcapng_option_data_packet_flags_link_layer_errors, ett_pcapng_option, hfx_pcapng_option_data_packet_flags_link_layer_errors, encoding); + offset += 2; + + proto_tree_add_bitmask(option_tree, tvb, offset, hf_pcapng_option_data_packet_flags, ett_pcapng_option, hfx_pcapng_option_data_packet_flags, encoding); + offset += 2; + } + + break; + case 0x0003: + proto_tree_add_item(option_tree, hf_pcapng_option_data_packet_hash_algorithm, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(option_tree, hf_pcapng_option_data_packet_hash_data, tvb, offset, option_length - 1, ENC_NA); + offset += option_length - 1; + + break; + default: + proto_tree_add_item(option_tree, hf_pcapng_option_data, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + + break; + case BLOCK_NAME_RESOLUTION: + switch (option_code) { + case 0x0002: + proto_tree_add_item(option_tree, hf_pcapng_option_data_dns_name, tvb, offset, option_length, ENC_NA | ENC_UTF_8); + str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, option_length, ENC_UTF_8); + offset += option_length; + + break; + case 0x0003: + if (option_length != 4) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); + TVB_SET_ADDRESS(&addr, AT_IPv4, tvb, offset, 4); + offset += 4; + + str = wmem_strdup_printf(wmem_packet_scope(), "%s", + address_to_display(wmem_packet_scope(), &addr)); + + break; + case 0x0004: + if (option_length != 16) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_ipv6, tvb, offset, 16, ENC_NA); + TVB_SET_ADDRESS(&addr, AT_IPv6, tvb, offset, 16); + offset += 16; + + str = wmem_strdup_printf(wmem_packet_scope(), "%s", + address_to_display(wmem_packet_scope(), &addr)); + + break; + default: + proto_tree_add_item(option_tree, hf_pcapng_option_data, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + + break; + case BLOCK_INTERFACE_STATISTICS: + switch (option_code) { + case 0x0002: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_start_time, tvb, offset, 8, encoding); + offset += 8; + + break; + case 0x0003: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_end_time, tvb, offset, 8, encoding); + offset += 8; + + break; + case 0x0004: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_received, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + offset += 8; + + break; + case 0x0005: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_dropped, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + offset += 8; + + break; + case 0x0006: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_accepted_by_filter, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + offset += 8; + + break; + case 0x0007: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_dropped_by_os, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + offset += 8; + + break; + case 0x0008: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_interface_delivered_to_user, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + offset += 8; + + break; + default: + proto_tree_add_item(option_tree, hf_pcapng_option_data, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + + break; + break; + case BLOCK_ENHANCED_PACKET: + switch (option_code) { + case 0x0002: + if (option_length != 4) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_bitmask(option_tree, tvb, offset, hf_pcapng_option_data_packet_flags, ett_pcapng_option, hfx_pcapng_option_data_packet_flags, encoding); + offset += 4; + + break; + case 0x0003: + proto_tree_add_item(option_tree, hf_pcapng_option_data_packet_hash_algorithm, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(option_tree, hf_pcapng_option_data_packet_hash_data, tvb, offset, option_length - 1, ENC_NA); + offset += option_length - 1; + + break; + case 0x0004: + if (option_length != 8) { + proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length); + offset += option_length; + break; + } + + proto_tree_add_item(option_tree, hf_pcapng_option_data_packet_drop_count, tvb, offset, 8, encoding); + value.u64 = tvb_get_guint64(tvb, offset, encoding); + str = wmem_strdup_printf(wmem_packet_scope(), "%"G_GUINT64_FORMAT, value.u64); + offset += 8; + + break; + default: + proto_tree_add_item(option_tree, hf_pcapng_option_data, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + + break; + default: + proto_tree_add_item(option_tree, hf_pcapng_option_data, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + + if (option_length % 4) { + proto_item_set_len(option_item, option_length + 2 * 2 + (4 - option_length % 4)); + option_length = 4 - option_length % 4; + proto_tree_add_item(option_tree, hf_pcapng_option_padding, tvb, offset, option_length, ENC_NA); + offset += option_length; + } + + if (str) + proto_item_append_text(option_item, " = %s", str); + + } + + return offset; +} + +static gint dissect_block(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, + guint encoding, struct info *info) +{ + proto_tree *block_tree; + proto_item *block_item; + proto_tree *block_data_tree; + proto_item *block_data_item; + proto_tree *packet_data_tree; + proto_item *packet_data_item; + gint offset = 0; + guint32 length; + guint32 captured_length; + guint32 block_type; + guint32 block_data_length; + guint32 interface_id; + tvbuff_t *next_tvb; + + block_type = tvb_get_guint32(tvb, offset + 0, encoding); + length = tvb_get_guint32(tvb, offset + 4, encoding); + + block_item = proto_tree_add_item(tree, hf_pcapng_block, tvb, offset, length, ENC_NA); + block_tree = proto_item_add_subtree(block_item, ett_pcapng_section_header_block); + proto_item_append_text(block_item, ": %s", val_to_str_const(block_type, block_type_vals, "Unknown")); + + proto_tree_add_bitmask_with_flags(block_tree, tvb, offset, hf_pcapng_block_type, ett_pcapng_option, hfx_pcapng_block_type, encoding, BMT_NO_APPEND); + offset += 4; + + proto_tree_add_item(block_tree, hf_pcapng_block_length, tvb, offset, 4, encoding); + block_data_length = tvb_get_guint32(tvb, offset, encoding) - 3 * 4; + offset += 4; + + block_data_item = proto_tree_add_item(block_tree, hf_pcapng_block_data, tvb, offset, block_data_length, ENC_NA); + block_data_tree = proto_item_add_subtree(block_data_item, ett_pcapng_block_data); + + switch (block_type) { + case BLOCK_SECTION_HEADER: /* Section Header Block */ + proto_item_append_text(block_item, " %u", info->file_number); + info->file_number += 1; + info->interface_number = 0; + info->frame_number = 1; + + proto_tree_add_item(block_data_tree, hf_pcapng_section_header_byte_order_magic, tvb, offset, 4, ENC_NA); + offset += 4; + + proto_tree_add_item(block_data_tree, hf_pcapng_section_header_major_version, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(block_data_tree, hf_pcapng_section_header_minor_version, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(block_data_tree, hf_pcapng_section_header_section_length, tvb, offset, 8, encoding); + offset += 8; + + next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - 4 - 2 - 2 - 8); + offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, NULL); + + break; + case BLOCK_INTERFACE_DESCRIPTION: { + struct interface_description interface_description; + + memset(&interface_description, 0, sizeof(struct interface_description)); + + proto_item_append_text(block_item, " %u", info->interface_number); + info->interface_number += 1; + + proto_tree_add_item(block_data_tree, hf_pcapng_interface_description_link_type, tvb, offset, 2, encoding); + interface_description.link_type = tvb_get_guint16(tvb, offset, encoding); + offset += 2; + + proto_tree_add_item(block_data_tree, hf_pcapng_interface_description_reserved, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(block_data_tree, hf_pcapng_interface_description_snap_length, tvb, offset, 4, encoding); + offset += 4; + + next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - 2 - 2 - 4); + offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, &interface_description); + + wmem_array_append_one(info->interfaces, interface_description); + } + break; + case BLOCK_PACKET: + proto_item_append_text(block_item, " %u", info->frame_number); + info->frame_number += 1; + + proto_tree_add_item(block_data_tree, hf_pcapng_packet_block_interface_id, tvb, offset, 2, encoding); + interface_id = tvb_get_guint16(tvb, offset, encoding); + offset += 2; + + proto_tree_add_item(block_data_tree, hf_pcapng_packet_block_drops_count, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(block_data_tree, hf_pcapng_timestamp_data, tvb, offset, 8, encoding); + offset += 8; + + proto_tree_add_item(block_data_tree, hf_pcapng_captured_length, tvb, offset, 4, encoding); + captured_length = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + + proto_tree_add_item(block_data_tree, hf_pcapng_packet_length, tvb, offset, 4, encoding); + offset += 4; + + packet_data_item = proto_tree_add_item(block_data_tree, hf_pcapng_packet_data, tvb, offset, captured_length, encoding); + packet_data_tree = proto_item_add_subtree(packet_data_item, ett_pcapng_packet_data); + if (pref_dissect_next_layer && interface_id < wmem_array_get_count(info->interfaces)) { + struct interface_description *interface_description; + + interface_description = (struct interface_description *) wmem_array_index(info->interfaces, interface_id); + call_dissector_with_data(pcap_pseudoheader_handle, tvb_new_subset_length(tvb, offset, captured_length), pinfo, packet_data_tree, &interface_description->link_type); + } + offset += captured_length; + + if (captured_length % 4) { + proto_tree_add_item(block_data_tree, hf_pcapng_packet_padding, tvb, offset, captured_length % 4?(4 - captured_length % 4):0, ENC_NA); + offset += captured_length % 4?(4 - captured_length % 4):0; + } + + next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - 2 - 2 - 8 - 4 - 4 - captured_length - (captured_length % 4?(4 - captured_length % 4):0)); + offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, NULL); + + break; + case BLOCK_SIMPLE_PACKET: + proto_item_append_text(block_item, " %u", info->frame_number); + info->frame_number += 1; + + proto_tree_add_item(block_data_tree, hf_pcapng_packet_length, tvb, offset, 4, encoding); + captured_length = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + + interface_id = 0; + + packet_data_item = proto_tree_add_item(block_data_tree, hf_pcapng_packet_data, tvb, offset, captured_length, encoding); + packet_data_tree = proto_item_add_subtree(packet_data_item, ett_pcapng_packet_data); + if (pref_dissect_next_layer && interface_id < wmem_array_get_count(info->interfaces)) { + struct interface_description *interface_description; + + interface_description = (struct interface_description *) wmem_array_index(info->interfaces, interface_id); + call_dissector_with_data(pcap_pseudoheader_handle, tvb_new_subset_length(tvb, offset, captured_length), pinfo, packet_data_tree, &interface_description->link_type); + } + offset += captured_length; + + if (captured_length % 4) { + proto_tree_add_item(block_data_tree, hf_pcapng_packet_padding, tvb, offset, captured_length % 4?(4 - captured_length % 4):0, ENC_NA); + offset += captured_length % 4?(4 - captured_length % 4):0; + } + + break; + case BLOCK_NAME_RESOLUTION: + { + proto_tree *records_tree; + proto_item *records_item; + proto_tree *record_tree; + proto_item *record_item; + gint offset_record_start; + gint offset_string_start; + guint16 record_code; + gint record_length; + gint string_length; + gchar *str = NULL; + address addr; + + records_item = proto_tree_add_item(block_data_tree, hf_pcapng_records, tvb, offset, block_data_length, ENC_NA); + records_tree = proto_item_add_subtree(records_item, ett_pcapng_records); + + offset_record_start = offset; + while (block_data_length - (offset_record_start - offset) > 0) { + record_code = tvb_get_guint16(tvb, offset, encoding); + record_length = tvb_get_guint16(tvb, offset + 2, encoding); + + record_item = proto_tree_add_item(records_tree, hf_pcapng_record, tvb, offset, record_length + 2 * 2, ENC_NA); + record_tree = proto_item_add_subtree(record_item, ett_pcapng_record); + + proto_item_append_text(record_item, ": %s", val_to_str_const(record_code, record_code_vals, "Unknown")); + + proto_tree_add_item(record_tree, hf_pcapng_record_code, tvb, offset, 2, encoding); + offset += 2; + + proto_tree_add_item(record_tree, hf_pcapng_record_length, tvb, offset, 2, encoding); + offset += 2; + + if (record_code == 0 && record_length == 0) { + break; + } else switch (record_code) { + case 0x0001: /* IPv4 Record */ + if (record_length < 5) { + proto_tree_add_expert(record_tree, pinfo, &ei_invalid_record_length, tvb, offset, record_length); + offset += record_length; + break; + } + + proto_tree_add_item(record_tree, hf_pcapng_record_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); + TVB_SET_ADDRESS(&addr, AT_IPv4, tvb, offset, 4); + offset += 4; + + offset_string_start = offset; + while (offset - offset_string_start < record_length - 4) { + string_length = tvb_strnlen(tvb, offset, (offset - offset_string_start) + record_length - 4); + if (string_length >= 0) { + proto_tree_add_item(record_tree, hf_pcapng_record_name, tvb, offset, string_length + 1, encoding); + offset += string_length + 1; + } else { + proto_tree_add_item(record_tree, hf_pcapng_record_data, tvb, offset, (record_length - 4) - (offset - offset_string_start), encoding); + offset += (record_length - 4) - (offset - offset_string_start); + } + } + + str = wmem_strdup_printf(wmem_packet_scope(), "%s", + address_to_display(wmem_packet_scope(), &addr)); + break; + case 0x0002: /* IPv6 Record */ + if (record_length < 17) { + proto_tree_add_expert(record_tree, pinfo, &ei_invalid_option_length, tvb, offset, record_length); + offset += record_length; + break; + } + + proto_tree_add_item(record_tree, hf_pcapng_record_ipv6, tvb, offset, 16, ENC_NA); + TVB_SET_ADDRESS(&addr, AT_IPv6, tvb, offset, 16); + offset += 16; + + offset_string_start = offset; + while (offset - offset_string_start < record_length - 16) { + string_length = tvb_strnlen(tvb, offset, (offset - offset_string_start) + record_length - 16); + if (string_length >= 0) { + proto_tree_add_item(record_tree, hf_pcapng_record_name, tvb, offset, string_length + 1, encoding); + offset += string_length + 1; + } else { + proto_tree_add_item(record_tree, hf_pcapng_record_data, tvb, offset, (record_length - 16) - (offset - offset_string_start), encoding); + offset += (record_length - 16) - (offset - offset_string_start); + } + } + + str = wmem_strdup_printf(wmem_packet_scope(), "%s", + address_to_display(wmem_packet_scope(), &addr)); + + break; + default: + proto_tree_add_item(record_tree, hf_pcapng_record_data, tvb, offset, record_length, ENC_NA); + offset += record_length; + } + + if (record_code != 0 && record_length % 4) { + proto_item_set_len(record_item, record_length + 2 * 2 + (4 - record_length % 4)); + record_length = 4 - record_length % 4; + proto_tree_add_item(record_tree, hf_pcapng_record_padding, tvb, offset, record_length, ENC_NA); + offset += record_length; + } + + if (str) + proto_item_append_text(record_item, " = %s", str); + } + + next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - (offset - offset_record_start)); + offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, NULL); + } + + break; + case BLOCK_INTERFACE_STATISTICS: + proto_tree_add_item(block_data_tree, hf_pcapng_interface_id, tvb, offset, 4, encoding); + offset += 4; + + proto_tree_add_item(block_data_tree, hf_pcapng_timestamp_data, tvb, offset, 8, encoding); + offset += 8; + + next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - 4 - 8); + offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, NULL); + + break; + case BLOCK_ENHANCED_PACKET: + proto_item_append_text(block_item, " %u", info->frame_number); + info->frame_number += 1; + + proto_tree_add_item(block_data_tree, hf_pcapng_interface_id, tvb, offset, 4, encoding); + interface_id = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + + if (interface_id < wmem_array_get_count(info->interfaces)) { + struct interface_description *interface_description; + nstime_t timestamp; + union { + guint32 u32[2]; + guint64 u64; + } ts; + guint32 base; + guint32 i_resolution; + guint64 resolution = 1; + + interface_description = (struct interface_description *) wmem_array_index(info->interfaces, interface_id); +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + ts.u32[1] = tvb_get_guint32(tvb, offset, encoding); + ts.u32[0] = tvb_get_guint32(tvb, offset + 4, encoding); +#else + ts.u32[0] = tvb_get_guint32(tvb, offset, encoding); + ts.u32[1] = tvb_get_guint32(tvb, offset + 4, encoding); +#endif + + ts.u64 += interface_description->timestamp_offset; + if (interface_description->timestamp_resolution == 0) + interface_description->timestamp_resolution = 6; + + if (interface_description->timestamp_resolution & 0x80) { + base = 2; + } else { + base = 10; + } + + for (i_resolution = 0; i_resolution < (interface_description->timestamp_resolution & 0x7F); i_resolution += 1) + resolution *= base; + timestamp.secs = ts.u64 / resolution; + timestamp.nsecs = ts.u64 - (ts.u64 / resolution) * resolution; + + proto_tree_add_time(block_data_tree, hf_pcapng_timestamp, tvb, offset, 8, ×tamp); + + pinfo->fd->abs_ts = timestamp; + } else { + proto_tree_add_item(block_data_tree, hf_pcapng_timestamp_data, tvb, offset, 8, encoding); + } + offset += 8; + + proto_tree_add_item(block_data_tree, hf_pcapng_captured_length, tvb, offset, 4, encoding); + captured_length = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + + proto_tree_add_item(block_data_tree, hf_pcapng_packet_length, tvb, offset, 4, encoding); + offset += 4; + + packet_data_item = proto_tree_add_item(block_data_tree, hf_pcapng_packet_data, tvb, offset, captured_length, encoding); + packet_data_tree = proto_item_add_subtree(packet_data_item, ett_pcapng_packet_data); + + if (pref_dissect_next_layer && interface_id < wmem_array_get_count(info->interfaces)) { + struct interface_description *interface_description; + + pinfo->fd->num = info->frame_number; + + + interface_description = (struct interface_description *) wmem_array_index(info->interfaces, interface_id); + call_dissector_with_data(pcap_pseudoheader_handle, tvb_new_subset_length(tvb, offset, captured_length), pinfo, packet_data_tree, &interface_description->link_type); + } + offset += captured_length; + + if (captured_length % 4) { + proto_tree_add_item(block_data_tree, hf_pcapng_packet_padding, tvb, offset, captured_length % 4?(4 - captured_length % 4):0, ENC_NA); + offset += captured_length % 4?(4 - captured_length % 4):0; + } + + next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - 4 - 8 - 4 - 4 - captured_length - (captured_length % 4?(4 - captured_length % 4):0)); + offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, NULL); + + break; + case BLOCK_IRIG_TIMESTAMP: + case BLOCK_ARINC_429: + default: + offset += block_data_length; + } + + proto_tree_add_item(block_tree, hf_pcapng_block_length, tvb, offset, 4, encoding); + offset += 4; + + return offset; +} + +static int +dissect_pcapng(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + static const guint8 pcapng_premagic[] = { 0x0A, 0x0D, 0x0D, 0x0A }; + static const guint8 pcapng_magic[] = { 0x1A, 0x2B, 0x3C, 0x4D }; + static const guint8 pcapng_swapped_magic[] = { 0x4D, 0x3C, 0x2B, 0x1A }; + gint offset = 0; + guint32 length; + guint32 encoding; + proto_tree *main_tree; + proto_item *main_item; + struct info info; + + if (tvb_memeql(tvb, 0, pcapng_premagic, sizeof(pcapng_premagic)) != 0) + return 0; + + if (tvb_memeql(tvb, 8, pcapng_magic, sizeof(pcapng_magic)) != 0) { + if (tvb_memeql(tvb, 8, pcapng_swapped_magic, sizeof(pcapng_swapped_magic)) != 0) { + return 0; + } + } + + info.file_number = 1; + info.interface_number = 0; + info.frame_number = 1; + info.interfaces = wmem_array_new(wmem_packet_scope(), sizeof(struct interface_description)); + + main_item = proto_tree_add_item(tree, proto_pcapng, tvb, offset, -1, ENC_NA); + main_tree = proto_item_add_subtree(main_item, ett_pcapng); + + encoding = tvb_get_guint32(tvb, offset + 8, ENC_HOST_ENDIAN); + if (encoding == 0x1A2B3C4D) { + encoding = ENC_LITTLE_ENDIAN; + } else if (encoding == 0x4D3C2B1A) { + encoding = ENC_BIG_ENDIAN; + } else { + expert_add_info(pinfo, main_item, &ei_unknown_encoding); + return offset; + } + + while (tvb_captured_length_remaining(tvb, offset)) { + tvbuff_t *next_tvb; + + length = tvb_get_guint32(tvb, offset + 4, encoding); + next_tvb = tvb_new_subset_length(tvb, offset, length); + + offset += dissect_block(main_tree, pinfo, next_tvb, encoding, &info); + } + + return offset; +} + +static gboolean +dissect_pcapng_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + return dissect_pcapng(tvb, pinfo, tree, NULL) > 0; +} + +void +proto_register_pcapng(void) +{ + module_t *module; + expert_module_t *expert_module; + + static hf_register_info hf[] = { + { &hf_pcapng_block, + { "Block", "pcapng.block", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_block_type, + { "Block Type", "pcapng.block.type", + FT_UINT32, BASE_HEX, VALS(block_type_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_block_type_vendor, + { "Block Type Vendor", "pcapng.block.type.vendor", + FT_BOOLEAN, 32, NULL, 0x80000000, + NULL, HFILL } + }, + { &hf_pcapng_block_type_value, + { "Block Type Value", "pcapng.block.type.value", + FT_UINT32, BASE_HEX, VALS(block_type_vals), 0x7FFFFFFF, + NULL, HFILL } + }, + { &hf_pcapng_block_length, + { "Block Length", "pcapng.block.length", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_block_data, + { "Block Data", "pcapng.block.data", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_options, + { "Options", "pcapng.options", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option, + { "Option", "pcapng.options.option", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_code_interface_description, + { "Code", "pcapng.options.option.code", + FT_UINT16, BASE_DEC, VALS(option_code_interface_description_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_code_enhanced_packet, + { "Code", "pcapng.options.option.code", + FT_UINT16, BASE_DEC, VALS(option_code_enhanced_packet_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_code_packet, + { "Code", "pcapng.options.option.code", + FT_UINT16, BASE_DEC, VALS(option_code_packet_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_code_name_resolution, + { "Code", "pcapng.options.option.code", + FT_UINT16, BASE_DEC, VALS(option_code_name_resolution_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_code_interface_statistics, + { "Code", "pcapng.options.option.code", + FT_UINT16, BASE_DEC, VALS(option_code_interface_statistics_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_code, + { "Code", "pcapng.options.option.code", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_length, + { "Length", "pcapng.options.option.length", + FT_INT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data, + { "Option Data", "pcapng.options.option.data", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_padding, + { "Option Padding", "pcapng.options.option.padding", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_comment, + { "Comment", "pcapng.options.option.data.comment", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_section_header_byte_order_magic, + { "Byte Order Magic", "pcapng.section_header.byte_order_magic", + FT_UINT32, BASE_HEX, VALS(byte_order_magic_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_section_header_major_version, + { "Major Version", "pcapng.section_header.version.major", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_section_header_minor_version, + { "Minor Version", "pcapng.section_header.version.minor", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_section_header_section_length, + { "Section Length", "pcapng.section_header.section_length", + FT_INT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_code_section_header, + { "Code", "pcapng.options.option.code", + FT_UINT16, BASE_DEC, VALS(option_code_section_header_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_section_header_hardware, + { "Hardware", "pcapng.options.option.data.hardware", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_section_header_os, + { "OS", "pcapng.options.option.data.os", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_section_header_user_application, + { "User Application", "pcapng.options.option.data.user_application", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_description_name, + { "Name", "pcapng.options.option.data.interface.name", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_description_description, + { "Description", "pcapng.options.option.data.interface.description", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_ipv4, + { "IPv4", "pcapng.options.option.data.ipv4", + FT_IPv4, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_ipv4_mask, + { "IPv4 Mask", "pcapng.options.option.data.ipv4_mask", + FT_IPv4, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_ipv6, + { "IPv6", "pcapng.options.option.data.ipv4", + FT_IPv6, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_ipv6_mask, + { "IPv6 Mask", "pcapng.options.option.data.ipv6_mask", + FT_UINT8, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_mac_address, + { "MAC Address", "pcapng.options.option.data.mac", + FT_ETHER, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_eui_address, + { "EUI Address", "pcapng.options.option.data.eui", + FT_EUI64, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_speed, + { "Speed", "pcapng.options.option.data.interface.speed", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_timestamp_resolution, + { "Timestamp Resolution", "pcapng.options.option.data.interface.timestamp_resolution", + FT_UINT8, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_timestamp_resolution_base, + { "Base", "pcapng.options.option.data.interface.timestamp_resolution.base", + FT_UINT8, BASE_HEX, VALS(timestamp_resolution_base_vals), 0x80, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_timestamp_resolution_value, + { "Value", "pcapng.options.option.data.interface.timestamp_resolution.value", + FT_UINT8, BASE_DEC, NULL, 0x7F, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_timezone, + { "Timezone", "pcapng.options.option.data.interface.timezone", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_filter, + { "Filter", "pcapng.options.option.data.interface.filter", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_os, + { "OS", "pcapng.options.option.data.interface.os", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_fcs_length, + { "FCS Length", "pcapng.options.option.data.interface.fcs_length", + FT_UINT8, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_timestamp_offset, + { "Timestamp Offset", "pcapng.options.option.data.interface.timestamp_offset", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_drop_count, + { "Drop Count", "pcapng.options.option.data.packet.drop_count", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_hash_algorithm, + { "Hash Algorithm", "pcapng.options.option.data.packet.hash.algorithm", + FT_UINT8, BASE_HEX, VALS(packet_hash_algorithm_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_hash_data, + { "Hash Data", "pcapng.options.option.data.packet.hash.data", + FT_BYTES, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors, + { "Link Layer Errors", "pcapng.options.option.data.packet.flags.link_layer_errors", + FT_UINT16, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + + { &hf_pcapng_option_data_packet_flags_link_layer_errors_symbol, + { "Symbol Error", "pcapng.options.option.data.packet.flags.link_layer_errors.symbol", + FT_BOOLEAN, 16, NULL, 0x8000, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_preamble, + { "Preamble Error", "pcapng.options.option.data.packet.flags.link_layer_errors.preamble", + FT_BOOLEAN, 16, NULL, 0x8000, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_start_frame_delimiter, + { "Preamble Error", "pcapng.options.option.data.packet.flags.link_layer_errors.preamble", + FT_BOOLEAN, 16, NULL, 0x8000, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_unaligned_frame, + { "Preamble Error", "pcapng.options.option.data.packet.flags.link_layer_errors.preamble", + FT_BOOLEAN, 16, NULL, 0x4000, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_wrong_inter_frame_gap, + { "Wrong Inter Frame Gap", "pcapng.options.option.data.packet.flags.link_layer_errors.wrong_inter_frame_gap", + FT_BOOLEAN, 16, NULL, 0x2000, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_packet_too_short, + { "Packet Too Short", "pcapng.options.option.data.packet.flags.link_layer_errors.packet_too_short", + FT_BOOLEAN, 16, NULL, 0x1000, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_packet_too_long, + { "Packet Too Long", "pcapng.options.option.data.packet.flags.link_layer_errors.packet_too_long", + FT_BOOLEAN, 16, NULL, 0x0800, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_crc_error, + { "CRC Error", "pcapng.options.option.data.packet.flags.link_layer_errors.crc", + FT_BOOLEAN, 16, NULL, 0x0400, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_link_layer_errors_reserved, + { "Reserved", "pcapng.options.option.data.packet.flags.link_layer_errors.reserved", + FT_UINT16, BASE_HEX, NULL, 0x03FF, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags, + { "Flags", "pcapng.options.option.data.packet.flags", + FT_UINT16, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_reserved, + { "Reserved", "pcapng.options.option.data.packet.flags.reserved", + FT_UINT16, BASE_HEX, NULL, 0xFE00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_fcs_length, + { "FCS Length", "pcapng.options.option.data.packet.flags.fcs_length", + FT_UINT16, BASE_DEC, NULL, 0x01E0, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_reception_type, + { "Reception Type", "pcapng.options.option.data.packet.flags.reception_type", + FT_UINT16, BASE_HEX, VALS(flags_reception_type_vals), 0x001C, + NULL, HFILL } + }, + { &hf_pcapng_option_data_packet_flags_direction, + { "Direction", "pcapng.options.option.data.packet.flags.direction", + FT_UINT16, BASE_HEX, VALS(packet_flags_direction_vals), 0x0003, + NULL, HFILL } + }, + { &hf_pcapng_option_data_dns_name, + { "DNS Name", "pcapng.options.option.data.dns_name", + FT_STRING, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_start_time, + { "Start Time", "pcapng.options.option.data.start_time", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_end_time, + { "End Time", "pcapng.options.option.data.end_time", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_received, + { "Number of Received Packets", "pcapng.options.option.data.interface.received", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_dropped, + { "Number of Dropped Packets", "pcapng.options.option.data.interface.dropped", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_accepted_by_filter, + { "Number of Accepted by Filter Packets", "pcapng.options.option.data.interface.accepted_by_filter", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_dropped_by_os, + { "Number of Dropped Packets by OS", "pcapng.options.option.data.interface.dropped_by_os", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_option_data_interface_delivered_to_user, + { "Number of Delivered to the User Packets", "pcapng.options.option.data.interface.delivered_to_user", + FT_UINT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_interface_description_link_type, + { "Link Type", "pcapng.interface_description.link_type", + FT_UINT16, BASE_DEC_HEX, VALS(link_type_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_interface_description_reserved, + { "Reserved", "pcapng.interface_description.reserved", + FT_UINT16, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_interface_description_snap_length, + { "Snap Length", "pcapng.interface_description.snap_length", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_packet_block_interface_id, + { "Interface", "pcapng.packet.interface_id", + FT_UINT16, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_packet_block_drops_count, + { "Drops Count", "pcapng.packet.drops_count", + FT_UINT16, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_captured_length, + { "Captured Length", "pcapng.packet.captured_length", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_packet_length, + { "Packet Length", "pcapng.packet.packet_length", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_packet_data, + { "Packet Data", "pcapng.packet.packet_data", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_packet_padding, + { "Packet Padding", "pcapng.packet.padding", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_interface_id, + { "Interface", "pcapng.interface_id", + FT_UINT16, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_timestamp, + { "Timestamp", "pcapng.timestamp", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_timestamp_data, + { "Timestamp", "pcapng.timestamp", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_records, + { "Records", "pcapng.records", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record, + { "Record", "pcapng.records.record", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record_code, + { "Code", "pcapng.records.record.code", + FT_UINT16, BASE_DEC, VALS(record_code_vals), 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record_length, + { "Length", "pcapng.records.record.length", + FT_INT64, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record_data, + { "Record Data", "pcapng.records.record.data", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record_padding, + { "Record Padding", "pcapng.records.record.padding", + FT_NONE, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record_ipv4, + { "IPv4", "pcapng.records.record.data.ipv4", + FT_IPv4, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record_ipv6, + { "IPv6", "pcapng.records.record.data.ipv6", + FT_IPv6, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_pcapng_record_name, + { "Name", "pcapng.records.record.data.name", + FT_STRINGZ, STR_ASCII, NULL, 0x00, + NULL, HFILL } + }, + }; + + static ei_register_info ei[] = { + { &ei_invalid_option_length, { "pcapng.invalid_option_length", PI_PROTOCOL, PI_ERROR, "Invalid Option Length", EXPFILL }}, + { &ei_invalid_record_length, { "pcapng.invalid_record_length", PI_PROTOCOL, PI_ERROR, "Invalid Record Length", EXPFILL }}, + { &ei_unknown_encoding, { "pcapng.unknown_encoding", PI_PROTOCOL, PI_ERROR, "Unknown Encoding", EXPFILL }} + }; + + static gint *ett[] = { + &ett_pcapng, + &ett_pcapng_section_header_block, + &ett_pcapng_block_data, + &ett_pcapng_options, + &ett_pcapng_option, + &ett_pcapng_records, + &ett_pcapng_record, + &ett_pcapng_packet_data + }; + + proto_pcapng = proto_register_protocol("PCAPNG File Format", "File-PCAPNG", "file-pcapng"); + proto_register_field_array(proto_pcapng, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + pcapng_handle = new_register_dissector("file-pcapng", dissect_pcapng, proto_pcapng); + + module = prefs_register_protocol(proto_pcapng, NULL); + prefs_register_static_text_preference(module, "version", + "PCAPNG version: 1.0", + "Version of file-format supported by this dissector."); + + prefs_register_bool_preference(module, "dissect_next_layer", + "Dissect next layer", + "Dissect next layer", + &pref_dissect_next_layer); + + expert_module = expert_register_protocol(proto_pcapng); + expert_register_field_array(expert_module, ei, array_length(ei)); +} + +void +proto_reg_handoff_pcapng(void) +{ + heur_dissector_add("wtap_file", dissect_pcapng_heur, "PCAPNG File", "pcapng_wtap", proto_pcapng, HEURISTIC_ENABLE); +} + +/* + * Editor modelines - http://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: + */ diff --git a/wiretap/mime_file.c b/wiretap/mime_file.c index 933846a538..17bb9608a5 100644 --- a/wiretap/mime_file.c +++ b/wiretap/mime_file.c @@ -71,6 +71,13 @@ static const guint8 gif87a_magic[] = { 'G', 'I', 'F', '8', '7', 'a'}; static const guint8 gif89a_magic[] = { 'G', 'I', 'F', '8', '9', 'a'}; static const guint8 elf_magic[] = { 0x7F, 'E', 'L', 'F'}; static const guint8 btsnoop_magic[] = { 'b', 't', 's', 'n', 'o', 'o', 'p', 0}; +static const guint8 pcap_magic[] = { 0xA1, 0xB2, 0xC3, 0xD4 }; +static const guint8 pcap_swapped_magic[] = { 0xD4, 0xC3, 0xB2, 0xA1 }; +static const guint8 pcapng_premagic[] = { 0x0A, 0x0D, 0x0D, 0x0A }; + +/* File does not start with it */ +static const guint8 pcapng_xmagic[] = { 0x1A, 0x2B, 0x3C, 0x4D }; +static const guint8 pcapng_swapped_xmagic[] = { 0x4D, 0x3C, 0x2B, 0x1A }; static const mime_files_t magic_files[] = { { jpeg_jfif_magic, sizeof(jpeg_jfif_magic) }, @@ -79,7 +86,10 @@ static const mime_files_t magic_files[] = { { gif87a_magic, sizeof(gif87a_magic) }, { gif89a_magic, sizeof(gif89a_magic) }, { elf_magic, sizeof(elf_magic) }, - { btsnoop_magic, sizeof(btsnoop_magic) } + { btsnoop_magic, sizeof(btsnoop_magic) }, + { pcap_magic, sizeof(pcap_magic) }, + { pcap_swapped_magic, sizeof(pcap_swapped_magic) }, + { pcapng_premagic, sizeof(pcapng_premagic) } }; #define N_MAGIC_TYPES (sizeof(magic_files) / sizeof(magic_files[0])) @@ -170,7 +180,7 @@ mime_file_open(wtap *wth, int *err, gchar **err_info) /* guint file_ok; */ guint i; - guint read_bytes = 0; + guint read_bytes = 12; for (i = 0; i < N_MAGIC_TYPES; i++) read_bytes = MAX(read_bytes, magic_files[i].magic_len); @@ -189,8 +199,12 @@ mime_file_open(wtap *wth, int *err, gchar **err_info) for (i = 0; i < N_MAGIC_TYPES; i++) { if ((guint) bytes_read >= magic_files[i].magic_len && !memcmp(magic_buf, magic_files[i].magic, MIN(magic_files[i].magic_len, (guint) bytes_read))) { if (!found_file) { + if (magic_files[i].magic == pcapng_premagic) { + if (memcmp(magic_buf + 8, pcapng_xmagic, sizeof(pcapng_xmagic)) && + memcmp(magic_buf + 8, pcapng_swapped_xmagic, sizeof(pcapng_swapped_xmagic))) + continue; + } found_file = TRUE; - /* file_ok = i; */ } else return WTAP_OPEN_NOT_MINE; /* many files matched, bad file */ } |