diff options
author | Guy Harris <guy@alum.mit.edu> | 2005-01-14 11:17:35 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2005-01-14 11:17:35 +0000 |
commit | 544216dd749011dd37083806515392fad4dc3342 (patch) | |
tree | a79c77ef3f2e52eba3b13c62b701e3299b5a1fbd /epan | |
parent | c3240e1ccb2042798f99b4fee774327bb9e188c4 (diff) |
From Stefano Pettini: RMT support for ALC and NORM.
svn path=/trunk/; revision=13029
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/Makefile.common | 10 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-alc.c | 276 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-alc.h | 81 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-common.c | 122 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-common.h | 59 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-fec.c | 270 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-fec.h | 138 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-lct.c | 469 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-lct.h | 185 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-norm.c | 281 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-norm.h | 82 |
11 files changed, 1973 insertions, 0 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 610cf1504b..15b63ee73d 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -438,6 +438,11 @@ DISSECTOR_SRC = \ packet-rmcp.c \ packet-rmi.c \ packet-rmp.c \ + packet-rmt-alc.c \ + packet-rmt-common.c \ + packet-rmt-fec.c \ + packet-rmt-lct.c \ + packet-rmt-norm.c \ packet-rpc.c \ packet-rpl.c \ packet-rquota.c \ @@ -716,6 +721,11 @@ DISSECTOR_INCLUDES = \ packet-raw.h \ packet-ripng.h \ packet-rmi.h \ + packet-rmt-alc.h \ + packet-rmt-common.h \ + packet-rmt-fec.h \ + packet-rmt-lct.h \ + packet-rmt-norm.h \ packet-rpc.h \ packet-rquota.h \ packet-rsvp.h \ diff --git a/epan/dissectors/packet-rmt-alc.c b/epan/dissectors/packet-rmt-alc.c new file mode 100644 index 0000000000..c882bd2a02 --- /dev/null +++ b/epan/dissectors/packet-rmt-alc.c @@ -0,0 +1,276 @@ +/* packet-rmt-alc.c + * Reliable Multicast Transport (RMT) + * ALC Protocol Instantiation dissector + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * Asynchronous Layered Coding (ALC): + * ---------------------------------- + * + * A massively scalable reliable content delivery protocol. + * Asynchronous Layered Coding combines the Layered Coding Transport + * (LCT) building block, a multiple rate congestion control building + * block and the Forward Error Correction (FEC) building block to + * provide congestion controlled reliable asynchronous delivery of + * content to an unlimited number of concurrent receivers from a single + * sender. + * + * References: + * RFC 3450, Asynchronous Layered Coding protocol instantiation + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/packet.h> +#include <epan/prefs.h> + +#include "packet-rmt-alc.h" + +/* Initialize the protocol and registered fields */ +/* ============================================= */ + +static int proto = -1; + +static struct _alc_hf hf; +static struct _alc_ett ett; + +static gboolean preferences_initialized = FALSE; +static struct _alc_prefs preferences; +static struct _alc_prefs preferences_old; + +/* Preferences */ +/* =========== */ + +/* Set/Reset preferences to default values */ +static void alc_prefs_set_default(struct _alc_prefs *prefs) +{ + prefs->use_default_udp_port = FALSE; + prefs->default_udp_port = 4001; + + lct_prefs_set_default(&prefs->lct); + fec_prefs_set_default(&prefs->fec); +} + +/* Register preferences */ +static void alc_prefs_register(struct _alc_prefs *prefs, module_t *module) +{ + prefs_register_bool_preference(module, + "default.udp_port.enabled", + "Use default UDP port", + "Whether that payload of UDP packets with a specific destination port should be automatically dissected as ALC packets", + &prefs->use_default_udp_port); + + prefs_register_uint_preference(module, + "default.udp_port", + "Default UDP destination port", + "Specifies the UDP destination port for automatic dissection of ALC packets", + 10, &prefs->default_udp_port); + + lct_prefs_register(&prefs->lct, module); + fec_prefs_register(&prefs->fec, module); +} + +/* Save preferences to alc_prefs_old */ +static void alc_prefs_save(struct _alc_prefs *p, struct _alc_prefs *p_old) +{ + *p_old = *p; +} + +/* Code to actually dissect the packets */ +/* ==================================== */ + +static void dissect_alc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + /* Logical packet representation */ + struct _alc alc; + + /* Offset for subpacket dissection */ + guint offset; + + /* Set up structures needed to add the protocol subtree and manage it */ + proto_item *ti; + proto_tree *alc_tree; + + /* Structures and variables initialization */ + offset = 0; + memset(&alc, 0, sizeof(struct _alc)); + + /* Update packet info */ + pinfo->current_proto = "ALC"; + + /* Make entries in Protocol column and Info column on summary display */ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "ALC"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + /* ALC header dissection */ + /* --------------------- */ + + alc.version = hi_nibble(tvb_get_guint8(tvb, offset)); + + if (tree) + { + /* Create subtree for the ALC protocol */ + ti = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE); + alc_tree = proto_item_add_subtree(ti, ett.main); + + /* Fill the ALC subtree */ + proto_tree_add_uint(alc_tree, hf.version, tvb, offset, 1, alc.version); + + } else + alc_tree = NULL; + + /* This dissector supports only ALCv1 packets. + * If alc.version > 1 print only version field and quit. + */ + if (alc.version == 1) { + + struct _lct_ptr l; + struct _fec_ptr f; + + l.lct = &alc.lct; + l.hf = &hf.lct; + l.ett = &ett.lct; + l.prefs = &preferences.lct; + + f.fec = &alc.fec; + f.hf = &hf.fec; + f.ett = &ett.fec; + f.prefs = &preferences.fec; + + /* LCT header dissection */ + /* --------------------- */ + + lct_dissector(l, f, tvb, alc_tree, &offset); + + /* FEC header dissection */ + /* --------------------- */ + + /* Only if it's present and if LCT dissector has determined FEC Encoding ID + * FEC dissector should be called with fec->encoding_id* and fec->instance_id* filled + */ + if (alc.fec.encoding_id_present && tvb_length(tvb) > offset) + fec_dissector(f, tvb, alc_tree, &offset); + + /* Add the Payload item */ + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(alc_tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); + + /* Complete entry in Info column on summary display */ + /* ------------------------------------------------ */ + + if (check_col(pinfo->cinfo, COL_INFO)) + { + lct_info_column(&alc.lct, pinfo); + fec_info_column(&alc.fec, pinfo); + } + + /* Free g_allocated memory */ + lct_dissector_free(&alc.lct); + fec_dissector_free(&alc.fec); + + } else { + + if (tree) + proto_tree_add_text(alc_tree, tvb, 0, -1, "Sorry, this dissector supports ALC version 1 only"); + + /* Complete entry in Info column on summary display */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_fstr(pinfo->cinfo, COL_INFO, "Version: %u (not supported)", alc.version); + } +} + +void proto_reg_handoff_alc(void) +{ + static dissector_handle_t handle; + + if (!preferences_initialized) + { + preferences_initialized = TRUE; + handle = create_dissector_handle(dissect_alc, proto); + dissector_add_handle("udp.port", handle); + + } else { + + if (preferences_old.use_default_udp_port) + dissector_delete("udp.port", preferences_old.default_udp_port, handle); + } + + if (preferences.use_default_udp_port) + dissector_add("udp.port", preferences.default_udp_port, handle); + + alc_prefs_save(&preferences, &preferences_old); +} + +void proto_register_alc(void) +{ + /* Setup ALC header fields */ + static hf_register_info hf_ptr[] = { + + { &hf.version, + { "Version", "alc.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, + + LCT_FIELD_ARRAY(hf.lct, "alc"), + FEC_FIELD_ARRAY(hf.fec, "alc"), + + { &hf.payload, + { "Payload", "alc.payload", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + /* Setup protocol subtree array */ + static gint *ett_ptr[] = { + &ett.main, + + LCT_SUBTREE_ARRAY(ett.lct), + FEC_SUBTREE_ARRAY(ett.fec) + }; + + module_t *module; + + /* Clear hf and ett fields */ + memset(&hf, 0xff, sizeof(struct _alc_hf)); + memset(&ett, 0xff, sizeof(struct _alc_ett)); + + /* Register the protocol name and description */ + proto = proto_register_protocol("Asynchronous Layered Coding", "ALC", "alc"); + + /* Register the header fields and subtrees used */ + proto_register_field_array(proto, hf_ptr, array_length(hf_ptr)); + proto_register_subtree_array(ett_ptr, array_length(ett_ptr)); + + /* Reset preferences */ + alc_prefs_set_default(&preferences); + alc_prefs_save(&preferences, &preferences_old); + + /* Register preferences */ + module = prefs_register_protocol(proto, proto_reg_handoff_alc); + alc_prefs_register(&preferences, module); +} diff --git a/epan/dissectors/packet-rmt-alc.h b/epan/dissectors/packet-rmt-alc.h new file mode 100644 index 0000000000..a60e0cfdd4 --- /dev/null +++ b/epan/dissectors/packet-rmt-alc.h @@ -0,0 +1,81 @@ +/* packet-rmt-alc.h + * Reliable Multicast Transport (RMT) + * ALC Protocol Instantiation function definitions + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_RMT_ALC__ +#define __PACKET_RMT_ALC__ + +#include "packet-rmt-common.h" +#include "packet-rmt-lct.h" +#include "packet-rmt-fec.h" + +/* Type definitions */ +/* ================ */ + +/* Logical ALC packet representation */ +struct _alc +{ + guint8 version; + struct _lct lct; + struct _fec fec; +}; + +/* Ethereal stuff */ +/* ============== */ + +/* ALC header field definitions*/ +struct _alc_hf +{ + int version; + + struct _lct_hf lct; + struct _fec_hf fec; + + int payload; +}; + +/* ALC subtrees */ +struct _alc_ett +{ + gint main; + + struct _lct_ett lct; + struct _fec_ett fec; +}; + +/* ALC preferences */ +struct _alc_prefs +{ + gboolean use_default_udp_port; + guint default_udp_port; + + struct _lct_prefs lct; + struct _fec_prefs fec; +}; + +/* Function declarations */ +/* ===================== */ + +#endif diff --git a/epan/dissectors/packet-rmt-common.c b/epan/dissectors/packet-rmt-common.c new file mode 100644 index 0000000000..7826d45e0f --- /dev/null +++ b/epan/dissectors/packet-rmt-common.c @@ -0,0 +1,122 @@ +/* packet-rmt-common.c + * Reliable Multicast Transport (RMT) + * Common RMT functions + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/packet.h> +#include <epan/strutil.h> + +#include "packet-rmt-common.h" + +/* Boolean string tables */ +const true_false_string boolean_set_notset = { "Set", "Not set" }; +const true_false_string boolean_yes_no = { "Yes", "No" }; + +/* Common RMT exported functions */ +/* ============================= */ + +/* Scan the tvb and put extensions found in an array */ +void rmt_ext_parse(GArray *a, tvbuff_t *tvb, guint *offset, guint offset_max) +{ + struct _ext e; + + while (*offset < offset_max) + { + /* Clear the temporary extension */ + memset(&e, 0, sizeof(struct _ext)); + + /* Dissect the extension */ + e.offset = *offset; + e.het = tvb_get_guint8(tvb, *offset); + + if (e.het <= 127) { + /* If HET <= 127, we have a variable-size extention */ + e.hel = tvb_get_guint8(tvb, *offset+1); + e.hec_offset = *offset + 2; + e.hec_size = e.hel * 4 - 2; + e.length = e.hel * 4; + } else { + /* If HET > 127, we have a short 32-bit extention */ + e.hel = 1; /* even if HEL field is not defined for HET > 127 */ + e.hec_offset = *offset + 1; + e.hec_size = 3; + e.length = 4; + } + + /* Prevents infinite loops */ + if (e.length == 0) + break; + + g_array_append_val(a, e); + *offset += e.length; + } +} + +/* Add default items to a subtree */ +void rmt_ext_decode_default_header(struct _ext *e, tvbuff_t *tvb, proto_tree *tree) +{ + if (tree) + { + proto_tree_add_text(tree, tvb, e->offset, 1, "Header Extension Type (HET): %u", e->het); + if (e->het <= 127) + proto_tree_add_text(tree, tvb, e->offset+1, 1, "Header Extension Length (HEL): %u", e->hel); + } +} + +/* Add a default subtree to a tree item */ +void rmt_ext_decode_default_subtree(struct _ext *e, tvbuff_t *tvb, proto_item *ti, gint ett) +{ + proto_tree *ext_tree; + + ext_tree = proto_item_add_subtree(ti, ett); + rmt_ext_decode_default_header(e, tvb, ext_tree); + + if (ext_tree) + proto_tree_add_text(ext_tree, tvb, e->hec_offset, e->hec_size, + "Header Extension Content (HEC): %s", tvb_bytes_to_str(tvb, e->hec_offset, e->hec_size)); +} + +/* Add a default subtree for unknown extensions */ +void rmt_ext_decode_default(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett) +{ + proto_item *ti; + + if (tree) + { + ti = proto_tree_add_text(tree, tvb, e->offset, e->length, + "Unknown extension (%u)", e->het); + + rmt_ext_decode_default_subtree(e, tvb, ti, ett); + } +} diff --git a/epan/dissectors/packet-rmt-common.h b/epan/dissectors/packet-rmt-common.h new file mode 100644 index 0000000000..b5dfb0c0c6 --- /dev/null +++ b/epan/dissectors/packet-rmt-common.h @@ -0,0 +1,59 @@ +/* packet-rmt-common.h + * Reliable Multicast Transport (RMT) + * Common RMT function definitions + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_RMT_COMMON__ +#define __PACKET_RMT_COMMON__ + +/* Boolean string tables external references */ +extern const true_false_string boolean_set_notset; +extern const true_false_string boolean_yes_no; + +/* Type definitions */ +/* ================ */ + +/* Logical header extension representation */ +struct _ext +{ + guint offset; + guint length; + + guint8 het; + guint8 hel; + + guint hec_offset; + guint8 hec_size; +}; + +/* Common RMT exported functions */ +/* ============================= */ + +void rmt_ext_parse(GArray *a, tvbuff_t *tvb, guint *offset, guint offset_max); + +void rmt_ext_decode_default(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett); +void rmt_ext_decode_default_subtree(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett); +void rmt_ext_decode_default_header(struct _ext *e, tvbuff_t *tvb, proto_tree *tree); + +#endif diff --git a/epan/dissectors/packet-rmt-fec.c b/epan/dissectors/packet-rmt-fec.c new file mode 100644 index 0000000000..6c263c1b8f --- /dev/null +++ b/epan/dissectors/packet-rmt-fec.c @@ -0,0 +1,270 @@ +/* packet-rmt-fec.c + * Reliable Multicast Transport (RMT) + * FEC Building Block dissector + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * Forward Error Correction (ALC): + * ------------------------------- + * + * The goal of the FEC building block is to describe functionality + * directly related to FEC codes that is common to all reliable content + * delivery IP multicast protocols, and to leave out any additional + * functionality that is specific to particular protocols. + * + * References: + * RFC 3452, Forward Error Correction Building Block + * RFC 3695, Compact Forward Error Correction (FEC) Schemes + * Simple XOR, Reed-Solomon, and Parity Check Matrix-based FEC Schemes draft-peltotalo-rmt-bb-fec-supp-xor-pcm-rs-00 + * IANA RMT FEC parameters (http://www.iana.org/assignments/rmt-fec-parameters) + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/packet.h> +#include <epan/prefs.h> + +#include "packet-rmt-fec.h" + +/* String tables */ +const value_string string_fec_encoding_id[] = +{ + { 0, "Compact No-Code" }, + { 2, "Simple XOR, Reed-Solomon, and Parity Check Matrix-based FEC Codes" }, + { 128, "Small Block, Large Block and Expandable FEC Codes" }, + { 129, "Small Block Systematic FEC Codes" }, + { 130, "Compact FEC Codes" }, + { 132, "Simple XOR, Reed-Solomon, and Parity Check Matrix-based FEC Codes" }, + { 0, NULL } +}; + +/* FEC exported functions */ +/* ====================== */ + +/* Info */ +/* ---- */ + +void fec_info_column(struct _fec *fec, packet_info *pinfo) +{ + if (fec->sbn_present) + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", fec->sbn); + + if (fec->esi_present) + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", fec->esi); +} + +/* Dissection */ +/* ---------- */ + +/* Decode an EXT_FTI extension and fill FEC array */ +void fec_decode_ext_fti(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett, struct _fec_ptr f) +{ + proto_item* ti = NULL; + proto_tree *ext_tree; + + if (tree) + ti = proto_tree_add_none_format(tree, f.hf->fti_header, tvb, e->offset, e->length, + "EXT_FTI, FEC Object Transmission Information (%u)", e->het); + + if (f.fec->encoding_id_present) + { + ext_tree = proto_item_add_subtree(ti, ett); + rmt_ext_decode_default_header(e, tvb, ext_tree); + + /* Decode 48-bit length field */ + f.fec->transfer_length = tvb_get_ntoh64(tvb, e->offset) & G_GINT64_CONSTANT(0xFFFFFFFFFFFFU); + + if (f.fec->encoding_id >= 128) + { + /* Decode FEC Instance ID */ + f.fec->instance_id_present = TRUE; + f.fec->instance_id = tvb_get_ntohs(tvb, e->offset+8); + } + + if (tree) + proto_tree_add_uint64(ext_tree, f.hf->fti_transfer_length, tvb, e->offset+2, 6, f.fec->transfer_length); + + switch (f.fec->encoding_id) + { + case 0: + case 2: + case 128: + case 130: + f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); + f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12); + + if (tree) + { + proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); + proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length); + } + break; + + case 129: + f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); + f.fec->max_source_block_length = tvb_get_ntohs(tvb, e->offset+12); + f.fec->max_number_encoding_symbols = tvb_get_ntohs(tvb, e->offset+14); + + if (tree) + { + proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); + proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 2, f.fec->max_source_block_length); + proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+14, 2, f.fec->max_number_encoding_symbols); + } + break; + + case 132: + f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); + f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12); + f.fec->max_number_encoding_symbols = tvb_get_ntohl(tvb, e->offset+16); + + if (tree) + { + proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); + proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length); + proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+16, 4, f.fec->max_number_encoding_symbols); + } + break; + } + + } else + if (tree) + rmt_ext_decode_default_subtree(e, tvb, ti, ett); +} + +/* Dissect a FEC header: + * fec - ptr to the logical FEC packet representation to fill + * hf - ptr to header fields array + * ett - ptr to ett array + * prefs - ptr to FEC prefs array + * tvb - buffer + * pinfo - packet info + * tree - tree where to add FEC header subtree + * offset - ptr to offset to use and update + */ +void fec_dissector(struct _fec_ptr f, tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_item *ti; + proto_tree *fec_tree; + + /* Create the FEC subtree */ + if (tree) + { + ti = proto_tree_add_item(tree, f.hf->header, tvb, *offset, -1, FALSE); + fec_tree = proto_item_add_subtree(ti, f.ett->main); + } else + fec_tree = NULL; + + /* FEC Encoding ID and FEC Instance ID processing */ + if (f.fec->encoding_id_present) + { + if (tree) + { + proto_tree_add_uint(fec_tree, f.hf->encoding_id, tvb, *offset, 0, f.fec->encoding_id); + + if (f.fec->encoding_id >= 128 && f.fec->instance_id_present) + proto_tree_add_uint(fec_tree, f.hf->instance_id, tvb, *offset, 0, f.fec->instance_id); + } + + switch (f.fec->encoding_id) + { + case 0: + case 130: + f.fec->sbn = tvb_get_ntohs(tvb, *offset); + f.fec->esi = tvb_get_ntohs(tvb, *offset+2); + + if (tree) + { + proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 2, f.fec->sbn); + proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+2, 2, f.fec->esi); + } + + f.fec->sbn_present = TRUE; + f.fec->esi_present = TRUE; + *offset += 4; + break; + + case 2: + case 128: + case 132: + f.fec->sbn = tvb_get_ntohl(tvb, *offset); + f.fec->esi = tvb_get_ntohl(tvb, *offset+4); + + if (tree) + { + proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 4, f.fec->sbn); + proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+4, 4, f.fec->esi); + } + + f.fec->sbn_present = TRUE; + f.fec->esi_present = TRUE; + *offset += 8; + break; + + case 129: + f.fec->sbn = tvb_get_ntohl(tvb, *offset); + f.fec->sbl = tvb_get_ntohs(tvb, *offset+4); + f.fec->esi = tvb_get_ntohs(tvb, *offset+6); + + if (tree) + { + proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 4, f.fec->sbn); + proto_tree_add_uint(fec_tree, f.hf->sbl, tvb, *offset+4, 2, f.fec->sbl); + proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+6, 2, f.fec->esi); + } + + f.fec->sbn_present = TRUE; + f.fec->sbl_present = TRUE; + f.fec->esi_present = TRUE; + *offset += 8; + break; + } + } +} + +void fec_dissector_free(struct _fec *fec) +{ + +} + +/* Preferences */ +/* ----------- */ + +/* Set/Reset preferences to default values */ +void fec_prefs_set_default(struct _fec_prefs *prefs) +{ + +} + +/* Register preferences */ +void fec_prefs_register(struct _fec_prefs *prefs, module_t *module) +{ + +} diff --git a/epan/dissectors/packet-rmt-fec.h b/epan/dissectors/packet-rmt-fec.h new file mode 100644 index 0000000000..ca2eb9ac21 --- /dev/null +++ b/epan/dissectors/packet-rmt-fec.h @@ -0,0 +1,138 @@ +/* packet-rmt-fec.h + * Reliable Multicast Transport (RMT) + * FEC Building Block function definitions + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_RMT_FEC__ +#define __PACKET_RMT_FEC__ + +#include "packet-rmt-common.h" + +/* String tables external references */ +extern const value_string string_fec_encoding_id[]; + +/* Type definitions */ +/* ================ */ + +struct _fec +{ + gboolean encoding_id_present; + gboolean instance_id_present; + guint8 encoding_id; + guint8 instance_id; + guint64 transfer_length; + guint32 encoding_symbol_length; + guint32 max_source_block_length; + guint32 max_number_encoding_symbols; + gboolean sbn_present; + gboolean sbl_present; + gboolean esi_present; + guint32 sbn; + guint32 sbl; + guint32 esi; +}; + +/* Ethereal stuff */ +/* ============== */ + +/* FEC header field definitions */ +struct _fec_hf +{ + int header; + int encoding_id; + int instance_id; + int sbn; + int sbl; + int esi; + int fti_header; + int fti_transfer_length; + int fti_encoding_symbol_length; + int fti_max_source_block_length; + int fti_max_number_encoding_symbols; +}; + +/* FEC subtrees */ +struct _fec_ett +{ + gint main; +}; + +/* FEC preferences */ +struct _fec_prefs +{ + gboolean dummy; +}; + +/* FEC pointers */ +struct _fec_ptr +{ + struct _fec *fec; + struct _fec_hf *hf; + struct _fec_ett *ett; + struct _fec_prefs *prefs; +}; + +/* Macros to generate static arrays */ + +#define FEC_FIELD_ARRAY(base_structure, base_protocol) \ + { &base_structure.header, \ + { "Forward Error Correction (FEC) header", base_protocol ".fec", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.encoding_id, \ + { "FEC Encoding ID", base_protocol ".fec.encoding_id", FT_UINT8, BASE_DEC, VALS(string_fec_encoding_id), 0x0, "", HFILL }}, \ + { &base_structure.instance_id, \ + { "FEC Instance ID", base_protocol ".fec.instance_id", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.sbn, \ + { "Source Block Number", base_protocol ".fec.sbn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.sbl, \ + { "Source Block Length", base_protocol ".fec.sbl", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.esi, \ + { "Encoding Symbol ID", base_protocol ".fec.esi", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fti_header, \ + { "FEC Object Transmission Information", base_protocol ".fec.fti", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fti_transfer_length, \ + { "Transfer Length", base_protocol ".fec.fti.transfer_length", FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fti_encoding_symbol_length, \ + { "Encoding Symbol Length", base_protocol ".fec.fti.encoding_symbol_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fti_max_source_block_length, \ + { "Maximum Source Block Length", base_protocol ".fec.fti.max_source_block_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fti_max_number_encoding_symbols, \ + { "Maximum Number of Encoding Symbols", base_protocol ".fec.fti.max_number_encoding_symbols", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }} + +#define FEC_SUBTREE_ARRAY(base_structure) \ + &base_structure.main + +/* FEC exported functions */ +/* ====================== */ + +void fec_info_column(struct _fec *fec, packet_info *pinfo); + +void fec_dissector(struct _fec_ptr f, tvbuff_t *tvb, proto_tree *tree, guint *offset); +void fec_dissector_free(struct _fec *fec); + +void fec_decode_ext_fti(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett, struct _fec_ptr f); + +void fec_prefs_set_default(struct _fec_prefs *prefs); +void fec_prefs_register(struct _fec_prefs *prefs, module_t *module); + +#endif diff --git a/epan/dissectors/packet-rmt-lct.c b/epan/dissectors/packet-rmt-lct.c new file mode 100644 index 0000000000..7dce3c9716 --- /dev/null +++ b/epan/dissectors/packet-rmt-lct.c @@ -0,0 +1,469 @@ +/* packet-rmt-lct.c + * Reliable Multicast Transport (RMT) + * LCT Building Block dissector + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * Layered Coding Transport (LCT): + * ------------------------------- + * + * Provides transport level support for reliable content delivery + * and stream delivery protocols. LCT is specifically designed to + * support protocols using IP multicast, but also provides support + * to protocols that use unicast. LCT is compatible with congestion + * control that provides multiple rate delivery to receivers and + * is also compatible with coding techniques that provide + * reliable delivery of content. + * + * References: + * RFC 3451, Layered Coding Transport (LCT) Building Block + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/strutil.h> + +#include "packet-rmt-lct.h" + +/* Enumerated data types for LCT preferences */ +static const enum_val_t enum_lct_ext_192[] = +{ + { "none", "Don't decode", LCT_PREFS_EXT_192_NONE }, + { "flute", "Decode as FLUTE extension (EXT_FDT)", LCT_PREFS_EXT_192_FLUTE }, + { NULL, NULL, 0 } +}; + +static const enum_val_t enum_lct_ext_193[] = +{ + { "none", "Don't decode", LCT_PREFS_EXT_193_NONE }, + { "flute", "Decode as FLUTE extension (EXT_CENC)", LCT_PREFS_EXT_193_FLUTE }, + { NULL, NULL, 0 } +}; + +/* LCT helper functions */ +/* ==================== */ + +static void lct_timestamp_parse(guint32 t, nstime_t* s) +{ + s->secs = t / 1000; + s->nsecs = (t % 1000) * 1000000; +} + +static void lct_ext_decode(struct _ext *e, struct _lct_prefs *prefs, tvbuff_t *tvb, proto_tree *tree, gint ett, struct _fec_ptr f) +{ + guint32 buffer32; + proto_item *ti; + proto_tree *ext_tree; + + switch (e->het) + { + + /* EXT_NOP */ + case 0: + if (tree) + { + ti = proto_tree_add_text(tree, tvb, e->offset, e->length, + "EXT_NOP, No-Operation (0)"); + + rmt_ext_decode_default_subtree(e, tvb, ti, ett); + } + break; + + /* EXT_AUTH */ + case 1: + if (tree) + { + ti = proto_tree_add_text(tree, tvb, e->offset, e->length, + "EXT_AUTH, Packet authentication (1)"); + + rmt_ext_decode_default_subtree(e, tvb, ti, ett); + } + break; + + /* EXT_FTI */ + case 64: + fec_decode_ext_fti(e, tvb, tree, ett, f); + break; + + /* EXT_FDT */ + case 192: + switch (prefs->ext_192) + { + case LCT_PREFS_EXT_192_NONE: + rmt_ext_decode_default(e, tvb, tree, ett); + break; + + case LCT_PREFS_EXT_192_FLUTE: + if (tree) + { + ti = proto_tree_add_text(tree, tvb, e->offset, e->length, + "EXT_FDT, FDT Instance Header (192)"); + + ext_tree = proto_item_add_subtree(ti, ett); + buffer32 = tvb_get_ntohl(tvb, e->offset); + + rmt_ext_decode_default_header(e, tvb, ext_tree); + + proto_tree_add_text(ext_tree, tvb, e->offset+1, 1, + "FLUTE version (V): %u", (buffer32 & 0x00F00000) >> 20); + + proto_tree_add_text(ext_tree, tvb, e->offset+1, 3, + "FDT Instance ID: %u", buffer32 & 0x000FFFFF); + } + break; + } + break; + + /* EXT_CENC */ + case 193: + switch (prefs->ext_193) + { + case LCT_PREFS_EXT_193_NONE: + rmt_ext_decode_default(e, tvb, tree, ett); + break; + + case LCT_PREFS_EXT_193_FLUTE: + if (tree) + { + ti = proto_tree_add_text(tree, tvb, e->offset, e->length, + "EXT_CENC, FDT Instance Content Encoding (193)"); + + ext_tree = proto_item_add_subtree(ti, ett); + buffer32 = tvb_get_ntohl(tvb, e->offset); + + rmt_ext_decode_default_header(e, tvb, ext_tree); + + proto_tree_add_text(ext_tree, tvb, e->offset+1, 1, + "Content Encoding Algorithm (CENC): %u", (buffer32 & 0x00FF0000) >> 16); + } + break; + } + break; + + default: + rmt_ext_decode_default(e, tvb, tree, ett); + } +} + +/* LCT exported functions */ +/* ====================== */ + +/* Info */ +/* ---- */ + +void lct_info_column(struct _lct *lct, packet_info *pinfo) +{ + if (lct->tsi_present) + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "TSI: %" PRIu64, lct->tsi); + + if (lct->toi_present) + { + if (lct->toi_size <= 8) + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "TOI: %" PRIu64, lct->toi); + else + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "TOI: 0x%s", bytes_to_str(lct->toi_extended, lct->toi_size)); + } + + if (lct->close_session) + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "Close session"); + + if (lct->close_object) + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "Close object"); +} + +/* Dissection */ +/* ---------- */ + +/* Dissect an LCT header: + * l - ptr to the logical LCT packet representation to fill, and related ethereal stuffs + * f - ptr to the FEC infos to fill (EXT_FTI), and related ethereal stuffs + * tvb - buffer + * pinfo - packet info + * tree - tree where to add LCT header subtree + * offset - ptr to offset to use and update + */ +void lct_dissector(struct _lct_ptr l, struct _fec_ptr f, tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + guint i; + guint offset_old; + guint offset_start; + guint16 buffer16; + + /* Set up structures needed to add the protocol subtree and manage it */ + proto_item *ti; + proto_tree *lct_tree; + proto_tree *lct_fsize_tree; + proto_tree *lct_flags_tree; + proto_tree *lct_ext_tree; + + /* LCT fixed-size fields dissection */ + /* -------------------------------- */ + + offset_start = *offset; + + buffer16 = tvb_get_ntohs(tvb, *offset); + + l.lct->version = ((buffer16 & 0xF000) >> 12); + + l.lct->cci_size = ((buffer16 & 0x0C00) >> 10) * 4 + 4; + l.lct->tsi_size = ((buffer16 & 0x0080) >> 7) * 4 + ((buffer16 & 0x0010) >> 4) * 2; + l.lct->toi_size = ((buffer16 & 0x0060) >> 5) * 4 + ((buffer16 & 0x0010) >> 4) * 2; + + l.lct->tsi_present = (l.lct->tsi_size > 0); + l.lct->toi_present = (l.lct->toi_size > 0); + l.lct->sct_present = (buffer16 & 0x0008) != 0; + l.lct->ert_present = (buffer16 & 0x0004) != 0; + l.lct->close_session = (buffer16 & 0x0002) != 0; + l.lct->close_object = (buffer16 & 0x0001) != 0; + + l.lct->hlen = tvb_get_guint8(tvb, *offset+2) * 4; + l.lct->codepoint = tvb_get_guint8(tvb, *offset+3); + + if (l.prefs->codepoint_as_fec_encoding) + { + f.fec->encoding_id_present = TRUE; + f.fec->encoding_id = l.lct->codepoint; + } + + if (tree) + { + /* Create the LCT subtree */ + ti = proto_tree_add_item(tree, l.hf->header, tvb, *offset, l.lct->hlen, FALSE); + lct_tree = proto_item_add_subtree(ti, l.ett->main); + + /* Fill the LCT subtree */ + proto_tree_add_uint(lct_tree, l.hf->version, tvb, *offset, 1, l.lct->version); + + ti = proto_tree_add_item(lct_tree, l.hf->fsize_header, tvb, *offset, 2, FALSE); + lct_fsize_tree = proto_item_add_subtree(ti, l.ett->fsize); + + ti = proto_tree_add_item(lct_tree, l.hf->flags_header, tvb, *offset, 2, FALSE); + lct_flags_tree = proto_item_add_subtree(ti, l.ett->flags); + + proto_tree_add_uint(lct_tree, l.hf->hlen, tvb, *offset+2, 1, l.lct->hlen); + proto_tree_add_uint(lct_tree, l.hf->codepoint, tvb, *offset+3, 1, l.lct->codepoint); + + /* Fill the LCT fsize subtree */ + proto_tree_add_uint(lct_fsize_tree, l.hf->fsize_cci, tvb, *offset, 1, l.lct->cci_size); + proto_tree_add_uint(lct_fsize_tree, l.hf->fsize_tsi, tvb, *offset+1, 1, l.lct->tsi_size); + proto_tree_add_uint(lct_fsize_tree, l.hf->fsize_toi, tvb, *offset+1, 1, l.lct->toi_size); + + /* Fill the LCT flags subtree */ + proto_tree_add_boolean(lct_flags_tree, l.hf->flags_sct_present, tvb, *offset+1, 1, l.lct->sct_present); + proto_tree_add_boolean(lct_flags_tree, l.hf->flags_ert_present, tvb, *offset+1, 1, l.lct->ert_present); + proto_tree_add_boolean(lct_flags_tree, l.hf->flags_close_session, tvb, *offset+1, 1, l.lct->close_session); + proto_tree_add_boolean(lct_flags_tree, l.hf->flags_close_object, tvb, *offset+1, 1, l.lct->close_object); + + } else { + lct_tree = NULL; + lct_fsize_tree = NULL; + lct_flags_tree = NULL; + } + + *offset += 4; + + /* LCT variable-size and optional fields dissection */ + /* ------------------------------------------------ */ + + /* Congestion Control Information (CCI) */ + if (l.lct->cci_size > 0) { + l.lct->cci = (guint8*) tvb_get_ptr(tvb, *offset, l.lct->cci_size); + if (tree) + proto_tree_add_bytes(lct_tree, l.hf->cci, tvb, *offset, l.lct->cci_size, l.lct->cci); + *offset += l.lct->cci_size; + } + + /* Transmission Session Identifier (TSI) */ + if (l.lct->tsi_present) { + + switch (l.lct->tsi_size) + { + case 0: + l.lct->tsi = 0; + break; + + case 2: + l.lct->tsi = tvb_get_ntohs(tvb, *offset); + break; + + case 4: + l.lct->tsi = tvb_get_ntohl(tvb, *offset); + break; + + case 6: + l.lct->tsi = tvb_get_ntoh64(tvb, *offset-2) & G_GINT64_CONSTANT(0x0000FFFFFFFFFFFFU); + break; + } + + if (tree) + proto_tree_add_uint64(lct_tree, l.hf->tsi, tvb, *offset, l.lct->tsi_size, l.lct->tsi); + *offset += l.lct->tsi_size; + } + + /* Transmission Object Identifier (TOI) */ + if (l.lct->toi_present) { + + switch (l.lct->toi_size) + { + case 0: + l.lct->toi = 0; + break; + + case 2: + l.lct->toi = tvb_get_ntohs(tvb, *offset); + break; + + case 4: + l.lct->toi = tvb_get_ntohl(tvb, *offset); + break; + + case 6: + l.lct->toi = tvb_get_ntoh64(tvb, *offset-2) & G_GINT64_CONSTANT(0x0000FFFFFFFFFFFFU); + break; + + case 8: + l.lct->toi = tvb_get_ntoh64(tvb, *offset); + break; + + case 10: + l.lct->toi = tvb_get_ntoh64(tvb, *offset+2); + break; + + case 12: + l.lct->toi = tvb_get_ntoh64(tvb, *offset+4); + break; + + case 14: + l.lct->toi = tvb_get_ntoh64(tvb, *offset)+6; + break; + } + + l.lct->toi_extended = (guint8*) tvb_get_ptr(tvb, *offset, l.lct->toi_size); + + if (tree) + { + if (l.lct->toi_size > 8) + proto_tree_add_uint64(lct_tree, l.hf->toi, tvb, *offset+(l.lct->toi_size-8), 8, l.lct->toi); + else + proto_tree_add_uint64(lct_tree, l.hf->toi, tvb, *offset, l.lct->toi_size, l.lct->toi); + + proto_tree_add_bytes(lct_tree, l.hf->toi_extended, tvb, *offset, l.lct->toi_size, l.lct->toi_extended); + } + + *offset += l.lct->toi_size; + } + + /* Sender Current Time (SCT) */ + if (l.lct->sct_present) { + lct_timestamp_parse(tvb_get_ntohl(tvb, *offset), &l.lct->sct); + if (tree) + proto_tree_add_time(lct_tree, l.hf->sct, tvb, *offset, 4, &l.lct->sct); + *offset += 4; + } + + /* Expected Residual Time (ERT) */ + if (l.lct->sct_present) { + lct_timestamp_parse(tvb_get_ntohl(tvb, *offset), &l.lct->ert); + if (tree) + proto_tree_add_time(lct_tree, l.hf->ert, tvb, *offset, 4, &l.lct->ert); + *offset += 4; + } + + /* LCT header extensions, if applicable */ + /* ------------------------------------ */ + + /* Allocate an array of _ext elements */ + l.lct->ext = g_array_new(FALSE, TRUE, sizeof(struct _ext)); + + offset_old = *offset; + rmt_ext_parse(l.lct->ext, tvb, offset, offset_start + l.lct->hlen); + + /* Resync the offset with the end of LCT header */ + *offset = offset_start + l.lct->hlen; + + if (l.lct->ext->len > 0) + { + if (tree) + { + /* Add the extensions subtree */ + ti = proto_tree_add_uint(lct_tree, l.hf->ext, tvb, offset_old, *offset - offset_old, l.lct->ext->len); + lct_ext_tree = proto_item_add_subtree(ti, l.ett->ext); + } else + lct_ext_tree = NULL; + + /* Add the extensions to the subtree */ + for (i = 0; i < l.lct->ext->len; i++) + lct_ext_decode(&g_array_index(l.lct->ext, struct _ext, i), l.prefs, tvb, lct_ext_tree, l.ett->ext_ext, f); + } +} + +void lct_dissector_free(struct _lct *lct) +{ + g_array_free(lct->ext, TRUE); +} + +/* Preferences */ +/* ----------- */ + +/* Set/Reset preferences to default values */ +void lct_prefs_set_default(struct _lct_prefs *prefs) +{ + prefs->codepoint_as_fec_encoding = TRUE; + prefs->ext_192 = LCT_PREFS_EXT_192_FLUTE; + prefs->ext_193 = LCT_PREFS_EXT_193_FLUTE; +} + +/* Register preferences */ +void lct_prefs_register(struct _lct_prefs *prefs, module_t *module) +{ + prefs_register_bool_preference(module, + "lct.codepoint_as_fec_id", + "LCT Codepoint as FEC Encoding ID", + "Whether the LCT header Codepoint field should be considered the FEC Encoding ID of carried object", + &prefs->codepoint_as_fec_encoding); + + prefs_register_enum_preference(module, + "lct.ext.192", + "LCT header extention 192", + "How to decode LCT header extention 192", + &prefs->ext_192, + enum_lct_ext_192, + FALSE); + + prefs_register_enum_preference(module, + "lct.ext.193", + "LCT header extention 193", + "How to decode LCT header extention 193", + &prefs->ext_193, + enum_lct_ext_193, + FALSE); +} diff --git a/epan/dissectors/packet-rmt-lct.h b/epan/dissectors/packet-rmt-lct.h new file mode 100644 index 0000000000..9cf79448c3 --- /dev/null +++ b/epan/dissectors/packet-rmt-lct.h @@ -0,0 +1,185 @@ +/* packet-rmt-lct.h + * Reliable Multicast Transport (RMT) + * LCT Building Block function definitions + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_RMT_LCT__ +#define __PACKET_RMT_LCT__ + +#include "packet-rmt-common.h" +#include "packet-rmt-fec.h" + +/* Type definitions */ +/* ================ */ + +/* Logical LCT header representation */ +struct _lct +{ + guint8 version; + guint8 cci_size; + guint8 tsi_size; + guint8 toi_size; + gboolean tsi_present; + gboolean toi_present; + gboolean sct_present; + gboolean ert_present; + gboolean close_session; + gboolean close_object; + guint16 hlen; + guint8 codepoint; + guint8 *cci; + guint64 tsi; + guint64 toi; + guint8 *toi_extended; + nstime_t sct; + nstime_t ert; + GArray *ext; +}; + +/* Ethereal stuff */ +/* ============== */ + +/* LCT header field definitions */ +struct _lct_hf +{ + int header; + int version; + int fsize_header; + int fsize_cci; + int fsize_tsi; + int fsize_toi; + int flags_header; + int flags_sct_present; + int flags_ert_present; + int flags_close_session; + int flags_close_object; + int hlen; + int codepoint; + int cci; + int tsi; + int toi; + int toi_extended; + int sct; + int ert; + int ext; +}; + +/* LCT subtrees */ +struct _lct_ett +{ + gint main; + + gint fsize; + gint flags; + gint ext; + gint ext_ext; +}; + +/* LCT preferences */ + +#define LCT_PREFS_EXT_192_NONE 0 +#define LCT_PREFS_EXT_192_FLUTE 1 + +#define LCT_PREFS_EXT_193_NONE 0 +#define LCT_PREFS_EXT_193_FLUTE 1 + +struct _lct_prefs +{ + gboolean codepoint_as_fec_encoding; + gint ext_192; + gint ext_193; +}; + +/* LCT pointers */ +struct _lct_ptr +{ + struct _lct *lct; + struct _lct_hf *hf; + struct _lct_ett *ett; + struct _lct_prefs *prefs; +}; + +/* Macros to generate static arrays */ + +#define LCT_FIELD_ARRAY(base_structure, base_protocol) \ + { &base_structure.header, \ + { "Layered Coding Transport (LCT) header", base_protocol ".lct", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.version, \ + { "Version", base_protocol ".lct.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fsize_header, \ + { "Field sizes (bytes)", base_protocol ".lct.fsize", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fsize_cci, \ + { "Congestion Control Information field size", base_protocol ".lct.fsize.cci", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fsize_tsi, \ + { "Transport Session Identifier field size", base_protocol ".lct.fsize.tsi", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.fsize_toi, \ + { "Transport Object Identifier field size", base_protocol ".lct.fsize.toi", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.flags_header, \ + { "Flags", base_protocol ".lct.flags", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.flags_sct_present, \ + { "Sender Current Time present flag", base_protocol ".lct.flags.sct_present", FT_BOOLEAN, BASE_NONE, TFS(&boolean_set_notset), 0x0, "", HFILL }}, \ + { &base_structure.flags_ert_present, \ + { "Expected Residual Time present flag", base_protocol ".lct.flags.ert_present", FT_BOOLEAN, BASE_NONE, TFS(&boolean_set_notset), 0x0, "", HFILL }}, \ + { &base_structure.flags_close_session, \ + { "Close Session flag", base_protocol ".lct.flags.close_session", FT_BOOLEAN, BASE_NONE, TFS(&boolean_set_notset), 0x0, "", HFILL }}, \ + { &base_structure.flags_close_object, \ + { "Close Object flag", base_protocol ".lct.flags.close_object", FT_BOOLEAN, BASE_NONE, TFS(&boolean_set_notset), 0x0, "", HFILL }}, \ + { &base_structure.hlen, \ + { "Header length", base_protocol ".lct.hlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.codepoint, \ + { "Codepoint", base_protocol ".lct.codepoint", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.cci, \ + { "Congestion Control Information", base_protocol ".lct.cci", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.tsi, \ + { "Transport Session Identifier", base_protocol ".lct.tsi", FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.toi, \ + { "Transport Object Identifier (up to 64 bites)", base_protocol ".lct.toi", FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL }}, \ + { &base_structure.toi_extended, \ + { "Transport Object Identifier (up to 112 bits)", base_protocol ".lct.toi_extended", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.sct, \ + { "Sender Current Time", base_protocol ".lct.sct", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.ert, \ + { "Expected Residual Time", base_protocol ".lct.ert", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }}, \ + { &base_structure.ext, \ + { "Extension count", base_protocol ".lct.ext", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }} + +#define LCT_SUBTREE_ARRAY(base_structure) \ + &base_structure.main, \ + &base_structure.fsize, \ + &base_structure.flags, \ + &base_structure.ext, \ + &base_structure.ext_ext + +/* LCT exported functions */ +/* ====================== */ + +void lct_info_column(struct _lct *lct, packet_info *pinfo); + +void lct_dissector(struct _lct_ptr l, struct _fec_ptr f, tvbuff_t *tvb, proto_tree *tree, guint *offset); +void lct_dissector_free(struct _lct *lct); + +void lct_prefs_set_default(struct _lct_prefs *prefs); +void lct_prefs_register(struct _lct_prefs *prefs, module_t *module); + +#endif diff --git a/epan/dissectors/packet-rmt-norm.c b/epan/dissectors/packet-rmt-norm.c new file mode 100644 index 0000000000..0b09b437b1 --- /dev/null +++ b/epan/dissectors/packet-rmt-norm.c @@ -0,0 +1,281 @@ +/* packet-rmt-norm.c + * Reliable Multicast Transport (RMT) + * NORM Protocol Instantiation dissector + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * Negative-acknowledgment (NACK)-Oriented Reliable Multicast (NORM): + * ------------------------------------------------------------------ + * + * This protocol is designed to provide end-to-end reliable transport of + * bulk data objects or streams over generic IP multicast routing and + * forwarding services. NORM uses a selective, negative acknowledgment + * mechanism for transport reliability and offers additional protocol + * mechanisms to allow for operation with minimal "a priori" + * coordination among senders and receivers. + * + * References: + * RFC 3490, Negative-acknowledgment (NACK)-Oriented Reliable Multicast (NORM) Protocol + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/packet.h> +#include <epan/prefs.h> + +#include "packet-rmt-norm.h" + +/* String tables */ +const value_string string_norm_type[] = +{ + { 1, "NORM_INFO" }, + { 2, "NORM_DATA" }, + { 3, "NORM_CMD" }, + { 4, "NORM_NACK" }, + { 5, "NORM_ACK" }, + { 6, "NORM_REPORT" }, + { 0, NULL } +}; + +/* Initialize the protocol and registered fields */ +/* ============================================= */ + +static int proto = -1; + +static struct _norm_hf hf; +static struct _norm_ett ett; + +static gboolean preferences_initialized = FALSE; +static struct _norm_prefs preferences; +static struct _norm_prefs preferences_old; + +/* Preferences */ +/* =========== */ + +/* Set/Reset preferences to default values */ +static void norm_prefs_set_default(struct _norm_prefs *prefs) +{ + fec_prefs_set_default(&prefs->fec); +} + +/* Register preferences */ +static void norm_prefs_register(struct _norm_prefs *prefs, module_t *module) +{ + fec_prefs_register(&prefs->fec, module); +} + +/* Save preferences to alc_prefs_old */ +static void norm_prefs_save(struct _norm_prefs *p, struct _norm_prefs *p_old) +{ + *p_old = *p; +} + +/* Code to actually dissect the packets */ +/* ==================================== */ + +static void dissect_norm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + /* Logical packet representation */ + struct _norm norm; + + /* Offset for subpacket dissection */ + guint offset; + + /* Set up structures needed to add the protocol subtree and manage it */ + proto_item *ti; + proto_tree *norm_tree; + + /* Structures and variables initialization */ + offset = 0; + memset(&norm, 0, sizeof(struct _norm)); + + /* Update packet info */ + pinfo->current_proto = "NORM"; + + /* Make entries in Protocol column and Info column on summary display */ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "NORM"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + /* NORM header dissection, part 1 */ + /* ------------------------------ */ + + norm.version = hi_nibble(tvb_get_guint8(tvb, offset)); + + if (tree) + { + /* Create subtree for the NORM protocol */ + ti = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE); + norm_tree = proto_item_add_subtree(ti, ett.main); + + /* Fill the NORM subtree */ + proto_tree_add_uint(norm_tree, hf.version, tvb, offset, 1, norm.version); + + } else + norm_tree = NULL; + + /* This dissector supports only NORMv1 packets. + * If norm.version > 1 print only version field and quit. + */ + if (norm.version == 1) { + + /* NORM header dissection, part 2 */ + /* ------------------------------ */ + + norm.type = lo_nibble(tvb_get_guint8(tvb, offset)); + norm.hlen = tvb_get_guint8(tvb, offset+1); + norm.sequence = tvb_get_ntohs(tvb, offset+2); + norm.source_id = tvb_get_ntohl(tvb, offset+4); + + if (tree) + { + proto_tree_add_uint(norm_tree, hf.type, tvb, offset, 1, norm.type); + proto_tree_add_uint(norm_tree, hf.hlen, tvb, offset+1, 1, norm.hlen); + proto_tree_add_uint(norm_tree, hf.sequence, tvb, offset+2, 2, norm.sequence); + proto_tree_add_uint(norm_tree, hf.source_id, tvb, offset+4, 4, norm.source_id); + } + + offset += 8; + + /* Add the Payload item */ + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(norm_tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); + + /* Complete entry in Info column on summary display */ + /* ------------------------------------------------ */ + + if (check_col(pinfo->cinfo, COL_INFO)) + switch (norm.type) + { + case 1: + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "INFO"); + break; + + case 2: + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "DATA"); + break; + + case 3: + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "CMD"); + break; + + case 4: + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "NACK"); + break; + + case 5: + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "ACK"); + break; + + case 6: + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "REPORT"); + break; + + default: + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "Unknown type"); + break; + } + + } else { + + if (tree) + proto_tree_add_text(norm_tree, tvb, 0, -1, "Sorry, this dissector supports NORM version 1 only"); + + /* Complete entry in Info column on summary display */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_fstr(pinfo->cinfo, COL_INFO, "Version: %u (not supported)", norm.version); + } +} + +void proto_reg_handoff_norm(void) +{ + static dissector_handle_t handle; + + if (!preferences_initialized) + { + preferences_initialized = TRUE; + handle = create_dissector_handle(dissect_norm, proto); + dissector_add_handle("udp.port", handle); + } + + norm_prefs_save(&preferences, &preferences_old); +} + +void proto_register_norm(void) +{ + /* Setup NORM header fields */ + static hf_register_info hf_ptr[] = { + + { &hf.version, + { "Version", "norm.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf.type, + { "Message Type", "norm.type", FT_UINT8, BASE_DEC, VALS(string_norm_type), 0x0, "", HFILL }}, + { &hf.hlen, + { "Header length", "norm.hlen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf.sequence, + { "Sequence", "norm.sequence", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf.source_id, + { "Source ID", "norm.source_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + + FEC_FIELD_ARRAY(hf.fec, "alc"), + + { &hf.payload, + { "Payload", "norm.payload", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + /* Setup protocol subtree array */ + static gint *ett_ptr[] = { + &ett.main, + + FEC_SUBTREE_ARRAY(ett.fec) + }; + + module_t *module; + + /* Clear hf and ett fields */ + memset(&hf, 0xff, sizeof(struct _norm_hf)); + memset(&ett, 0xff, sizeof(struct _norm_ett)); + + /* Register the protocol name and description */ + proto = proto_register_protocol("Negative-acknowledgment Oriented Reliable Multicast", "NORM", "norm"); + + /* Register the header fields and subtrees used */ + proto_register_field_array(proto, hf_ptr, array_length(hf_ptr)); + proto_register_subtree_array(ett_ptr, array_length(ett_ptr)); + + /* Reset preferences */ + norm_prefs_set_default(&preferences); + norm_prefs_save(&preferences, &preferences_old); + + /* Register preferences */ + module = prefs_register_protocol(proto, proto_reg_handoff_norm); + norm_prefs_register(&preferences, module); +} diff --git a/epan/dissectors/packet-rmt-norm.h b/epan/dissectors/packet-rmt-norm.h new file mode 100644 index 0000000000..c353bd9a7a --- /dev/null +++ b/epan/dissectors/packet-rmt-norm.h @@ -0,0 +1,82 @@ +/* packet-rmt-norm.h + * Reliable Multicast Transport (RMT) + * NORM Protocol Instantiation function definitions + * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_RMT_NORM__ +#define __PACKET_RMT_NORM__ + +#include "packet-rmt-common.h" +#include "packet-rmt-fec.h" + +/* Type definitions */ +/* ================ */ + +/* Logical NORM packet representation */ +struct _norm +{ + guint8 version; + guint8 type; + guint8 hlen; + guint16 sequence; + guint32 source_id; + + struct _fec fec; +}; + +/* Ethereal stuff */ +/* ============== */ + +/* NORM header field definitions*/ +struct _norm_hf +{ + int version; + int type; + int hlen; + int sequence; + int source_id; + + struct _fec_hf fec; + + int payload; +}; + +/* NORM subtrees */ +struct _norm_ett +{ + gint main; + + struct _fec_ett fec; +}; + +/* NORM preferences */ +struct _norm_prefs +{ + struct _fec_prefs fec; +}; + +/* Function declarations */ +/* ===================== */ + +#endif |