summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dvb-s2-bb.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-dvb-s2-bb.c')
-rw-r--r--epan/dissectors/packet-dvb-s2-bb.c2610
1 files changed, 2610 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dvb-s2-bb.c b/epan/dissectors/packet-dvb-s2-bb.c
new file mode 100644
index 00000000..3f603b20
--- /dev/null
+++ b/epan/dissectors/packet-dvb-s2-bb.c
@@ -0,0 +1,2610 @@
+/* packet-dvb-s2-bb.c
+ * Routines for DVB Dynamic Mode Adaptation dissection
+ * refer to
+ * https://web.archive.org/web/20170226064346/http://satlabs.org/pdf/sl_561_Mode_Adaptation_Input_and_Output_Interfaces_for_DVB-S2_Equipment_v1.3.pdf
+ *
+ * (http://satlabs.org/pdf/sl_561_Mode_Adaptation_Input_and_Output_Interfaces_for_DVB-S2_Equipment_v1.3.pdf
+ * is no longer available)
+ *
+ * Standards:
+ * ETSI EN 302 307-1 - Digital Video Broadcasting (DVB) - Framing Structure Part 1: DVB-S2
+ * ETSI EN 302 307-2 - Digital Video Broadcasting (DVB) - Framing Structure Part 2: DVB-S2X
+ * ETSI TS 102 606-1 - Digital Video Broadcasting (DVB) - Generic Stream Encapsulation (GSE) Part 1: Protocol
+ * ETSI TS 102 771 - Digital Video Broadcasting (DVB) - GSE implementation guidelines
+ * SatLabs sl_561 - Mode Adaptation Interfaces for DVB-S2 equipment
+ * ETSI EN 302 769 - Digital Video Broadcasting (DVB) - Framing Structure DVB-C2
+ * ETSI EN 302 755 - Digital Video Broadcasting (DVB) - Framing Structure DVB-T2
+ * ETSI EN 301 545 - Digital Video Broadcasting (DVB) - Second Generation DVB Interactive Satellite System (DVB-RCS2)
+ * RFC 4326 - Unidirectional Lightweight Encapsulation (ULE) for Transmission of IP Datagrams over an MPEG-2 Transport Stream (TS)
+ * IANA registries:
+ *
+ * Mandatory Extension Headers (or link-dependent type fields) for ULE (Range 0-255 decimal):
+ *
+ * https://www.iana.org/assignments/ule-next-headers/ule-next-headers.xhtml#ule-next-headers-1
+ *
+ * and
+ *
+ * Optional Extension Headers for ULE (Range 256-511 decimal):
+ *
+ * https://www.iana.org/assignments/ule-next-headers/ule-next-headers.xhtml#ule-next-headers-2
+ *
+ * Copyright 2012, Tobias Rutz <tobias.rutz@work-microwave.de>
+ * Copyright 2013-2020, Thales Alenia Space
+ * Copyright 2013-2021, Viveris Technologies <adrien.destugues@opensource.viveris.fr>
+ * Copyright 2021, John Thacker <johnthacker@gmail.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/crc32-tvb.h>
+#include <epan/etypes.h>
+#include <epan/expert.h>
+#include <epan/reassemble.h>
+#include <epan/conversation.h>
+#include <epan/proto_data.h>
+#include <epan/stream.h>
+#include <wsutil/bits_count_ones.h>
+#include <wsutil/str_util.h>
+
+#include "packet-mp2t.h"
+
+#define BIT_IS_SET(var, bit) ((var) & (1 << (bit)))
+#define BIT_IS_CLEAR(var, bit) !BIT_IS_SET(var, bit)
+
+#define DVB_S2_MODEADAPT_MINSIZE (DVB_S2_BB_OFFS_CRC + 1)
+
+/* Types of mode adaptation headers supported. */
+#define DVB_S2_MODEADAPT_TYPE_L1 1
+#define DVB_S2_MODEADAPT_TYPE_L2 2
+#define DVB_S2_MODEADAPT_TYPE_L3 3
+#define DVB_S2_MODEADAPT_TYPE_L4 4
+
+#define DVB_S2_MODEADAPT_L1SIZE 0
+#define DVB_S2_MODEADAPT_L2SIZE 2
+#define DVB_S2_MODEADAPT_L3SIZE 4
+#define DVB_S2_MODEADAPT_L4SIZE 3
+
+static const int dvb_s2_modeadapt_sizes[] = {
+ [DVB_S2_MODEADAPT_TYPE_L1] = DVB_S2_MODEADAPT_L1SIZE,
+ [DVB_S2_MODEADAPT_TYPE_L2] = DVB_S2_MODEADAPT_L2SIZE,
+ [DVB_S2_MODEADAPT_TYPE_L3] = DVB_S2_MODEADAPT_L3SIZE,
+ [DVB_S2_MODEADAPT_TYPE_L4] = DVB_S2_MODEADAPT_L4SIZE,
+};
+
+
+/* CRC table crc-8, poly=0xD5 */
+static guint8 crc8_table[256] = {
+ 0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54, 0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D,
+ 0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06, 0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F,
+ 0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0, 0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9,
+ 0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2, 0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B,
+ 0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9, 0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0,
+ 0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B, 0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2,
+ 0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D, 0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44,
+ 0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F, 0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16,
+ 0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB, 0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92,
+ 0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9, 0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0,
+ 0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F, 0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36,
+ 0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D, 0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64,
+ 0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26, 0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F,
+ 0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74, 0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D,
+ 0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82, 0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB,
+ 0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0, 0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9
+};
+
+
+static dissector_handle_t ip_handle;
+static dissector_handle_t ipv6_handle;
+static dissector_handle_t eth_withoutfcs_handle;
+static dissector_handle_t dvb_s2_table_handle;
+static dissector_handle_t data_handle;
+static dissector_handle_t mp2t_handle;
+static dissector_handle_t dvb_s2_modeadapt_handle;
+
+void proto_register_dvb_s2_modeadapt(void);
+void proto_reg_handoff_dvb_s2_modeadapt(void);
+
+/* preferences */
+#define DVB_S2_RCS_TABLE_DECODING 0
+#define DVB_S2_RCS2_TABLE_DECODING 1
+
+static const enum_val_t dvb_s2_modeadapt_enum[] = {
+ {"l1", "L.1 (0 bytes)", DVB_S2_MODEADAPT_TYPE_L1},
+ {"l2", "L.2 (2 bytes including sync)", DVB_S2_MODEADAPT_TYPE_L2},
+ {"l3", "L.3 (4 bytes including sync)", DVB_S2_MODEADAPT_TYPE_L3},
+ {"l4", "L.4 (3 bytes)", DVB_S2_MODEADAPT_TYPE_L4},
+ {NULL, NULL, -1}
+};
+
+static gboolean dvb_s2_full_dissection = FALSE;
+static gboolean dvb_s2_df_dissection = FALSE;
+static gint dvb_s2_default_modeadapt = DVB_S2_MODEADAPT_TYPE_L3;
+static gboolean dvb_s2_try_all_modeadapt = TRUE;
+
+/* Initialize the protocol and registered fields */
+static int proto_dvb_s2_modeadapt = -1;
+static int hf_dvb_s2_modeadapt_sync = -1;
+static int hf_dvb_s2_modeadapt_acm = -1;
+static int hf_dvb_s2_modeadapt_acm_fecframe = -1;
+static int hf_dvb_s2_modeadapt_acm_pilot = -1;
+static int hf_dvb_s2_modeadapt_acm_modcod = -1;
+static int hf_dvb_s2_modeadapt_acm_modcod_s2x = -1;
+static int hf_dvb_s2_modeadapt_cni = -1;
+static int hf_dvb_s2_modeadapt_frameno = -1;
+
+static int proto_dvb_s2_bb = -1;
+static int hf_dvb_s2_bb_matype1 = -1;
+static int hf_dvb_s2_bb_matype1_gs = -1;
+static int hf_dvb_s2_bb_matype1_mis = -1;
+static int hf_dvb_s2_bb_matype1_acm = -1;
+static int hf_dvb_s2_bb_matype1_issyi = -1;
+static int hf_dvb_s2_bb_matype1_npd = -1;
+static int hf_dvb_s2_bb_matype1_high_ro = -1;
+static int hf_dvb_s2_bb_matype1_low_ro = -1;
+static int hf_dvb_s2_bb_matype2 = -1;
+static int hf_dvb_s2_bb_upl = -1;
+static int hf_dvb_s2_bb_dfl = -1;
+static int hf_dvb_s2_bb_sync = -1;
+static int hf_dvb_s2_bb_syncd = -1;
+static int hf_dvb_s2_bb_crc = -1;
+static int hf_dvb_s2_bb_crc_status = -1;
+static int hf_dvb_s2_bb_df = -1;
+static int hf_dvb_s2_bb_eip_crc32 = -1;
+static int hf_dvb_s2_bb_eip_crc32_status = -1;
+static int hf_dvb_s2_bb_up_crc = -1;
+static int hf_dvb_s2_bb_up_crc_status = -1;
+static int hf_dvb_s2_bb_issy_short = -1;
+static int hf_dvb_s2_bb_issy_long = -1;
+static int hf_dvb_s2_bb_dnp = -1;
+
+static int hf_dvb_s2_bb_packetized = -1;
+static int hf_dvb_s2_bb_transport = -1;
+static int hf_dvb_s2_bb_reserved = -1;
+
+static int proto_dvb_s2_gse = -1;
+static int hf_dvb_s2_gse_hdr = -1;
+static int hf_dvb_s2_gse_hdr_start = -1;
+static int hf_dvb_s2_gse_hdr_stop = -1;
+static int hf_dvb_s2_gse_hdr_labeltype = -1;
+static int hf_dvb_s2_gse_hdr_length = -1;
+static int hf_dvb_s2_gse_padding = -1;
+static int hf_dvb_s2_gse_proto_next_header = -1;
+static int hf_dvb_s2_gse_proto_ethertype = -1;
+static int hf_dvb_s2_gse_label6 = -1;
+static int hf_dvb_s2_gse_label3 = -1;
+static int hf_dvb_s2_gse_fragid = -1;
+static int hf_dvb_s2_gse_totlength = -1;
+static int hf_dvb_s2_gse_exthdr = -1;
+static int hf_dvb_s2_gse_ncr = -1;
+static int hf_dvb_s2_gse_data = -1;
+static int hf_dvb_s2_gse_crc32 = -1;
+static int hf_dvb_s2_gse_crc32_status = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_dvb_s2_modeadapt = -1;
+static gint ett_dvb_s2_modeadapt_acm = -1;
+
+static gint ett_dvb_s2_bb = -1;
+static gint ett_dvb_s2_bb_matype1 = -1;
+
+static gint ett_dvb_s2_gse = -1;
+static gint ett_dvb_s2_gse_hdr = -1;
+static gint ett_dvb_s2_gse_ncr = -1;
+
+static expert_field ei_dvb_s2_bb_crc = EI_INIT;
+static expert_field ei_dvb_s2_bb_header_ambiguous = EI_INIT;
+static expert_field ei_dvb_s2_bb_issy_invalid = EI_INIT;
+static expert_field ei_dvb_s2_bb_npd_invalid = EI_INIT;
+static expert_field ei_dvb_s2_bb_upl_invalid = EI_INIT;
+static expert_field ei_dvb_s2_bb_dfl_invalid = EI_INIT;
+static expert_field ei_dvb_s2_bb_sync_invalid = EI_INIT;
+static expert_field ei_dvb_s2_bb_syncd_invalid = EI_INIT;
+static expert_field ei_dvb_s2_bb_up_reassembly_invalid = EI_INIT;
+static expert_field ei_dvb_s2_bb_reserved = EI_INIT;
+
+static expert_field ei_dvb_s2_gse_length_invalid = EI_INIT;
+static expert_field ei_dvb_s2_gse_totlength_invalid = EI_INIT;
+static expert_field ei_dvb_s2_gse_crc32 = EI_INIT;
+
+/* Reassembly support */
+
+/* ETSI TS 102 606-1 3.1 distinguishes "slicing", the splitting of a User
+ * Packet over consecutive Base Band Frames of the same stream, and
+ * "fragmentation", the splitting of a PDU (& optionally Extension Header)
+ * over multiple GSE packets.
+ *
+ * Slicing does not occur with GSE as carried in DVB-S2 according to the
+ * original method in ETSI EN 302 307-1 (TS/GS bits 01), but it does occur
+ * with Transport Streams, Generic Packetized Streams (non-GSE, deprecated),
+ * and with the GSE High Efficiency Mode used in DVB-C2, DVB-T2, and DVB-S2X
+ * (TS/GS bits 10, originally reserved.)
+ *
+ * According to ETSI TS 102 606-1 D.2.2 "Fragmention", for simplicity when
+ * GSE-HEM and thus slicing is used, PDU fragmentation is not performed
+ * on the GSE layer (but note it's possible to mix stream types in one
+ * capture.)
+ *
+ * We have two sets of fragment items, one for slicing of User Packets at the
+ * BBF level, and one for GSE fragmentation. We only have one reassembly table,
+ * however, as the slicing of User Packets is handled through the stream.h
+ * API.
+ */
+
+static gint ett_dvbs2_fragments = -1;
+static gint ett_dvbs2_fragment = -1;
+static int hf_dvbs2_fragments = -1;
+static int hf_dvbs2_fragment = -1;
+static int hf_dvbs2_fragment_overlap = -1;
+static int hf_dvbs2_fragment_overlap_conflict = -1;
+static int hf_dvbs2_fragment_multiple_tails = -1;
+static int hf_dvbs2_fragment_too_long_fragment = -1;
+static int hf_dvbs2_fragment_error = -1;
+static int hf_dvbs2_fragment_count = -1;
+static int hf_dvbs2_reassembled_in = -1;
+static int hf_dvbs2_reassembled_length = -1;
+static int hf_dvbs2_reassembled_data = -1;
+
+static const fragment_items dvbs2_frag_items = {
+ &ett_dvbs2_fragment,
+ &ett_dvbs2_fragments,
+ &hf_dvbs2_fragments,
+ &hf_dvbs2_fragment,
+ &hf_dvbs2_fragment_overlap,
+ &hf_dvbs2_fragment_overlap_conflict,
+ &hf_dvbs2_fragment_multiple_tails,
+ &hf_dvbs2_fragment_too_long_fragment,
+ &hf_dvbs2_fragment_error,
+ &hf_dvbs2_fragment_count,
+ &hf_dvbs2_reassembled_in,
+ &hf_dvbs2_reassembled_length,
+ &hf_dvbs2_reassembled_data,
+ "DVB-S2 UP fragments"
+};
+
+static reassembly_table dvb_s2_gse_reassembly_table;
+
+static void
+dvb_s2_gse_defragment_init(void)
+{
+ reassembly_table_init(&dvb_s2_gse_reassembly_table,
+ &addresses_reassembly_table_functions);
+}
+
+static gint ett_dvb_s2_gse_fragments = -1;
+static gint ett_dvb_s2_gse_fragment = -1;
+static int hf_dvb_s2_gse_fragments = -1;
+static int hf_dvb_s2_gse_fragment = -1;
+static int hf_dvb_s2_gse_fragment_overlap = -1;
+static int hf_dvb_s2_gse_fragment_overlap_conflict = -1;
+static int hf_dvb_s2_gse_fragment_multiple_tails = -1;
+static int hf_dvb_s2_gse_fragment_too_long_fragment = -1;
+static int hf_dvb_s2_gse_fragment_error = -1;
+static int hf_dvb_s2_gse_fragment_count = -1;
+static int hf_dvb_s2_gse_reassembled_in = -1;
+static int hf_dvb_s2_gse_reassembled_length = -1;
+static int hf_dvb_s2_gse_reassembled_data = -1;
+
+static const fragment_items dvb_s2_gse_frag_items = {
+ &ett_dvb_s2_gse_fragment,
+ &ett_dvb_s2_gse_fragments,
+ &hf_dvb_s2_gse_fragments,
+ &hf_dvb_s2_gse_fragment,
+ &hf_dvb_s2_gse_fragment_overlap,
+ &hf_dvb_s2_gse_fragment_overlap_conflict,
+ &hf_dvb_s2_gse_fragment_multiple_tails,
+ &hf_dvb_s2_gse_fragment_too_long_fragment,
+ &hf_dvb_s2_gse_fragment_error,
+ &hf_dvb_s2_gse_fragment_count,
+ &hf_dvb_s2_gse_reassembled_in,
+ &hf_dvb_s2_gse_reassembled_length,
+ &hf_dvb_s2_gse_reassembled_data,
+ "DVB-S2 GSE fragments"
+};
+
+/* Offset in SYNC MARKER */
+#define DVB_S2_OFFS_SYNCBYTE 0
+
+/* *** DVB-S2 Modeadaption Header *** */
+
+/* first byte */
+#define DVB_S2_MODEADAPT_OFFS_SYNCBYTE 0
+#define DVB_S2_MODEADAPT_SYNCBYTE 0xB8
+
+/* second byte */
+#define DVB_S2_MODEADAPT_MODCODS_MASK 0x1F
+#define DVB_S2_MODEADAPT_MODCODS_S2X_MASK 0xDF
+static const value_string modeadapt_modcods[] = {
+ { 0, "DUMMY PLFRAME"},
+ { 1, "QPSK 1/4"},
+ { 2, "QPSK 1/3"},
+ { 3, "QPSK 2/5"},
+ { 4, "QPSK 1/2"},
+ { 5, "QPSK 3/5"},
+ { 6, "QPSK 2/3"},
+ { 7, "QPSK 3/4"},
+ { 8, "QPSK 4/5"},
+ { 9, "QPSK 5/6"},
+ {10, "QPSK 8/9"},
+ {11, "QPSK 9/10"},
+ {12, "8PSK 3/5"},
+ {13, "8PSK 2/3"},
+ {14, "8PSK 3/4"},
+ {15, "8PSK 5/6"},
+ {16, "8PSK 8/9"},
+ {17, "8PSK 9/10"},
+ {18, "16APSK 2/3"},
+ {19, "16APSK 3/4"},
+ {20, "16APSK 4/5"},
+ {21, "16APSK 5/6"},
+ {22, "16APSK 8/9"},
+ {23, "16APSK 9/10"},
+ {24, "32APSK 3/4"},
+ {25, "32APSK 4/5"},
+ {26, "32APSK 5/6"},
+ {27, "32APSK 8/9"},
+ {28, "32APSK 9/10"},
+ {29, "reserved"},
+ {30, "reserved"},
+ {31, "reserved"},
+ {32, "QPSK 1/3 SF48"},
+ {33, "QPSK 1/2 SF48"},
+ {34, "QPSK 1/4 SF12"},
+ {35, "QPSK 1/3 SF12"},
+ {36, "QPSK 1/2 SF12"},
+ {37, "QPSK 1/3 SF6"},
+ {38, "QPSK 1/2 SF6"},
+ {39, "QPSK 1/3 SF3"},
+ {40, "QPSK 2/5 SF3"},
+ {41, "QPSK 1/3 SF2"},
+ {42, "QPSK 2/5 SF2"},
+ {43, "QPSK 1/2 SF2"},
+ {44, "QPSK 1/3 SF1"},
+ {45, "QPSK 2/5 SF1"},
+ {46, "QPSK 1/2 SF1"},
+ {47, "reserved"},
+ {48, "reserved"},
+ {49, "reserved"},
+ {50, "reserved"},
+ {51, "reserved"},
+ {52, "reserved"},
+ {53, "reserved"},
+ {54, "reserved"},
+ {55, "reserved"},
+ {56, "reserved"},
+ {57, "reserved"},
+ {58, "reserved"},
+ {59, "reserved"},
+ {60, "reserved"},
+ {61, "reserved"},
+ {62, "reserved"},
+ {63, "reserved"},
+ {64, "reserved"},
+ {65, "reserved"},
+ {66, "reserved"},
+ {67, "reserved"},
+ {68, "reserved"},
+ {69, "reserved"},
+ {70, "reserved"},
+ {71, "reserved"},
+ {72, "reserved"},
+ {73, "reserved"},
+ {74, "reserved"},
+ {75, "reserved"},
+ {76, "reserved"},
+ {77, "reserved"},
+ {78, "reserved"},
+ {79, "reserved"},
+ {80, "reserved"},
+ {81, "reserved"},
+ {82, "reserved"},
+ {83, "reserved"},
+ {84, "reserved"},
+ {85, "reserved"},
+ {86, "reserved"},
+ {87, "reserved"},
+ {88, "reserved"},
+ {89, "reserved"},
+ {90, "reserved"},
+ {91, "reserved"},
+ {92, "reserved"},
+ {93, "reserved"},
+ {94, "reserved"},
+ {95, "reserved"},
+ {96, "reserved"},
+ {97, "reserved"},
+ {98, "reserved"},
+ {99, "reserved"},
+ {100, "reserved"},
+ {101, "reserved"},
+ {102, "reserved"},
+ {103, "reserved"},
+ {104, "reserved"},
+ {105, "reserved"},
+ {106, "reserved"},
+ {107, "reserved"},
+ {108, "reserved"},
+ {109, "reserved"},
+ {110, "reserved"},
+ {111, "reserved"},
+ {112, "reserved"},
+ {113, "reserved"},
+ {114, "reserved"},
+ {115, "reserved"},
+ {116, "reserved"},
+ {117, "reserved"},
+ {118, "reserved"},
+ {119, "reserved"},
+ {120, "reserved"},
+ {121, "reserved"},
+ {122, "reserved"},
+ {123, "reserved"},
+ {124, "reserved"},
+ {125, "reserved"},
+ {126, "reserved"},
+ {127, "reserved"},
+ {128, "reserved"},
+ {129, "reserved"},
+ {130, "reserved"},
+ {131, "reserved"},
+ {132, "QPSK 13/45"},
+ {133, "reserved"},
+ {134, "QPSK 9/20"},
+ {135, "reserved"},
+ {136, "QPSK 11/20"},
+ {137, "reserved"},
+ {138, "8PSK 5/9-L"},
+ {139, "reserved"},
+ {140, "8PSK 26/45-L"},
+ {141, "reserved"},
+ {142, "8PSK 23/36"},
+ {143, "reserved"},
+ {144, "8PSK 25/36"},
+ {145, "reserved"},
+ {146, "8PSK 13/18"},
+ {147, "reserved"},
+ {148, "16APSK 1/2-L"},
+ {149, "reserved"},
+ {150, "16APSK 8/15-L"},
+ {151, "reserved"},
+ {152, "16APSK 5/9-L"},
+ {153, "reserved"},
+ {154, "16APSK 26/45"},
+ {155, "reserved"},
+ {156, "16APSK 3/5"},
+ {157, "reserved"},
+ {158, "16APSK 3/5-L"},
+ {159, "reserved"},
+ {160, "16APSK 28/45"},
+ {161, "reserved"},
+ {162, "16APSK 23/36"},
+ {163, "reserved"},
+ {164, "16APSK 2/3-L"},
+ {165, "reserved"},
+ {166, "16APSK 25/36"},
+ {167, "reserved"},
+ {168, "16APSK 13/18"},
+ {169, "reserved"},
+ {170, "16APSK 7/9"},
+ {171, "reserved"},
+ {172, "16APSK 77/90"},
+ {173, "reserved"},
+ {174, "32APSK 2/3-L"},
+ {175, "reserved"},
+ {176, "reserved"},
+ {177, "reserved"},
+ {178, "32APSK 32/45"},
+ {179, "reserved"},
+ {180, "32APSK 11/15"},
+ {181, "reserved"},
+ {182, "32APSK 7/9"},
+ {183, "reserved"},
+ {184, "64APSK 32/45-L"},
+ {185, "reserved"},
+ {186, "64APSK 11/15"},
+ {187, "reserved"},
+ {188, "reserved"},
+ {189, "reserved"},
+ {190, "64APSK 7/9"},
+ {191, "reserved"},
+ {192, "reserved"},
+ {193, "reserved"},
+ {194, "64APSK 4/5"},
+ {195, "reserved"},
+ {196, "reserved"},
+ {197, "reserved"},
+ {198, "64APSK 5/6"},
+ {199, "reserved"},
+ {200, "128APSK 3/4"},
+ {201, "reserved"},
+ {202, "128APSK 7/9"},
+ {203, "reserved"},
+ {204, "256APSK 29/45-L"},
+ {205, "reserved"},
+ {206, "256APSK 2/3-L"},
+ {207, "reserved"},
+ {208, "256APSK 31/45-L"},
+ {209, "reserved"},
+ {210, "256APSK 32/45"},
+ {211, "reserved"},
+ {212, "256APSK 11/15-L"},
+ {213, "reserved"},
+ {214, "256APSK 3/4"},
+ {215, "reserved"},
+ {216, "QPSK 11/45"},
+ {217, "reserved"},
+ {218, "QPSK 4/15"},
+ {219, "reserved"},
+ {220, "QPSK 14/45"},
+ {221, "reserved"},
+ {222, "QPSK 7/15"},
+ {223, "reserved"},
+ {224, "QPSK 8/15"},
+ {225, "reserved"},
+ {226, "QPSK 32/45"},
+ {227, "reserved"},
+ {228, "8PSK 7/15"},
+ {229, "reserved"},
+ {230, "8PSK 8/15"},
+ {231, "reserved"},
+ {232, "8PSK 26/45"},
+ {233, "reserved"},
+ {234, "8PSK 32/45"},
+ {235, "reserved"},
+ {236, "16APSK 7/15"},
+ {237, "reserved"},
+ {238, "16APSK 8/15"},
+ {239, "reserved"},
+ {240, "16APSK 26/45"},
+ {241, "reserved"},
+ {242, "16APSK 3/5"},
+ {243, "reserved"},
+ {244, "16APSK 32/45"},
+ {245, "reserved"},
+ {246, "32APSK 2/3"},
+ {247, "reserved"},
+ {248, "32APSK 32/45"},
+ {249, "reserved"},
+ {250, "reserved"},
+ {251, "reserved"},
+ {252, "reserved"},
+ {253, "reserved"},
+ {254, "reserved"},
+ {255, "reserved"},
+ { 0, NULL}
+};
+static value_string_ext modeadapt_modcods_ext = VALUE_STRING_EXT_INIT(modeadapt_modcods);
+
+#define DVB_S2_MODEADAPT_PILOTS_MASK 0x20
+
+#define DVB_S2_MODEADAPT_FECFRAME_MASK 0x40
+static const true_false_string tfs_modeadapt_fecframe = {
+ "short",
+ "normal"
+};
+
+/* third byte */
+#define DVB_S2_MODEADAPT_OFFS_CNI 2
+static const value_string modeadapt_esno[] = {
+ { 0, "modem unlocked, SNR not available"},
+ { 1, "-1.000"},
+ { 2, "-0.875"},
+ { 3, "-0.750"},
+ { 4, "-0.625"},
+ { 5, "-0.500"},
+ { 6, "-0.375"},
+ { 7, "-0.250"},
+ { 8, "-0.125"},
+ { 9, "0.000"},
+ { 10, "0.125"},
+ { 11, "0.250"},
+ { 12, "0.375"},
+ { 13, "0.500"},
+ { 14, "0.625"},
+ { 15, "0.750"},
+ { 16, "0.875"},
+ { 17, "1.000"},
+ { 18, "1.125"},
+ { 19, "1.250"},
+ { 20, "1.375"},
+ { 21, "1.500"},
+ { 22, "1.625"},
+ { 23, "1.750"},
+ { 24, "1.875"},
+ { 25, "2.000"},
+ { 26, "2.125"},
+ { 27, "2.250"},
+ { 28, "2.375"},
+ { 29, "2.500"},
+ { 30, "2.625"},
+ { 31, "2.750"},
+ { 32, "2.875"},
+ { 33, "3.000"},
+ { 34, "3.125"},
+ { 35, "3.250"},
+ { 36, "3.375"},
+ { 37, "3.500"},
+ { 38, "3.625"},
+ { 39, "3.750"},
+ { 40, "3.875"},
+ { 41, "4.000"},
+ { 42, "4.125"},
+ { 43, "4.250"},
+ { 44, "4.375"},
+ { 45, "4.500"},
+ { 46, "4.625"},
+ { 47, "4.750"},
+ { 48, "4.875"},
+ { 49, "5.000"},
+ { 50, "5.125"},
+ { 51, "5.250"},
+ { 52, "5.375"},
+ { 53, "5.500"},
+ { 54, "5.625"},
+ { 55, "5.750"},
+ { 56, "5.875"},
+ { 57, "6.000"},
+ { 58, "6.125"},
+ { 59, "6.250"},
+ { 60, "6.375"},
+ { 61, "6.500"},
+ { 62, "6.625"},
+ { 63, "6.750"},
+ { 64, "6.875"},
+ { 65, "7.000"},
+ { 66, "7.125"},
+ { 67, "7.250"},
+ { 68, "7.375"},
+ { 69, "7.500"},
+ { 70, "7.625"},
+ { 71, "7.750"},
+ { 72, "7.875"},
+ { 73, "8.000"},
+ { 74, "8.125"},
+ { 75, "8.250"},
+ { 76, "8.375"},
+ { 77, "8.500"},
+ { 78, "8.625"},
+ { 79, "8.750"},
+ { 80, "8.875"},
+ { 81, "9.000"},
+ { 82, "9.125"},
+ { 83, "9.250"},
+ { 84, "9.375"},
+ { 85, "9.500"},
+ { 86, "9.625"},
+ { 87, "9.750"},
+ { 88, "9.875"},
+ { 89, "10.000"},
+ { 90, "10.125"},
+ { 91, "10.250"},
+ { 92, "10.375"},
+ { 93, "10.500"},
+ { 94, "10.625"},
+ { 95, "10.750"},
+ { 96, "10.875"},
+ { 97, "11.000"},
+ { 98, "11.125"},
+ { 99, "11.250"},
+ {100, "11.375"},
+ {101, "11.500"},
+ {102, "11.625"},
+ {103, "11.750"},
+ {104, "11.875"},
+ {105, "12.000"},
+ {106, "12.125"},
+ {107, "12.250"},
+ {108, "12.375"},
+ {109, "12.500"},
+ {110, "12.625"},
+ {111, "12.750"},
+ {112, "12.875"},
+ {113, "13.000"},
+ {114, "13.125"},
+ {115, "13.250"},
+ {116, "13.375"},
+ {117, "13.500"},
+ {118, "13.625"},
+ {119, "13.750"},
+ {120, "13.875"},
+ {121, "14.000"},
+ {122, "14.125"},
+ {123, "14.250"},
+ {124, "14.375"},
+ {125, "14.500"},
+ {126, "14.625"},
+ {127, "14.750"},
+ {128, "14.875"},
+ {129, "15.000"},
+ {130, "15.125"},
+ {131, "15.250"},
+ {132, "15.375"},
+ {133, "15.500"},
+ {134, "15.625"},
+ {135, "15.750"},
+ {136, "15.875"},
+ {137, "16.000"},
+ {138, "16.125"},
+ {139, "16.250"},
+ {140, "16.375"},
+ {141, "16.500"},
+ {142, "16.625"},
+ {143, "16.750"},
+ {144, "16.875"},
+ {145, "17.000"},
+ {146, "17.125"},
+ {147, "17.250"},
+ {148, "17.375"},
+ {149, "17.500"},
+ {150, "17.625"},
+ {151, "17.750"},
+ {152, "17.875"},
+ {153, "18.000"},
+ {154, "18.125"},
+ {155, "18.250"},
+ {156, "18.375"},
+ {157, "18.500"},
+ {158, "18.625"},
+ {159, "18.750"},
+ {160, "18.875"},
+ {161, "19.000"},
+ {162, "19.125"},
+ {163, "19.250"},
+ {164, "19.375"},
+ {165, "19.500"},
+ {166, "19.625"},
+ {167, "19.750"},
+ {168, "19.875"},
+ {169, "20.000"},
+ {170, "20.125"},
+ {171, "20.250"},
+ {172, "20.375"},
+ {173, "20.500"},
+ {174, "20.625"},
+ {175, "20.750"},
+ {176, "20.875"},
+ {177, "21.000"},
+ {178, "21.125"},
+ {179, "21.250"},
+ {180, "21.375"},
+ {181, "21.500"},
+ {182, "21.625"},
+ {183, "21.750"},
+ {184, "21.875"},
+ {185, "22.000"},
+ {186, "22.125"},
+ {187, "22.250"},
+ {188, "22.375"},
+ {189, "22.500"},
+ {190, "22.625"},
+ {191, "22.750"},
+ {192, "22.875"},
+ {193, "23.000"},
+ {194, "23.125"},
+ {195, "23.250"},
+ {196, "23.375"},
+ {197, "23.500"},
+ {198, "23.625"},
+ {199, "23.750"},
+ {200, "23.875"},
+ {201, "24.000"},
+ {202, "24.125"},
+ {203, "24.250"},
+ {204, "24.375"},
+ {205, "24.500"},
+ {206, "24.625"},
+ {207, "24.750"},
+ {208, "24.875"},
+ {209, "25.000"},
+ {210, "25.125"},
+ {211, "25.250"},
+ {212, "25.375"},
+ {213, "25.500"},
+ {214, "25.625"},
+ {215, "25.750"},
+ {216, "25.875"},
+ {217, "26.000"},
+ {218, "26.125"},
+ {219, "26.250"},
+ {220, "26.375"},
+ {221, "26.500"},
+ {222, "26.625"},
+ {223, "26.750"},
+ {224, "26.875"},
+ {225, "27.000"},
+ {226, "27.125"},
+ {227, "27.250"},
+ {228, "27.375"},
+ {229, "27.500"},
+ {230, "27.625"},
+ {231, "27.750"},
+ {232, "27.875"},
+ {233, "28.000"},
+ {234, "28.125"},
+ {235, "28.250"},
+ {236, "28.375"},
+ {237, "28.500"},
+ {238, "28.625"},
+ {239, "28.750"},
+ {240, "28.875"},
+ {241, "29.000"},
+ {242, "29.125"},
+ {243, "29.250"},
+ {244, "29.375"},
+ {245, "29.500"},
+ {246, "29.625"},
+ {247, "29.750"},
+ {248, "29.875"},
+ {249, "30.000"},
+ {250, "30.125"},
+ {251, "30.250"},
+ {252, "30.375"},
+ {253, "30.500"},
+ {254, "30.625"},
+ {255, ">30.750"},
+ { 0, NULL}
+};
+static value_string_ext modeadapt_esno_ext = VALUE_STRING_EXT_INIT(modeadapt_esno);
+
+/* fourth byte */
+#define DVB_S2_MODEADAPT_OFFS_FNO 3
+
+/* *** DVB-S2 Base-Band Frame *** */
+
+#define DVB_S2_BB_HEADER_LEN ((guint)10)
+
+#define DVB_S2_BB_OFFS_MATYPE1 0
+#define DVB_S2_BB_TSGS_MASK 0xC0
+#define DVB_S2_BB_TSGS_GENERIC_PACKETIZED 0x00
+#define DVB_S2_BB_TSGS_GENERIC_CONTINUOUS 0x40
+#define DVB_S2_BB_TSGS_TRANSPORT_STREAM 0xC0
+#define DVB_S2_BB_TSGS_RESERVED 0x80
+static const value_string bb_tsgs[] = {
+ {0, "Generic Packetized (not GSE)"},
+ {1, "Generic Continuous (GSE)"},
+ {2, "GSE High Efficiency Mode (GSE-HEM)"},
+ {3, "Transport (TS)"},
+ {0, NULL}
+};
+
+#define DVB_S2_BB_MIS_POS 5
+#define DVB_S2_BB_MIS_MASK 0x20
+static const true_false_string tfs_bb_mis = {
+ "single (SIS)",
+ "multiple (MIS)"
+};
+
+#define DVB_S2_BB_ACM_MASK 0x10
+static const true_false_string tfs_bb_acm = {
+ "constant (CCM)",
+ "adaptive (ACM)"
+};
+
+#define DVB_S2_BB_ISSYI_POS 3
+#define DVB_S2_BB_ISSYI_MASK 0x08
+
+#define DVB_S2_BB_NPD_POS 2
+#define DVB_S2_BB_NPD_MASK 0x04
+
+#define DVB_S2_BB_RO_MASK 0x03
+static const value_string bb_high_ro[] = {
+ {0, "0,35"},
+ {1, "0,25"},
+ {2, "0,20"},
+ {3, "Low rolloff flag"},
+ {0, NULL}
+};
+
+static const value_string bb_low_ro[] = {
+ {0, "0,15"},
+ {1, "0,10"},
+ {2, "0,05"},
+ {3, "Low rolloff flag"},
+ {0, NULL}
+};
+
+
+#define DVB_S2_BB_OFFS_MATYPE2 1
+#define DVB_S2_BB_OFFS_UPL 2
+#define DVB_S2_BB_OFFS_DFL 4
+#define DVB_S2_BB_OFFS_SYNC 6
+#define DVB_S2_BB_OFFS_SYNCD 7
+#define DVB_S2_BB_OFFS_CRC 9
+#define DVB_S2_BB_EIP_CRC32_LEN 4
+#define DVB_S2_BB_SYNC_EIP_CRC32 1
+
+/* *** DVB-S2 GSE Frame *** */
+
+#define DVB_S2_GSE_MINSIZE 2
+
+#define DVB_S2_GSE_OFFS_HDR 0
+#define DVB_S2_GSE_HDR_START_MASK 0x8000
+#define DVB_S2_GSE_HDR_START_POS 15
+#define DVB_S2_GSE_HDR_STOP_MASK 0x4000
+#define DVB_S2_GSE_HDR_STOP_POS 14
+
+
+#define DVB_S2_GSE_HDR_LABELTYPE_MASK 0x3000
+#define DVB_S2_GSE_HDR_LABELTYPE_SHIFT 12
+static const value_string gse_labeltype[] = {
+ {0, "6 byte"},
+ {1, "3 byte"},
+ {2, "0 byte (Broadcast)"},
+ {3, "re-use last label"},
+ {0, NULL}
+};
+
+#define DVB_S2_GSE_HDR_LENGTH_MASK 0x0FFF
+
+#define DVB_RCS2_NCR 0x0081
+#define DVB_RCS2_SIGNAL_TABLE 0x0082
+
+static const value_string gse_proto_next_header_str[] = {
+ /* Mandatory Extension Headers (or link-dependent type fields) for ULE (Range 0-255 decimal) */
+ {0x0000, "Test SNDU" },
+ {0x0001, "Bridged Frame" },
+ {0x0002, "TS-Concat" },
+ {0x0003, "PDU-Concat" },
+ {DVB_RCS2_NCR, "NCR" },
+ {DVB_RCS2_SIGNAL_TABLE, "Signaling Table" },
+ {131, "LL_RCS_DCP" },
+ {132, "LL_RCS_1" },
+ {133, "LL_RCS_TRANSEC_SYS" },
+ {134, "LL_RCS_TRANSEC_PAY" },
+ {135, "DVB-GSE_LLC" },
+ /* Unassigned, private, unassigned ranges */
+ {200, "LL_RCS_FEC_EDT" },
+ /* Unassigned */
+
+ /* Optional Extension Headers for ULE (Range 256-511 decimal) */
+ {256, "Extension-Padding" },
+ {257, "Timestamp" },
+ /* Unassigned */
+ {450, "LL_RCS_FEC_ADT" },
+ {451, "LL_CRC32" },
+ /* Unassigned */
+
+ {0, NULL}
+};
+
+#define DVB_S2_GSE_CRC32_LEN 4
+
+/* Virtual circuit handling
+ *
+ * BBFrames have an Input Stream Identifier (equivalently PLP_ID in -T2, -C2),
+ * but (cf. H.223), we are likely to encounter Base Band Frames over UDP or RTP.
+ * In those situations, the ISI might be reused on different conversations
+ * (or unused/0 on all of them). So we have a hash table that maps the
+ * conversation and the ISI to a unique virtual stream identifier.
+ */
+
+typedef struct {
+ const conversation_t* conv;
+ guint32 isi;
+} virtual_stream_key;
+
+static wmem_map_t *virtual_stream_hashtable = NULL;
+static guint virtual_stream_count = 1;
+
+/* Hash functions */
+static gint
+virtual_stream_equal(gconstpointer v, gconstpointer w)
+{
+ const virtual_stream_key *v1 = (const virtual_stream_key *)v;
+ const virtual_stream_key *v2 = (const virtual_stream_key *)w;
+ gint result;
+ result = (v1->conv == v2->conv && v1->isi == v2->isi);
+ return result;
+}
+
+static guint
+virtual_stream_hash(gconstpointer v)
+{
+ const virtual_stream_key *key = (const virtual_stream_key *)v;
+ guint hash_val = (GPOINTER_TO_UINT(key->conv)) ^ (key->isi << 16);
+ return hash_val;
+}
+
+static guint32
+virtual_stream_lookup(const conversation_t* conv, guint32 isi)
+{
+ virtual_stream_key key, *new_key;
+ guint32 virtual_isi;
+ key.conv = conv;
+ key.isi = isi;
+ virtual_isi = GPOINTER_TO_UINT(wmem_map_lookup(virtual_stream_hashtable, &key));
+ if (virtual_isi == 0) {
+ new_key = wmem_new(wmem_file_scope(), virtual_stream_key);
+ *new_key = key;
+ virtual_isi = virtual_stream_count++;
+ wmem_map_insert(virtual_stream_hashtable, new_key, GUINT_TO_POINTER(virtual_isi));
+ }
+ return virtual_isi;
+}
+
+static void
+virtual_stream_init(void)
+{
+ virtual_stream_count = 1;
+}
+
+/* Data that is associated with a receiver at the BBFrame level, stored
+ * at the conversation level. The Transmission Roll-off factor applies
+ * for all ISI in a Multiple Input Stream Configuration (see ETSI EN
+ * 302 307-2, clause 5.1.6 "Base-Band Header insertion".) Upon first
+ * detection of '11' for the RO value, receiver will switch to low
+ * roll-off range for the entire conversation.
+ */
+typedef struct {
+ guint32 use_low_ro;
+} dvbs2_bb_conv_data;
+
+static dvbs2_bb_conv_data *
+get_dvbs2_bb_conv_data(conversation_t *conv)
+{
+ dvbs2_bb_conv_data *bb_data;
+
+ bb_data = (dvbs2_bb_conv_data *)conversation_get_proto_data(conv, proto_dvb_s2_bb);
+ if (!bb_data) {
+ bb_data = wmem_new0(wmem_file_scope(), dvbs2_bb_conv_data);
+ conversation_add_proto_data(conv, proto_dvb_s2_bb, bb_data);
+ }
+
+ return bb_data;
+}
+
+/* Data that is associated with one BBFrame, used by GSE or TS packets
+ * contained within it. Lifetime of the packet.
+ */
+typedef struct {
+ address src;
+ address dst;
+ port_type ptype;
+ guint32 srcport;
+ guint32 destport;
+ guint8 isi;
+} dvbs2_bb_data;
+
+/* GSE defragmentation related data, one set of data per conversation.
+ * Two tables are used. One is for the first pass, and contains the most
+ * recent information for each Frag ID for that conversation. The other is
+ * for later random access, indexed by both packet number and Frag ID.
+ * (It seems very unlikely according to the spec that the same Frag ID would
+ * be reused on the same BBFrame that it was completed. If that does happen,
+ * then we would have to index by something else, say, subpacket number in the
+ * BBFrame (which we would have to track ourselves.)
+ */
+typedef struct {
+ wmem_tree_t *fragid_table;
+ wmem_tree_t *subpacket_table;
+} gse_analysis_data;
+
+typedef struct {
+ guint8 labeltype;
+} gse_frag_data;
+
+static gse_analysis_data *
+init_gse_analysis_data(void)
+{
+ gse_analysis_data *gse_data;
+
+ gse_data = wmem_new0(wmem_file_scope(), gse_analysis_data);
+ gse_data->fragid_table = wmem_tree_new(wmem_file_scope());
+ gse_data->subpacket_table = wmem_tree_new(wmem_file_scope());
+
+ return gse_data;
+}
+
+static gse_analysis_data *
+get_gse_analysis_data(conversation_t *conv)
+{
+ gse_analysis_data *gse_data;
+
+ gse_data = (gse_analysis_data *)conversation_get_proto_data(conv, proto_dvb_s2_gse);
+ if (!gse_data) {
+ gse_data = init_gse_analysis_data();
+ conversation_add_proto_data(conv, proto_dvb_s2_gse, gse_data);
+ }
+
+ return gse_data;
+}
+
+static gse_frag_data *
+get_gse_frag_data(gse_analysis_data *dvbs2_data, guint32 fragid, gboolean create)
+{
+ gse_frag_data *frag_data;
+
+ frag_data = (gse_frag_data *)wmem_tree_lookup32(dvbs2_data->fragid_table, fragid);
+ if (!frag_data && create) {
+ frag_data = wmem_new0(wmem_file_scope(), gse_frag_data);
+ wmem_tree_insert32(dvbs2_data->fragid_table, fragid, (void *)frag_data);
+ }
+ return frag_data;
+}
+
+static gse_frag_data *
+get_gse_subpacket_data(gse_analysis_data *dvbs2_data, guint32 num, guint32 fragid, gboolean create)
+{
+ gse_frag_data *subpacket_data;
+ wmem_tree_key_t subpacket_key[3];
+
+ subpacket_key[0].length = 1;
+ subpacket_key[0].key = &num;
+ subpacket_key[1].length = 1;
+ subpacket_key[1].key = &fragid;
+ subpacket_key[2].length = 0;
+ subpacket_key[2].key = NULL;
+
+ subpacket_data = (gse_frag_data *)wmem_tree_lookup32_array(dvbs2_data->subpacket_table, subpacket_key);
+ if (!subpacket_data && create) {
+ subpacket_data = wmem_new0(wmem_file_scope(), gse_frag_data);
+ wmem_tree_insert32_array(dvbs2_data->subpacket_table, subpacket_key, (void *)subpacket_data);
+ }
+ return subpacket_data;
+}
+
+/* *** helper functions *** */
+static guint8 compute_crc8(tvbuff_t *p, guint8 len, guint offset)
+{
+ int i;
+ guint8 crc = 0, tmp;
+
+ for (i = 0; i < len; i++) {
+ tmp = tvb_get_guint8(p, offset++);
+ crc = crc8_table[crc ^ tmp];
+ }
+ return crc;
+}
+
+/* *** Code to actually dissect the packets *** */
+static int dissect_dvb_s2_gse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ int new_off = 0;
+ guint8 labeltype, isi = 0;
+ guint16 gse_hdr, data_len, packet_len, gse_proto = 0;
+ guint32 fragid, totlength, crc32_calc = 0;
+
+ proto_item *ti;
+ proto_item *ttf;
+ proto_tree *dvb_s2_gse_tree, *dvb_s2_gse_ncr_tree;
+
+ tvbuff_t *next_tvb, *data_tvb;
+ gboolean dissected = FALSE;
+ gboolean update_col_info = TRUE;
+ gboolean complete = FALSE;
+
+ dvbs2_bb_data *pdata;
+ conversation_t *conv;
+ gse_analysis_data *gse_data;
+
+ address save_src, save_dst;
+ port_type save_ptype;
+ guint32 save_srcport, save_destport;
+
+ static int * const gse_header_bitfields[] = {
+ &hf_dvb_s2_gse_hdr_start,
+ &hf_dvb_s2_gse_hdr_stop,
+ &hf_dvb_s2_gse_hdr_labeltype,
+ &hf_dvb_s2_gse_hdr_length,
+ NULL
+ };
+
+ col_append_str(pinfo->cinfo, COL_INFO, " GSE");
+
+ /* get the GSE header */
+ gse_hdr = tvb_get_ntohs(tvb, DVB_S2_GSE_OFFS_HDR);
+ labeltype = (gse_hdr & DVB_S2_GSE_HDR_LABELTYPE_MASK) >> DVB_S2_GSE_HDR_LABELTYPE_SHIFT;
+
+ /* check if this is just padding, which takes up the rest of the frame */
+ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) &&
+ BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS) &&
+ labeltype == 0) {
+
+ packet_len = tvb_reported_length(tvb);
+ proto_tree_add_uint_format(tree, hf_dvb_s2_gse_padding, tvb, new_off, packet_len, packet_len,
+ "DVB-S2 GSE Padding, Length: %d", packet_len);
+ col_append_str(pinfo->cinfo, COL_INFO, " pad");
+ } else {
+ /* Not padding, parse as a GSE Header */
+
+ copy_address_shallow(&save_src, &pinfo->src);
+ copy_address_shallow(&save_dst, &pinfo->dst);
+ save_ptype = pinfo->ptype;
+ save_srcport = pinfo->srcport;
+ save_destport = pinfo->destport;
+
+ /* We restore the original addresses and ports before each
+ * GSE packet so reassembly works. We do it here, because
+ * we don't want to restore them after calling a subdissector
+ * (so that the final values are that from the last protocol
+ * in the last PDU), but we also don't want to restore them
+ * if the remainder is just padding either, for the same reason.
+ * So we restore them here after the test for padding.
+ */
+ if (data) { // Called from the BBFrame dissector
+ pdata = (dvbs2_bb_data *)data;
+ isi = pdata->isi;
+ copy_address_shallow(&pinfo->src, &pdata->src);
+ copy_address_shallow(&pinfo->dst, &pdata->dst);
+ pinfo->ptype = pdata->ptype;
+ pinfo->srcport = pdata->srcport;
+ pinfo->destport = pdata->destport;
+ }
+
+ conv = find_or_create_conversation(pinfo);
+ gse_data = get_gse_analysis_data(conv);
+
+ /* Length in header does not include header itself */
+ packet_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) + 2;
+ ti = proto_tree_add_item(tree, proto_dvb_s2_gse, tvb, 0, packet_len, ENC_NA);
+ dvb_s2_gse_tree = proto_item_add_subtree(ti, ett_dvb_s2_gse);
+ new_off += 2;
+ ti = proto_tree_add_bitmask_with_flags(dvb_s2_gse_tree, tvb, DVB_S2_GSE_OFFS_HDR, hf_dvb_s2_gse_hdr,
+ ett_dvb_s2_gse_hdr, gse_header_bitfields, ENC_BIG_ENDIAN, BMT_NO_TFS);
+ if (packet_len > tvb_reported_length(tvb)) {
+ expert_add_info(pinfo, ti, &ei_dvb_s2_gse_length_invalid);
+ packet_len = tvb_reported_length(tvb);
+ }
+
+ /* If not both a start and an end packet, then it's a fragment */
+ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) || BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
+ proto_tree_add_item_ret_uint(dvb_s2_gse_tree, hf_dvb_s2_gse_fragid, tvb, new_off, 1, ENC_BIG_ENDIAN, &fragid);
+ col_append_str(pinfo->cinfo, COL_INFO, "(frag) ");
+ /* Differentiate between the same frag id on different ISI */
+ fragid ^= (isi << 8);
+ new_off += 1;
+
+ gse_frag_data *subpacket_data = NULL;
+ if (!PINFO_FD_VISITED(pinfo)) {
+ gse_frag_data *frag_data;
+ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS)) {
+ frag_data = get_gse_frag_data(gse_data, fragid, TRUE);
+ frag_data->labeltype = labeltype;
+ /* Delete any previous in-progress reassembly if
+ * we get a new start packet. */
+ data_tvb = fragment_delete(&dvb_s2_gse_reassembly_table,
+ pinfo, fragid, NULL);
+ /* Since we use fragment_add_seq_next, which (as part of
+ * the fragment_*_check family) moves completed assemblies
+ * to a new table (and only checks the completed table
+ * after a packet is visited once), this will never return
+ * non-NULL nor cause problems later.
+ * If it does, something changed in the API.
+ */
+ if (data_tvb != NULL) {
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ subpacket_data = get_gse_subpacket_data(gse_data, pinfo->num, fragid, TRUE);
+ subpacket_data->labeltype = frag_data->labeltype;
+ } else {
+ frag_data = get_gse_frag_data(gse_data, fragid, FALSE);
+ /* ETSI TS 102 601-1 A.2 Reassembly
+ * Discard the packet if no buffer is in the re-assembly
+ * state for the Frag ID (check with fragment_get).
+ */
+ if (frag_data && fragment_get(&dvb_s2_gse_reassembly_table, pinfo, fragid, NULL)) {
+ subpacket_data = get_gse_subpacket_data(gse_data, pinfo->num, fragid, TRUE);
+ subpacket_data->labeltype = frag_data->labeltype;
+ }
+ }
+ } else {
+ subpacket_data = get_gse_subpacket_data(gse_data, pinfo->num, fragid, FALSE);
+ }
+ fragment_head *dvbs2_frag_head = NULL;
+ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
+ data_len = packet_len - new_off - DVB_S2_GSE_CRC32_LEN;
+ } else {
+ data_len = packet_len - new_off;
+ }
+ if (subpacket_data) {
+ dvbs2_frag_head = fragment_add_seq_next(&dvb_s2_gse_reassembly_table, tvb, new_off,
+ pinfo, fragid, NULL, data_len, BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS));
+ }
+ next_tvb = process_reassembled_data(tvb, new_off, pinfo, "Reassembled GSE",
+ dvbs2_frag_head, &dvb_s2_gse_frag_items, &update_col_info, tree);
+
+ if (next_tvb != NULL) {
+ /* We have a reassembled packet. */
+ complete = TRUE;
+ labeltype = subpacket_data->labeltype;
+ crc32_calc = crc32_mpeg2_tvb_offset(next_tvb, 0, tvb_reported_length(next_tvb));
+ new_off = 0;
+ ti = proto_tree_add_item_ret_uint(dvb_s2_gse_tree, hf_dvb_s2_gse_totlength, next_tvb, new_off, 2, ENC_BIG_ENDIAN, &totlength);
+ new_off += 2;
+ /* Value of totlength field does not include itself or the
+ * CRC32.
+ */
+ if (totlength != (guint32)tvb_reported_length_remaining(next_tvb, new_off)) {
+ expert_add_info(pinfo, ti, &ei_dvb_s2_gse_totlength_invalid);
+ }
+ } else {
+ next_tvb = tvb_new_subset_length(tvb, new_off, data_len);
+ new_off = 0;
+ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS)) {
+ /* Start packet, add the total length */
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_totlength, next_tvb, new_off, 2, ENC_BIG_ENDIAN);
+ new_off += 2;
+ }
+ }
+ } else {
+ complete = TRUE;
+ next_tvb = tvb_new_subset_length(tvb, 0, packet_len);
+ }
+
+ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS) || complete) {
+ /* Start packet, decode the header */
+ gse_proto = tvb_get_ntohs(next_tvb, new_off);
+
+ /* Protocol Type */
+ if (gse_proto <= 1535) {
+ /* Type 1 (Next-Header Type field) */
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_proto_next_header, next_tvb, new_off, 2, ENC_BIG_ENDIAN);
+ }
+ else {
+ /* Type 2 (EtherType compatible Type Fields) */
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_proto_ethertype, next_tvb, new_off, 2, ENC_BIG_ENDIAN);
+ }
+ new_off += 2;
+
+ switch (labeltype) {
+ case 0:
+ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
+ col_append_str(pinfo->cinfo, COL_INFO, "6 ");
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label6, next_tvb, new_off, 6, ENC_NA);
+ new_off += 6;
+ break;
+ case 1:
+ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
+ col_append_str(pinfo->cinfo, COL_INFO, "3 ");
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label3, next_tvb, new_off, 3, ENC_BIG_ENDIAN);
+ new_off += 3;
+ break;
+ case 2:
+ case 3:
+ /* TODO: Case 3 means "same as previous in the BBF."
+ * We can treat it as no label length because nothing
+ * is in the packet.
+ * In the future we could save the values in packet data
+ * and include them here as generated values. Then we
+ * could also set expert_info if no previous packet in
+ * the BBF had a label, or if the previous label was
+ * zero length, both illegal according to ETSI TS
+ * 102 606-1 A.1 "Filtering".
+ */
+ if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
+ col_append_str(pinfo->cinfo, COL_INFO, "0 ");
+ break;
+ }
+ if (gse_proto < 0x0600 && gse_proto >= 0x100) {
+ /* Only display optional extension headers */
+ /* TODO: needs to be tested */
+
+ /* TODO: implementation needs to be checked (len of ext-header??) */
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_exthdr, next_tvb, new_off, 1, ENC_BIG_ENDIAN);
+
+ new_off += 1;
+ }
+ }
+
+ data_tvb = tvb_new_subset_remaining(next_tvb, new_off);
+
+ copy_address_shallow(&pinfo->src, &save_src);
+ copy_address_shallow(&pinfo->dst, &save_dst);
+ pinfo->ptype = save_ptype;
+ pinfo->srcport = save_srcport;
+ pinfo->destport = save_destport;
+
+ if (complete) {
+ switch (gse_proto) {
+ case ETHERTYPE_IP:
+ if (dvb_s2_full_dissection)
+ {
+ call_dissector(ip_handle, data_tvb, pinfo, tree);
+ dissected = TRUE;
+ }
+ break;
+
+ case ETHERTYPE_IPv6:
+ if (dvb_s2_full_dissection)
+ {
+ call_dissector(ipv6_handle, data_tvb, pinfo, tree);
+ dissected = TRUE;
+ }
+ break;
+
+ case ETHERTYPE_VLAN:
+ if (dvb_s2_full_dissection)
+ {
+ call_dissector(eth_withoutfcs_handle, data_tvb, pinfo, tree);
+ dissected = TRUE;
+ }
+ break;
+
+ case DVB_RCS2_SIGNAL_TABLE:
+ call_dissector(dvb_s2_table_handle, data_tvb, pinfo, tree);
+ dissected = TRUE;
+ break;
+
+ case DVB_RCS2_NCR:
+ ttf = proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_ncr, data_tvb, 0, -1, ENC_NA);
+ dvb_s2_gse_ncr_tree = proto_item_add_subtree(ttf, ett_dvb_s2_gse_ncr);
+ proto_tree_add_item(dvb_s2_gse_ncr_tree, hf_dvb_s2_gse_data, data_tvb, 0, -1, ENC_NA);
+ dissected = TRUE;
+ break;
+
+ default:
+ /* Not handled! TODO: expert info? */
+ break;
+ }
+ }
+
+ if (!dissected) {
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, data_tvb, 0, -1, ENC_NA);
+ }
+
+ /* add crc32 if last fragment */
+ if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
+ guint flags = PROTO_CHECKSUM_NO_FLAGS;
+ if (complete) {
+ flags = PROTO_CHECKSUM_VERIFY;
+ }
+ proto_tree_add_checksum(dvb_s2_gse_tree, tvb, packet_len - DVB_S2_GSE_CRC32_LEN, hf_dvb_s2_gse_crc32, hf_dvb_s2_gse_crc32_status, &ei_dvb_s2_gse_crc32, pinfo, crc32_calc, ENC_BIG_ENDIAN, flags);
+ }
+ }
+
+ return packet_len;
+}
+
+static gboolean test_dvb_s2_crc(tvbuff_t *tvb, guint offset) {
+
+ guint8 input8;
+
+ /* only check BB Header and return */
+ if (tvb_captured_length(tvb) < (offset + DVB_S2_BB_HEADER_LEN))
+ return FALSE;
+
+ input8 = tvb_get_guint8(tvb, offset + DVB_S2_BB_OFFS_CRC);
+
+ if (compute_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, offset) != input8)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+
+
+static int dissect_dvb_s2_bb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ proto_item *ti;
+ proto_tree *dvb_s2_bb_tree;
+
+ tvbuff_t *sync_tvb = NULL, *tsp_tvb = NULL, *next_tvb = NULL;
+
+ conversation_t *conv, *subcircuit;
+ stream_t *ts_stream;
+ stream_pdu_fragment_t *ts_frag;
+ fragment_head *fd_head;
+ dvbs2_bb_conv_data *conv_data;
+ dvbs2_bb_data *pdata;
+
+ gboolean npd, composite_init = FALSE;
+ guint8 input8, matype1, crc8, isi = 0, issyi;
+ guint8 sync_flag = 0;
+ guint16 input16, bb_data_len = 0, user_packet_length, syncd;
+ guint32 virtual_id;
+ guint flags;
+
+ int sub_dissected = 0, flag_is_ms = 0, new_off = 0;
+
+ static int * const bb_header_bitfields_low_ro[] = {
+ &hf_dvb_s2_bb_matype1_gs,
+ &hf_dvb_s2_bb_matype1_mis,
+ &hf_dvb_s2_bb_matype1_acm,
+ &hf_dvb_s2_bb_matype1_issyi,
+ &hf_dvb_s2_bb_matype1_npd,
+ &hf_dvb_s2_bb_matype1_low_ro,
+ NULL
+ };
+
+ static int * const bb_header_bitfields_high_ro[] = {
+ &hf_dvb_s2_bb_matype1_gs,
+ &hf_dvb_s2_bb_matype1_mis,
+ &hf_dvb_s2_bb_matype1_acm,
+ &hf_dvb_s2_bb_matype1_issyi,
+ &hf_dvb_s2_bb_matype1_npd,
+ &hf_dvb_s2_bb_matype1_high_ro,
+ NULL
+ };
+
+ conv = find_or_create_conversation(pinfo);
+
+ col_append_str(pinfo->cinfo, COL_PROTOCOL, "BB ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Baseband ");
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_dvb_s2_bb, tvb, 0, DVB_S2_BB_HEADER_LEN, ENC_NA);
+ dvb_s2_bb_tree = proto_item_add_subtree(ti, ett_dvb_s2_bb);
+
+ matype1 = tvb_get_guint8(tvb, DVB_S2_BB_OFFS_MATYPE1);
+ new_off += 1;
+
+ if (BIT_IS_CLEAR(matype1, DVB_S2_BB_MIS_POS))
+ flag_is_ms = 1;
+
+ issyi = (matype1 & DVB_S2_BB_ISSYI_MASK) >> DVB_S2_BB_ISSYI_POS;
+ npd = (matype1 & DVB_S2_BB_NPD_MASK) >> DVB_S2_BB_NPD_POS;
+
+ conv_data = get_dvbs2_bb_conv_data(conv);
+
+ if (((matype1 & DVB_S2_BB_RO_MASK) == 3) && !conv_data->use_low_ro) {
+ conv_data->use_low_ro = pinfo->num;
+ }
+ if (conv_data->use_low_ro && pinfo->num >= conv_data->use_low_ro) {
+ proto_tree_add_bitmask_with_flags(dvb_s2_bb_tree, tvb, DVB_S2_BB_OFFS_MATYPE1, hf_dvb_s2_bb_matype1,
+ ett_dvb_s2_bb_matype1, bb_header_bitfields_low_ro, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
+ } else {
+ proto_tree_add_bitmask_with_flags(dvb_s2_bb_tree, tvb, DVB_S2_BB_OFFS_MATYPE1, hf_dvb_s2_bb_matype1,
+ ett_dvb_s2_bb_matype1, bb_header_bitfields_high_ro, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
+ }
+
+ input8 = tvb_get_guint8(tvb, DVB_S2_BB_OFFS_MATYPE2);
+ new_off += 1;
+ if (flag_is_ms) {
+ proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb,
+ DVB_S2_BB_OFFS_MATYPE2, 1, input8, "Input Stream Identifier (ISI): %d",
+ input8);
+ isi = input8;
+ } else {
+ proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb,
+ DVB_S2_BB_OFFS_MATYPE2, 1, input8, "reserved");
+ }
+
+ user_packet_length = input16 = tvb_get_ntohs(tvb, DVB_S2_BB_OFFS_UPL);
+ new_off += 2;
+
+ proto_tree_add_uint_format(dvb_s2_bb_tree, hf_dvb_s2_bb_upl, tvb,
+ DVB_S2_BB_OFFS_UPL, 2, input16, "User Packet Length: %d bits (%d bytes)",
+ (guint16) input16, (guint16) input16 / 8);
+
+ new_off += 2;
+ bb_data_len = input16 = tvb_get_ntohs(tvb, DVB_S2_BB_OFFS_DFL);
+ bb_data_len /= 8;
+ if (bb_data_len + DVB_S2_BB_HEADER_LEN > tvb_reported_length(tvb)) {
+ /* DFL can be less than the length of the BBFrame (zero padding is
+ * applied, see ETSI EN 302 307-1 5.2.1), but cannot be greater
+ * than the frame length (minus 10 bytes of header).
+ */
+ expert_add_info(pinfo, ti, &ei_dvb_s2_bb_dfl_invalid);
+ bb_data_len = tvb_reported_length_remaining(tvb, DVB_S2_BB_HEADER_LEN);
+ }
+
+ proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_dfl, tvb,
+ DVB_S2_BB_OFFS_DFL, 2, input16, "%d bits (%d bytes)", input16, input16 / 8);
+
+ new_off += 1;
+ sync_flag = tvb_get_guint8(tvb, DVB_S2_BB_OFFS_SYNC);
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_sync, tvb, DVB_S2_BB_OFFS_SYNC, 1, ENC_BIG_ENDIAN);
+
+ new_off += 2;
+ syncd = tvb_get_ntohs(tvb, DVB_S2_BB_OFFS_SYNCD);
+ proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_syncd, tvb,
+ DVB_S2_BB_OFFS_SYNCD, 2, syncd, "%d bits (%d bytes)", syncd, syncd >> 3);
+
+ new_off += 1;
+ proto_tree_add_checksum(dvb_s2_bb_tree, tvb, DVB_S2_BB_OFFS_CRC, hf_dvb_s2_bb_crc, hf_dvb_s2_bb_crc_status, &ei_dvb_s2_bb_crc, pinfo,
+ compute_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, 0), ENC_NA, PROTO_CHECKSUM_VERIFY);
+
+ /* The Base-Band Frame can have multiple GSE (or TS, which can have ULE
+ * or MPE) packets that are concatenated, can be fragmented, and can call
+ * subdissectors including IP (which itself can be fragmented) that
+ * overwrite the pinfo addresses & ports, which are used as keys for
+ * reassembly tables, conversations, and other purposes.
+ *
+ * Thus, we need to save the current values before any subdissectors
+ * are run, and restore them each time before each subpacket.
+ *
+ * When BBFrames are carried over UDP or RTP we can't necessarily rely on
+ * the ISI being unique - a capture might include different streams sent
+ * as single input streams or with the same ISI over different UDP
+ * endpoints and we don't want to mix data when defragmenting. So we
+ * create a virtual ISI.
+ */
+
+ /* UDP and RTP both always create conversations. If we later have
+ * support for DVB Base Band Frames as the link-layer of a capture file,
+ * we'll need to handle it differently. In that case just use the
+ * ISI directly in conversation_new_by_id() instead of creating a
+ * virtual stream identifier.
+ */
+
+ if (conv) {
+ virtual_id = virtual_stream_lookup(conv, isi);
+ /* DVB Base Band streams are unidirectional. Differentiate by direction
+ * for the unlikely case of two streams between the same endpointss in
+ * the opposite direction.
+ */
+ if (addresses_equal(&pinfo->src, conversation_key_addr1(conv->key_ptr))) {
+ pinfo->p2p_dir = P2P_DIR_SENT;
+ } else {
+ pinfo->p2p_dir = P2P_DIR_RECV;
+ }
+
+ } else {
+ virtual_id = isi;
+ pinfo->p2p_dir = P2P_DIR_SENT;
+ }
+ subcircuit = find_conversation_by_id(pinfo->num, CONVERSATION_DVBBBF, virtual_id);
+ if (subcircuit == NULL) {
+ subcircuit = conversation_new_by_id(pinfo->num, CONVERSATION_DVBBBF, virtual_id);
+ }
+
+ /* conversation_set_conv_addr_port_endpoints() could be useful for the subdissectors
+ * this calls (whether GSE or TS, and replace passing the packet data
+ * below), but it could cause problems when the subdissectors of those
+ * subdissectors try and call find_or_create_conversation().
+ * pinfo->use_conv_addr_port_endpoints doesn't affect reassembly tables
+ * in the default reassembly functions, either. So maybe the eventual
+ * approach is to create a conversation key but set
+ * pinfo->use_conv_addr_port_endpoints back to FALSE, and also make the
+ * GSE and MP2T dissectors more (DVB BBF) conversation key aware,
+ * including in their reassembly functions.
+ */
+
+ pdata = wmem_new0(pinfo->pool, dvbs2_bb_data);
+ copy_address_shallow(&pdata->src, &pinfo->src);
+ copy_address_shallow(&pdata->dst, &pinfo->dst);
+ pdata->ptype = pinfo->ptype;
+ pdata->srcport = pinfo->srcport;
+ pdata->destport = pinfo->destport;
+ pdata->isi = isi;
+
+ switch (matype1 & DVB_S2_BB_TSGS_MASK) {
+ case DVB_S2_BB_TSGS_GENERIC_CONTINUOUS:
+ /* Check GSE constraints on the BB header per 9.2.1 of ETSI TS 102 771 */
+ if (issyi) {
+ expert_add_info(pinfo, ti, &ei_dvb_s2_bb_issy_invalid);
+ }
+ if (npd) {
+ expert_add_info(pinfo, ti, &ei_dvb_s2_bb_npd_invalid);
+ }
+ if (user_packet_length != 0x0000) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_upl_invalid,
+ "UPL is 0x%04x. It must be 0x0000 for GSE packets.", user_packet_length);
+ }
+
+
+ if (dvb_s2_df_dissection) {
+ while (bb_data_len) {
+ if (sync_flag == DVB_S2_BB_SYNC_EIP_CRC32 && bb_data_len == DVB_S2_BB_EIP_CRC32_LEN) {
+ proto_tree_add_checksum(dvb_s2_bb_tree, tvb, new_off, hf_dvb_s2_bb_eip_crc32, hf_dvb_s2_bb_eip_crc32_status, &ei_dvb_s2_bb_crc, pinfo, crc32_mpeg2_tvb_offset(tvb, DVB_S2_BB_HEADER_LEN, new_off - DVB_S2_BB_HEADER_LEN), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+ bb_data_len = 0;
+ new_off += DVB_S2_BB_EIP_CRC32_LEN;
+ } else {
+ /* start DVB-GSE dissector */
+ sub_dissected = dissect_dvb_s2_gse(tvb_new_subset_length(tvb, new_off, bb_data_len), pinfo, tree, pdata);
+ new_off += sub_dissected;
+
+ if ((sub_dissected <= bb_data_len) && (sub_dissected >= DVB_S2_GSE_MINSIZE)) {
+ bb_data_len -= sub_dissected;
+ if (bb_data_len < DVB_S2_GSE_MINSIZE)
+ bb_data_len = 0;
+ } else {
+ bb_data_len = 0;
+ }
+ }
+ }
+ } else {
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_df, tvb, new_off, bb_data_len, ENC_NA);
+ new_off += bb_data_len;
+ }
+ break;
+
+ case DVB_S2_BB_TSGS_GENERIC_PACKETIZED:
+ proto_tree_add_item(tree, hf_dvb_s2_bb_packetized, tvb, new_off, bb_data_len, ENC_NA);
+ new_off += bb_data_len;
+ break;
+
+ case DVB_S2_BB_TSGS_TRANSPORT_STREAM:
+ crc8 = 0;
+ // TODO: Save from frame to frame to test the first TSP when syncd == 0?
+ flags = PROTO_CHECKSUM_NO_FLAGS;
+ /* Check TS constraints on the BB header per 5.1 of ETSI EN 302 307 */
+ if (sync_flag != MP2T_SYNC_BYTE) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_sync_invalid,
+ "Copy of User Packet Sync is 0x%02x. It must be 0x%02x for TS packets.", sync_flag, MP2T_SYNC_BYTE);
+ }
+ /* ETSI 302 307-1 5.1.6: SYNCD == 0xFFFF -> "no UP starts in the
+ * DATA FIELD"; otherwise it should not point past the UPL.
+ */
+ if (syncd != 0xFFFF && (syncd >> 3) >= bb_data_len) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_syncd_invalid,
+ "SYNCD >= DFL (points past the end of the Data Field)");
+ syncd = 0xFFFF;
+ }
+ /* Assume byte aligned. */
+ user_packet_length >>= 3;
+ /* UPL should be *at least* MP2T_PACKET_SIZE, depending on npd (1 byte)
+ * and issy (2 or 3 bytes). The fields are overdetermined (something
+ * addressed in -C2 and -T2's High Efficency Mode for TS), so how to
+ * process in the case of inconsistency is a judgment call. The
+ * approach here is to disable anything for which there is insufficent
+ * room, but not to enable anything marked as inactive.
+ */
+ switch (user_packet_length) {
+ case MP2T_PACKET_SIZE:
+ if (issyi) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_issy_invalid,
+ "ISSYI is active on TS but UPL is only %d bytes",
+ user_packet_length);
+ issyi = 0;
+ }
+ if (npd) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_npd_invalid,
+ "NPD is active on TS but UPL is only %d bytes",
+ user_packet_length);
+ npd = FALSE;
+ }
+ break;
+ case MP2T_PACKET_SIZE + 1:
+ if (issyi) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_issy_invalid,
+ "ISSYI is active on TS but UPL is only %d bytes",
+ user_packet_length);
+ issyi = 0;
+ }
+ if (!npd) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_npd_invalid,
+ "NPD is inactive on TS but UPL is %d bytes",
+ user_packet_length);
+ }
+ break;
+ case MP2T_PACKET_SIZE + 2:
+ if (!issyi) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_issy_invalid,
+ "ISSYI is inactive on TS but UPL is %d bytes",
+ user_packet_length);
+ } else {
+ issyi = 2;
+ }
+ if (npd) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_npd_invalid,
+ "NPD is active on TS but UPL is %d bytes",
+ user_packet_length);
+ npd = FALSE;
+ }
+ break;
+ case MP2T_PACKET_SIZE + 3:
+ if (npd) {
+ if (!issyi) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_issy_invalid,
+ "ISSYI is inactive on TS with NPD active but UPL is %d bytes",
+ user_packet_length);
+ } else {
+ issyi = 2;
+ }
+ } else {
+ if (!issyi) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_issy_invalid,
+ "ISSYI is inactive on TS with NPD inactive but UPL is %d bytes",
+ user_packet_length);
+ } else {
+ issyi = 3;
+ }
+ }
+ break;
+ case MP2T_PACKET_SIZE + 4:
+ if (!issyi) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_issy_invalid,
+ "ISSYI is inactive on TS but UPL is %d bytes",
+ user_packet_length);
+ } else {
+ issyi = 3;
+ }
+ if (!npd) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_npd_invalid,
+ "NPD is inactive on TS but UPL is %d bytes",
+ user_packet_length);
+ }
+ break;
+ default:
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_upl_invalid,
+ "UPL is %d byte%s. It must be between %d and %d bytes for TS packets.",
+ user_packet_length, plurality(user_packet_length, "", "s"),
+ MP2T_PACKET_SIZE, MP2T_PACKET_SIZE+4);
+ if (user_packet_length < MP2T_PACKET_SIZE) {
+ user_packet_length = 0;
+ }
+ break;
+ }
+ if (dvb_s2_df_dissection && user_packet_length) {
+ sync_tvb = tvb_new_subset_length(tvb, DVB_S2_BB_OFFS_SYNC, 1);
+ ts_stream = find_stream(subcircuit, pinfo->p2p_dir);
+ if (ts_stream == NULL) {
+ ts_stream = stream_new(subcircuit, pinfo->p2p_dir);
+ }
+ if (syncd == 0xFFFF) {
+ /* Largely theoretical for TS (cf. Generic Packetized, GSE-HEM)
+ * due to the small size of TSPs versus transmitted BBFrames.
+ */
+ next_tvb = tvb_new_subset_length(tvb, new_off, bb_data_len);
+ ts_frag = stream_find_frag(ts_stream, pinfo->num, new_off);
+ if (ts_frag == NULL) {
+ ts_frag = stream_add_frag(ts_stream, pinfo->num, new_off,
+ next_tvb, pinfo, TRUE);
+ }
+ stream_process_reassembled(next_tvb, 0, pinfo,
+ "Reassembled TSP", ts_frag, &dvbs2_frag_items, NULL,
+ tree);
+ new_off += bb_data_len;
+ } else {
+ syncd >>= 3;
+ /* Do this even if syncd is zero just to clear out a partial
+ * fragment from before in the case of drops or out of order. */
+ next_tvb = tvb_new_subset_length(tvb, new_off, syncd);
+ ts_frag = stream_find_frag(ts_stream, pinfo->num, new_off);
+ if (ts_frag == NULL) {
+ ts_frag = stream_add_frag(ts_stream, pinfo->num, new_off,
+ next_tvb, pinfo, FALSE);
+ }
+ fd_head = stream_get_frag_data(ts_frag);
+ /* Don't put anything in the tree when SYNCD is 0 and there was
+ * no earlier fragment (i.e., zero length reassembly)
+ */
+ if (syncd || (fd_head && fd_head->datalen)) {
+ next_tvb = stream_process_reassembled(next_tvb, 0, pinfo,
+ "Reassembled TSP", ts_frag, &dvbs2_frag_items, NULL,
+ tree);
+ if (next_tvb && tvb_reported_length(next_tvb) == user_packet_length) {
+ tsp_tvb = tvb_new_composite();
+ composite_init = TRUE;
+ tvb_composite_append(tsp_tvb, sync_tvb);
+ proto_tree_add_checksum(dvb_s2_bb_tree, next_tvb, 0,
+ hf_dvb_s2_bb_up_crc, hf_dvb_s2_bb_up_crc_status,
+ &ei_dvb_s2_bb_crc, pinfo, crc8, ENC_NA, flags);
+ crc8 = compute_crc8(next_tvb, user_packet_length - 1, 1);
+ flags = PROTO_CHECKSUM_VERIFY;
+ tvb_composite_append(tsp_tvb, tvb_new_subset_length(next_tvb, 1, MP2T_PACKET_SIZE - 1));
+ /* XXX: ISSY is not fully dissected */
+ if (issyi == 2) {
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_issy_short,
+ next_tvb, MP2T_PACKET_SIZE, issyi, ENC_BIG_ENDIAN);
+ } else if (issyi == 3) {
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_issy_short,
+ next_tvb, MP2T_PACKET_SIZE, issyi, ENC_BIG_ENDIAN);
+ }
+ if (npd) {
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_dnp,
+ next_tvb, MP2T_PACKET_SIZE + issyi, 1, ENC_NA);
+ }
+ } else if (pinfo->num != subcircuit->setup_frame) {
+ /* Bad reassembly due to a dropped or out of order
+ * packet, or maybe the previous packet cut short.
+ */
+ expert_add_info(pinfo, ti, &ei_dvb_s2_bb_up_reassembly_invalid);
+ }
+ new_off += syncd;
+ }
+ }
+ while ((bb_data_len + DVB_S2_BB_HEADER_LEN - new_off) >= user_packet_length) {
+ proto_tree_add_checksum(dvb_s2_bb_tree, tvb, new_off,
+ hf_dvb_s2_bb_up_crc, hf_dvb_s2_bb_up_crc_status,
+ &ei_dvb_s2_bb_crc, pinfo, crc8, ENC_NA, flags);
+ if (!composite_init) {
+ tsp_tvb = tvb_new_composite();
+ composite_init = TRUE;
+ }
+ tvb_composite_append(tsp_tvb, sync_tvb);
+ new_off++;
+ crc8 = compute_crc8(tvb, user_packet_length - 1, new_off);
+ flags = PROTO_CHECKSUM_VERIFY;
+ tvb_composite_append(tsp_tvb, tvb_new_subset_length(tvb, new_off, MP2T_PACKET_SIZE - 1));
+ new_off += MP2T_PACKET_SIZE - 1;
+ /* XXX: ISSY is not fully dissected */
+ if (issyi == 2) {
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_issy_short,
+ tvb, new_off, issyi, ENC_BIG_ENDIAN);
+ } else if (issyi == 3) {
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_issy_long,
+ tvb, new_off, issyi, ENC_BIG_ENDIAN);
+ }
+ if (npd) {
+ proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_dnp,
+ tvb, new_off + issyi, 1, ENC_NA);
+ }
+ new_off += user_packet_length - MP2T_PACKET_SIZE;
+ }
+ if (bb_data_len + DVB_S2_BB_HEADER_LEN - new_off) {
+ next_tvb = tvb_new_subset_length(tvb, new_off, bb_data_len + DVB_S2_BB_HEADER_LEN - new_off);
+ ts_frag = stream_find_frag(ts_stream, pinfo->num, new_off);
+ if (ts_frag == NULL) {
+ ts_frag = stream_add_frag(ts_stream, pinfo->num, new_off,
+ next_tvb, pinfo, TRUE);
+ }
+ stream_process_reassembled(next_tvb, 0, pinfo,
+ "Reassembled TSP", ts_frag, &dvbs2_frag_items, NULL, tree);
+ }
+ if (composite_init) {
+ tvb_composite_finalize(tsp_tvb);
+ add_new_data_source(pinfo, tsp_tvb, "Sync-swapped TS");
+ /* The way the MP2T dissector handles reassembly (using the
+ * offsets into the TVB to store per-packet information), it
+ * needs the entire composite TVB at once rather than be passed
+ * one TSP at a time. That's why bb_data_len is limited to the
+ * reported frame length, to avoid throwing an exception running
+ * off the end before processing the TSPs that are present.
+ */
+ call_dissector(mp2t_handle, tsp_tvb, pinfo, tree);
+ }
+ } else {
+ proto_tree_add_item(tree, hf_dvb_s2_bb_transport, tvb, new_off, bb_data_len, ENC_NA);
+ new_off += bb_data_len;
+ }
+ break;
+
+ default:
+ proto_tree_add_item(tree, hf_dvb_s2_bb_reserved, tvb, new_off, bb_data_len, ENC_NA);
+ new_off += bb_data_len;
+ expert_add_info(pinfo, ti, &ei_dvb_s2_bb_reserved);
+ break;
+ }
+
+ return new_off;
+}
+
+static int detect_dvb_s2_modeadapt(tvbuff_t *tvb)
+{
+ int matched_headers = 0;
+
+ /* Check that there's enough data */
+ if (tvb_captured_length(tvb) < DVB_S2_MODEADAPT_MINSIZE)
+ return 0;
+
+ /* There are four different mode adaptation formats, with different
+ length headers. Two of them have a sync byte at the beginning, but
+ the other two do not. In every case, the mode adaptation header is
+ followed by the baseband header, which is protected by a CRC-8.
+ The CRC-8 is weak protection, so it can match by accident, leading
+ to an ambiguity in identifying which format is in use. We will
+ check for ambiguity and report it. */
+ /* Try L.1 format: no header. */
+ if (test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L1SIZE)) {
+ matched_headers |= (1 << DVB_S2_MODEADAPT_TYPE_L1);
+ }
+
+ /* Try L.2 format: header includes sync byte */
+ if ((tvb_get_guint8(tvb, DVB_S2_MODEADAPT_OFFS_SYNCBYTE) == DVB_S2_MODEADAPT_SYNCBYTE) &&
+ test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L2SIZE)) {
+ matched_headers |= (1 << DVB_S2_MODEADAPT_TYPE_L2);
+ }
+
+ /* Try L.4 format: header does not include sync byte */
+ if (test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L4SIZE)) {
+ matched_headers |= (1 << DVB_S2_MODEADAPT_TYPE_L4);
+ }
+
+ /* Try L.3 format: header includes sync byte */
+ if ((tvb_get_guint8(tvb, DVB_S2_MODEADAPT_OFFS_SYNCBYTE) == DVB_S2_MODEADAPT_SYNCBYTE) &&
+ test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L3SIZE)) {
+ matched_headers |= (1 << DVB_S2_MODEADAPT_TYPE_L3);
+ }
+
+ return matched_headers;
+}
+
+static int dissect_dvb_s2_modeadapt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ int cur_off = 0, modeadapt_len, modeadapt_type, matched_headers = 0;
+
+ proto_item *ti, *tf;
+ proto_tree *dvb_s2_modeadapt_tree;
+ proto_tree *dvb_s2_modeadapt_acm_tree;
+
+ unsigned int modcod, mc;
+ static int * const modeadapt_acm_bitfields[] = {
+ &hf_dvb_s2_modeadapt_acm_fecframe,
+ &hf_dvb_s2_modeadapt_acm_pilot,
+ &hf_dvb_s2_modeadapt_acm_modcod,
+ NULL
+ };
+
+ if (dvb_s2_try_all_modeadapt) {
+ matched_headers = detect_dvb_s2_modeadapt(tvb);
+ if (matched_headers & (1 << dvb_s2_default_modeadapt)) {
+ /* If the default value from preferences matches, use it first */
+ modeadapt_type = dvb_s2_default_modeadapt;
+ } else if (matched_headers & (1 << DVB_S2_MODEADAPT_TYPE_L3)) {
+ /* In my experience and in product data sheets, L.3 format is the
+ * most common for outputting over UDP or RTP, so try it next.
+ */
+ modeadapt_type = DVB_S2_MODEADAPT_TYPE_L3;
+ } else if (matched_headers & (1 << DVB_S2_MODEADAPT_TYPE_L4)) {
+ modeadapt_type = DVB_S2_MODEADAPT_TYPE_L4;
+ } else if (matched_headers & (1 << DVB_S2_MODEADAPT_TYPE_L2)) {
+ modeadapt_type = DVB_S2_MODEADAPT_TYPE_L2;
+ } else if (matched_headers & (1 << DVB_S2_MODEADAPT_TYPE_L1)) {
+ modeadapt_type = DVB_S2_MODEADAPT_TYPE_L1;
+ } else {
+ /* If nothing matches, use the default value from preferences.
+ */
+ modeadapt_type = dvb_s2_default_modeadapt;
+ }
+ } else {
+ /* Assume it's the preferred type */
+ modeadapt_type = dvb_s2_default_modeadapt;
+ }
+ modeadapt_len = dvb_s2_modeadapt_sizes[modeadapt_type];
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DVB-S2 ");
+ col_set_str(pinfo->cinfo, COL_INFO, "DVB-S2 ");
+
+ /* Add the protocol even if no length (L.1) so we get access to prefs. */
+ ti = proto_tree_add_protocol_format(tree, proto_dvb_s2_modeadapt, tvb, 0, modeadapt_len,
+ "DVB-S2 Mode Adaptation Header L.%d", modeadapt_type);
+ if (ws_count_ones(matched_headers) > 1) {
+ expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_header_ambiguous,
+ "Mode adaptation header format is ambiguous. Assuming L.%d", modeadapt_type);
+ }
+ /* If there's a mode adaptation header, create display subtree for it */
+ if (modeadapt_len > 0) {
+ dvb_s2_modeadapt_tree = proto_item_add_subtree(ti, ett_dvb_s2_modeadapt);
+
+ /* SYNC byte if used in this header format; value has already been checked */
+ if (modeadapt_type == DVB_S2_MODEADAPT_TYPE_L2 ||
+ modeadapt_type == DVB_S2_MODEADAPT_TYPE_L3) {
+ proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_sync, tvb, cur_off, 1, ENC_BIG_ENDIAN);
+ cur_off++;
+ }
+
+ /* ACM byte and subfields if used in this header format */
+ if (modeadapt_type == DVB_S2_MODEADAPT_TYPE_L2 ||
+ modeadapt_type == DVB_S2_MODEADAPT_TYPE_L3 ||
+ modeadapt_type == DVB_S2_MODEADAPT_TYPE_L4) {
+ mc = tvb_get_guint8(tvb, cur_off);
+ if (mc & 0x80) {
+ modcod = 0x80;
+ modcod |= ((mc & 0x1F) << 2);
+ modcod |= ((mc & 0x40) >> 5);
+ tf = proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_acm, tvb,
+ cur_off, 1, ENC_BIG_ENDIAN);
+
+ dvb_s2_modeadapt_acm_tree = proto_item_add_subtree(tf, ett_dvb_s2_modeadapt_acm);
+
+ proto_tree_add_item(dvb_s2_modeadapt_acm_tree, hf_dvb_s2_modeadapt_acm_pilot, tvb,
+ cur_off, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_uint_format_value(dvb_s2_modeadapt_acm_tree, hf_dvb_s2_modeadapt_acm_modcod_s2x, tvb,
+ cur_off, 1, mc, "DVBS2X %s(%d)", modeadapt_modcods[modcod].strptr, modcod);
+ } else {
+ proto_tree_add_bitmask_with_flags(dvb_s2_modeadapt_tree, tvb, cur_off, hf_dvb_s2_modeadapt_acm,
+ ett_dvb_s2_modeadapt_acm, modeadapt_acm_bitfields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
+ }
+ cur_off++;
+ }
+
+ /* CNI and Frame No if used in this header format */
+ if (modeadapt_type == DVB_S2_MODEADAPT_TYPE_L3 ||
+ modeadapt_type == DVB_S2_MODEADAPT_TYPE_L4) {
+ proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_cni, tvb, cur_off, 1, ENC_BIG_ENDIAN);
+ cur_off++;
+
+ proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_frameno, tvb, cur_off, 1, ENC_BIG_ENDIAN);
+ cur_off++;
+ }
+ }
+
+ /* start DVB-BB dissector */
+ cur_off += dissect_dvb_s2_bb(tvb_new_subset_remaining(tvb, cur_off), pinfo, tree, NULL);
+
+ return cur_off;
+}
+
+static gboolean dissect_dvb_s2_modeadapt_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ int matched_headers = detect_dvb_s2_modeadapt(tvb);
+ if (dvb_s2_try_all_modeadapt) {
+ if (matched_headers == 0) {
+ /* This does not look like a DVB-S2-BB frame at all. We are a
+ heuristic dissector, so we should just punt and let another
+ dissector have a try at this one. */
+ return FALSE;
+ }
+ } else if (! (matched_headers & (1 << dvb_s2_default_modeadapt))) {
+ return FALSE;
+ }
+
+ int dissected_bytes;
+ dissected_bytes = dissect_dvb_s2_modeadapt(tvb, pinfo, tree, data);
+ if (dissected_bytes > 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/* Register the protocol with Wireshark */
+void proto_register_dvb_s2_modeadapt(void)
+{
+ module_t *dvb_s2_modeadapt_module;
+
+ static hf_register_info hf_modeadapt[] = {
+ {&hf_dvb_s2_modeadapt_sync, {
+ "Sync Byte", "dvb-s2_modeadapt.sync",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Das Sync Byte", HFILL}
+ },
+ {&hf_dvb_s2_modeadapt_acm, {
+ "ACM command", "dvb-s2_modeadapt.acmcmd",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}
+ },
+ {&hf_dvb_s2_modeadapt_acm_fecframe, {
+ "FEC frame size", "dvb-s2_modeadapt.acmcmd.fecframe",
+ FT_BOOLEAN, 8, TFS(&tfs_modeadapt_fecframe), DVB_S2_MODEADAPT_FECFRAME_MASK,
+ "FEC", HFILL}
+ },
+ {&hf_dvb_s2_modeadapt_acm_pilot, {
+ "Pilots configuration", "dvb-s2_modeadapt.acmcmd.pilots",
+ FT_BOOLEAN, 8, TFS(&tfs_on_off), DVB_S2_MODEADAPT_PILOTS_MASK,
+ "Pilots", HFILL}
+ },
+ {&hf_dvb_s2_modeadapt_acm_modcod, {
+ "Modcod indicator", "dvb-s2_modeadapt.acmcmd.modcod",
+ FT_UINT8, BASE_DEC|BASE_EXT_STRING, &modeadapt_modcods_ext, DVB_S2_MODEADAPT_MODCODS_MASK,
+ "Modcod", HFILL}
+ },
+ {&hf_dvb_s2_modeadapt_acm_modcod_s2x, {
+ "Modcod indicator", "dvb-s2_modeadapt.acmcmd.modcod",
+ FT_UINT8, BASE_DEC|BASE_EXT_STRING, &modeadapt_modcods_ext, DVB_S2_MODEADAPT_MODCODS_S2X_MASK,
+ "Modcod S2X", HFILL}
+ },
+ {&hf_dvb_s2_modeadapt_cni, {
+ "Carrier to Noise [dB]", "dvb-s2_modeadapt.cni",
+ FT_UINT8, BASE_DEC|BASE_EXT_STRING, &modeadapt_esno_ext, 0x0,
+ "CNI", HFILL}
+ },
+ {&hf_dvb_s2_modeadapt_frameno, {
+ "Frame number", "dvb-s2_modeadapt.frameno",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "fno", HFILL}
+ }
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett_modeadapt[] = {
+ &ett_dvb_s2_modeadapt,
+ &ett_dvb_s2_modeadapt_acm
+ };
+
+ static hf_register_info hf_bb[] = {
+ {&hf_dvb_s2_bb_matype1, {
+ "MATYPE1", "dvb-s2_bb.matype1",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "MATYPE1 Header Field", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype1_gs, {
+ "TS/GS Stream Input", "dvb-s2_bb.matype1.tsgs",
+ FT_UINT8, BASE_DEC, VALS(bb_tsgs), DVB_S2_BB_TSGS_MASK,
+ "Transport Stream Input or Generic Stream Input", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype1_mis, {
+ "Input Stream", "dvb-s2_bb.matype1.mis",
+ FT_BOOLEAN, 8, TFS(&tfs_bb_mis), DVB_S2_BB_MIS_MASK,
+ "Single Input Stream or Multiple Input Stream", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype1_acm, {
+ "Coding and Modulation", "dvb-s2_bb.matype1.acm",
+ FT_BOOLEAN, 8, TFS(&tfs_bb_acm), DVB_S2_BB_ACM_MASK,
+ "Constant Coding and Modulation or Adaptive Coding and Modulation", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype1_issyi, {
+ "ISSYI", "dvb-s2_bb.matype1.issyi",
+ FT_BOOLEAN, 8, TFS(&tfs_active_inactive), DVB_S2_BB_ISSYI_MASK,
+ "Input Stream Synchronization Indicator", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype1_npd, {
+ "NPD", "dvb-s2_bb.matype1.npd",
+ FT_BOOLEAN, 8, TFS(&tfs_active_inactive), DVB_S2_BB_NPD_MASK,
+ "Null-packet deletion enabled", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype1_high_ro, {
+ "RO", "dvb-s2_bb.matype1.ro",
+ FT_UINT8, BASE_DEC, VALS(bb_high_ro), DVB_S2_BB_RO_MASK,
+ "Transmission Roll-off factor", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype1_low_ro, {
+ "RO", "dvb-s2_bb.matype1.ro",
+ FT_UINT8, BASE_DEC, VALS(bb_low_ro), DVB_S2_BB_RO_MASK,
+ "Transmission Roll-off factor", HFILL}
+ },
+ {&hf_dvb_s2_bb_matype2, {
+ "MATYPE2", "dvb-s2_bb.matype2",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "MATYPE2 Header Field", HFILL}
+ },
+ {&hf_dvb_s2_bb_upl, {
+ "UPL", "dvb-s2_bb.upl",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "User Packet Length", HFILL}
+ },
+ {&hf_dvb_s2_bb_dfl, {
+ "DFL", "dvb-s2_bb.dfl",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Data Field Length", HFILL}
+ },
+ {&hf_dvb_s2_bb_sync, {
+ "SYNC", "dvb-s2_bb.sync",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Copy of the User Packet Sync-byte", HFILL}
+ },
+ {&hf_dvb_s2_bb_syncd, {
+ "SYNCD", "dvb-s2_bb.syncd",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Distance to first user packet", HFILL}
+ },
+ {&hf_dvb_s2_bb_crc, {
+ "Checksum", "dvb-s2_bb.crc",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "BB Header CRC-8", HFILL}
+ },
+ {&hf_dvb_s2_bb_crc_status, {
+ "Checksum Status", "dvb-s2_bb.crc.status",
+ FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
+ NULL, HFILL}
+ },
+ {&hf_dvb_s2_bb_packetized, {
+ "Packetized Generic Stream Data", "dvb-s2_bb.packetized",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Packetized Generic Stream (non-TS) Data", HFILL}
+ },
+ {&hf_dvb_s2_bb_transport, {
+ "Transport Stream Data", "dvb-s2_bb.transport",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Transport Stream (TS) Data", HFILL}
+ },
+ {&hf_dvb_s2_bb_reserved, {
+ "GSE High Efficiency Mode Data", "dvb-s2_bb.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "GSE High Efficiency Mode (GSE-HEM) Data", HFILL}
+ },
+ {&hf_dvb_s2_bb_df, {
+ "BBFrame user data", "dvb-s2_bb.df",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ {&hf_dvb_s2_bb_issy_short, {
+ "ISSY (short)", "dvb-s2_bb.issy.short",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Input stream synchronizer (2 octet version)", HFILL}
+ },
+ {&hf_dvb_s2_bb_issy_long, {
+ "ISSY (long)", "dvb-s2_bb.issy.long",
+ FT_UINT24, BASE_HEX, NULL, 0x0,
+ "Input stream synchronizer (3 octet version)", HFILL}
+ },
+ {&hf_dvb_s2_bb_dnp, {
+ "DNP", "dvb-s2_bb.dnp",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Deleted Null-Packets counter", HFILL}
+ },
+ {&hf_dvb_s2_bb_eip_crc32, {
+ "EIP CRC32", "dvb-s2_bb.eip_crc32",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Explicit Integrity Protection CRC32", HFILL}
+ },
+ {&hf_dvb_s2_bb_eip_crc32_status, {
+ "EIP CRC32 Status", "dvb-s2_bb.eip_crc32.status",
+ FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
+ NULL, HFILL}
+ },
+ {&hf_dvb_s2_bb_up_crc, {
+ "UP Checksum", "dvb-s2_bb.up.crc",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "User Packet CRC-8", HFILL}
+ },
+ {&hf_dvb_s2_bb_up_crc_status, {
+ "UP Checksum Status", "dvb-s2_bb.up.crc.status",
+ FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
+ NULL, HFILL}
+ },
+ { &hf_dvbs2_fragment_overlap,
+ { "Fragment overlap", "dvb-s2_bb.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+ { &hf_dvbs2_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "dvb-s2_bb.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+ { &hf_dvbs2_fragment_multiple_tails,
+ { "Multiple tail fragments found", "dvb-s2_bb.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+ { &hf_dvbs2_fragment_too_long_fragment,
+ { "Fragment too long", "dvb-s2_bb.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+ { &hf_dvbs2_fragment_error,
+ { "Defragmentation error", "dvb-s2_bb.fragment.error", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
+ { &hf_dvbs2_fragment_count,
+ { "Fragment count", "dvb-s2_bb.fragment.count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_dvbs2_fragment,
+ { "DVB-S2 UP Fragment", "dvb-s2_bb.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_dvbs2_fragments,
+ { "DVB-S2 UP Fragments", "dvb-s2_bb.fragments", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_dvbs2_reassembled_in,
+ { "Reassembled DVB-S2 UP in frame", "dvb-s2_bb.reassembled_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "This User Packet is reassembled in this frame", HFILL }},
+
+ { &hf_dvbs2_reassembled_length,
+ { "Reassembled DVB-S2 UP length", "dvb-s2_bb.reassembled.length", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "The total length of the reassembled payload", HFILL }},
+
+ { &hf_dvbs2_reassembled_data,
+ { "Reassembled DVB-S2 UP data", "dvb-s2_bb.reassembled.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "The reassembled payload", HFILL }}
+ };
+
+ static gint *ett_bb[] = {
+ &ett_dvb_s2_bb,
+ &ett_dvb_s2_bb_matype1,
+ &ett_dvbs2_fragments,
+ &ett_dvbs2_fragment,
+ };
+
+ /* DVB-S2 GSE Frame */
+ static hf_register_info hf_gse[] = {
+ {&hf_dvb_s2_gse_hdr, {
+ "GSE header", "dvb-s2_gse.hdr",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "GSE Header (start/stop/length)", HFILL}
+ },
+ {&hf_dvb_s2_gse_hdr_start, {
+ "Start", "dvb-s2_gse.hdr.start",
+ FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), DVB_S2_GSE_HDR_START_MASK,
+ "Start Indicator", HFILL}
+ },
+ {&hf_dvb_s2_gse_hdr_stop, {
+ "Stop", "dvb-s2_gse.hdr.stop",
+ FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), DVB_S2_GSE_HDR_STOP_MASK,
+ "Stop Indicator", HFILL}
+ },
+ {&hf_dvb_s2_gse_hdr_labeltype, {
+ "Label Type", "dvb-s2_gse.hdr.labeltype",
+ FT_UINT16, BASE_HEX, VALS(gse_labeltype), DVB_S2_GSE_HDR_LABELTYPE_MASK,
+ "Label Type Indicator", HFILL}
+ },
+ {&hf_dvb_s2_gse_hdr_length, {
+ "Length", "dvb-s2_gse.hdr.length",
+ FT_UINT16, BASE_DEC, NULL, DVB_S2_GSE_HDR_LENGTH_MASK,
+ "GSE Length", HFILL}
+ },
+ {&hf_dvb_s2_gse_padding, {
+ "GSE Padding", "dvb-s2_gse.padding",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "GSE Padding Bytes", HFILL}
+ },
+ {&hf_dvb_s2_gse_proto_next_header, {
+ "Protocol", "dvb-s2_gse.proto",
+ FT_UINT16, BASE_HEX, VALS(gse_proto_next_header_str), 0x0,
+ "Protocol Type", HFILL}
+ },
+ {&hf_dvb_s2_gse_proto_ethertype, {
+ "Protocol", "dvb-s2_gse.proto",
+ FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
+ "Protocol Type", HFILL}
+ },
+ {&hf_dvb_s2_gse_label6, {
+ "Label", "dvb-s2_gse.label_ether",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Label Field", HFILL}
+ },
+ {&hf_dvb_s2_gse_label3, {
+ "Label", "dvb-s2_gse.label",
+ FT_UINT24, BASE_HEX, NULL, 0x0,
+ "Label Field", HFILL}
+ },
+ {&hf_dvb_s2_gse_fragid, {
+ "Frag ID", "dvb-s2_gse.fragid",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Fragment ID", HFILL}
+ },
+ {&hf_dvb_s2_gse_totlength, {
+ "Total Length", "dvb-s2_gse.totlength",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "GSE Total Frame Length", HFILL}
+ },
+ {&hf_dvb_s2_gse_exthdr, {
+ "Extension Header", "dvb-s2_gse.exthdr",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "optional Extension Header", HFILL}
+ },
+ {&hf_dvb_s2_gse_ncr, {
+ "NCR Packet", "dvb-s2_gse.ncr",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "GSE NCR PAcket", HFILL}
+ },
+ {&hf_dvb_s2_gse_data, {
+ "PDU Data", "dvb-s2_gse.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "GSE Frame User Data", HFILL}
+ },
+ {&hf_dvb_s2_gse_crc32, {
+ "CRC", "dvb-s2_gse.crc",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "CRC-32", HFILL}
+ },
+ {&hf_dvb_s2_gse_crc32_status, {
+ "CRC Status", "dvb-s2_gse.crc.status",
+ FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
+ NULL, HFILL}
+ },
+ { &hf_dvb_s2_gse_fragment_overlap,
+ { "Fragment overlap", "dvb-s2_gse.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_dvb_s2_gse_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "dvb-s2_gse.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_dvb_s2_gse_fragment_multiple_tails,
+ { "Multiple tail fragments found", "dvb-s2_gse.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_dvb_s2_gse_fragment_too_long_fragment,
+ { "Fragment too long", "dvb-s2_gse.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_dvb_s2_gse_fragment_error,
+ { "Defragmentation error", "dvb-s2_gse.fragment.error", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_dvb_s2_gse_fragment_count,
+ { "Fragment count", "dvb-s2_gse.fragment.count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_dvb_s2_gse_fragment,
+ { "DVB-S2 GSE Fragment", "dvb-s2_gse.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_dvb_s2_gse_fragments,
+ { "DVB-S2 GSE Fragments", "dvb-s2_gse.fragments", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_dvb_s2_gse_reassembled_in,
+ { "Reassembled DVB-S2 GSE in frame", "dvb-s2_gse.reassembled_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "This GSE packet is reassembled in this frame", HFILL }},
+
+ { &hf_dvb_s2_gse_reassembled_length,
+ { "Reassembled DVB-S2 GSE length", "dvb-s2_gse.reassembled.length", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "The total length of the reassembled payload", HFILL }},
+
+ { &hf_dvb_s2_gse_reassembled_data,
+ { "Reassembled DVB-S2 GSE data", "dvb-s2_gse.reassembled.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "The reassembled payload", HFILL }}
+ };
+
+ static gint *ett_gse[] = {
+ &ett_dvb_s2_gse,
+ &ett_dvb_s2_gse_hdr,
+ &ett_dvb_s2_gse_ncr,
+ &ett_dvb_s2_gse_fragments,
+ &ett_dvb_s2_gse_fragment,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_dvb_s2_bb_crc, { "dvb-s2_bb.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
+ { &ei_dvb_s2_bb_issy_invalid, {"dvb-s2_bb.issy_invalid", PI_PROTOCOL, PI_WARN, "ISSY is active, which is not allowed for GSE packets", EXPFILL }},
+ { &ei_dvb_s2_bb_npd_invalid, {"dvb-s2_bb.npd_invalid", PI_PROTOCOL, PI_WARN, "NPD is active, which is not allowed for GSE packets", EXPFILL }},
+ { &ei_dvb_s2_bb_upl_invalid, {"dvb-s2_bb.upl_invalid", PI_PROTOCOL, PI_WARN, "User Packet Length non-zero, which is not allowed for GSE packets", EXPFILL }},
+ { &ei_dvb_s2_bb_dfl_invalid, {"dvb-s2_bb.dfl_invalid", PI_PROTOCOL, PI_WARN, "Data Field Length greater than reported frame length", EXPFILL }},
+ { &ei_dvb_s2_bb_sync_invalid, {"dvb-s2_bb.sync_invalid", PI_PROTOCOL, PI_WARN, "User Packet Sync-byte not 0x47, which is not allowed for TS packets", EXPFILL }},
+ { &ei_dvb_s2_bb_syncd_invalid, {"dvb-s2_bb.syncd_invalid", PI_PROTOCOL, PI_WARN, "Sync Distance is invalid", EXPFILL }},
+ { &ei_dvb_s2_bb_up_reassembly_invalid, {"dvb-s2_bb.up_reassembly_invalid", PI_REASSEMBLE, PI_ERROR, "Reassembled User Packet has invalid length (dropped or out of order frames)", EXPFILL }},
+ { &ei_dvb_s2_bb_reserved, {"dvb-s2_bb.reserved_frame_format", PI_UNDECODED, PI_WARN, "Dissection of GSE-HEM is not (yet) supported", EXPFILL }},
+ { &ei_dvb_s2_bb_header_ambiguous, { "dvb-s2_bb.header_ambiguous", PI_ASSUMPTION, PI_WARN, "Mode Adaptation header ambiguous", EXPFILL }},
+ };
+
+ expert_module_t* expert_dvb_s2_bb;
+
+ static ei_register_info ei_gse[] = {
+ { &ei_dvb_s2_gse_length_invalid, {"dvb-s2_gse.hdr.length_invalid", PI_PROTOCOL, PI_ERROR, "Length field in header exceeds available bytes in frame", EXPFILL }},
+ { &ei_dvb_s2_gse_totlength_invalid, {"dvb-s2_gse.totlength_invalid", PI_REASSEMBLE, PI_ERROR, "Length of reassembled packet does not equal total length field (missing fragments?)", EXPFILL }},
+ { &ei_dvb_s2_gse_crc32, { "dvb-s2_gse.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
+ };
+
+ expert_module_t* expert_dvb_s2_gse;
+
+ proto_dvb_s2_modeadapt = proto_register_protocol("DVB-S2 Mode Adaptation Header", "DVB-S2", "dvb-s2_modeadapt");
+
+ proto_dvb_s2_bb = proto_register_protocol("DVB-S2 Baseband Frame", "DVB-S2-BB", "dvb-s2_bb");
+
+ proto_dvb_s2_gse = proto_register_protocol("DVB-S2 GSE Packet", "DVB-S2-GSE", "dvb-s2_gse");
+
+ proto_register_field_array(proto_dvb_s2_modeadapt, hf_modeadapt, array_length(hf_modeadapt));
+ proto_register_subtree_array(ett_modeadapt, array_length(ett_modeadapt));
+
+ proto_register_field_array(proto_dvb_s2_bb, hf_bb, array_length(hf_bb));
+ proto_register_subtree_array(ett_bb, array_length(ett_bb));
+ expert_dvb_s2_bb = expert_register_protocol(proto_dvb_s2_bb);
+ expert_register_field_array(expert_dvb_s2_bb, ei, array_length(ei));
+
+ proto_register_field_array(proto_dvb_s2_gse, hf_gse, array_length(hf_gse));
+ proto_register_subtree_array(ett_gse, array_length(ett_gse));
+ expert_dvb_s2_gse = expert_register_protocol(proto_dvb_s2_gse);
+ expert_register_field_array(expert_dvb_s2_gse, ei_gse, array_length(ei_gse));
+
+ dvb_s2_modeadapt_module = prefs_register_protocol(proto_dvb_s2_modeadapt, NULL);
+
+ prefs_register_obsolete_preference(dvb_s2_modeadapt_module, "enable");
+
+ prefs_register_bool_preference(dvb_s2_modeadapt_module, "decode_df",
+ "Enable dissection of DATA FIELD",
+ "Check this to enable full protocol dissection of data above BBHeader",
+ &dvb_s2_df_dissection);
+
+ prefs_register_bool_preference(dvb_s2_modeadapt_module, "full_decode",
+ "Enable dissection of GSE data",
+ "Check this to enable full protocol dissection of data above GSE Layer",
+ &dvb_s2_full_dissection);
+
+ prefs_register_enum_preference(dvb_s2_modeadapt_module, "default_modeadapt",
+ "Preferred Mode Adaptation Interface",
+ "The preferred Mode Adaptation Interface",
+ &dvb_s2_default_modeadapt, dvb_s2_modeadapt_enum, FALSE);
+
+ prefs_register_bool_preference(dvb_s2_modeadapt_module, "try_all_modeadapt",
+ "Try all Mode Adaptation Interface Types",
+ "Try all supported Mode Adaptation Interface Types, using the preferred"
+ " value in the case of ambiguity; if unset, only look for Base Band"
+ " Frames with the preferred type",
+ &dvb_s2_try_all_modeadapt);
+
+ prefs_register_obsolete_preference(dvb_s2_modeadapt_module, "dynamic.payload.type");
+
+ register_init_routine(dvb_s2_gse_defragment_init);
+ register_init_routine(&virtual_stream_init);
+
+ virtual_stream_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), virtual_stream_hash, virtual_stream_equal);
+
+ dvb_s2_modeadapt_handle = register_dissector_with_description("dvb-s2_modeadapt", "DVB-S2 Mode adaptation header", dissect_dvb_s2_modeadapt, proto_dvb_s2_modeadapt);
+}
+
+void proto_reg_handoff_dvb_s2_modeadapt(void)
+{
+ heur_dissector_add("udp", dissect_dvb_s2_modeadapt_heur, "DVB-S2 over UDP", "dvb_s2_udp", proto_dvb_s2_modeadapt, HEURISTIC_DISABLE);
+ dissector_add_for_decode_as("udp.port", dvb_s2_modeadapt_handle);
+ ip_handle = find_dissector_add_dependency("ip", proto_dvb_s2_bb);
+ ipv6_handle = find_dissector_add_dependency("ipv6", proto_dvb_s2_bb);
+ dvb_s2_table_handle = find_dissector("dvb-s2_table");
+ eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
+ data_handle = find_dissector("data");
+ mp2t_handle = find_dissector_add_dependency("mp2t", proto_dvb_s2_bb);
+
+ dissector_add_string("rtp_dyn_payload_type","DVB-S2", dvb_s2_modeadapt_handle);
+ dissector_add_uint_range_with_preference("rtp.pt", "", dvb_s2_modeadapt_handle);
+}
+
+/*
+ * 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:
+ */