ANNOUNCEMENT: Live Wireshark University & Allegro Packets online APAC Wireshark Training Session
April 17th, 2024 | 14:30-16:00 SGT (UTC+8) | Online

Wireshark-dev: [Wireshark-dev] [PATCH] plugins/rdm: Update to ANSI E1.20-2006

Date Prev · Date Next · Thread Prev · Thread Next
From: "Shaun Jackman" <sjackman@xxxxxxxxx>
Date: Sat, 30 Sep 2006 11:00:37 -0600
The RDM protocol has been accepted as ANSI standard E1.20-2006. The
following patch updates the decoder to that spec. Please apply.

Cheers,
Shaun

2006-09-30  Shaun Jackman  <sjackman@xxxxxxxxx>

	* plugins/rdm/moduleinfo.h (VERSION): Bump to 0.1.0.
	* plugins/rdm/packet-rdm.c: Update to the ANSI E1.20-2006 spec.

Index: packet-rdm.c
===================================================================
--- packet-rdm.c	(revision 19385)
+++ packet-rdm.c	(working copy)
@@ -1,14 +1,25 @@
-/* packet-rdm.c
- * Routines for RDM packet disassembly
+/* RDM (Remote Devcie Management) packet disassembly.
 *
+ * ANSI E1.20-2006, Entertainment Technology
+ * Remote Device Management over USITT DMX512, describes a method of
+ * bi-directional communications over a USITT DMX512/1990 data link
+ * between an entertainment lighting controller and one or more
+ * remotely controlled lighting devices. The protocol also is intended
+ * to work with the ANSI E1.11-2004 control protocol. It allows
+ * discovery of devices on a DMX512/E1.11 network and the remote
+ * setting of DMX starting addresses, as well as status and fault
+ * reporting back to the control console.
+ *
 * $Id$
 *
- * Copyright (c) 2003 by Erwin Rol <erwin@xxxxxxxxxxxx>
+ * Written by
 *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@xxxxxxxxxxxxx>
- * Copyright 1999 Gerald Combs
+ *  Shaun Jackman <sjackman@xxxxxxxxx>
+ *  Copyright 2006 Pathway Connectivity
 *
+ *  Erwin Rol <erwin@xxxxxxxxxxxx>
+ *  Copyright 2003 Erwin Rol
+ *
 * 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
@@ -18,16 +29,10 @@
 * 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.
 */

-/* Include files */
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif

#include <stdio.h>
@@ -42,216 +47,255 @@
#include <epan/etypes.h>
#include <epan/strutil.h>

-/*
- * See http://www.esta.org/tsp/E1-20inst.htm
- *
- */
-
-void proto_reg_handoff_rdm(void);
-
-/* Define the rdm proto */
static int proto_rdm = -1;

-/* Header */
+static int hf_rdm_start_code = -1;
static int hf_rdm_sub_start_code = -1;
-static int hf_rdm_slot_count = -1;
+static int hf_rdm_message_length = -1;
static int hf_rdm_dest_uid = -1;
static int hf_rdm_src_uid = -1;
-static int hf_rdm_seq_nr = -1;
-static int hf_rdm_res_type = -1;
-static int hf_rdm_msg_count = -1;
+static int hf_rdm_transaction_number = -1;
+static int hf_rdm_response_type = -1;
+static int hf_rdm_message_count = -1;
static int hf_rdm_sub_device = -1;
-static int hf_rdm_mdb = -1;
+static int hf_rdm_command_class = -1;
+static int hf_rdm_parameter_id = -1;
+static int hf_rdm_parameter_data_length = -1;
+static int hf_rdm_parameter_data = -1;
+static int hf_rdm_intron = -1;
static int hf_rdm_checksum = -1;
+static int hf_rdm_trailer = -1;

-/* Define the tree for rdm */
static int ett_rdm = -1;

+static guint16 rdm_checksum(tvbuff_t *tvb, unsigned length)
+{
+	guint16 sum = 0;
+	unsigned i;
+	for (i = 0; i < length; i++)
+		sum += tvb_get_guint8(tvb, i);
+	return sum;
+}
+
static void
-dissect_rdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-  gint offset = 0, start_offset,i;
-  guint16 checksum,calc_checksum;
-  gint mdb_size;
-  proto_tree *ti=NULL,*rdm_tree=NULL;
-  proto_item* item;
-
-  /* Set the protocol column */
-  if(check_col(pinfo->cinfo,COL_PROTOCOL)){
-    col_set_str(pinfo->cinfo,COL_PROTOCOL,"RDM");
-  }
-
-  /* Clear out stuff in the info column */
-  if(check_col(pinfo->cinfo,COL_INFO)){
-    col_clear(pinfo->cinfo,COL_INFO);
-  }
-
-  if (tree) {
-    ti = proto_tree_add_item(tree, proto_rdm, tvb, offset, -1, FALSE);
-    rdm_tree = proto_item_add_subtree(ti, ett_rdm);
-  }
-
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
-                    "RDM");
-  }
-
-  if (tree)
-  {
-    start_offset = offset;
-
-    proto_tree_add_item(rdm_tree, hf_rdm_sub_start_code, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+dissect_rdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDM");

-    mdb_size = tvb_get_guint8(tvb, offset) - 19;
+	if (check_col(pinfo->cinfo, COL_INFO))
+		col_set_str(pinfo->cinfo, COL_INFO, "RDM");

-    if (mdb_size < 20) {
-      proto_tree_add_text(rdm_tree, tvb, offset, 1, "Invalid MDB size: %d",
-			mdb_size + 19);
-      return;
-    }
+	if (tree != NULL) {
+		guint8 message_length;
+		guint16 checksum, checksum_shouldbe;
+		unsigned parameter_data_length;
+		proto_item *item;
+		unsigned offset = 0;

-    proto_tree_add_item(rdm_tree, hf_rdm_slot_count, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree *ti = proto_tree_add_item(tree, proto_rdm, tvb,
+				offset, -1, FALSE);
+		proto_tree *rdm_tree = proto_item_add_subtree(ti, ett_rdm);

-    proto_tree_add_item(rdm_tree, hf_rdm_dest_uid, tvb,
-                        offset, 6, FALSE);
-    offset += 6;
+		proto_tree_add_item(rdm_tree, hf_rdm_start_code, tvb,
+				offset, 1, FALSE);
+		offset++;

-    proto_tree_add_item(rdm_tree, hf_rdm_src_uid, tvb,
-                        offset, 6, FALSE);
-    offset += 6;
+		proto_tree_add_item(rdm_tree, hf_rdm_sub_start_code, tvb,
+				offset, 1, FALSE);
+		offset++;

-    proto_tree_add_item(rdm_tree, hf_rdm_seq_nr, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		message_length = tvb_get_guint8(tvb, offset);
+		proto_tree_add_item(rdm_tree, hf_rdm_message_length, tvb,
+				offset, 1, FALSE);
+		offset++;

-    proto_tree_add_item(rdm_tree, hf_rdm_res_type, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree_add_item(rdm_tree, hf_rdm_dest_uid, tvb,
+				offset, 6, FALSE);
+		offset += 6;

-    proto_tree_add_item(rdm_tree, hf_rdm_msg_count, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree_add_item(rdm_tree, hf_rdm_src_uid, tvb,
+				offset, 6, FALSE);
+		offset += 6;

-    proto_tree_add_item(rdm_tree, hf_rdm_sub_device, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree_add_item(rdm_tree, hf_rdm_transaction_number, tvb,
+				offset, 1, FALSE);
+		offset++;

-    tvb_ensure_bytes_exist(tvb, offset, mdb_size);
-    proto_tree_add_item(rdm_tree, hf_rdm_mdb, tvb,
-                        offset, mdb_size, FALSE);
-    offset += mdb_size;
+		proto_tree_add_item(rdm_tree, hf_rdm_response_type, tvb,
+				offset, 1, FALSE);
+		offset++;

-    calc_checksum = 0x00f0;
-    for( i = start_offset; i < offset; i++)
-    {
-      calc_checksum += tvb_get_guint8( tvb, i );
-    }
+		proto_tree_add_item(rdm_tree, hf_rdm_message_count, tvb,
+				offset, 1, FALSE);
+		offset++;

-    checksum = tvb_get_ntohs( tvb, offset );
-    item = proto_tree_add_item(rdm_tree, hf_rdm_checksum, tvb,
-                        offset, 2, FALSE);
+		proto_tree_add_item(rdm_tree, hf_rdm_sub_device, tvb,
+				offset, 2, FALSE);
+		offset += 2;

-    if( calc_checksum != checksum )
-      proto_item_append_text( item, " ( INCORRECT should be 0x%04x
)", calc_checksum );
-    else
-      proto_item_append_text( item, " ( CORRECT )" );
-
-    offset += 2;
-  }
+		proto_tree_add_item(rdm_tree, hf_rdm_command_class, tvb,
+				offset, 1, FALSE);
+		offset++;
+
+		proto_tree_add_item(rdm_tree, hf_rdm_parameter_id, tvb,
+				offset, 2, FALSE);
+		offset += 2;
+
+		parameter_data_length = tvb_get_guint8(tvb, offset);
+		proto_tree_add_item(rdm_tree, hf_rdm_parameter_data_length, tvb,
+				offset, 1, FALSE);
+		offset++;
+
+		if (parameter_data_length > 0) {
+			proto_tree_add_item(rdm_tree, hf_rdm_parameter_data, tvb,
+					offset, parameter_data_length, FALSE);
+			offset += parameter_data_length;
+		}
+
+		if (offset < message_length) {
+			proto_tree_add_item(rdm_tree, hf_rdm_intron, tvb,
+					offset, message_length - offset, FALSE);
+			offset = message_length;
+		}
+
+		checksum_shouldbe = rdm_checksum(tvb, offset);
+		checksum = tvb_get_ntohs(tvb, offset);
+		item = proto_tree_add_item(rdm_tree, hf_rdm_checksum, tvb,
+				offset, 2, FALSE);
+		proto_item_append_text(item, checksum == checksum_shouldbe
+				? " [correct]"
+				: " [incorrect, should be 0x%04x]", checksum_shouldbe);
+		offset += 2;
+
+		if (offset < tvb_length(tvb)) {
+			proto_tree_add_item(rdm_tree, hf_rdm_trailer, tvb,
+					offset, -1, FALSE);
+		}
+	}
}

void
-proto_register_rdm(void) {
-  static hf_register_info hf[] = {
-    { &hf_rdm_sub_start_code,
-      { "Sub Start Code",
-        "rdm.sub_start_code",
-        FT_UINT8, BASE_HEX, NULL, 0x0,
-        "Sub Start Code", HFILL }},
-
-    { &hf_rdm_slot_count,
-      { "Slot Count",
-        "rdm.slot_count",
-        FT_UINT8, BASE_DEC, NULL, 0x0,
-        "Slot Count", HFILL }},
-
-   { &hf_rdm_dest_uid,
-      { "Dest. UID",
-        "rdm.dest_uid",
-        FT_BYTES, BASE_HEX, NULL, 0x0,
-        "Dest. UID", HFILL }},
+proto_register_rdm(void)
+{
+	static hf_register_info hf[] = {
+		{ &hf_rdm_start_code,
+			{ "Start code",
+				"rdm.sc",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},

-   { &hf_rdm_src_uid,
-      { "Source UID",
-        "rdm.src_uid",
-        FT_BYTES, BASE_HEX, NULL, 0x0,
-        "Source UID", HFILL }},
-
-    { &hf_rdm_seq_nr,
-      { "Sequence Number",
-        "rdm.seq_nr",
-        FT_UINT8, BASE_DEC, NULL, 0x0,
-        "Sequence Number", HFILL }},
+		{ &hf_rdm_sub_start_code,
+			{ "Sub-start code",
+				"rdm.ssc",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},

-    { &hf_rdm_res_type,
-      { "Response Type",
-        "rdm.res_type",
-        FT_UINT8, BASE_HEX, NULL, 0x0,
-        "Response Type", HFILL }},
+		{ &hf_rdm_message_length,
+			{ "Message length",
+				"rdm.len",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},

-    { &hf_rdm_msg_count,
-      { "Message Count",
-        "rdm.msg_count",
-        FT_UINT8, BASE_DEC, NULL, 0x0,
-        "Message Count", HFILL }},
+		{ &hf_rdm_dest_uid,
+			{ "Destination UID",
+				"rdm.dst",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},

-    { &hf_rdm_sub_device,
-      { "Sub Device",
-        "rdm.sub_device",
-        FT_UINT8, BASE_HEX, NULL, 0x0,
-        "Sub Device", HFILL }},
-
-   { &hf_rdm_mdb,
-      { "MDB",
-        "rdm.mdb",
-        FT_BYTES, BASE_HEX, NULL, 0x0,
-        "MDB", HFILL }},
+		{ &hf_rdm_src_uid,
+			{ "Source UID",
+				"rdm.src",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},

-    { &hf_rdm_checksum,
-      { "Checksum",
-        "rdm.checksum",
-        FT_UINT16, BASE_HEX, NULL, 0x0,
-        "Checksum", HFILL }}
-  };
+		{ &hf_rdm_transaction_number,
+			{ "Transaction number",
+				"rdm.tn",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},

-  static gint *ett[] = {
-    &ett_rdm,
-  };
+		{ &hf_rdm_response_type,
+			{ "Response type",
+				"rdm.rt",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},

-  proto_rdm = proto_register_protocol("RDM","RDM","rdm");
+		{ &hf_rdm_message_count,
+			{ "Message count",
+				"rdm.mc",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},

-  proto_register_field_array(proto_rdm,hf,array_length(hf));
-  proto_register_subtree_array(ett,array_length(ett));
+		{ &hf_rdm_sub_device,
+			{ "Sub-device",
+				"rdm.sd",
+				FT_UINT16, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},

-  register_dissector("rdm", dissect_rdm, proto_rdm);
+		{ &hf_rdm_command_class,
+			{ "Command class",
+				"rdm.cc",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_parameter_id,
+			{ "Parameter ID",
+				"rdm.pid",
+				FT_UINT16, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_parameter_data_length,
+			{ "Parameter data length",
+				"rdm.pdl",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_parameter_data,
+			{ "Parameter data",
+				"rdm.pd",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_intron,
+			{ "Intron",
+				"rdm.intron",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_checksum,
+			{ "Checksum",
+				"rdm.checksum",
+				FT_UINT16, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_trailer,
+			{ "Trailer",
+				"rdm.trailer",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+	};
+
+	static gint *ett[] = {
+		&ett_rdm,
+	};
+
+	proto_rdm = proto_register_protocol("RDM", "RDM", "rdm");
+
+	proto_register_field_array(proto_rdm, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
+
+	register_dissector("rdm", dissect_rdm, proto_rdm);
}

-/* The registration hand-off routing */
+void
+proto_reg_handoff_rdm(void)
+{
+	static int rdm_initialized = FALSE;
+	static dissector_handle_t rdm_handle;

-void
-proto_reg_handoff_rdm(void) {
-  static int rdm_initialized = FALSE;
-  static dissector_handle_t rdm_handle;
-
-  if(!rdm_initialized) {
-    rdm_handle = create_dissector_handle(dissect_rdm,proto_rdm);
-    rdm_initialized = TRUE;
-  } else {
-    dissector_delete("udp.port",0,rdm_handle);
-  }
-
-  dissector_add("udp.port",0,rdm_handle);
+	if (!rdm_initialized) {
+		rdm_handle = create_dissector_handle(dissect_rdm, proto_rdm);
+		rdm_initialized = TRUE;
+	}
}
2006-09-30  Shaun Jackman  <sjackman@xxxxxxxxx>

	* plugins/rdm/moduleinfo.h (VERSION): Bump to 0.1.0.
	* plugins/rdm/packet-rdm.c: Update to the ANSI E1.20-2006 spec.

Index: plugins/rdm/moduleinfo.h
===================================================================
--- plugins/rdm/moduleinfo.h	(revision 19385)
+++ plugins/rdm/moduleinfo.h	(working copy)
@@ -13,5 +13,5 @@
 #endif
 
 /* Version number of package */
-#define VERSION "0.0.1"
+#define VERSION "0.1.0"
 
Index: plugins/rdm/packet-rdm.c
===================================================================
--- plugins/rdm/packet-rdm.c	(revision 19385)
+++ plugins/rdm/packet-rdm.c	(working copy)
@@ -1,14 +1,25 @@
-/* packet-rdm.c
- * Routines for RDM packet disassembly
+/* RDM (Remote Devcie Management) packet disassembly.
  *
+ * ANSI E1.20-2006, Entertainment Technology
+ * Remote Device Management over USITT DMX512, describes a method of
+ * bi-directional communications over a USITT DMX512/1990 data link
+ * between an entertainment lighting controller and one or more
+ * remotely controlled lighting devices. The protocol also is intended
+ * to work with the ANSI E1.11-2004 control protocol. It allows
+ * discovery of devices on a DMX512/E1.11 network and the remote
+ * setting of DMX starting addresses, as well as status and fault
+ * reporting back to the control console.
+ *
  * $Id$
  *
- * Copyright (c) 2003 by Erwin Rol <erwin@xxxxxxxxxxxx>
+ * Written by
  *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@xxxxxxxxxxxxx>
- * Copyright 1999 Gerald Combs
+ *  Shaun Jackman <sjackman@xxxxxxxxx>
+ *  Copyright 2006 Pathway Connectivity
  *
+ *  Erwin Rol <erwin@xxxxxxxxxxxx>
+ *  Copyright 2003 Erwin Rol
+ *
  * 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
@@ -18,16 +29,10 @@
  * 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.
  */
 
-/* Include files */
-
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
 #endif
 
 #include <stdio.h>
@@ -42,216 +47,255 @@
 #include <epan/etypes.h>
 #include <epan/strutil.h>
 
-/*
- * See http://www.esta.org/tsp/E1-20inst.htm
- *
- */
-
-void proto_reg_handoff_rdm(void);
-
-/* Define the rdm proto */
 static int proto_rdm = -1;
 
-/* Header */
+static int hf_rdm_start_code = -1;
 static int hf_rdm_sub_start_code = -1;
-static int hf_rdm_slot_count = -1;
+static int hf_rdm_message_length = -1;
 static int hf_rdm_dest_uid = -1;
 static int hf_rdm_src_uid = -1;
-static int hf_rdm_seq_nr = -1;
-static int hf_rdm_res_type = -1;
-static int hf_rdm_msg_count = -1;
+static int hf_rdm_transaction_number = -1;
+static int hf_rdm_response_type = -1;
+static int hf_rdm_message_count = -1;
 static int hf_rdm_sub_device = -1;
-static int hf_rdm_mdb = -1;
+static int hf_rdm_command_class = -1;
+static int hf_rdm_parameter_id = -1;
+static int hf_rdm_parameter_data_length = -1;
+static int hf_rdm_parameter_data = -1;
+static int hf_rdm_intron = -1;
 static int hf_rdm_checksum = -1;
+static int hf_rdm_trailer = -1;
 
-/* Define the tree for rdm */
 static int ett_rdm = -1;
 
+static guint16 rdm_checksum(tvbuff_t *tvb, unsigned length)
+{
+	guint16 sum = 0;
+	unsigned i;
+	for (i = 0; i < length; i++)
+		sum += tvb_get_guint8(tvb, i);
+	return sum;
+}
+
 static void
-dissect_rdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-  gint offset = 0, start_offset,i;
-  guint16 checksum,calc_checksum;
-  gint mdb_size;
-  proto_tree *ti=NULL,*rdm_tree=NULL;
-  proto_item* item;
-  
-  /* Set the protocol column */
-  if(check_col(pinfo->cinfo,COL_PROTOCOL)){
-    col_set_str(pinfo->cinfo,COL_PROTOCOL,"RDM");
-  }
-                                                                                                                                                                                                     
-  /* Clear out stuff in the info column */
-  if(check_col(pinfo->cinfo,COL_INFO)){
-    col_clear(pinfo->cinfo,COL_INFO);
-  }
-                                                                                                                                                                                                     
-  if (tree) {
-    ti = proto_tree_add_item(tree, proto_rdm, tvb, offset, -1, FALSE);
-    rdm_tree = proto_item_add_subtree(ti, ett_rdm);
-  }
-                                                                                                                                                                                                     
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
-                    "RDM");
-  }
-                                                                                                                                                                                                     
-  if (tree)
-  {
-    start_offset = offset;
-  
-    proto_tree_add_item(rdm_tree, hf_rdm_sub_start_code, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+dissect_rdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDM");
 
-    mdb_size = tvb_get_guint8(tvb, offset) - 19;
+	if (check_col(pinfo->cinfo, COL_INFO))
+		col_set_str(pinfo->cinfo, COL_INFO, "RDM");
 
-    if (mdb_size < 20) {
-      proto_tree_add_text(rdm_tree, tvb, offset, 1, "Invalid MDB size: %d", 
-			mdb_size + 19);
-      return;
-    }
+	if (tree != NULL) {
+		guint8 message_length;
+		guint16 checksum, checksum_shouldbe;
+		unsigned parameter_data_length;
+		proto_item *item;
+		unsigned offset = 0;
 
-    proto_tree_add_item(rdm_tree, hf_rdm_slot_count, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree *ti = proto_tree_add_item(tree, proto_rdm, tvb,
+				offset, -1, FALSE);
+		proto_tree *rdm_tree = proto_item_add_subtree(ti, ett_rdm);
 
-    proto_tree_add_item(rdm_tree, hf_rdm_dest_uid, tvb,
-                        offset, 6, FALSE);
-    offset += 6;
+		proto_tree_add_item(rdm_tree, hf_rdm_start_code, tvb,
+				offset, 1, FALSE);
+		offset++;
 
-    proto_tree_add_item(rdm_tree, hf_rdm_src_uid, tvb,
-                        offset, 6, FALSE);
-    offset += 6;
+		proto_tree_add_item(rdm_tree, hf_rdm_sub_start_code, tvb,
+				offset, 1, FALSE);
+		offset++;
 
-    proto_tree_add_item(rdm_tree, hf_rdm_seq_nr, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		message_length = tvb_get_guint8(tvb, offset);
+		proto_tree_add_item(rdm_tree, hf_rdm_message_length, tvb,
+				offset, 1, FALSE);
+		offset++;
 
-    proto_tree_add_item(rdm_tree, hf_rdm_res_type, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree_add_item(rdm_tree, hf_rdm_dest_uid, tvb,
+				offset, 6, FALSE);
+		offset += 6;
 
-    proto_tree_add_item(rdm_tree, hf_rdm_msg_count, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree_add_item(rdm_tree, hf_rdm_src_uid, tvb,
+				offset, 6, FALSE);
+		offset += 6;
 
-    proto_tree_add_item(rdm_tree, hf_rdm_sub_device, tvb,
-                        offset, 1, FALSE);
-    offset += 1;
+		proto_tree_add_item(rdm_tree, hf_rdm_transaction_number, tvb,
+				offset, 1, FALSE);
+		offset++;
 
-    tvb_ensure_bytes_exist(tvb, offset, mdb_size);
-    proto_tree_add_item(rdm_tree, hf_rdm_mdb, tvb,
-                        offset, mdb_size, FALSE);
-    offset += mdb_size;
+		proto_tree_add_item(rdm_tree, hf_rdm_response_type, tvb,
+				offset, 1, FALSE);
+		offset++;
 
-    calc_checksum = 0x00f0;
-    for( i = start_offset; i < offset; i++)
-    {
-      calc_checksum += tvb_get_guint8( tvb, i );    
-    }
+		proto_tree_add_item(rdm_tree, hf_rdm_message_count, tvb,
+				offset, 1, FALSE);
+		offset++;
 
-    checksum = tvb_get_ntohs( tvb, offset );
-    item = proto_tree_add_item(rdm_tree, hf_rdm_checksum, tvb,
-                        offset, 2, FALSE);
+		proto_tree_add_item(rdm_tree, hf_rdm_sub_device, tvb,
+				offset, 2, FALSE);
+		offset += 2;
 
-    if( calc_checksum != checksum )
-      proto_item_append_text( item, " ( INCORRECT should be 0x%04x )", calc_checksum );
-    else
-      proto_item_append_text( item, " ( CORRECT )" );
-  
-    offset += 2;
-  }
+		proto_tree_add_item(rdm_tree, hf_rdm_command_class, tvb,
+				offset, 1, FALSE);
+		offset++;
+
+		proto_tree_add_item(rdm_tree, hf_rdm_parameter_id, tvb,
+				offset, 2, FALSE);
+		offset += 2;
+
+		parameter_data_length = tvb_get_guint8(tvb, offset);
+		proto_tree_add_item(rdm_tree, hf_rdm_parameter_data_length, tvb,
+				offset, 1, FALSE);
+		offset++;
+
+		if (parameter_data_length > 0) {
+			proto_tree_add_item(rdm_tree, hf_rdm_parameter_data, tvb,
+					offset, parameter_data_length, FALSE);
+			offset += parameter_data_length;
+		}
+
+		if (offset < message_length) {
+			proto_tree_add_item(rdm_tree, hf_rdm_intron, tvb,
+					offset, message_length - offset, FALSE);
+			offset = message_length;
+		}
+
+		checksum_shouldbe = rdm_checksum(tvb, offset);
+		checksum = tvb_get_ntohs(tvb, offset);
+		item = proto_tree_add_item(rdm_tree, hf_rdm_checksum, tvb,
+				offset, 2, FALSE);
+		proto_item_append_text(item, checksum == checksum_shouldbe
+				? " [correct]"
+				: " [incorrect, should be 0x%04x]", checksum_shouldbe);
+		offset += 2;
+
+		if (offset < tvb_length(tvb)) {
+			proto_tree_add_item(rdm_tree, hf_rdm_trailer, tvb,
+					offset, -1, FALSE);
+		}
+	}
 }
 
 void
-proto_register_rdm(void) {
-  static hf_register_info hf[] = {
-    { &hf_rdm_sub_start_code,
-      { "Sub Start Code",
-        "rdm.sub_start_code",
-        FT_UINT8, BASE_HEX, NULL, 0x0,
-        "Sub Start Code", HFILL }},
-        
-    { &hf_rdm_slot_count,
-      { "Slot Count",
-        "rdm.slot_count",
-        FT_UINT8, BASE_DEC, NULL, 0x0,
-        "Slot Count", HFILL }},
-        
-   { &hf_rdm_dest_uid,
-      { "Dest. UID",
-        "rdm.dest_uid",
-        FT_BYTES, BASE_HEX, NULL, 0x0,
-        "Dest. UID", HFILL }},        
+proto_register_rdm(void)
+{
+	static hf_register_info hf[] = {
+		{ &hf_rdm_start_code,
+			{ "Start code",
+				"rdm.sc",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
 
-   { &hf_rdm_src_uid,
-      { "Source UID",
-        "rdm.src_uid",
-        FT_BYTES, BASE_HEX, NULL, 0x0,
-        "Source UID", HFILL }}, 
-        
-    { &hf_rdm_seq_nr,
-      { "Sequence Number",
-        "rdm.seq_nr",
-        FT_UINT8, BASE_DEC, NULL, 0x0,
-        "Sequence Number", HFILL }},
+		{ &hf_rdm_sub_start_code,
+			{ "Sub-start code",
+				"rdm.ssc",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
 
-    { &hf_rdm_res_type,
-      { "Response Type",
-        "rdm.res_type",
-        FT_UINT8, BASE_HEX, NULL, 0x0,
-        "Response Type", HFILL }},
+		{ &hf_rdm_message_length,
+			{ "Message length",
+				"rdm.len",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},
 
-    { &hf_rdm_msg_count,
-      { "Message Count",
-        "rdm.msg_count",
-        FT_UINT8, BASE_DEC, NULL, 0x0,
-        "Message Count", HFILL }},
+		{ &hf_rdm_dest_uid,
+			{ "Destination UID",
+				"rdm.dst",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
 
-    { &hf_rdm_sub_device,
-      { "Sub Device",
-        "rdm.sub_device",
-        FT_UINT8, BASE_HEX, NULL, 0x0,
-        "Sub Device", HFILL }},
-        
-   { &hf_rdm_mdb,
-      { "MDB",
-        "rdm.mdb",
-        FT_BYTES, BASE_HEX, NULL, 0x0,
-        "MDB", HFILL }}, 
+		{ &hf_rdm_src_uid,
+			{ "Source UID",
+				"rdm.src",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
 
-    { &hf_rdm_checksum,
-      { "Checksum",
-        "rdm.checksum",
-        FT_UINT16, BASE_HEX, NULL, 0x0,
-        "Checksum", HFILL }}
-  };
+		{ &hf_rdm_transaction_number,
+			{ "Transaction number",
+				"rdm.tn",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},
 
-  static gint *ett[] = {
-    &ett_rdm,
-  };
+		{ &hf_rdm_response_type,
+			{ "Response type",
+				"rdm.rt",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
 
-  proto_rdm = proto_register_protocol("RDM","RDM","rdm");
+		{ &hf_rdm_message_count,
+			{ "Message count",
+				"rdm.mc",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},
 
-  proto_register_field_array(proto_rdm,hf,array_length(hf));
-  proto_register_subtree_array(ett,array_length(ett));
+		{ &hf_rdm_sub_device,
+			{ "Sub-device",
+				"rdm.sd",
+				FT_UINT16, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},
 
-  register_dissector("rdm", dissect_rdm, proto_rdm);
+		{ &hf_rdm_command_class,
+			{ "Command class",
+				"rdm.cc",
+				FT_UINT8, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_parameter_id,
+			{ "Parameter ID",
+				"rdm.pid",
+				FT_UINT16, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_parameter_data_length,
+			{ "Parameter data length",
+				"rdm.pdl",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_parameter_data,
+			{ "Parameter data",
+				"rdm.pd",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_intron,
+			{ "Intron",
+				"rdm.intron",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_checksum,
+			{ "Checksum",
+				"rdm.checksum",
+				FT_UINT16, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+
+		{ &hf_rdm_trailer,
+			{ "Trailer",
+				"rdm.trailer",
+				FT_BYTES, BASE_HEX, NULL, 0x0,
+				NULL, HFILL }},
+	};
+
+	static gint *ett[] = {
+		&ett_rdm,
+	};
+
+	proto_rdm = proto_register_protocol("RDM", "RDM", "rdm");
+
+	proto_register_field_array(proto_rdm, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
+
+	register_dissector("rdm", dissect_rdm, proto_rdm);
 }
 
-/* The registration hand-off routing */
+void
+proto_reg_handoff_rdm(void)
+{
+	static int rdm_initialized = FALSE;
+	static dissector_handle_t rdm_handle;
 
-void
-proto_reg_handoff_rdm(void) {
-  static int rdm_initialized = FALSE;
-  static dissector_handle_t rdm_handle;
-     
-  if(!rdm_initialized) {
-    rdm_handle = create_dissector_handle(dissect_rdm,proto_rdm);
-    rdm_initialized = TRUE;
-  } else {
-    dissector_delete("udp.port",0,rdm_handle);
-  }
-                           
-  dissector_add("udp.port",0,rdm_handle);
+	if (!rdm_initialized) {
+		rdm_handle = create_dissector_handle(dissect_rdm, proto_rdm);
+		rdm_initialized = TRUE;
+	}
 }