Ethereal-dev: [Ethereal-dev] Reliable Multicast Transport dissectors ready!

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 10 Jan 2005 01:43:04 +0100
Hello,

Thanks to all of you (especially LEGO and Guy Harris), I'm pleased to announce to the ethereal development list that most of the Reliable Multicast Transport (RMT) dissectors are complete.

Please find attached a patch against SVN release 12999.

There are two new protocol dissectors: ALC (rfc 3450) and NORM (rfc 3940); two building block "subdissectors": LCT (rfc 3451) and FEC (rfc 3452, 3453, 3695); plus few common functions.

Please note that:

1) Considering how ethereal defines a "protocol", there are only 2 new protocol dissectors (ALC and NORM). LCT and FEC are building blocks that define protocol instantiations and are shared among them.

2) ALC and LCT dissectors are complete and support even complex fields defined in rfc 3451 (variable length TSI and TOI, Sender Current Time and Expected Residual Time). LCT dissector can also decode extensions 0, 1, 64, 192 and 193. FEC dissector supports FEC Encoding ID 0, 128, 129 and 130.

3) NORM dissector implementation is far from complete. Only first 8 bytes are decoded. It will be completed in the future.

4) Since there isn't a reliable way to determine if an UDP is carrying an ALC or NORM payload, dissectors have to be started manually using the "Decode as ..." window. There's an ALC user preference for a default UDP destination port. There will be a simiar preference for NORM in the future.

That's all !!

Thanks.

Stefano
Index: epan/dissectors/packet-rmt-common.c
===================================================================
--- epan/dissectors/packet-rmt-common.c	(revision 0)
+++ epan/dissectors/packet-rmt-common.c	(revision 0)
@@ -0,0 +1,122 @@
+/* packet-rmt-common.c
+ * Reliable Multicast Transport (RMT)
+ * Common RMT functions
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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);
+	}
+}
Index: epan/dissectors/packet-rmt-common.h
===================================================================
--- epan/dissectors/packet-rmt-common.h	(revision 0)
+++ epan/dissectors/packet-rmt-common.h	(revision 0)
@@ -0,0 +1,59 @@
+/* packet-rmt-common.h
+ * Reliable Multicast Transport (RMT)
+ * Common RMT function definitions
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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
Index: epan/dissectors/packet-rmt-fec.c
===================================================================
--- epan/dissectors/packet-rmt-fec.c	(revision 0)
+++ epan/dissectors/packet-rmt-fec.c	(revision 0)
@@ -0,0 +1,251 @@
+/* packet-rmt-fec.c
+ * Reliable Multicast Transport (RMT)
+ * FEC Building Block dissector
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * 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
+ *     IANA RMT FEC parameters (http://www.iana.org/assignments/rmt-fec-parameters)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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" },
+	{ 128, "Small Block, Large Block and Expandable FEC Codes" },
+	{ 129, "Small Block Systematic FEC Codes" },
+	{ 130, "Compact FEC" },
+	{ 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 128:
+		case 130:
+			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);
+			
+			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);
+			}
+			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;
+		}
+				
+	} 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 128:
+			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)
+{
+
+}
Index: epan/dissectors/packet-rmt-fec.h
===================================================================
--- epan/dissectors/packet-rmt-fec.h	(revision 0)
+++ epan/dissectors/packet-rmt-fec.h	(revision 0)
@@ -0,0 +1,138 @@
+/* packet-rmt-fec.h
+ * Reliable Multicast Transport (RMT)
+ * FEC Building Block function definitions
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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
Index: epan/dissectors/Makefile.common
===================================================================
--- epan/dissectors/Makefile.common	(revision 12999)
+++ epan/dissectors/Makefile.common	(working copy)
@@ -438,6 +438,11 @@
 	packet-rmcp.c	\
 	packet-rmi.c	\
 	packet-rmp.c	\
+	packet-rmt-common.c	\
+	packet-rmt-lct.c	\
+	packet-rmt-fec.c	\
+	packet-rmt-alc.c	\
+	packet-rmt-norm.c	\
 	packet-rpc.c	\
 	packet-rpl.c	\
 	packet-rquota.c	\
@@ -716,6 +721,11 @@
 	packet-raw.h	\
 	packet-ripng.h	\
 	packet-rmi.h	\
+	packet-rmt-common.h	\
+	packet-rmt-lct.h	\
+	packet-rmt-fec.h	\
+	packet-rmt-alc.h	\
+	packet-rmt-norm.h	\
 	packet-rpc.h	\
 	packet-rquota.h	\
 	packet-rsvp.h	\
Index: epan/dissectors/packet-rmt-alc.c
===================================================================
--- epan/dissectors/packet-rmt-alc.c	(revision 0)
+++ epan/dissectors/packet-rmt-alc.c	(revision 0)
@@ -0,0 +1,276 @@
+/* packet-rmt-alc.c
+ * Reliable Multicast Transport (RMT)
+ * ALC Protocol Instantiation dissector
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * 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@xxxxxxxxxxxx>
+ * 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);	
+}
Index: epan/dissectors/packet-rmt-alc.h
===================================================================
--- epan/dissectors/packet-rmt-alc.h	(revision 0)
+++ epan/dissectors/packet-rmt-alc.h	(revision 0)
@@ -0,0 +1,81 @@
+/* packet-rmt-alc.h
+ * Reliable Multicast Transport (RMT)
+ * ALC Protocol Instantiation function definitions
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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
Index: epan/dissectors/packet-rmt-norm.c
===================================================================
--- epan/dissectors/packet-rmt-norm.c	(revision 0)
+++ epan/dissectors/packet-rmt-norm.c	(revision 0)
@@ -0,0 +1,281 @@
+/* packet-rmt-norm.c
+ * Reliable Multicast Transport (RMT)
+ * NORM Protocol Instantiation dissector
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * 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@xxxxxxxxxxxx>
+ * 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);	
+}
Index: epan/dissectors/packet-rmt-norm.h
===================================================================
--- epan/dissectors/packet-rmt-norm.h	(revision 0)
+++ epan/dissectors/packet-rmt-norm.h	(revision 0)
@@ -0,0 +1,82 @@
+/* packet-rmt-norm.h
+ * Reliable Multicast Transport (RMT)
+ * NORM Protocol Instantiation function definitions
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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
Index: epan/dissectors/packet-rmt-lct.c
===================================================================
--- epan/dissectors/packet-rmt-lct.c	(revision 0)
+++ epan/dissectors/packet-rmt-lct.c	(revision 0)
@@ -0,0 +1,469 @@
+/* packet-rmt-lct.c
+ * Reliable Multicast Transport (RMT)
+ * LCT Building Block dissector
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * 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@xxxxxxxxxxxx>
+ * 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);
+}
Index: epan/dissectors/packet-rmt-lct.h
===================================================================
--- epan/dissectors/packet-rmt-lct.h	(revision 0)
+++ epan/dissectors/packet-rmt-lct.h	(revision 0)
@@ -0,0 +1,185 @@
+/* packet-rmt-lct.h
+ * Reliable Multicast Transport (RMT)
+ * LCT Building Block function definitions
+ * Copyright 2005, Stefano Pettini <spettini@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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