/* packet-dvb-s2-bb.c
- * Routines for DVB Dynamic Mode Adaptation dissection
+ * Routines for DVB Dynamic Mode Adaption dissection
* refer to
* http://satlabs.org/pdf/sl_561_Mode_Adaptation_Input_and_Output_Interfaces_for_DVB-S2_Equipment_v1.3.pdf
*
#define BIT_IS_SET(var, bit) ((var) & (1 << (bit)))
#define BIT_IS_CLEAR(var, bit) !BIT_IS_SET(var, bit)
-/* Types of mode adaptation headers supported. */
-#define DVB_S2_MODEADAPT_TYPE_GUESS 0
-#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
-
+#define DVB_S2_MODEADAPT_MINSIZE (DVB_S2_MODEADAPT_OUTSIZE + DVB_S2_BB_OFFS_CRC + 1)
+#define DVB_S2_MODEADAPT_INSIZE 2
+#define DVB_S2_MODEADAPT_OUTSIZE 4
/* CRC table crc-8, poly=0xD5 */
static guint8 crc8_table[256] = {
static int hf_dvb_s2_gse_exthdr = -1;
static int hf_dvb_s2_gse_data = -1;
static int hf_dvb_s2_gse_crc32 = -1;
-static int hf_dvb_s2_gse_crc32_partial = -1;
/* Initialize the subtree pointers */
static gint ett_dvb_s2_modeadapt = -1;
static expert_field ei_dvb_s2_bb_crc = EI_INIT;
-/* *** DVB-S2 Mode Adaptation Header *** */
-
-/* The type of mode adaptation header in use on this link. */
-static const enum_val_t dvb_s2_modeadapt_type_vals[] = {
- { "Guess", "Try to guess", DVB_S2_MODEADAPT_TYPE_GUESS },
- { "L1", "L.1 (No inline mode adaptation header)", DVB_S2_MODEADAPT_TYPE_L1 },
- { "L2", "L.2 (Input interface, 2-byte header)", DVB_S2_MODEADAPT_TYPE_L2 },
- { "L3", "L.3 (Output interface, 4-byte header)", DVB_S2_MODEADAPT_TYPE_L3 },
- { "L4", "L.4 (Parallel output interface, 3-byte header)", DVB_S2_MODEADAPT_TYPE_L4 },
- { NULL, NULL, 0 }
-};
-
-static gint dvb_s2_modeadapt_type = DVB_S2_MODEADAPT_TYPE_GUESS;
+/* *** DVB-S2 Modeadaption Header *** */
-/* sync byte, used in L2 and L3 formats */
+/* first byte */
+#define DVB_S2_MODEADAPT_OFFS_SYNCBYTE 0
#define DVB_S2_MODEADAPT_SYNCBYTE 0xB8
-/* ACM byte, used in L2, L3, and L4 formats */
+/* second byte */
+#define DVB_S2_MODEADAPT_OFFS_ACMBYTE 1
#define DVB_S2_MODEADAPT_MODCODS_MASK 0x1F
static const value_string modeadapt_modcods[] = {
{ 0, "DUMMY PLFRAME"},
"normal"
};
-/* CNI byte, used in L3 and L4 formats */
+/* third byte */
+#define DVB_S2_MODEADAPT_OFFS_CNI 2
static const value_string modeadapt_esno[] = {
{ 0, "modem unlocked, SNR not available"},
{ 1, "-1.000"},
};
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_GSE_CRC32_LEN 4
/* *** helper functions *** */
-static guint8 compute_crc8(tvbuff_t *p, guint8 len, guint8 offset)
+static gboolean check_crc8(tvbuff_t *p, guint8 len, guint8 offset, guint8 received_fcs)
{
int i;
guint8 crc = 0, tmp;
tmp = tvb_get_guint8(p, offset++);
crc = crc8_table[crc ^ tmp];
}
- return crc;
+ if (received_fcs == crc)
+ return TRUE;
+ else
+ return FALSE;
}
/* *** Code to actually dissect the packets *** */
{
int new_off = 0;
int frag_len;
- guint16 gse_hdr, gse_proto = 0;
- gint16 data_len;
+ guint16 gse_hdr, data_len, gse_proto = 0;
proto_item *ti, *tf;
proto_tree *dvb_s2_gse_tree, *dvb_s2_gse_hdr_tree;
next_tvb = tvb_new_subset_remaining(tvb, cur_off + new_off);
- if (tvb_captured_length(next_tvb) > 0) {
- if (dvb_s2_full_dissection)
- {
- switch (gse_proto) {
- case ETHERTYPE_IP:
- new_off += call_dissector(ip_handle, next_tvb, pinfo, tree);
- break;
- case ETHERTYPE_IPv6:
- new_off += call_dissector(ipv6_handle, next_tvb, pinfo, tree);
- break;
- default:
- if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
- data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN;
- } else
- data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE);
- if (data_len > 0) {
- proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
- new_off += data_len;
- }
- break;
- }
- }
- else
- {
+ if (dvb_s2_full_dissection)
+ {
+ switch (gse_proto) {
+ case ETHERTYPE_IP:
+ new_off += call_dissector(ip_handle, next_tvb, pinfo, tree);
+ break;
+ case ETHERTYPE_IPv6:
+ new_off += call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ break;
+ default:
if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN;
} else
data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE);
- if (data_len > 0) {
- proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
- new_off += data_len;
- }
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
+ new_off += data_len;
+ break;
}
-
- /* add crc32 (or partial crc32) if last fragment */
+ }
+ else
+ {
if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
+ data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN;
+ } else
data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE);
- if (data_len == DVB_S2_GSE_CRC32_LEN) {
- proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32, tvb, cur_off + new_off, data_len, ENC_BIG_ENDIAN);
- } else
- proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32_partial, tvb, cur_off + new_off, data_len, ENC_NA);
- new_off += data_len;
- }
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
+ new_off += data_len;
+ }
+
+ /* 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)) {
+ proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32, tvb, cur_off + new_off, DVB_S2_GSE_CRC32_LEN, ENC_BIG_ENDIAN);
+ new_off += DVB_S2_GSE_CRC32_LEN;
}
}
input8 = tvb_get_guint8(tvb, offset + DVB_S2_BB_OFFS_CRC);
- if (compute_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, offset) != input8)
+ if (!check_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, offset, input8))
return FALSE;
else
return TRUE;
new_off += 1;
proto_tree_add_checksum(dvb_s2_bb_tree, tvb, cur_off + 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, cur_off), ENC_NA, PROTO_CHECKSUM_VERIFY);
+ check_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, cur_off, input8), ENC_NA, PROTO_CHECKSUM_VERIFY);
while (bb_data_len) {
/* start DVB-GSE dissector */
proto_tree *dvb_s2_modeadapt_acm_tree;
guint8 byte;
- gint modeadapt_type;
/* Check that there's enough data */
if (tvb_captured_length(tvb) < 1)
return 0;
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "DVB-S2 ");
- col_set_str(pinfo->cinfo, COL_INFO, "DVB-S2 ");
+ /* Check if first byte is valid for this dissector */
+ byte = tvb_get_guint8(tvb, DVB_S2_MODEADAPT_OFFS_SYNCBYTE);
+ cur_off++;
+ if (byte != DVB_S2_MODEADAPT_SYNCBYTE)
+ return 0;
- /* Determine what type of mode adaptation header is present */
-
- /* The packet format for mode adaptation does not contain an explicit
- type identifier, so in general the user preferences must tell us what
- type of mode adaptation header is in use. By default, or if the user
- doesn't know, we will try to guess. Two of the formats start with a
- known sync byte, which helps. Each header format is a different
- length, and the mode adaptation header is followed by the baseband
- header, which is protected by a CRC. So we can guess the format by
- checking the CRC of the baseband header. Unfortunately, it's only an
- 8-bit CRC, so this method will be ambiguous for some packets. We could
- attempt deeper inspection, but for now we will just resolve any
- ambiguities arbitrarily. And if checking the sync byte and the baseband
- CRC doesn't match for any known header format, we'll default to the
- L1 format (no header). */
- if (dvb_s2_modeadapt_type == DVB_S2_MODEADAPT_TYPE_GUESS) {
- byte = tvb_get_guint8(tvb, cur_off);
- if (byte == DVB_S2_MODEADAPT_SYNCBYTE && test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L2SIZE)) {
- modeadapt_type = DVB_S2_MODEADAPT_TYPE_L2;
- } else if (byte == DVB_S2_MODEADAPT_SYNCBYTE && test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L3SIZE)) {
- modeadapt_type = DVB_S2_MODEADAPT_TYPE_L3;
- } else if (test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L4SIZE)) {
- modeadapt_type = DVB_S2_MODEADAPT_TYPE_L4;
- } else if (test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_L1SIZE)) {
- modeadapt_type = DVB_S2_MODEADAPT_TYPE_L1;
- } else {
- modeadapt_type = DVB_S2_MODEADAPT_TYPE_L1;
- }
- } else {
- modeadapt_type = dvb_s2_modeadapt_type;
- }
+ /* Check if BB-Header CRC is valid and determine input or output */
- /* Determine the length of the mode adaptation header */
- switch(modeadapt_type) {
- case DVB_S2_MODEADAPT_TYPE_L1:
- dvb_s2_modeadapt_len = DVB_S2_MODEADAPT_L1SIZE;
- break;
- case DVB_S2_MODEADAPT_TYPE_L2:
- dvb_s2_modeadapt_len = DVB_S2_MODEADAPT_L2SIZE;
- break;
- case DVB_S2_MODEADAPT_TYPE_L3:
- dvb_s2_modeadapt_len = DVB_S2_MODEADAPT_L3SIZE;
- break;
- case DVB_S2_MODEADAPT_TYPE_L4:
- dvb_s2_modeadapt_len = DVB_S2_MODEADAPT_L4SIZE;
- break;
- default:
+ if (test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_INSIZE)) {
+ dvb_s2_modeadapt_len = 2;
+ } else if (test_dvb_s2_crc(tvb, DVB_S2_MODEADAPT_OUTSIZE)) {
+ dvb_s2_modeadapt_len = 4;
+ } else {
return 0;
}
- /* If there's a mode adaptation header, create display subtree for it */
- if (dvb_s2_modeadapt_len > 0) {
- ti = proto_tree_add_item(tree, proto_dvb_s2_modeadapt, tvb, 0, dvb_s2_modeadapt_len, ENC_NA);
- dvb_s2_modeadapt_tree = proto_item_add_subtree(ti, ett_dvb_s2_modeadapt);
-
- /* SYNC byte if used in this header format */
- if (modeadapt_type == DVB_S2_MODEADAPT_TYPE_L2 ||
- modeadapt_type == DVB_S2_MODEADAPT_TYPE_L3) {
- byte = tvb_get_guint8(tvb, cur_off);
- if (byte == DVB_S2_MODEADAPT_SYNCBYTE) {
- proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_sync, tvb, cur_off, 1, ENC_BIG_ENDIAN);
- } else {
- proto_tree_add_uint_format(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_sync, tvb, cur_off, 1,
- byte, "Sync Byte: 0x%02x (Incorrect, should be 0xb8)", byte);
- }
- cur_off++;
- }
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DVB-S2 ");
+ col_set_str(pinfo->cinfo, COL_INFO, "DVB-S2 ");
- /* 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) {
- 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_fecframe, tvb,
- cur_off, 1, ENC_BIG_ENDIAN);
- 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_item(dvb_s2_modeadapt_acm_tree, hf_dvb_s2_modeadapt_acm_modcod, tvb,
- cur_off, 1, ENC_BIG_ENDIAN);
- cur_off++;
- }
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_dvb_s2_modeadapt, tvb, 0, dvb_s2_modeadapt_len, ENC_NA);
+ dvb_s2_modeadapt_tree = proto_item_add_subtree(ti, ett_dvb_s2_modeadapt);
- /* 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_sync, tvb, DVB_S2_MODEADAPT_OFFS_SYNCBYTE, 1, ENC_BIG_ENDIAN);
- proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_frameno, tvb, cur_off, 1, ENC_BIG_ENDIAN);
- cur_off++;
- }
+ cur_off++;
+ tf = proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_acm, tvb,
+ DVB_S2_MODEADAPT_OFFS_ACMBYTE, 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_fecframe, tvb,
+ DVB_S2_MODEADAPT_OFFS_ACMBYTE, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(dvb_s2_modeadapt_acm_tree, hf_dvb_s2_modeadapt_acm_pilot, tvb,
+ DVB_S2_MODEADAPT_OFFS_ACMBYTE, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(dvb_s2_modeadapt_acm_tree, hf_dvb_s2_modeadapt_acm_modcod, tvb,
+ DVB_S2_MODEADAPT_OFFS_ACMBYTE, 1, ENC_BIG_ENDIAN);
+
+ if (dvb_s2_modeadapt_len > 2) {
+ cur_off++;
+ proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_cni, tvb, DVB_S2_MODEADAPT_OFFS_CNI, 1, ENC_BIG_ENDIAN);
+
+ cur_off++;
+ proto_tree_add_item(dvb_s2_modeadapt_tree, hf_dvb_s2_modeadapt_frameno, tvb, DVB_S2_MODEADAPT_OFFS_FNO, 1, ENC_BIG_ENDIAN);
}
/* start DVB-BB dissector */
cur_off = dissect_dvb_s2_bb(tvb, cur_off, tree, pinfo);
+
return cur_off;
}
"CRC", "dvb-s2_gse.crc",
FT_UINT32, BASE_HEX, NULL, 0x0,
"CRC-32", HFILL}
- },
- {&hf_dvb_s2_gse_crc32_partial, {
- "CRC partial", "dvb-s2_gse.crc_partial",
- FT_BYTES, SEP_SPACE, NULL, 0x0,
- "Partial CRC-32", HFILL}
}
};
expert_module_t* expert_dvb_s2_bb;
- proto_dvb_s2_modeadapt = proto_register_protocol("DVB-S2 Mode Adaptation Header", "DVB-S2", "dvb-s2_modeadapt");
+ proto_dvb_s2_modeadapt = proto_register_protocol("DVB-S2 Modeadaption Header", "DVB-S2", "dvb-s2_modeadapt");
proto_dvb_s2_bb = proto_register_protocol("DVB-S2 Baseband Frame", "DVB-S2-BB", "dvb-s2_bb");
prefs_register_obsolete_preference(dvb_s2_modeadapt_module, "enable");
- prefs_register_enum_preference(dvb_s2_modeadapt_module, "modeadapt_interface_type",
- "Mode Adaptation Interface Type",
- "Select the type of Mode Adaptation interface to assume",
- &dvb_s2_modeadapt_type,
- dvb_s2_modeadapt_type_vals,
- FALSE);
-
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",