localtime() can return a NULL ptr.
[obnox/wireshark/wip.git] / plugins / gryphon / packet-gryphon.c
index 0c9fb493ba50edb0020677ffd1b964c112814987..63bf50d617534a25f2b98b9aa2bc99048a4a4814 100644 (file)
@@ -1,67 +1,53 @@
 /* packet-gryphon.c
  * Routines for Gryphon protocol packet disassembly
- *
- * $Id: packet-gryphon.c,v 1.19 2001/01/09 06:32:08 guy Exp $
- *
- * Ethereal - Network traffic analyzer
  * By Steve Limkemann <stevelim@dgtech.com>
  * Copyright 1998 Steve Limkemann
  *
- * 
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 "plugins/plugin_api.h"
-
-#include "moduleinfo.h"
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#include <gmodule.h>
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#include "packet.h"
+#include <glib.h>
+#include <epan/packet.h>
 #include "packet-gryphon.h"
+#include <epan/dissectors/packet-tcp.h>
+#include <epan/prefs.h>
 
-G_MODULE_EXPORT const gchar version[] = VERSION;
-
-#ifndef G_HAVE_GINT64
-#error "Sorry, this won't compile without 64-bit integer support"
-#endif                                                                  
+/*
+ * See
+ *
+ *     http://www.dgtech.com/gryphon/sys/www/docs/html/
+ */
 
 static int proto_gryphon = -1;
 
-static int hf_gryph_src = -1;
-static int hf_gryph_srcchan = -1;
-static int hf_gryph_dest = -1;
-static int hf_gryph_destchan= -1;
-static int hf_gryph_type = -1;
-static int hf_gryph_cmd = -1;
+static int hf_gryphon_src = -1;
+static int hf_gryphon_srcchan = -1;
+static int hf_gryphon_dest = -1;
+static int hf_gryphon_destchan= -1;
+static int hf_gryphon_type = -1;
+static int hf_gryphon_cmd = -1;
 
 static gint ett_gryphon = -1;
 static gint ett_gryphon_header = -1;
@@ -80,189 +66,291 @@ static gint ett_gryphon_cmd_response_block = -1;
 static gint ett_gryphon_pgm_list = -1;
 static gint ett_gryphon_pgm_status = -1;
 static gint ett_gryphon_pgm_options = -1;
+static gint ett_gryphon_valid_headers = -1;
+static gint ett_gryphon_usdt_data = -1;
+static gint ett_gryphon_digital_data = -1;
+
+/* desegmentation of Gryphon */
+static gboolean gryphon_desegment = TRUE;
+
+static void dissect_gryphon_message(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *tree, gboolean is_msgresp_add);
+static int decode_command(tvbuff_t*, int, int, proto_tree*);
+static int decode_response(tvbuff_t*, int, int, proto_tree*);
+static int decode_data(tvbuff_t*, int, proto_tree*);
+static int decode_event(tvbuff_t*, int, proto_tree*);
+static int decode_misc(tvbuff_t*, int, proto_tree*);
+static int cmd_init(tvbuff_t*, int, proto_tree*);
+static int resp_time(tvbuff_t*, int, proto_tree*);
+static int cmd_setfilt(tvbuff_t*, int, proto_tree*);
+static int cmd_ioctl(tvbuff_t*, int, proto_tree*);
+static int cmd_addfilt(tvbuff_t*, int, proto_tree*);
+static int resp_addfilt(tvbuff_t*, int, proto_tree*);
+static int cmd_modfilt(tvbuff_t*, int, proto_tree*);
+static int resp_filthan(tvbuff_t*, int, proto_tree*);
+static int dfiltmode(tvbuff_t*, int, proto_tree*);
+static int filtmode(tvbuff_t*, int, proto_tree*);
+static int resp_events(tvbuff_t*, int, proto_tree*);
+static int cmd_register(tvbuff_t*, int, proto_tree*);
+static int resp_register(tvbuff_t*, int, proto_tree*);
+static int resp_getspeeds(tvbuff_t*, int, proto_tree*);
+static int cmd_sort(tvbuff_t*, int, proto_tree*);
+static int cmd_optimize(tvbuff_t*, int, proto_tree*);
+static int resp_config(tvbuff_t*, int, proto_tree*);
+static int cmd_sched(tvbuff_t*, int, proto_tree*);
+static int cmd_sched_rep(tvbuff_t*, int, proto_tree*);
+static int resp_blm_data(tvbuff_t*, int, proto_tree*);
+static int resp_blm_stat(tvbuff_t*, int, proto_tree*);
+static int cmd_addresp(tvbuff_t*, int, proto_tree*);
+static int resp_addresp(tvbuff_t*, int, proto_tree*);
+static int cmd_modresp(tvbuff_t*, int, proto_tree*);
+static int resp_resphan(tvbuff_t*, int, proto_tree*);
+static int resp_sched(tvbuff_t*, int, proto_tree*);
+static int cmd_desc(tvbuff_t*, int, proto_tree*);
+static int resp_desc(tvbuff_t*, int, proto_tree*);
+static int cmd_upload(tvbuff_t*, int, proto_tree*);
+static int cmd_delete(tvbuff_t*, int, proto_tree*);
+static int cmd_list(tvbuff_t*, int, proto_tree*);
+static int resp_list(tvbuff_t*, int, proto_tree*);
+static int cmd_start(tvbuff_t*, int, proto_tree*);
+static int resp_start(tvbuff_t*, int, proto_tree*);
+static int resp_status(tvbuff_t*, int, proto_tree*);
+static int cmd_options(tvbuff_t*, int, proto_tree*);
+static int cmd_files(tvbuff_t*, int, proto_tree*);
+static int resp_files(tvbuff_t*, int, proto_tree*);
+static int eventnum(tvbuff_t*, int, proto_tree*);
+static int speed(tvbuff_t*, int, proto_tree*);
+static int filter_block(tvbuff_t*, int, proto_tree*);
+static int blm_mode(tvbuff_t*, int, proto_tree*);
+static int cmd_usdt(tvbuff_t*, int, proto_tree*);
+static int cmd_bits_in(tvbuff_t*, int, proto_tree*);
+static int cmd_bits_out(tvbuff_t*, int, proto_tree*);
+static int cmd_init_strat(tvbuff_t*, int, proto_tree*);
+
+static const char *frame_type[] = {
+       "",
+       "Command request",
+       "Command response",
+       "Network (vehicle) data",
+       "Event",
+       "Miscellaneous",
+       "Text string"
+};
+
+/*
+ * Length of the frame header.
+ */
+#define FRAME_HEADER_LEN       8
 
+static guint
+get_gryphon_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
+{
+    guint16 plen;
+    int padded_len;
+
+    /*
+     * Get the length of the Gryphon packet, and then get the length as
+     * padded to a 4-byte boundary.
+     */
+    plen = tvb_get_ntohs(tvb, offset + 4);
+    padded_len = plen + 3 - (plen + 3) % 4;
+
+    /*
+     * That length doesn't include the fixed-length part of the header;
+     * add that in.
+     */
+    return padded_len + FRAME_HEADER_LEN;
+}
 
+static void
+dissect_gryphon_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    dissect_gryphon_message(tvb, pinfo, tree, FALSE);
+}
 
 static void
-dissect_gryphon(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+dissect_gryphon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
+    tcp_dissect_pdus(tvb, pinfo, tree, gryphon_desegment, FRAME_HEADER_LEN,
+       get_gryphon_pdu_len, dissect_gryphon_pdu);
+}
 
-    proto_tree     *gryphon_tree, *header_tree, *body_tree, *localTree;
-    proto_item     *ti, *header_item, *body_item, *localItem;
-    const u_char    *data, *dataend, *msgend;
-    int                    src, msglen, msgpad, dest, frmtyp, i, end_of_frame;
-    static const u_char *frame_type[] = {"",
-                                        "Command request",
-                                        "Command response",
-                                        "Network (vehicle) data",
-                                        "Event",
-                                        "Miscelaneous",
-                                        "Text string"};
-    static const value_string src_dest[] = {
-           {SD_CARD,           "Card"},
-           {SD_SERVER,         "Server"},
-           {SD_CLIENT,         "Client"},
-           {SD_SCHED,          "Scheduler"},
-           {SD_SCRIPT,         "Script Processor"},
-           {SD_PGM,            "Program Loader"},
-           {SD_USDT,           "USDT Server"},
-           {SD_BLM,            "Bus Load Monitoring"},
-           {SD_FLIGHT,         "Flight Recorder"},
-           {SD_RESP,           "Message Responder"},
-           {-1,                "- unknown -"},
-           };                         
-
-    OLD_CHECK_DISPLAY_AS_DATA(proto_gryphon, pd, offset, fd, tree);
-
-    data = &pd[offset];
-    if (fd) {
-        end_of_frame = END_OF_FRAME;
-    }
-    else {
-       end_of_frame = pntohs (data + 4) + 8;
-       end_of_frame += 3 - (end_of_frame + 3 ) % 4;
+static const value_string src_dest[] = {
+    {SD_CARD,          "Card"},
+    {SD_SERVER,        "Server"},
+    {SD_CLIENT,                "Client"},
+    {SD_SCHED,         "Scheduler"},
+    {SD_SCRIPT,                "Script Processor"},
+    {SD_PGM,           "Program Loader"},
+    {SD_USDT,          "USDT Server"},
+    {SD_BLM,           "Bus Load Monitoring"},
+    {SD_FLIGHT,        "Flight Recorder"},
+    {SD_RESP,          "Message Responder"},
+    {SD_IOPWR,          "I/O and power"},
+    {SD_UTIL,           "Utility/Miscellaneous"},
+    {0,                        NULL}
+};
+
+static void
+dissect_gryphon_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    gboolean is_msgresp_add)
+{
+    int                    offset = 0;
+    proto_tree     *gryphon_tree;
+    proto_item     *ti;
+    proto_tree     *header_tree, *body_tree, *localTree;
+    proto_item     *header_item, *body_item, *localItem, *hiddenItem;
+    int                    start_offset, msgend;
+    int                    msglen, msgpad;
+    unsigned int    src, dest, i, frmtyp;
+    guint8         flags;
+
+    if (!is_msgresp_add) {
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gryphon");
+       col_clear(pinfo->cinfo, COL_INFO);
     }
-    dataend = data + end_of_frame;
 
-    if (fd && check_col(fd, COL_PROTOCOL))
-       col_add_str(fd, COL_PROTOCOL, "Gryphon");
+    if (!is_msgresp_add) {
+       ti = proto_tree_add_item(tree, proto_gryphon, tvb, 0, -1, FALSE);
+       gryphon_tree = proto_item_add_subtree(ti, ett_gryphon);
+    } else
+       gryphon_tree = tree;
+
+    src = tvb_get_guint8(tvb, offset + 0);
+    dest = tvb_get_guint8(tvb, offset + 2);
+    msglen = tvb_get_ntohs(tvb, offset + 4);
+    flags = tvb_get_guint8(tvb, offset + 6);
+    frmtyp = flags & ~RESPONSE_FLAGS;
+
+    if (!is_msgresp_add) {
+               /*
+                * This tvbuff includes padding to make its length a multiple
+                * of 4 bytes; set it to the actual length.
+                */
+               set_actual_length(tvb, msglen + FRAME_HEADER_LEN);
+
+           /*
+            * Indicate what kind of message this is.
+            */
+           if (frmtyp >= SIZEOF (frame_type))
+                       col_set_str(pinfo->cinfo, COL_INFO, "- Invalid -");
+           else
+                       col_set_str(pinfo->cinfo, COL_INFO, frame_type[frmtyp]);
+    }
 
-    if (END_OF_FRAME < 8)
+    if (tree == NULL)
        return;
 
-    if (fd && check_col(fd, COL_INFO)) {
+    if (frmtyp >= SIZEOF (frame_type)) {
        /*
-        * Indicate what kind of message this is.
+        * Unknown message type.
         */
-       frmtyp = data[6] & ~RESPONSE_FLAGS;
-       if (frmtyp >= SIZEOF (frame_type))
-           col_add_str (fd, COL_INFO, "- Invalid -");
-       else
-           col_add_str (fd, COL_INFO, frame_type[frmtyp]);
+       proto_tree_add_text(gryphon_tree, tvb, offset, msglen, "Data");
+       return;
     }
-    if (tree) {
-       if (fd) {
-           ti = proto_tree_add_item(tree, proto_gryphon, NullTVB, offset,
-                   end_of_frame, FALSE);
-           gryphon_tree = proto_item_add_subtree(ti, ett_gryphon);
-       } else
-           gryphon_tree = tree;
-
-       while (data < dataend) {
-           src = data[0];
-           dest = data[2];
-           frmtyp = data[6] & ~RESPONSE_FLAGS;
-           if (frmtyp >= SIZEOF (frame_type)) {
-               i = dataend - data;
-               proto_tree_add_text(gryphon_tree, NullTVB, offset, i, "Data");
-               BUMP (offset, data, i);
-               continue;
-           }
-           msglen = pntohs ((unsigned short *)&data[4]);
-
-           header_item = proto_tree_add_text(gryphon_tree, NullTVB, offset,
-                   MSG_HDR_SZ, "Header");
-           header_tree = proto_item_add_subtree(header_item,
-                   ett_gryphon_header);
-           for (i = 0; i < SIZEOF(src_dest); i++) {
-               if (src_dest[i].value == src)
-                   break;
-           }
-           if (i >= SIZEOF(src_dest))
-               i = SIZEOF(src_dest) - 1;
-           proto_tree_add_text(header_tree, NullTVB, offset, 2,
-                   "Source: %s, channel %hd", src_dest[i].strptr, data[1]);
-           proto_tree_add_uint_hidden(header_tree, hf_gryph_src, NullTVB, offset, 1, src);
-           proto_tree_add_uint_hidden(header_tree, hf_gryph_srcchan, NullTVB, offset+1, 1, data[1]);
-
-           for (i = 0; i < SIZEOF(src_dest); i++) {
-               if (src_dest[i].value == dest)
-                   break;
-           }
-           if (i >= SIZEOF(src_dest))
-               i = SIZEOF(src_dest) - 1;
-           proto_tree_add_text(header_tree, NullTVB, offset+2, 2,
-                   "Destination: %s, channel %hd", src_dest[i].strptr, data[3]);
-           proto_tree_add_uint_hidden(header_tree, hf_gryph_dest, NullTVB, offset+2, 1, dest);
-           proto_tree_add_uint_hidden(header_tree, hf_gryph_destchan, NullTVB, offset+3, 1, data[3]);
-
-           proto_tree_add_text(header_tree, NullTVB, offset+4, 2,
-                   "Data length: %d bytes", msglen);
-           proto_tree_add_text(header_tree, NullTVB, offset+6, 1,
-                   "Frame type: %s", frame_type[frmtyp]);
-           if (!fd) {
-               localItem = proto_tree_add_text(header_tree, NullTVB, offset+6, 1, "Flags");
-               localTree = proto_item_add_subtree (localItem, ett_gryphon_flags);
-               if (data[6] & DONT_WAIT_FOR_RESP) {
-                   proto_tree_add_text(localTree, NullTVB, offset+6, 1,
-                           "1... .... = Don't wait for response");
-               } else {
-                   proto_tree_add_text(localTree, NullTVB, offset+6, 1,
-                           "0... .... = Wait for response");
-               }
-               if (data[6] & WAIT_FOR_PREV_RESP) {
-                   proto_tree_add_text(localTree, NullTVB, offset+6, 1,
-                           ".1.. .... = Wait for previous responses");
-               } else {
-                   proto_tree_add_text(localTree, NullTVB, offset+6, 1,
-                           ".0.. .... = Don't wait for previous responses");
-               }
-           }
-           proto_tree_add_text(header_tree, NullTVB, offset+7, 1, "reserved");
-
-           proto_tree_add_uint_hidden(header_tree, hf_gryph_type, NullTVB, offset+6, 1, frmtyp);
-           msgpad = 3 - (msglen + 3) % 4;
-           msgend = data + msglen + msgpad + MSG_HDR_SZ;
-
-           body_item = proto_tree_add_text(gryphon_tree, NullTVB, offset + MSG_HDR_SZ,
-                   msglen + msgpad, "Body");
-           body_tree = proto_item_add_subtree(body_item, ett_gryphon_body);
 
-           offset += MSG_HDR_SZ;
-           data += MSG_HDR_SZ;
-           switch (frmtyp) {
-           case GY_FT_CMD:
-               decode_command (dest, &data, dataend, &offset, msglen, body_tree);
-               break;
-           case GY_FT_RESP:
-               decode_response (src, &data, dataend, &offset, msglen, body_tree);
-               break;
-           case GY_FT_DATA:
-               decode_data (src, &data, dataend, &offset, msglen, body_tree);
-               break;
-           case GY_FT_EVENT:
-               decode_event (src, &data, dataend, &offset, msglen, body_tree);
-               break;
-           case GY_FT_MISC:
-               break;
-           case GY_FT_TEXT:
-               break;
-           default:
-               break;
-           }
-           if (data < msgend - msgpad) {
-               i = msgend - msgpad - data;
-               proto_tree_add_text(gryphon_tree, NullTVB, offset, i, "Data");
-               BUMP (offset, data, i);
-           }
-           if (data < msgend) {
-               i = msgend - data;
-               proto_tree_add_text(gryphon_tree, NullTVB, offset, i, "padding");
-               BUMP (offset, data, i);
-           }
-       }
-
-   }
+    header_item = proto_tree_add_text(gryphon_tree, tvb, offset, MSG_HDR_SZ, "Header");
+    header_tree = proto_item_add_subtree(header_item, ett_gryphon_header);
+    proto_tree_add_text(header_tree, tvb, offset, 2,
+       "Source: %s, channel %u",
+       val_to_str(src, src_dest, "Unknown (0x%02x)"),
+       tvb_get_guint8(tvb, offset + 1));
+
+       hiddenItem = proto_tree_add_uint(header_tree, hf_gryphon_src, tvb,
+       offset, 1, src);
+       PROTO_ITEM_SET_HIDDEN(hiddenItem);
+
+       hiddenItem = proto_tree_add_uint(header_tree, hf_gryphon_srcchan, tvb,
+       offset+1, 1, tvb_get_guint8(tvb, offset + 1));
+       PROTO_ITEM_SET_HIDDEN(hiddenItem);
+
+    proto_tree_add_text(header_tree, tvb, offset+2, 2,
+       "Destination: %s, channel %u",
+       val_to_str(dest, src_dest, "Unknown (0x%02x)"),
+       tvb_get_guint8(tvb, offset + 3));
+
+       hiddenItem = proto_tree_add_uint(header_tree, hf_gryphon_dest, tvb,
+       offset+2, 1, dest);
+       PROTO_ITEM_SET_HIDDEN(hiddenItem);
+
+    hiddenItem = proto_tree_add_uint(header_tree, hf_gryphon_destchan, tvb,
+       offset+3, 1, tvb_get_guint8(tvb, offset + 3));
+       PROTO_ITEM_SET_HIDDEN(hiddenItem);
+
+    proto_tree_add_text(header_tree, tvb, offset+4, 2,
+       "Data length: %u byte%s", msglen, msglen == 1 ? "" : "s");
+    proto_tree_add_text(header_tree, tvb, offset+6, 1,
+       "Frame type: %s", frame_type[frmtyp]);
+
+       if (is_msgresp_add) {
+       localItem = proto_tree_add_text(header_tree, tvb, offset+6, 1, "Flags");
+       localTree = proto_item_add_subtree (localItem, ett_gryphon_flags);
+       proto_tree_add_text(localTree, tvb, offset+6, 1, "%s",
+           decode_boolean_bitfield(flags, DONT_WAIT_FOR_RESP, 8,
+               "Don't wait for response",
+               "Wait for response"));
+       proto_tree_add_text(localTree, tvb, offset+6, 1, "%s",
+           decode_boolean_bitfield(flags, WAIT_FOR_PREV_RESP, 8,
+               "Wait for previous responses",
+               "Don't wait for previous responses"));
+    }
+    proto_tree_add_text(header_tree, tvb, offset+7, 1, "reserved");
+
+    hiddenItem = proto_tree_add_uint(header_tree, hf_gryphon_type, tvb,
+       offset+6, 1, frmtyp);
+       PROTO_ITEM_SET_HIDDEN(hiddenItem);
+
+    msgpad = 3 - (msglen + 3) % 4;
+    msgend = offset + msglen + msgpad + MSG_HDR_SZ;
+
+    body_item = proto_tree_add_text(gryphon_tree, tvb, offset + MSG_HDR_SZ,
+       msglen + msgpad, "Body");
+    body_tree = proto_item_add_subtree(body_item, ett_gryphon_body);
+
+    start_offset = offset;
+    offset += MSG_HDR_SZ;
+    switch (frmtyp) {
+    case GY_FT_CMD:
+       offset = decode_command(tvb, offset, dest, body_tree);
+       break;
+    case GY_FT_RESP:
+       offset = decode_response(tvb, offset, src, body_tree);
+       break;
+    case GY_FT_DATA:
+       offset = decode_data(tvb, offset, body_tree);
+       break;
+    case GY_FT_EVENT:
+       offset = decode_event(tvb, offset, body_tree);
+       break;
+    case GY_FT_MISC:
+       offset = decode_misc (tvb, offset, body_tree);
+       break;
+    case GY_FT_TEXT:
+       break;
+    default:
+       break;
+    }
+    if (offset < msgend - msgpad) {
+       i = msgend - msgpad - offset;
+       proto_tree_add_text(gryphon_tree, tvb, offset, i, "Data");
+       offset += i;
+    }
+    if (offset < msgend) {
+       i = msgend - offset;
+       proto_tree_add_text(gryphon_tree, tvb, offset, i, "padding");
+       offset += i;
+    }
 }
 
 
 static const val_str_dsp cmds[] = {
-       {CMD_INIT,              "Initialize", cmd_init, NULL},
-        {CMD_GET_STAT,         "Get status", NULL, NULL},
-        {CMD_GET_CONFIG,       "Get configuration", NULL, resp_config},
-        {CMD_EVENT_ENABLE,     "Enable event", eventnum, NULL},
-        {CMD_EVENT_DISABLE,    "Disable event", eventnum, NULL},
+       {CMD_INIT,              "Initialize", cmd_init, NULL},
+       {CMD_GET_STAT,          "Get status", NULL, NULL},
+       {CMD_GET_CONFIG,        "Get configuration", NULL, resp_config},
+       {CMD_EVENT_ENABLE,      "Enable event", eventnum, NULL},
+       {CMD_EVENT_DISABLE,     "Disable event", eventnum, NULL},
        {CMD_GET_TIME,          "Get time", NULL, resp_time},
+       {CMD_SET_TIME,          "Set time", resp_time, NULL},
        {CMD_GET_RXDROP,        "Get number of dropped RX messages", NULL, NULL},
        {CMD_RESET_RXDROP,      "Clear number of dropped RX messages", NULL, NULL},
        {CMD_BCAST_ON,          "Set broadcasts on", NULL, NULL},
@@ -285,8 +373,8 @@ static const val_str_dsp cmds[] = {
        {CMD_CARD_GET_EVNAMES,  "Get event names", NULL, resp_events},
        {CMD_CARD_GET_SPEEDS,   "Get defined speeds", NULL, resp_getspeeds},
        {CMD_SERVER_REG,        "Register with server", cmd_register, resp_register},
-       {CMD_SERVER_SET_SORT,   "Set the sorting behavior", cmd_sort, NULL},
-       {CMD_SERVER_SET_OPT,    "Set the type of optimization", cmd_optimize, NULL},
+       {CMD_SERVER_SET_SORT,   "Set the sorting behavior", cmd_sort, NULL},
+       {CMD_SERVER_SET_OPT,    "Set the type of optimization", cmd_optimize, NULL},
        {CMD_BLM_SET_MODE,      "Set Bus Load Monitoring mode", blm_mode, NULL},
        {CMD_BLM_GET_MODE,      "Get Bus Load Monitoring mode", NULL, blm_mode},
        {CMD_BLM_GET_DATA,      "Get Bus Load data", NULL, resp_blm_data},
@@ -303,18 +391,32 @@ static const val_str_dsp cmds[] = {
        {CMD_PGM_DELETE,        "Delete an uploaded program", cmd_delete, NULL},
        {CMD_PGM_LIST,          "Get a list of uploaded programs", cmd_list, resp_list},
        {CMD_PGM_START,         "Start an uploaded program", cmd_start, resp_start},
+       {CMD_PGM_START2,        "Start an uploaded program", NULL, resp_start},
        {CMD_PGM_STOP,          "Stop an uploaded program", resp_start, NULL},
        {CMD_PGM_STATUS,        "Get status of an uploaded program", cmd_delete, resp_status},
        {CMD_PGM_OPTIONS,       "Set program upload options", cmd_options, resp_status},
-       {CMD_PGM_FILES,         "Get a list of files & directories", cmd_files, resp_files},
+       {CMD_PGM_FILES,         "Get a list of files & directories", cmd_files, resp_files},
        {CMD_SCHED_TX,          "Schedule transmission of messages", cmd_sched, resp_sched},
-       {CMD_SCHED_KILL_TX,     "Stop and destroy a message transmission", NULL, NULL},
-       {CMD_SCHED_STOP_TX,     "Kill a message transmission (deprecated)", NULL, NULL},
+       {CMD_SCHED_KILL_TX,     "Stop and destroy a message transmission", resp_sched, NULL},
+       {CMD_SCHED_STOP_TX,     "Kill a message transmission (deprecated)", resp_sched, NULL},
+        {CMD_SCHED_MSG_REPLACE, "Replace a scheduled message", cmd_sched_rep, NULL},
        {CMD_USDT_IOCTL,        "Register/Unregister with USDT server", cmd_usdt, NULL},
+       {CMD_USDT_REGISTER,     "Register/Unregister with USDT server", cmd_usdt, NULL},
+        {CMD_USDT_SET_FUNCTIONAL, "Set IDs to use extended addressing", cmd_usdt, NULL},
+        {CMD_IOPWR_GETINP,      "Read current digital inputs", NULL, cmd_bits_in},
+        {CMD_IOPWR_GETLATCH,    "Read latched digital inputs", NULL, cmd_bits_in},
+        {CMD_IOPWR_CLRLATCH,    "Read & clear latched digital inputs", cmd_bits_in, cmd_bits_in},
+        {CMD_IOPWR_GETOUT,      "Read digital outputs", NULL, cmd_bits_out},
+        {CMD_IOPWR_SETOUT,      "Write digital outputs", cmd_bits_out, NULL},
+        {CMD_IOPWR_SETBIT,      "Set indicated output bits", cmd_bits_out, NULL},
+        {CMD_IOPWR_CLRBIT,      "Clear indicated output bits", cmd_bits_out, NULL},
+        {CMD_IOPWR_GETPOWER,    "Read digital inputs at power on time", NULL, cmd_bits_in},
+        {CMD_UTIL_SET_INIT_STRATEGY, "Set initialization strategy", cmd_init_strat, NULL},
+        {CMD_UTIL_GET_INIT_STRATEGY, "Get initialization strategy", NULL, cmd_init_strat},
        {-1,                    "- unknown -", NULL, NULL},
-        };
+       };
 
-static const value_string responses[] = {
+static const value_string responses_vs[] = {
        {RESP_OK,               "OK - no error"},
        {RESP_UNKNOWN_ERR,      "Unknown error"},
        {RESP_UNKNOWN_CMD,      "Unrecognised command"},
@@ -332,9 +434,9 @@ static const value_string responses[] = {
        {RESP_UNAVAILABLE,      "Unavailable"},
        {RESP_BUF_FULL,         "Buffer full"},
        {RESP_NO_SUCH_JOB,      "No such job"},
-       {-1,                    "- unknown -"},
+       {0,                     NULL},
        };
-       
+
 static const value_string filter_data_types[] = {
        {FILTER_DATA_TYPE_HEADER_FRAME, "frame header"},
        {FILTER_DATA_TYPE_HEADER,       "data message header"},
@@ -342,7 +444,7 @@ static const value_string filter_data_types[] = {
        {FILTER_DATA_TYPE_EXTRA_DATA,   "data message extra data"},
        {FILTER_EVENT_TYPE_HEADER,      "event message header"},
        {FILTER_EVENT_TYPE_DATA,        "event message"},
-       {-1,                            "- unknown -"},
+       {0,                             NULL},
        };
 
 static const value_string operators[] = {
@@ -360,27 +462,27 @@ static const value_string operators[] = {
        {DIG_LOW_TO_HIGH,       "Digital, low to high transistion"},
        {DIG_HIGH_TO_LOW,       "Digital, high to low transistion"},
        {DIG_TRANSITION,        "Digital, change of state"},
-       {-1,                    "- unknown -"},
+       {0,                     NULL},
        };
 
 static const value_string modes[] = {
        {FILTER_OFF_PASS_ALL,   "Filter off, pass all messages"},
        {FILTER_OFF_BLOCK_ALL,  "Filter off, block all messages"},
        {FILTER_ON,             "Filter on"},
-       {-1,                    "- unknown -"},
+       {0,                     NULL},
        };
 
 static const value_string dmodes[] = {
        {DEFAULT_FILTER_BLOCK,  "Block"},
        {DEFAULT_FILTER_PASS,   "Pass"},
-       {-1,                    "- unknown -"},
+       {0,                     NULL},
        };
 
 static const value_string filtacts[] = {
        {DELETE_FILTER,         "Delete"},
        {ACTIVATE_FILTER,       "Activate"},
        {DEACTIVATE_FILTER,     "Deactivate"},
-       {-1,                    "- unknown -"},
+       {0,                     NULL},
        };
 
 static const value_string ioctls[] = {
@@ -410,8 +512,8 @@ static const value_string ioctls[] = {
        {GSETRAM,               "GSETRAM: Write value to RAM"},
        {GCANGETBTRS,           "GCANGETBTRS: Read CAN bit timing registers"},
        {GCANSETBTRS,           "GCANSETBTRS: Write CAN bit timing registers"},
-       {GCANGETBC,             "GCANGETBC: Read CAN byte count"},
-       {GCANSETBC,             "GCANSETBC: Write CAN byte count"},
+       {GCANGETBC,             "GCANGETBC: Read CAN bus configuration register"},
+       {GCANSETBC,             "GCANSETBC: Write CAN bus configuration register"},
        {GCANGETMODE,           "GCANGETMODE"},
        {GCANSETMODE,           "GCANSETMODE"},
        {GCANGETTRANS,          "GCANGETTRANS"},
@@ -465,19 +567,82 @@ static const value_string ioctls[] = {
        {GUBPSETINTERBYTE,      "GUBPSETINTERBYTE"},
        {GUBPGETNACKMODE,       "GUBPGETNACKMODE"},
        {GUBPSETNACKMODE,       "GUBPSETNACKMODE"},
-       {-1,                    "- unknown -"},
+        {GUBPGETRETRYDELAY,    "GUBPGETRETRYDELAY"},
+        {GUBPSETRETRYDELAY,    "GUBPSETRETRYDELAY"},
+        {GRESETHC08,            "GRESETHC08: Reset the HC08 processor"},
+        {GTESTHC08COP,          "GTESTHC08COP: Stop updating the HC08 watchdog timer"},
+        {GSJAGETLISTEN,         "GSJAGETLISTEN"},
+        {GSJASETLISTEN,         "GSJASETLISTEN"},
+        {GSJAGETSELFTEST,       "GSJAGETSELFTEST"},
+        {GSJASETSELFTEST,       "GSJASETSELFTEST"},
+        {GSJAGETXMITONCE,       "GSJAGETXMITONCE"},
+        {GSJASETXMITONCE,       "GSJASETXMITONCE"},
+        {GSJAGETTRIGSTATE,      "GSJAGETTRIGSTATE"},
+        {GSJASETTRIGCTRL,       "GSJASETTRIGCTRL"},
+        {GSJAGETTRIGCTRL,       "GSJAGETTRIGCTRL"},
+        {GSJAGETOUTSTATE,       "GSJAGETOUTSTATE"},
+        {GSJASETOUTSTATE,       "GSJASETOUTSTATE"},
+        {GSJAGETFILTER,         "GSJAGETFILTER"},
+        {GSJASETFILTER,         "GSJASETFILTER"},
+        {GSJAGETMASK,           "GSJAGETMASK"},
+        {GSJASETMASK,           "GSJASETMASK"},
+        {GSJAGETINTTERM,        "GSJAGETINTTERM"},
+        {GSJASETINTTERM,        "GSJASETINTTERM"},
+        {GSJAGETFTTRANS,        "GSJAGETFTTRANS"},
+        {GSJASETFTTRANS,        "GSJASETFTTRANS"},
+        {GSJAGETFTERROR,        "GSJAGETFTERROR"},
+        {GLINGETBITRATE,        "GLINGETBITRATE: Get the current bit rate"},
+        {GLINSETBITRATE,        "GLINSETBITRATE: Set the bit rate"},
+        {GLINGETBRKSPACE,       "GLINGETBRKSPACE"},
+        {GLINSETBRKSPACE,       "GLINSETBRKSPACE"},
+        {GLINGETBRKMARK,        "GLINGETBRKMARK"},
+        {GLINSETBRKMARK,        "GLINSETBRKMARK"},
+        {GLINGETIDDELAY,        "GLINGETIDDELAY"},
+        {GLINSETIDDELAY,        "GLINSETIDDELAY"},
+        {GLINGETRESPDELAY,      "GLINGETRESPDELAY"},
+        {GLINSETRESPDELAY,      "GLINSETRESPDELAY"},
+        {GLINGETINTERBYTE,      "GLINGETINTERBYTE"},
+        {GLINSETINTERBYTE,      "GLINSETINTERBYTE"},
+        {GLINGETWAKEUPDELAY,    "GLINGETWAKEUPDELAY"},
+        {GLINSETWAKEUPDELAY,    "GLINSETWAKEUPDELAY"},
+        {GLINGETWAKEUPTIMEOUT,  "GLINGETWAKEUPTIMEOUT"},
+        {GLINSETWAKEUPTIMEOUT,  "GLINSETWAKEUPTIMEOUT"},
+        {GLINGETWUTIMOUT3BR,    "GLINGETWUTIMOUT3BR"},
+        {GLINSETWUTIMOUT3BR,    "GLINSETWUTIMOUT3BR"},
+        {GLINSENDWAKEUP,        "GLINSENDWAKEUP"},
+        {GLINGETMODE,           "GLINGETMODE"},
+        {GLINSETMODE,           "GLINSETMODE"},
+        {GINPGETINP,            "GINPGETINP: Read current digital inputs"},
+        {GINPGETLATCH,          "GINPGETLATCH: Read latched digital inputs"},
+        {GINPCLRLATCH,          "GINPCLRLATCH: Read and clear latched digital inputs"},
+        {GOUTGET,               "GOUTGET: Read digital outputs"},
+        {GOUTSET,               "GOUTSET: Write digital outputs"},
+        {GOUTSETBIT,            "GOUTSETBIT: Set digital output bits"},
+        {GOUTCLEARBIT,          "GOUTCLEARBIT"},
+        {GPWRGETWHICH,          "GPWRGETWHICH"},
+        {GPWROFF,               "GPWROFF"},
+        {GPWROFFRESET,          "GPWROFFRESET"},
+        {GPWRRESET,             "GPWRRESET"},
+
+
+
+       {0,                     NULL},
        };
 
 
-void
-decode_command (int dst, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+decode_command(tvbuff_t *tvb, int offset, int dst, proto_tree *pt)
 {
-    int            cmd, i, padding;
+    int            cmd, padding, msglen;
+    unsigned int    i;
     proto_tree     *ft;
     proto_item     *ti;
+    proto_item     *hi;
 
-    cmd = (*data)[0];
-    proto_tree_add_uint_hidden(pt, hf_gryph_cmd, NullTVB, *offset, 1, cmd);
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    cmd = tvb_get_guint8(tvb, offset);
+    hi = proto_tree_add_uint(pt, hf_gryphon_cmd, tvb, offset, 1, cmd);
+       PROTO_ITEM_SET_HIDDEN(hi);
     if (cmd > 0x3F)
        cmd += dst * 256;
 
@@ -495,26 +660,30 @@ decode_command (int dst, const u_char **data, const u_char *dataend, int *offset
     if (i >= SIZEOF(cmds))
        i = SIZEOF(cmds) - 1;
 
-    proto_tree_add_text (pt, NullTVB, *offset, 4, "Command: %s", cmds[i].strptr);
-    BUMP (*offset, *data, 4);
+    proto_tree_add_text (pt, tvb, offset, 4, "Command: %s", cmds[i].strptr);
+    offset += 4;
+    msglen -= 4;
 
-/*  if (cmds[i].cmd_fnct && dataend - *data) { */
-    if (cmds[i].cmd_fnct && msglen > 4) {
+    if (cmds[i].cmd_fnct && msglen > 0) {
        padding = 3 - (msglen + 3) % 4;
-       ti = proto_tree_add_text(pt, NullTVB, *offset, msglen-4, "Data: (%d bytes)", msglen-4);
+       ti = proto_tree_add_text(pt, tvb, offset, -1, "Data: (%d byte%s)",
+                msglen, msglen == 1 ? "" : "s");
        ft = proto_item_add_subtree(ti, ett_gryphon_command_data);
-       (*(cmds[i].cmd_fnct)) (dst, data, dataend, offset, msglen, ft);
+       offset = (*(cmds[i].cmd_fnct)) (tvb, offset, ft);
     }
+    return offset;
 }
 
-void
-decode_response (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+decode_response(tvbuff_t *tvb, int offset, int src, proto_tree *pt)
 {
-    int            cmd, i, j, resp;
+    int            cmd, msglen;
+    unsigned int    i, resp;
     proto_tree     *ft;
     proto_item     *ti;
 
-    cmd = (*data)[0];
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    cmd = tvb_get_guint8(tvb, offset);
     if (cmd > 0x3F)
        cmd += src * 256;
 
@@ -531,28 +700,27 @@ decode_response (int src, const u_char **data, const u_char *dataend, int *offse
     }
     if (i >= SIZEOF(cmds))
        i = SIZEOF(cmds) - 1;
-    proto_tree_add_text (pt, NullTVB, *offset, 4, "Command: %s", cmds[i].strptr);
-    BUMP (*offset, *data, 4);
-    
-    resp = pntohl ((unsigned long *)data[0]);
-    for (j = 0; j < SIZEOF(responses); j++) {
-       if (responses[j].value == resp)
-           break;
-    }
-    if (j >= SIZEOF(responses))
-       j = SIZEOF(responses) - 1;
-    proto_tree_add_text (pt, NullTVB, *offset, 4, "Status: %s", responses[j].strptr);
-    BUMP (*offset, *data, 4);
-
-    if (cmds[i].rsp_fnct) {
-    ti = proto_tree_add_text(pt, NullTVB, *offset, msglen-8, "Data: (%d bytes)", msglen-8);
-    ft = proto_item_add_subtree(ti, ett_gryphon_response_data);
-       (*(cmds[i].rsp_fnct)) (src, data, dataend, offset, msglen, ft);
+    proto_tree_add_text (pt, tvb, offset, 4, "Command: %s", cmds[i].strptr);
+    offset += 4;
+    msglen -= 4;
+
+    resp = tvb_get_ntohl (tvb, offset);
+    proto_tree_add_text (pt, tvb, offset, 4, "Status: %s",
+       val_to_str(resp, responses_vs, "Unknown (0x%08x)"));
+    offset += 4;
+    msglen -= 4;
+
+    if (cmds[i].rsp_fnct && msglen > 0) {
+       ti = proto_tree_add_text(pt, tvb, offset, msglen, "Data: (%d byte%s)",
+                msglen, msglen == 1 ? "" : "s");
+       ft = proto_item_add_subtree(ti, ett_gryphon_response_data);
+       offset = (*(cmds[i].rsp_fnct)) (tvb, offset, ft);
     }
+    return offset;
 }
 
-void
-decode_data (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+decode_data(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
     proto_item *item, *item1;
     proto_tree *tree, *tree1;
@@ -560,912 +728,1121 @@ decode_data (int src, const u_char **data, const u_char *dataend, int *offset, i
     int     hours, minutes, seconds, fraction;
     unsigned long   timestamp;
 
-       hdrsize = (*data)[0];
-       hdrbits = (*data)[1];
-       datasize = pntohs ((unsigned short *)((*data)+2));
-       extrasize = (*data)[4];
-       padding = 3 - (hdrsize + datasize + extrasize + 3) % 4;
-       msgsize = hdrsize + datasize + extrasize + padding + 16;
-
-       item = proto_tree_add_text(pt, NullTVB, *offset, 16, "Message header");
-       tree = proto_item_add_subtree (item, ett_gryphon_data_header);
-       proto_tree_add_text(tree, NullTVB, *offset, 2, "Header length: %d bytes, %d bits", hdrsize, hdrbits);
-       proto_tree_add_text(tree, NullTVB, *offset+2, 2, "Data length: %d bytes", datasize);
-       proto_tree_add_text(tree, NullTVB, *offset+4, 1, "Extra data length: %d bytes", extrasize);
-       mode = (*data)[5];
-       item1 = proto_tree_add_text(tree, NullTVB, *offset+5, 1, "Mode: %hd", mode);
-       if (mode) {
-           tree1 = proto_item_add_subtree (item1, ett_gryphon_flags);
-           if (mode & 0x80)
-               proto_tree_add_text(tree1, NullTVB, *offset+5, 1, "1... .... = Transmitted message");
-           if (mode & 0x40)
-               proto_tree_add_text(tree1, NullTVB, *offset+5, 1, ".1.. .... = Received message");
-           if (mode & 0x20)
-               proto_tree_add_text(tree1, NullTVB, *offset+5, 1, "..1. .... = Local message");
-           if (mode & 0x10)
-               proto_tree_add_text(tree1, NullTVB, *offset+5, 1, "...1 .... = Remote message");
-           if (mode & 0x01)
-               proto_tree_add_text(tree1, NullTVB, *offset+5, 1, ".... ...1 = Internal message");
+    hdrsize = tvb_get_guint8(tvb, offset+0);
+    hdrbits = tvb_get_guint8(tvb, offset+1);
+    datasize = tvb_get_ntohs(tvb, offset+2);
+    extrasize = tvb_get_guint8(tvb, offset+4);
+    padding = 3 - (hdrsize + datasize + extrasize + 3) % 4;
+    msgsize = hdrsize + datasize + extrasize + padding + 16;
+
+    item = proto_tree_add_text(pt, tvb, offset, 16, "Message header");
+    tree = proto_item_add_subtree (item, ett_gryphon_data_header);
+    proto_tree_add_text(tree, tvb, offset, 2, "Header length: %d byte%s, %d bits",
+            hdrsize, plurality(hdrsize, "", "s"), hdrbits);
+    proto_tree_add_text(tree, tvb, offset+2, 2, "Data length: %d byte%s",
+            datasize, plurality(datasize, "", "s"));
+    proto_tree_add_text(tree, tvb, offset+4, 1, "Extra data length: %d byte%s",
+            extrasize, plurality(extrasize, "", "s"));
+    mode = tvb_get_guint8(tvb, offset+5);
+    item1 = proto_tree_add_text(tree, tvb, offset+5, 1, "Mode: %d", mode);
+    if (mode) {
+       tree1 = proto_item_add_subtree (item1, ett_gryphon_flags);
+       if (mode & 0x80) {
+           proto_tree_add_text(tree1, tvb, offset+5, 1, "%s",
+               decode_boolean_bitfield(mode, 0x80, 8,
+                   "Transmitted message", NULL));
        }
-       proto_tree_add_text(tree, NullTVB, *offset+6, 1, "Priority: %d", (*data)[6]);
-       proto_tree_add_text(tree, NullTVB, *offset+7, 1, "Error status: %hd", (*data)[7]);
-       timestamp = pntohl ((unsigned long *)((*data)+8));
-       hours = timestamp /(100000 * 60 *60);
-       minutes = (timestamp / (100000 * 60)) % 60;
-       seconds = (timestamp / 100000) % 60;
-       fraction = timestamp % 100000;
-       proto_tree_add_text(tree, NullTVB, *offset+8, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
-       proto_tree_add_text(tree, NullTVB, *offset+12, 1, "Context: %hd", (*data)[12]);
-       proto_tree_add_text(tree, NullTVB, *offset+13, 3, "reserved:");
-       BUMP (*offset, *data, 16);
-       item = proto_tree_add_text(pt, NullTVB, *offset, msgsize-16-padding, "Message Body");
-       tree = proto_item_add_subtree (item, ett_gryphon_data_body);
-       if (hdrsize) {
-           proto_tree_add_text(tree, NullTVB, *offset, hdrsize, "Header");
-           BUMP (*offset, *data, hdrsize);
+       if (mode & 0x40) {
+           proto_tree_add_text(tree1, tvb, offset+5, 1, "%s",
+               decode_boolean_bitfield(mode, 0x40, 8,
+                   "Received message", NULL));
        }
-       if (datasize) {
-           proto_tree_add_text(tree, NullTVB, *offset, datasize, "Data");
-           BUMP (*offset, *data, datasize);
+       if (mode & 0x20) {
+           proto_tree_add_text(tree1, tvb, offset+5, 1, "%s",
+               decode_boolean_bitfield(mode, 0x20, 8,
+                   "Local message", NULL));
        }
-       if (extrasize) {
-           proto_tree_add_text(tree, NullTVB, *offset, extrasize, "Extra data");
-           BUMP (*offset, *data, extrasize);
+       if (mode & 0x10) {
+           proto_tree_add_text(tree1, tvb, offset+5, 1, "%s",
+               decode_boolean_bitfield(mode, 0x10, 8,
+                   "Remote message", NULL));
        }
-       if (padding) {
-           proto_tree_add_text(pt, NullTVB, *offset, padding, "padding");
-           BUMP (*offset, *data, padding);
+       if (mode & 0x01) {
+           proto_tree_add_text(tree1, tvb, offset+5, 1, "%s",
+               decode_boolean_bitfield(mode, 0x01, 8,
+                   "Internal message", NULL));
        }
+    }
+    proto_tree_add_text(tree, tvb, offset+6, 1, "Priority: %u",
+       tvb_get_guint8(tvb, offset+6));
+    proto_tree_add_text(tree, tvb, offset+7, 1, "Error status: %u",
+       tvb_get_guint8(tvb, offset+7));
+    timestamp = tvb_get_ntohl(tvb, offset+8);
+    hours = timestamp /(100000 * 60 *60);
+    minutes = (timestamp / (100000 * 60)) % 60;
+    seconds = (timestamp / 100000) % 60;
+    fraction = timestamp % 100000;
+    proto_tree_add_text(tree, tvb, offset+8, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
+    proto_tree_add_text(tree, tvb, offset+12, 1, "Context: %u",
+       tvb_get_guint8(tvb, offset+12));
+    proto_tree_add_text(tree, tvb, offset+13, 3, "reserved:");
+    offset += 16;
+    item = proto_tree_add_text(pt, tvb, offset, msgsize-16-padding, "Message Body");
+    tree = proto_item_add_subtree (item, ett_gryphon_data_body);
+    if (hdrsize) {
+       proto_tree_add_text(tree, tvb, offset, hdrsize, "Header");
+       offset += hdrsize;
+    }
+    if (datasize) {
+       proto_tree_add_text(tree, tvb, offset, datasize, "Data");
+       offset += datasize;
+    }
+    if (extrasize) {
+       proto_tree_add_text(tree, tvb, offset, extrasize, "Extra data");
+       offset += extrasize;
+    }
+    if (padding) {
+       proto_tree_add_text(pt, tvb, offset, padding, "padding");
+       offset += padding;
+    }
+    return offset;
 }
 
-void
-decode_event (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+decode_event(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
+    int                    msglen;
     int            hours, minutes, seconds, fraction, padding, length;
     unsigned long   timestamp;
-    const u_char    *msgend;
+    int                    msgend;
 
+    msglen = tvb_reported_length_remaining(tvb, offset);
     padding = 3 - (msglen + 3) % 4;
-    msgend = *data + msglen;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Event ID: %hd", **data);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 1, "Event context: %hd", *((*data)+1));
-    proto_tree_add_text(pt, NullTVB, *offset+2, 2, "reserved");
-    BUMP (*offset, *data, 4);
-    timestamp = pntohl ((unsigned long *)(*data));
+    msgend = offset + msglen;
+    proto_tree_add_text(pt, tvb, offset, 1, "Event ID: %u",
+       tvb_get_guint8(tvb, offset));
+    proto_tree_add_text(pt, tvb, offset+1, 1, "Event context: %u",
+       tvb_get_guint8(tvb, offset+1));
+    proto_tree_add_text(pt, tvb, offset+2, 2, "reserved");
+    offset += 4;
+    timestamp = tvb_get_ntohl(tvb, offset);
     hours = timestamp /(100000 * 60 *60);
     minutes = (timestamp / (100000 * 60)) % 60;
     seconds = (timestamp / 100000) % 60;
     fraction = timestamp % 100000;
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
-    BUMP (*offset, *data, 4);
-    if (*data < msgend) {
-       length = msgend - *data;
-       proto_tree_add_text (pt, NullTVB, *offset, length, "Data (%d bytes)", length);
-       BUMP (*offset, *data, length);
+    proto_tree_add_text(pt, tvb, offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
+    offset += 4;
+    if (offset < msgend) {
+       length = msgend - offset;
+       proto_tree_add_text (pt, tvb, offset, length, "Data (%d byte%s)",
+                length, length == 1 ? "" : "s");
+       offset += length;
     }
     if (padding) {
-       proto_tree_add_text (pt, NullTVB, *offset, padding, "padding");
-       BUMP (*offset, *data, padding);
+       proto_tree_add_text(pt, tvb, offset, padding, "padding");
+       offset += padding;
     }
+    return offset;
 }
 
-void
-cmd_init (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+decode_misc (tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    #define         LENGTH 120
+    int            padding, msglen;
+    gint            length;
+    unsigned char   local_data[LENGTH+1];
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    padding = 3 - (msglen + 3) % 4;
+    length = tvb_get_nstringz0(tvb, offset, LENGTH, local_data);
+    proto_tree_add_text(pt, tvb, offset, msglen, "Data: %s", local_data);
+    offset += msglen;
+    if (padding) {
+       proto_tree_add_text (pt, tvb, offset, padding, "padding");
+       offset += padding;
+    }
+    return offset;
+}
+
+static int
+cmd_init(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    char       *ptr;
-    
-    if (*data >= dataend)
-       return;
-    if (**data == 0)
+    const char         *ptr;
+
+    if (tvb_get_guint8(tvb, offset) == 0)
        ptr = "Always initialize";
     else
        ptr = "Initialize if not previously initialized";
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Mode: %s", ptr);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
+    proto_tree_add_text(pt, tvb, offset, 1, "Mode: %s", ptr);
+    proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-eventnum (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+eventnum(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    unsigned char   event = **data;
-    
+    guint8     event = tvb_get_guint8(tvb, offset);
+
     if (event)
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Event number: %hd", event);
+       proto_tree_add_text(pt, tvb, offset, 1, "Event number: %u", event);
     else
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Event numbers: All");
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "padding");
-    BUMP (*offset, *data, 4);
+       proto_tree_add_text(pt, tvb, offset, 1, "Event numbers: All");
+    proto_tree_add_text(pt, tvb, offset+1, 3, "padding");
+    offset += 4;
+    return offset;
 }
 
-void
-resp_time (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_time(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    int     hours, minutes, seconds, fraction;
-    union {
-       unsigned int            lng[2];
-       guint64                 lnglng;
-    } ts;
-    unsigned int    timestamp;
-    unsigned char   date[45];
-   
-    ts.lng[1] = pntohl ((unsigned int *)(*data));
-    ts.lng[0] = pntohl ((unsigned int *)((*data)+4));
-    timestamp = ts.lnglng / 100000L;
-    strncpy (date, ctime((time_t*)&timestamp), sizeof(date));
-    date[strlen(date)-1] = 0x00;
-    proto_tree_add_text(pt, NullTVB, *offset, 8, "Date/Time: %s", date);
-    timestamp = ts.lng[0];
-    hours = timestamp /(100000 * 60 *60);
-    minutes = (timestamp / (100000 * 60)) % 60;
-    seconds = (timestamp / 100000) % 60;
-    fraction = timestamp % 100000;
-    proto_tree_add_text(pt, NullTVB, *offset+4, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
-    BUMP (*offset, *data, 8);
+    guint64 ts;
+    time_t  timestamp;
+    struct tm *tmp;
+    static const char *mon_names[12] = {
+        "Jan",
+        "Feb",
+        "Mar",
+        "Apr",
+        "May",
+        "Jun",
+        "Jul",
+        "Aug",
+        "Sep",
+        "Oct",
+        "Nov",
+        "Dec"
+    };
+
+    ts = tvb_get_ntoh64(tvb, offset);
+    timestamp = (time_t) (ts / 100000);
+    tmp = localtime(&timestamp);
+
+    if (tmp) {
+        proto_tree_add_text(pt, tvb, offset, 8,
+                            "Date/Time: %s %d, %d %02d:%02d:%02d.%05u",
+                            mon_names[tmp->tm_mon],
+                            tmp->tm_mday,
+                            tmp->tm_year + 1900,
+                            tmp->tm_hour,
+                            tmp->tm_min,
+                            tmp->tm_sec,
+                            (guint) (ts % 100000));
+    } else {
+        proto_tree_add_text(pt, tvb, offset, 8,
+                            "Date/Time: [Invalid]");
+    }
+    offset += 8;
+    return offset;
 }
 
-void
-cmd_setfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_setfilt(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    int            flag = pntohl ((unsigned int *)((*data)+4));
+    int            flag = tvb_get_ntohl(tvb, offset);
     int            length, padding;
-    unsigned char   mode[30];
-    
-    length =  *((*data)+4) + *((*data)+5) + pntohs ((unsigned short *)((*data)+6));
+    char   mode[30];
+
+    length =  tvb_get_guint8(tvb, offset+4) + tvb_get_guint8(tvb, offset+5)
+       + tvb_get_ntohs(tvb, offset+6);
     if (flag)
-       strcpy (mode, "Pass");
+       g_strlcpy (mode, "Pass", 30);
     else
-       strcpy (mode, "Block");
+       g_strlcpy (mode, "Block", 30);
     if (length == 0)
-       strcat (mode, " all");
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "Pass/Block flag: %s", mode);
-    proto_tree_add_text(pt, NullTVB, *offset+4, 4, "Length of Pattern & Mask: %d", length);
-    BUMP (*offset, *data, 8);
+       g_strlcat (mode, " all", 30);
+    proto_tree_add_text(pt, tvb, offset, 4, "Pass/Block flag: %s", mode);
+    proto_tree_add_text(pt, tvb, offset+4, 4, "Length of Pattern & Mask: %d", length);
+    offset += 8;
     if (length) {
-       proto_tree_add_text(pt, NullTVB, *offset, length * 2, "discarded data");
-       BUMP (*offset, *data, length * 2);
+       proto_tree_add_text(pt, tvb, offset, length * 2, "discarded data");
+       offset += length * 2;
     }
     padding = 3 - (length * 2 + 3) % 4;
     if (padding) {
-       proto_tree_add_text(pt, NullTVB, *offset+1, 3, "padding");
-       BUMP (*offset, *data, padding);
+       proto_tree_add_text(pt, tvb, offset+1, 3, "padding");
+       offset += padding;
     }
+    return offset;
 }
 
-void
-cmd_ioctl (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_ioctl(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
+    int                    msglen;
     unsigned int    ioctl;
-    int            i;
 
-    ioctl = pntohl ((unsigned int *)(*data));
-    for (i = 0; i < SIZEOF(ioctls); i++) {
-       if (ioctls[i].value == ioctl)
-           break;
-    }
-    if (i >= SIZEOF(ioctls))
-       i = SIZEOF(ioctls) - 1;
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "IOCTL: %s", ioctls[i].strptr);
-    BUMP (*offset, *data, 4);
-    if (msglen > 8) {
-      proto_tree_add_text(pt, NullTVB, *offset, msglen-8, "Data");
-      BUMP (*offset, *data, msglen-8);
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    ioctl = tvb_get_ntohl(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 4, "IOCTL: %s",
+       val_to_str(ioctl, ioctls, "Unknown (0x%08x)"));
+    offset += 4;
+    msglen -= 4;
+    if (msglen > 0) {
+       proto_tree_add_text(pt, tvb, offset, msglen, "Data");
+       offset += msglen;
     }
+    return offset;
 }
 
-void
-cmd_addfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_addfilt(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
     proto_item *item;
     proto_tree *tree;
+    guint8     flags;
     int        blocks, i, length;
-    char       *ptr;
-    char       pass[] = ".... ...1 = Conforming messages are passed";
-    char       block[] = ".... ...0 = Conforming messages are blocked";
-    char       active[] = ".... ..1. = The filter is active";
-    char       inactive[] = ".... ..0. = The filter is inactive";
 
-    item = proto_tree_add_text(pt, NullTVB, *offset, 1, "Flags");
+    item = proto_tree_add_text(pt, tvb, offset, 1, "Flags");
     tree = proto_item_add_subtree (item, ett_gryphon_flags);
-    if (**data & FILTER_PASS_FLAG)
-       ptr = pass;
-    else
-       ptr = block;
-    proto_tree_add_text(tree, NullTVB, *offset, 1, ptr);
-    if (**data & FILTER_ACTIVE_FLAG)
-       ptr = active;
-    else
-       ptr = inactive;
-    proto_tree_add_text(tree, NullTVB, *offset, 1, ptr);
-    BUMP (*offset, *data, 1);
-    blocks = **data;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of filter blocks = %d", blocks);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 6, "reserved");
-    BUMP (*offset, *data, 7);
+    flags = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(tree, tvb, offset, 1, "%s",
+       decode_boolean_bitfield(flags, FILTER_PASS_FLAG, 8,
+           "Conforming messages are passed",
+           "Conforming messages are blocked"));
+    proto_tree_add_text(tree, tvb, offset, 1, "%s",
+       decode_boolean_bitfield(flags, FILTER_ACTIVE_FLAG, 8,
+           "The filter is active", "The filter is inactive"));
+    offset += 1;
+    blocks = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Number of filter blocks = %d", blocks);
+    proto_tree_add_text(pt, tvb, offset+1, 6, "reserved");
+    offset += 7;
     for (i = 1; i <= blocks; i++) {
-       length = pntohs ((unsigned short *)((*data)+2)) * 2 + 8;
+       length = tvb_get_ntohs(tvb, offset+2) * 2 + 8;
        length += 3 - (length + 3) % 4;
-       item = proto_tree_add_text(pt, NullTVB, *offset, length, "Filter block %d", i);
+       item = proto_tree_add_text(pt, tvb, offset, length, "Filter block %d", i);
        tree = proto_item_add_subtree (item, ett_gryphon_cmd_filter_block);
-       filter_block (src, data, dataend, offset, msglen, tree);
+       offset = filter_block(tvb, offset, tree);
     }
+    return offset;
 }
 
-void
-resp_addfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_addfilt(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Filter handle: %hd", **data);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
+    proto_tree_add_text(pt, tvb, offset, 1, "Filter handle: %u",
+       tvb_get_guint8(tvb, offset));
+    proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-cmd_modfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_modfilt(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
+    guint8         filter_handle;
     unsigned char   action;
-    int            i;
 
-    if (**data)
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Filter handle: %hd", **data);
+    filter_handle = tvb_get_guint8(tvb, offset);
+    if (filter_handle)
+       proto_tree_add_text(pt, tvb, offset, 1, "Filter handle: %u",
+           filter_handle);
     else
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Filter handles: all");
-    action = *((*data) + 1);
-    for (i = 0; i < SIZEOF(filtacts); i++) {
-       if (filtacts[i].value == action)
-           break;
-    }
-    if (i >= SIZEOF(filtacts))
-       i = SIZEOF(filtacts) - 1;
-    proto_tree_add_text(pt, NullTVB, *offset+1, 1, "Action: %s filter", filtacts[i].strptr);
-    proto_tree_add_text(pt, NullTVB, *offset+2, 2, "reserved");
-    BUMP (*offset, *data, 4);
+       proto_tree_add_text(pt, tvb, offset, 1, "Filter handles: all");
+    action = tvb_get_guint8(tvb, offset + 1);
+    proto_tree_add_text(pt, tvb, offset+1, 1, "Action: %s filter",
+       val_to_str(action, filtacts, "Unknown (%u)"));
+    proto_tree_add_text(pt, tvb, offset+2, 2, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-resp_filthan (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_filthan(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    int        handles = **data;
+    int        handles = tvb_get_guint8(tvb, offset);
     int        i, padding;
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of filter handles: %d", handles);
+
+    proto_tree_add_text(pt, tvb, offset, 1, "Number of filter handles: %d", handles);
     for (i = 1; i <= handles; i++){
-       proto_tree_add_text(pt, NullTVB, *offset+i, 1, "Handle %d: %hd", i, *(*data+i));
+       proto_tree_add_text(pt, tvb, offset+i, 1, "Handle %d: %u", i,
+           tvb_get_guint8(tvb, offset+i));
     }
     padding = 3 - (handles + 1 + 3) % 4;
     if (padding)
-       proto_tree_add_text(pt, NullTVB, *offset+1+handles, padding, "padding");
-    BUMP (*offset, *data, 1+handles+padding);
+       proto_tree_add_text(pt, tvb, offset+1+handles, padding, "padding");
+    offset += 1+handles+padding;
+    return offset;
 }
 
-void
-dfiltmode (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    int            i;
+static int
+dfiltmode(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
     unsigned char   mode;
-    
-    mode = **data;
-    for (i = 0; i < SIZEOF(modes); i++) {
-       if (dmodes[i].value == mode)
-           break;
-    }
-    if (i >= SIZEOF(dmodes))
-       i = SIZEOF(dmodes) - 1;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Filter mode: %s", dmodes[i].strptr);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
+
+    mode = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Filter mode: %s",
+       val_to_str(mode, dmodes, "Unknown (%u)"));
+    proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-filtmode (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    int            i;
+static int
+filtmode(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
     unsigned char   mode;
-    
-    mode = **data;
-    for (i = 0; i < SIZEOF(modes); i++) {
-       if (modes[i].value == mode)
-           break;
-    }
-    if (i >= SIZEOF(modes))
-       i = SIZEOF(modes) - 1;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Filter mode: %s", modes[i].strptr);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
+
+    mode = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Filter mode: %s",
+       val_to_str(mode, modes, "Unknown (%u)"));
+    proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-resp_events (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    int            i;
+static int
+resp_events(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int                    msglen;
+    unsigned int    i;
     proto_tree     *tree;
     proto_item     *item;
-    
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
     i = 1;
-    while (*data < dataend) {
-       item = proto_tree_add_text(pt, NullTVB, *offset, 20, "Event %d:", i);
+    while (msglen != 0) {
+       item = proto_tree_add_text(pt, tvb, offset, 20, "Event %d:", i);
        tree = proto_item_add_subtree (item, ett_gryphon_cmd_events_data);
-       proto_tree_add_text(tree, NullTVB, *offset, 1, "Event ID: %hd", **data);
-       proto_tree_add_text(tree, NullTVB, *offset+1, 19, "Event name: %s", (*data)+1);
-       BUMP (*offset, *data, 20);
+       proto_tree_add_text(tree, tvb, offset, 1, "Event ID: %u",
+           tvb_get_guint8(tvb, offset));
+       proto_tree_add_text(tree, tvb, offset+1, 19, "Event name: %.19s",
+               tvb_get_ephemeral_string(tvb, offset+1, 19));
+       offset += 20;
+       msglen -= 20;
        i++;
     }
+    return offset;
 }
 
-void
-cmd_register (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_register(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    char       string[33];
-    
-    MEMCPY (string, *data, 16);
-    proto_tree_add_text(pt, NullTVB, *offset, 16, "Username: %s", string);
-    BUMP (*offset, *data, 16);
-    MEMCPY (string, *data, 32);
-    proto_tree_add_text(pt, NullTVB, *offset, 32, "Password: %s", string);
-    BUMP (*offset, *data, 32);
+    proto_tree_add_text(pt, tvb, offset, 16, "Username: %.16s",
+       tvb_get_ephemeral_string(tvb, offset, 16));
+    offset += 16;
+    proto_tree_add_text(pt, tvb, offset, 32, "Password: %.32s",
+       tvb_get_ephemeral_string(tvb, offset, 32));
+    offset += 32;
+    return offset;
 }
 
-void
-resp_register (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Client ID: %hd", (*data)[0]);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 1, "Privileges: %hd", (*data)[1]);
-    proto_tree_add_text(pt, NullTVB, *offset+2, 2, "reserved");
-    BUMP (*offset, *data, 4);
+static int
+resp_register(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    proto_tree_add_text(pt, tvb, offset, 1, "Client ID: %u",
+       tvb_get_guint8(tvb, offset));
+    proto_tree_add_text(pt, tvb, offset+1, 1, "Privileges: %u",
+       tvb_get_guint8(tvb, offset+1));
+    proto_tree_add_text(pt, tvb, offset+2, 2, "reserved");
+    offset += 4;
+    return offset;
 }
 
 
-void
-resp_getspeeds (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    int number = (*data)[9];
-    int size = (*data)[8];
+static int
+resp_getspeeds(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int size;
+    int number;
     int index;
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "Set Speed IOCTL");
-    proto_tree_add_text(pt, NullTVB, *offset+4, 4, "Get Speed IOCTL");
-    proto_tree_add_text(pt, NullTVB, *offset+8, 1, "Speed data size is %d bytes", size);
-    proto_tree_add_text(pt, NullTVB, *offset+9, 1, "There are %d preset speeds", number);
-    BUMP (*offset, *data, 10);
+
+    proto_tree_add_text(pt, tvb, offset, 4, "Set Speed IOCTL");
+    proto_tree_add_text(pt, tvb, offset+4, 4, "Get Speed IOCTL");
+    size = tvb_get_guint8(tvb, offset+8);
+    proto_tree_add_text(pt, tvb, offset+8, 1, "Speed data size is %d byte%s",
+            size, size == 1 ? "" : "s");
+    number = tvb_get_guint8(tvb, offset+9);
+    proto_tree_add_text(pt, tvb, offset+9, 1, "There %s %d preset speed%s",
+        number == 1 ? "is" : "are", number, number == 1 ? "" : "s");
+    offset += 10;
     for (index = 0; index < number; index++) {
-       proto_tree_add_text(pt, NullTVB, *offset, size, "Data for preset %d", index+1);
-       BUMP (*offset, *data, size);
+       proto_tree_add_text(pt, tvb, offset, size, "Data for preset %d",
+           index+1);
+       offset += size;
     }
+    return offset;
 }
 
-
-
-void
-cmd_sort (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_sort(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    char       *which;
-    
-    which = (*data)[0] ? "Sort into blocks of up to 16 messages" :
-           "Do not sort messages";
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Set sorting: %s", which);
-    BUMP (*offset, *data, 1);
+    const char *which;
+
+    which = tvb_get_guint8(tvb, offset) ?
+           "Sort into blocks of up to 16 messages" :
+           "Do not sort messages";
+    proto_tree_add_text(pt, tvb, offset, 1, "Set sorting: %s", which);
+    offset += 1;
+    return offset;
 }
 
-void
-
-cmd_optimize (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_optimize(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    char       *which;
-    
-    which = (*data)[0] ? "Optimize for latency (Nagle algorithm disabled)" :
-           "Optimize for throughput (Nagle algorithm enabled)";
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Set optimization: %s", which);
-    BUMP (*offset, *data, 1);
+    const char *which;
+
+    which = tvb_get_guint8(tvb, offset) ?
+           "Optimize for latency (Nagle algorithm disabled)" :
+           "Optimize for throughput (Nagle algorithm enabled)";
+    proto_tree_add_text(pt, tvb, offset, 1, "Set optimization: %s", which);
+    offset += 1;
+    return offset;
 }
 
-void
-resp_config (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    proto_item *ti;
-    proto_tree *ft;
-    char       string[33];
+static int
+resp_config(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    proto_item *ti, *item;
+    proto_tree *ft, *tree;
     int        devices;
-    int        i, j, x;
-    
+    int        i;
+    unsigned int j, x;
+
     static const value_string protocol_types[] = {
        {GDUMMY * 256 + GDGDMARKONE,    "Dummy device driver"},
        {GCAN * 256 + G82527,           "CAN, 82527 subtype"},
        {GCAN * 256 + GSJA1000,         "CAN, SJA1000 subtype"},
        {GCAN * 256 + G82527SW,         "CAN, 82527 single wire subtype"},
+       {GCAN * 256 + G82527ISO11992,   "CAN, 82527 ISO11992 subtype"},
+       {GCAN * 256 + G82527_SINGLECHAN, "CAN, Fiber Optic 82527 subtype"},
+       {GCAN * 256 + G82527SW_SINGLECHAN, "CAN, Fiber Optic 82527 single wire subtype"},
+       {GCAN * 256 + G82527ISO11992_SINGLECHAN,        "CAN, Fiber Optic ISO11992 subtype"},
+       {GCAN * 256 + GSJA1000FT,       "CAN, SJA1000 Fault Tolerant subtype"},
+       {GCAN * 256 + GSJA1000C,        "CAN, SJA1000 onboard subtype"},
+       {GCAN * 256 + GSJA1000FT_FO,    "CAN, SJA1000 Fiber Optic Fault Tolerant subtype"},
        {GJ1850 * 256 + GHBCCPAIR,      "J1850, HBCC subtype"},
        {GJ1850 * 256 + GDLC,           "J1850, GM DLC subtype"},
        {GJ1850 * 256 + GCHRYSLER,      "J1850, Chrysler subtype"},
        {GJ1850 * 256 + GDEHC12,        "J1850, DE HC12 KWP/BDLC subtype"},
-       {GKWP2000 * 256 + GDEHC12KWP,   "Keyword protocol 2000"},
+       {GKWP2000 * 256 + GDEHC12KWP,   "Keyword protocol 2000/ISO 9141"},
        {GHONDA * 256 + GDGHC08,        "Honda UART, DG HC08 subtype"},
        {GFORDUBP * 256 + GDGUBP08,     "Ford UBP, DG HC08 subtype"},
-       {-1,                            "- unknown -"},
+        {GSCI * 256 + G16550SCI,        "Chrysler SCI, UART subtype"},
+        {GCCD * 256 + G16550CDP68HC68,  "Chrysler C2D, UART / CDP68HC68S1 subtype"},
+        {GLIN * 256 + GDGLIN08,         "LIN, DG HC08 subtype"},
+       {0,                             NULL},
     };
 
+    proto_tree_add_text(pt, tvb, offset, 20, "Device name: %.20s",
+       tvb_get_ephemeral_string(tvb, offset, 20));
+    offset += 20;
 
+    proto_tree_add_text(pt, tvb, offset, 8, "Device version: %.8s",
+       tvb_get_ephemeral_string(tvb, offset, 8));
+    offset += 8;
 
+    proto_tree_add_text(pt, tvb, offset, 20, "Device serial number: %.20s",
+       tvb_get_ephemeral_string(tvb, offset, 20));
+    offset += 20;
 
-   MEMCPY (string, *data, 20);
-    proto_tree_add_text(pt, NullTVB, *offset, 20, "Device name: %s", string);
-    BUMP (*offset, *data, 20);
-
-    MEMCPY (string, *data, 8);
-    proto_tree_add_text(pt, NullTVB, *offset, 8, "Device version: %s", string);
-    BUMP (*offset, *data, 8);
-
-    MEMCPY (string, *data, 20);
-    proto_tree_add_text(pt, NullTVB, *offset, 20, "Device serial number: %s", string);
-    BUMP (*offset, *data, 20);
-
-    devices = **data;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of channels: %d", devices);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 15, "reserved");
-    BUMP (*offset, *data, 16);
+    devices = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Number of channels: %d", devices);
+    proto_tree_add_text(pt, tvb, offset+1, 11, "Name & version extension: %.11s",
+       tvb_get_ephemeral_string(tvb, offset+1, 11));
+    proto_tree_add_text(pt, tvb, offset+12, 4, "reserved");
+    offset += 16;
     for (i = 1; i <= devices; i++) {
-       ti = proto_tree_add_text(pt, NullTVB, *offset, 80, "Channel %d:", i);
+       ti = proto_tree_add_text(pt, tvb, offset, 80, "Channel %d:", i);
        ft = proto_item_add_subtree(ti, ett_gryphon_cmd_config_device);
-       MEMCPY (string, *data, 20);
-       proto_tree_add_text(ft, NullTVB, *offset, 20, "Driver name: %s", string);
-       BUMP (*offset, *data, 20);
-
-       MEMCPY (string, *data, 8);
-       proto_tree_add_text(ft, NullTVB, *offset, 8, "Driver version: %s", string);
-       BUMP (*offset, *data, 8);
-
-       MEMCPY (string, *data, 24);
-       proto_tree_add_text(ft, NullTVB, *offset, 24, "device security string: %s", string);
-       BUMP (*offset, *data, 24);
+       proto_tree_add_text(ft, tvb, offset, 20, "Driver name: %.20s",
+           tvb_get_ephemeral_string(tvb, offset, 20));
+       offset += 20;
+
+       proto_tree_add_text(ft, tvb, offset, 8, "Driver version: %.8s",
+           tvb_get_ephemeral_string(tvb, offset, 8));
+       offset += 8;
+
+       proto_tree_add_text(ft, tvb, offset, 16, "Device security string: %.16s",
+           tvb_get_ephemeral_string(tvb, offset, 16));
+       offset += 16;
+
+        x = tvb_get_ntohl (tvb, offset);
+        if (x) {
+            item = proto_tree_add_text(ft, tvb, offset, 4, "Valid Header lengths");
+            tree = proto_item_add_subtree (item, ett_gryphon_valid_headers);
+            for (j = 0; ; j++) {
+                if (x & 1) {
+                   proto_tree_add_text(tree, tvb, offset, 4, "%d byte%s", j,
+                    j == 1 ? "" : "s");
+                }
+                if ((x >>= 1) == 0)
+                    break;
+            }
+        }
+       offset += 4;
+
+        x = tvb_get_ntohs (tvb, offset);
+       proto_tree_add_text(ft, tvb, offset, 2, "Maximum data length = %d byte%s",
+                x, x == 1 ? "" : "s");
+       offset += 2;
+
+        x = tvb_get_ntohs (tvb, offset);
+       proto_tree_add_text(ft, tvb, offset, 2, "Minimum data length = %d byte%s",
+                x, x == 1 ? "" : "s");
+       offset += 2;
+
+       proto_tree_add_text(ft, tvb, offset, 20, "Hardware serial number: %.20s",
+           tvb_get_ephemeral_string(tvb, offset, 20));
+       offset += 20;
+
+       x = tvb_get_ntohs(tvb, offset);
+       proto_tree_add_text(ft, tvb, offset, 2, "Protocol type & subtype: %s",
+           val_to_str(x, protocol_types, "Unknown (0x%04x)"));
+       offset += 2;
+
+       proto_tree_add_text(ft, tvb, offset, 1, "Channel ID: %u",
+           tvb_get_guint8(tvb, offset));
+        offset++;
+
+       proto_tree_add_text(ft, tvb, offset, 1, "Card slot number: %u",
+           tvb_get_guint8(tvb, offset));
+        offset ++;
+
+        x = tvb_get_ntohs (tvb, offset);
+       proto_tree_add_text(ft, tvb, offset, 2, "Maximum extra data = %d byte%s",
+                x, x == 1 ? "" : "s");
+        offset += 2;
+
+        x = tvb_get_ntohs (tvb, offset);
+       proto_tree_add_text(ft, tvb, offset, 2, "Minimum extra data = %d byte%s",
+                x, x == 1 ? "" : "s");
+        offset += 2;
 
-       MEMCPY (string, *data, 20);
-       proto_tree_add_text(ft, NullTVB, *offset, 20, "Hardware serial number: %s", string);
-       BUMP (*offset, *data, 20);
-
-       x = pntohs ((unsigned short *)*data);
-       for (j = 0; j < SIZEOF(protocol_types); j++) {
-           if (protocol_types[j].value == x)
-               break;
-       }
-       if (j >= SIZEOF(protocol_types))
-           j = SIZEOF(protocol_types) -1;
-       proto_tree_add_text(ft, NullTVB, *offset, 2, "Protocol type & subtype: %s", protocol_types[j].strptr);
-       BUMP (*offset, *data, 2);
-
-       proto_tree_add_text(ft, NullTVB, *offset, 1, "Channel ID: %hd", **data);
-       proto_tree_add_text(ft, NullTVB, *offset+1, 5, "reserved");
-       BUMP (*offset, *data, 6);
     }
+    return offset;
 }
 
-void
-cmd_sched (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_sched(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
+    int                    msglen;
     proto_item     *item, *item1;
     proto_tree     *tree, *tree1;
+    int                    save_offset;
     unsigned int    i, x, length;
-    unsigned char   def_chan = *((*data)-9);
-    char           *ptr;
-    char           crit[] = ".... ...1 = Critical scheduler";
-    char           norm[] = ".... ...0 = Normal scheduler";
-    
-    x = pntohl ((unsigned int *)*data);
+    unsigned char   def_chan = tvb_get_guint8(tvb, offset-9);
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    x = tvb_get_ntohl(tvb, offset);
     if (x == 0xFFFFFFFF)
-       proto_tree_add_text(pt, NullTVB, *offset, 4, "Number of iterations: infinite");
+       proto_tree_add_text(pt, tvb, offset, 4, "Number of iterations: \"infinite\"");
     else
-       proto_tree_add_text(pt, NullTVB, *offset, 4, "Number of iterations: %d", x);
-    BUMP (*offset, *data, 4);
-    x = pntohl ((unsigned int *)*data);
-    item = proto_tree_add_text(pt, NullTVB, *offset, 4, "Flags");
+       proto_tree_add_text(pt, tvb, offset, 4, "Number of iterations: %u", x);
+    offset += 4;
+    msglen -= 4;
+    x = tvb_get_ntohl(tvb, offset);
+    item = proto_tree_add_text(pt, tvb, offset, 4, "Flags: 0x%08x", x);
     tree = proto_item_add_subtree (item, ett_gryphon_flags);
-    ptr = x & 1 ? crit : norm;
-    proto_tree_add_text(tree, NullTVB, *offset, 4, ptr, NULL);
-    BUMP (*offset, *data, 4);
+    proto_tree_add_text(tree, tvb, offset, 4, "%s",
+       decode_boolean_bitfield(x, 0x01, 32,
+           "Critical scheduler", "Normal scheduler"));
+    offset += 4;
+    msglen -= 4;
     i = 1;
-    while (*data < dataend) {
-       length = 16 + (*data)[16] + pntohs ((unsigned short *)((*data)+18)) + (*data)[20] + 16;
+    while (msglen > 0) {
+       length = 16 + tvb_get_guint8(tvb, offset+16) +
+           tvb_get_ntohs(tvb, offset+18) + tvb_get_guint8(tvb, offset+20) + 16;
        length += 3 - (length + 3) % 4;
-       item = proto_tree_add_text(pt, NullTVB, *offset, length, "Message %d", i);
+       item = proto_tree_add_text(pt, tvb, offset, length, "Message %d", i);
        tree = proto_item_add_subtree (item, ett_gryphon_cmd_sched_data);
-       x = pntohl ((unsigned int *)*data);
-       proto_tree_add_text(tree, NullTVB, *offset, 4, "Sleep: %d milliseconds", x);
-       BUMP (*offset, *data, 4);
-       x = pntohl ((unsigned int *)*data);
-       proto_tree_add_text(tree, NullTVB, *offset, 4, "Transmit count: %d", x);
-       BUMP (*offset, *data, 4);
-       x = pntohl ((unsigned int *)*data);
-       proto_tree_add_text(tree, NullTVB, *offset, 4, "Transmit period: %d milliseconds", x);
-       BUMP (*offset, *data, 4);
-       proto_tree_add_text(tree, NullTVB, *offset, 2, "reserved flags");
-       x = *((*data)+2);
+       x = tvb_get_ntohl(tvb, offset);
+       proto_tree_add_text(tree, tvb, offset, 4, "Sleep: %u milliseconds", x);
+       offset += 4;
+       msglen -= 4;
+       x = tvb_get_ntohl(tvb, offset);
+       proto_tree_add_text(tree, tvb, offset, 4, "Transmit count: %u", x);
+       offset += 4;
+       msglen -= 4;
+       x = tvb_get_ntohl(tvb, offset);
+       proto_tree_add_text(tree, tvb, offset, 4, "Transmit period: %u milliseconds", x);
+       offset += 4;
+       msglen -= 4;
+        x = tvb_get_ntohs(tvb, offset);
+       item1 = proto_tree_add_text(tree, tvb, offset, 2, "Flags");
+        tree1 = proto_item_add_subtree (item1, ett_gryphon_flags);
+        proto_tree_add_text(tree1, tvb, offset, 2, "%s%s",
+               decode_boolean_bitfield(x, 1, 16, "S", "Do not s"),
+                "kip the last \"Transmit period\"");
+        if (i == 1) {
+            proto_tree_add_text(tree1, tvb, offset, 2, "%s%s",
+                   decode_boolean_bitfield(x, 2, 16, "S", "Do not s"),
+                    "kip the first \"Sleep\" value");
+        }
+       x = tvb_get_guint8(tvb, offset+2);
        if (x == 0)
            x = def_chan;
-       proto_tree_add_text(tree, NullTVB, *offset+2, 1, "Channel: %d", x);
-       proto_tree_add_text(tree, NullTVB, *offset+3, 1, "reserved");
-       BUMP (*offset, *data, 4);
-       item1 = proto_tree_add_text(tree, NullTVB, *offset, length, "Message");
+       proto_tree_add_text(tree, tvb, offset+2, 1, "Channel: %u", x);
+       proto_tree_add_text(tree, tvb, offset+3, 1, "reserved");
+       offset += 4;
+       msglen -= 4;
+       item1 = proto_tree_add_text(tree, tvb, offset, length, "Message");
        tree1 = proto_item_add_subtree (item1, ett_gryphon_cmd_sched_cmd);
-       decode_data (src, data, dataend, offset, msglen, tree1);
+       save_offset = offset;
+       offset = decode_data(tvb, offset, tree1);
+       msglen -= offset - save_offset;
        i++;
     }
+    return offset;
 }
 
-void
-resp_blm_data (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_sched_rep(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    int     hours, minutes, seconds, fraction, i, x, fract;
-    unsigned long   timestamp;
-    char    *fields[] = {
+    int                    msglen;
+    proto_item     *item;
+    int                    save_offset;
+    unsigned int    x;
+    const char      *type;
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    x = tvb_get_ntohl(tvb, offset);
+    if (x & 0x80000000)
+        type = "Critical";
+    else
+        type = "Normal";
+    proto_tree_add_text(pt, tvb, offset, 4, "%s schedule ID: %u", type, x);
+    offset += 4;
+    msglen -= 4;
+    x= tvb_get_guint8(tvb, offset);
+    item = proto_tree_add_text(pt, tvb, offset, 1, "Message index: %d", x);
+    item = proto_tree_add_text(pt, tvb, offset + 1, 3, "reserved");
+    offset += 4;
+    msglen -= 4;
+    save_offset = offset;
+    offset = decode_data(tvb, offset, pt);
+    msglen -= offset - save_offset;
+    return offset;
+}
+
+static int
+resp_blm_data(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    unsigned int      i;
+    int               hours, minutes, seconds, fraction, x, fract;
+    unsigned long     timestamp;
+    static const char *fields[] = {
        "Bus load average: %d.%02d%%",
        "Current bus load: %d.%02d%%",
        "Peak bus load: %d.%02d%%",
        "Historic peak bus load: %d.%02d%%"
     };
 
-    timestamp = pntohl ((unsigned long *)(*data));
+    timestamp = tvb_get_ntohl(tvb, offset);
     hours = timestamp /(100000 * 60 *60);
     minutes = (timestamp / (100000 * 60)) % 60;
     seconds = (timestamp / 100000) % 60;
     fraction = timestamp % 100000;
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
-    BUMP (*offset, *data, 4);
+    proto_tree_add_text(pt, tvb, offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
+    offset += 4;
     for (i = 0; i < SIZEOF(fields); i++){
-       x = pntohs ((unsigned short *)(*data));
+       x = tvb_get_ntohs(tvb, offset);
        fract = x % 100;
        x /= 100;
-       proto_tree_add_text(pt, NullTVB, *offset, 2, fields[i], x, fract);
-       BUMP (*offset, *data, 2);
+       proto_tree_add_text(pt, tvb, offset, 2, fields[i], x, fract);
+       offset += 2;
     }
+    return offset;
 }
 
-void
-resp_blm_stat (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_blm_stat(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
     unsigned int    x, i;
-    char           *fields[] = {
-       "Receive frame count: %d",
-       "Transmit frame count: %d",
-       "Receive dropped frame count: %d",
-       "Transmit dropped frame count: %d",
-       "Receive error count: %d",
-       "Transmit error count: %d",
+    const char             *fields[] = {
+       "Receive frame count: %u",
+       "Transmit frame count: %u",
+       "Receive dropped frame count: %u",
+       "Transmit dropped frame count: %u",
+       "Receive error count: %u",
+       "Transmit error count: %u",
     };
 
-    resp_blm_data (src, data, dataend, offset, msglen, pt);
+    offset = resp_blm_data(tvb, offset, pt);
     for (i = 0; i < SIZEOF(fields); i++){
-       x = pntohl ((unsigned int *)(*data));
-       proto_tree_add_text(pt, NullTVB, *offset, 4, fields[i], x);
-       BUMP (*offset, *data, 4);
+       x = tvb_get_ntohl(tvb, offset);
+       proto_tree_add_text(pt, tvb, offset, 4, fields[i], x);
+       offset += 4;
     }
+    return offset;
 }
 
-void
-cmd_addresp (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static const value_string action_vals[] = {
+    { FR_RESP_AFTER_EVENT,  "Send response(s) for each conforming message" },
+    { FR_RESP_AFTER_PERIOD, "Send response(s) after the specified period expires following a conforming message" },
+    { FR_IGNORE_DURING_PER, "Send response(s) for a conforming message and ignore\nfurther messages until the specified period expires" },
+    { 0,                    NULL }
+};
+
+static const value_string deact_on_event_vals[] = {
+    { FR_DEACT_ON_EVENT,
+       "Deactivate this response for a conforming message" },
+    { FR_DELETE|FR_DEACT_ON_EVENT,
+       "Delete this response for a conforming message" },
+    { 0,
+       NULL }
+};
+
+static const value_string deact_after_per_vals[] = {
+    { FR_DEACT_AFTER_PER,
+       "Deactivate this response after the specified period following a conforming message" },
+    { FR_DELETE|FR_DEACT_AFTER_PER,
+       "Delete this response after the specified period following a conforming message" },
+    { 0,
+       NULL }
+};
+
+static int
+cmd_addresp(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
     proto_item *item;
     proto_tree *tree;
-    int        blocks, responses, old_handle, i, length;
+    guint8     flags;
+    int        blocks, responses, old_handle, i, msglen, length;
     int        action, actionType, actionValue;
-    char       *ptr;
-    char       active[] = ".... ..1. = The response is active";
-    char       inactive[] = ".... ..0. = The response is inactive";
+    tvbuff_t   *next_tvb;
 
     actionType = 0;
-    item = proto_tree_add_text(pt, NullTVB, *offset, 1, "Flags");
+    flags = tvb_get_guint8(tvb, offset);
+    item = proto_tree_add_text(pt, tvb, offset, 1, "Flags: 0x%02x", flags);
     tree = proto_item_add_subtree (item, ett_gryphon_flags);
-    if (**data & FILTER_ACTIVE_FLAG)
-       ptr = active;
-    else
-       ptr = inactive;
-    proto_tree_add_text(tree, NullTVB, *offset, 1, ptr, NULL);
-    BUMP (*offset, *data, 1);
-    blocks = **data;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of filter blocks = %d", blocks);
-    BUMP (*offset, *data, 1);
-    responses = **data;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of response blocks = %d", responses);
-    BUMP (*offset, *data, 1);
-    old_handle = **data;
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Old handle = %d", old_handle);
-    BUMP (*offset, *data, 1);
-    action = **data;
-    switch (action & 7) {
-    case FR_RESP_AFTER_EVENT:
-       ptr = "Send response(s) for each conforming message";
-       break;
-    case FR_RESP_AFTER_PERIOD:
-       ptr = "Send response(s) after the specified period expires following a conforming message";
-       break;
-    case FR_IGNORE_DURING_PER:
-       ptr = "Send response(s) for a conforming message and ignore\nfurther messages until the specified period expires";
-       break;
-    default:
-       ptr = "- unknown -";
-    }
-    item = proto_tree_add_text(pt, NullTVB, *offset, 1, "Action = %s", ptr);
+    proto_tree_add_text(tree, tvb, offset, 1, "%s",
+       decode_boolean_bitfield(flags, FILTER_ACTIVE_FLAG, 8,
+               "The response is active", "The response is inactive"));
+    offset += 1;
+    blocks = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Number of filter blocks = %d", blocks);
+    offset += 1;
+    responses = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Number of response blocks = %d", responses);
+    offset += 1;
+    old_handle = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Old handle = %d", old_handle);
+    offset += 1;
+    action = tvb_get_guint8(tvb, offset);
+    item = proto_tree_add_text(pt, tvb, offset, 1, "Action: %s",
+       val_to_str(action & 0x07, action_vals, "Unknown (%u)"));
     tree = proto_item_add_subtree (item, ett_gryphon_flags);
-    if (action & FR_DEACT_AFTER_PER && !(action & FR_DELETE)){
-       proto_tree_add_text(tree, NullTVB, *offset, 1,
-               "1.0. .... Deactivate this response after the specified period following a conforming message");
-    }
-    if (action & FR_DEACT_ON_EVENT && !(action & FR_DELETE)){
-       proto_tree_add_text(tree, NullTVB, *offset, 1,
-               ".10. .... Deactivate this response for a conforming message");
-    }
-    if (action & FR_DEACT_AFTER_PER && action & FR_DELETE){
-       proto_tree_add_text(tree, NullTVB, *offset, 1,
-               "1.1. .... Delete this response after the specified period following a conforming message");
-    }
-    if (action & FR_DEACT_ON_EVENT && action & FR_DELETE){
-       proto_tree_add_text(tree, NullTVB, *offset, 1,
-               ".11. .... Delete this response for a conforming message");
-    }
-    actionValue = pntohs ((unsigned short *)((*data)+2));
+    proto_tree_add_text(tree, tvb, offset, 1, "%s",
+       decode_enumerated_bitfield(action, 0x07, 8, action_vals, "%s"));
+    actionValue = tvb_get_ntohs(tvb, offset+2);
     if (actionValue) {
-       if (action & FR_PERIOD_MSGS){
-           ptr = "...1 .... The period is in frames";
+       if (action & FR_PERIOD_MSGS) {
            actionType = 1;
        } else {
-           ptr = "...0 .... The period is in 0.01 seconds";
            actionType = 0;
        }
-       proto_tree_add_text(tree, NullTVB, *offset, 1, ptr, NULL);
+       proto_tree_add_text(tree, tvb, offset, 1, "%s",
+           decode_boolean_bitfield(action, FR_PERIOD_MSGS, 8,
+               "The period is in frames", "The period is in 0.01 seconds"));
+    }
+    if (action & FR_DEACT_ON_EVENT) {
+       proto_tree_add_text(tree, tvb, offset, 1, "%s",
+           decode_enumerated_bitfield(action, FR_DELETE|FR_DEACT_ON_EVENT, 8,
+               deact_on_event_vals, "%s"));
+    }
+    if (action & FR_DEACT_AFTER_PER) {
+       proto_tree_add_text(tree, tvb, offset, 1, "%s",
+           decode_enumerated_bitfield(action, FR_DELETE|FR_DEACT_AFTER_PER, 8,
+               deact_after_per_vals, "%s"));
     }
-    BUMP (*offset, *data, 1);
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "reserved");
-    BUMP (*offset, *data, 1);
+    offset += 1;
+    proto_tree_add_text(pt, tvb, offset, 1, "reserved");
+    offset += 1;
     if (actionValue) {
        if (actionType == 1) {
-           proto_tree_add_text(tree, NullTVB, *offset, 2, "Period: %d messages", actionValue);
+           proto_tree_add_text(tree, tvb, offset, 2, "Period: %d messages", actionValue);
        } else {
-           proto_tree_add_text(tree, NullTVB, *offset, 2, "Period: %d.%02d seconds", actionValue/100, actionValue%100);
+           proto_tree_add_text(tree, tvb, offset, 2, "Period: %d.%02d seconds", actionValue/100, actionValue%100);
        }
     }
-    BUMP (*offset, *data, 2);
+    offset += 2;
     for (i = 1; i <= blocks; i++) {
-       length = pntohs ((unsigned short *)((*data)+2)) * 2 + 8;
+       length = tvb_get_ntohs(tvb, offset+2) * 2 + 8;
        length += 3 - (length + 3) % 4;
-       item = proto_tree_add_text(pt, NullTVB, *offset, length, "Filter block %d", i);
+       item = proto_tree_add_text(pt, tvb, offset, length, "Filter block %d", i);
        tree = proto_item_add_subtree (item, ett_gryphon_cmd_filter_block);
-       filter_block (src, data, dataend, offset, msglen, tree);
+       offset = filter_block(tvb, offset, tree);
     }
     for (i = 1; i <= responses; i++) {
-       length = pntohs ((unsigned short *)((*data)+4)) + 8;
-       length += 3 - (length + 3) % 4;
-       item = proto_tree_add_text(pt, NullTVB, *offset, length, "Response block %d", i);
+       msglen = tvb_get_ntohs(tvb, offset+4) + 8;
+       length = msglen + 3 - (msglen + 3) % 4;
+       item = proto_tree_add_text(pt, tvb, offset, length, "Response block %d", i);
        tree = proto_item_add_subtree (item, ett_gryphon_cmd_response_block);
-       dissect_gryphon((*data)-*offset, *offset, NULL, tree);
-       BUMP (*offset, *data, length);
+       next_tvb = tvb_new_subset(tvb, offset, msglen, msglen);
+       dissect_gryphon_message(next_tvb, NULL, tree, TRUE);
+       offset += length;
     }
+    return offset;
 }
 
-void
-resp_addresp (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_addresp(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    if (*data < dataend) {
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Response handle: %hd", **data);
-       proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-       BUMP (*offset, *data, 4);
-    }
+    proto_tree_add_text(pt, tvb, offset, 1, "Response handle: %u",
+       tvb_get_guint8(tvb, offset));
+    proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-cmd_modresp (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_modresp(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
     unsigned char   action;
-    unsigned char   dest = *((*data)-5);
-    int            i;
+    unsigned char   dest = tvb_get_guint8(tvb, offset-5);
+    guint8         resp_handle;
 
-    if (**data)
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Response handle: %hd", **data);
+    resp_handle = tvb_get_guint8(tvb, offset);
+    if (resp_handle)
+       proto_tree_add_text(pt, tvb, offset, 1, "Response handle: %u",
+           resp_handle);
     else if (dest)
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Response handles: all on channel %hd", dest);
+       proto_tree_add_text(pt, tvb, offset, 1, "Response handles: all on channel %c", dest);
     else
-       proto_tree_add_text(pt, NullTVB, *offset, 1, "Response handles: all");
-    action = *((*data) + 1);
-    for (i = 0; i < SIZEOF(filtacts); i++) {
-       if (filtacts[i].value == action)
-           break;
-    }
-    if (i >= SIZEOF(filtacts))
-       i = SIZEOF(filtacts) - 1;
-    proto_tree_add_text(pt, NullTVB, *offset+1, 1, "Action: %s response", filtacts[i].strptr);
-    proto_tree_add_text(pt, NullTVB, *offset+2, 2, "reserved");
-    BUMP (*offset, *data, 4);
+       proto_tree_add_text(pt, tvb, offset, 1, "Response handles: all");
+    action = tvb_get_guint8(tvb, offset+1);
+    proto_tree_add_text(pt, tvb, offset+1, 1, "Action: %s response",
+       val_to_str(action, filtacts, "Unknown (%u)"));
+    proto_tree_add_text(pt, tvb, offset+2, 2, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-resp_resphan (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_resphan(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    int        handles = **data;
+    int        handles = tvb_get_guint8(tvb, offset);
     int        i, padding;
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of response handles: %d", handles);
+
+    proto_tree_add_text(pt, tvb, offset, 1, "Number of response handles: %d", handles);
     for (i = 1; i <= handles; i++){
-       proto_tree_add_text(pt, NullTVB, *offset+i, 1, "Handle %d: %hd", i, *(*data+i));
+       proto_tree_add_text(pt, tvb, offset+i, 1, "Handle %d: %u", i,
+           tvb_get_guint8(tvb, offset+i));
     }
     padding = 3 - (handles + 1 + 3) % 4;
     if (padding)
-       proto_tree_add_text(pt, NullTVB, *offset+1+handles, padding, "padding");
-    BUMP (*offset, *data, 1+handles+padding);
+       proto_tree_add_text(pt, tvb, offset+1+handles, padding, "padding");
+    offset += 1+handles+padding;
+    return offset;
 }
 
-void
-resp_sched (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_sched(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    unsigned int    id = pntohl ((unsigned int *)(*data));
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "Transmit schedule ID: %d", id);
-    BUMP (*offset, *data, 4);
+    unsigned int    id = tvb_get_ntohl(tvb, offset);
+
+    proto_tree_add_text(pt, tvb, offset, 4, "Transmit schedule ID: %u", id);
+    offset += 4;
+    return offset;
 }
 
-void
-cmd_desc (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_desc(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    u_char  string[81];
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "Program size: %d bytes", pntohl ((unsigned int *)(*data)));
-    BUMP (*offset, *data, 4);
-    strncpy (string, *data, 32);
-    string[32] = 0;
-    proto_tree_add_text(pt, NullTVB, *offset, 32, "Program name: %s", string);
-    BUMP (*offset, *data, 32);
-    strncpy (string, *data, 80);
-    string[80] = 0;
-    proto_tree_add_text(pt, NullTVB, *offset, 80, "Program description: %s", string);
-    BUMP (*offset, *data, 80);
+    proto_tree_add_text(pt, tvb, offset, 4, "Program size: %u bytes",
+       tvb_get_ntohl(tvb, offset));
+    offset += 4;
+    proto_tree_add_text(pt, tvb, offset, 32, "Program name: %.32s",
+       tvb_get_ephemeral_string(tvb, offset, 32));
+    offset += 32;
+    proto_tree_add_text(pt, tvb, offset, 80, "Program description: %.80s",
+       tvb_get_ephemeral_string(tvb, offset, 80));
+    offset += 80;
+    return offset;
 }
 
-void
-resp_desc (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+resp_desc(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
     proto_item *item;
     proto_tree *tree;
-    char       *ptr;
-    char       missing[] = ".... ...0 = The program is not present";
-    char       present[] = ".... ...1 = The program is already present";
-    
-    item = proto_tree_add_text(pt, NullTVB, *offset, 1, "Flags");
+    guint8     flags;
+
+    flags = tvb_get_guint8(tvb, offset);
+    item = proto_tree_add_text(pt, tvb, offset, 1, "Flags: 0x%02x", flags);
     tree = proto_item_add_subtree (item, ett_gryphon_flags);
-    if (**data & 1)
-       ptr = present;
-    else
-       ptr = missing;
-    proto_tree_add_text(tree, NullTVB, *offset, 1, ptr);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 1, "Handle: %hd", (*data)[1]);
-    proto_tree_add_text(pt, NullTVB, *offset+2, 2, "reserved");
-    BUMP (*offset, *data, 4);
+    proto_tree_add_text(tree, tvb, offset, 1, "%s",
+       decode_boolean_bitfield(flags, 0x01, 8,
+               "The program is already present",
+               "The program is not present"));
+    proto_tree_add_text(pt, tvb, offset+1, 1, "Handle: %u",
+       tvb_get_guint8(tvb, offset+1));
+    proto_tree_add_text(pt, tvb, offset+2, 2, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-cmd_upload (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
+static int
+cmd_upload(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int                    msglen;
     unsigned int    length;
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 2, "Block number: %d", pntohs ((unsigned short *)(*data)));
-    BUMP (*offset, *data, 4);
-    proto_tree_add_text(pt, NullTVB, *offset+2, 1, "Handle: %hd", (*data)[2]);
-    BUMP (*offset, *data, 3);
-    length = *data - dataend;
-    proto_tree_add_text(pt, NullTVB, *offset, length, "Data (%d bytes)", length);
-    BUMP (*offset, *data, length);
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 2, "Block number: %u",
+       tvb_get_ntohs(tvb, offset));
+    proto_tree_add_text(pt, tvb, offset+2, 1, "Handle: %u",
+       tvb_get_guint8(tvb, offset+2));
+    offset += 3;
+    msglen -= 3;
+    length = msglen;
+    proto_tree_add_text(pt, tvb, offset, length, "Data (%u byte%s)",
+            length, length == 1 ? "" : "s");
+    offset += length;
     length = 3 - (length + 3) % 4;
     if (length) {
-       proto_tree_add_text(pt, NullTVB, *offset, length, "padding");
-       BUMP (*offset, *data, length);
+       proto_tree_add_text(pt, tvb, offset, length, "padding");
+       offset += length;
     }
+    return offset;
 }
 
-void
-cmd_delete (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    u_char  string[33];
-    
-    strncpy (string, *data, 32);
-    string[32] = 0;
-    proto_tree_add_text(pt, NullTVB, *offset, 32, "Program name: %s", string);
-    BUMP (*offset, *data, 32);
+static int
+cmd_delete(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    proto_tree_add_text(pt, tvb, offset, 32, "Program name: %.32s",
+       tvb_get_ephemeral_string(tvb, offset, 32));
+    offset += 32;
+    return offset;
 }
 
-void
-cmd_list (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Block number: %hd", (*data)[0]);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
+static int
+cmd_list(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    proto_tree_add_text(pt, tvb, offset, 1, "Block number: %u",
+       tvb_get_guint8(tvb, offset));
+    proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    return offset;
 }
 
-void
-resp_list (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
+static int
+resp_list(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
     proto_item *item;
     proto_tree *tree;
-    u_char  string[81];
     unsigned int    i, count;
-    
-    count = (*data)[0];
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of programs in this response: %d", count);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 1, "reserved");
-    BUMP (*offset, *data, 2);
-    proto_tree_add_text(pt, NullTVB, *offset, 2, "Number of remaining programs: %d", pntohs ((unsigned short *)(*data)));
-    BUMP (*offset, *data, 2);
+
+    count = tvb_get_guint8(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 1, "Number of programs in this response: %u", count);
+    proto_tree_add_text(pt, tvb, offset+1, 1, "reserved");
+    offset += 2;
+    proto_tree_add_text(pt, tvb, offset, 2, "Number of remaining programs: %u",
+       tvb_get_ntohs(tvb, offset));
+    offset += 2;
     for (i = 1; i <= count; i++) {
-       item = proto_tree_add_text(pt, NullTVB, *offset, 112, "Program %d", i);
+       item = proto_tree_add_text(pt, tvb, offset, 112, "Program %u", i);
        tree = proto_item_add_subtree (item, ett_gryphon_pgm_list);
-       strncpy (string, *data, 32);
-       string[32] = 0;
-       proto_tree_add_text(tree, NullTVB, *offset, 32, "Name: %s", string);
-       BUMP (*offset, *data, 32);
-       strncpy (string, *data, 80);
-       string[80] = 0;
-       proto_tree_add_text(tree, NullTVB, *offset, 80, "Description: %s", string);
-       BUMP (*offset, *data, 80);
+       proto_tree_add_text(tree, tvb, offset, 32, "Name: %.32s",
+           tvb_get_ephemeral_string(tvb, offset, 32));
+       offset += 32;
+       proto_tree_add_text(tree, tvb, offset, 80, "Description: %.80s",
+           tvb_get_ephemeral_string(tvb, offset, 80));
+       offset += 80;
     }
+    return offset;
 }
 
-void
-cmd_start (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    u_char         string[120];
-    unsigned int    length;
-    
-    cmd_delete (src, data, dataend, offset, msglen, pt);
-    strncpy (string, *data, 119);
-    string[119] = 0;
-    length = strlen (string) + 1;
-    proto_tree_add_text(pt, NullTVB, *offset, length, "Arguments: %s", string);
-    BUMP (*offset, *data, length);
-    length = 3 - (length + 3) % 4;
-    if (length) {
-       proto_tree_add_text(pt, NullTVB, *offset, length, "padding");
-       BUMP (*offset, *data, length);
+static int
+cmd_start(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    guint8         *string;
+    gint           length;
+    int             msglen;
+    int             hdr_stuff = offset;
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    offset = cmd_delete(tvb, offset, pt);      /* decode the name */
+    if (offset < msglen + hdr_stuff) {
+        string = tvb_get_ephemeral_stringz(tvb, offset, &length);
+        if (length > 1) {
+            proto_tree_add_text(pt, tvb, offset, length, "Arguments: %s", string);
+            offset += length;
+            length = 3 - (length + 3) % 4;
+            if (length) {
+               proto_tree_add_text(pt, tvb, offset, length, "padding");
+               offset += length;
+            }
+        }
     }
+    return offset;
 }
 
-void
-resp_start (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Channel (Client) number: %hd", (*data)[0]);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
+static int
+resp_start(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int             msglen;
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    if (msglen > 0) {
+        proto_tree_add_text(pt, tvb, offset, 1, "Channel (Client) number: %u",
+           tvb_get_guint8(tvb, offset));
+        proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+        offset += 4;
+    }
+    return offset;
 }
 
-void
-resp_status (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
+static int
+resp_status(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
     proto_item *item;
     proto_tree *tree;
     unsigned int    i, copies, length;
-    
-    copies = (*data)[0];
-    item = proto_tree_add_text(pt, NullTVB, *offset, 1, "Number of running copies: %d", copies);
+
+    copies = tvb_get_guint8(tvb, offset);
+    item = proto_tree_add_text(pt, tvb, offset, 1, "Number of running copies: %u", copies);
     tree = proto_item_add_subtree (item, ett_gryphon_pgm_status);
-    BUMP (*offset, *data, 1);
+    offset += 1;
     if (copies) {
        for (i = 1; i <= copies; i++) {
-           proto_tree_add_text(tree, NullTVB, *offset, 1, "Program %d channel (client) number %hd", i, (*data)[0]);
-           BUMP (*offset, *data, 1);
+           proto_tree_add_text(tree, tvb, offset, 1, "Program %u channel (client) number %u",
+               i, tvb_get_guint8(tvb, offset));
+           offset += 1;
        }
     }
     length = 3 - (copies + 1 + 3) % 4;
     if (length) {
-       proto_tree_add_text(pt, NullTVB, *offset, length, "padding");
-       BUMP (*offset, *data, length);
+       proto_tree_add_text(pt, tvb, offset, length, "padding");
+       offset += length;
     }
+    return offset;
 }
 
-void
-cmd_options (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    proto_item *item;
-    proto_tree *tree;
+static int
+cmd_options(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int                    msglen;
+    proto_item     *item;
+    proto_tree     *tree;
     unsigned int    i, size, padding, option, option_length, option_value;
-    unsigned char   *string, *string1;
-    
-    item = proto_tree_add_text(pt, NullTVB, *offset, 1, "Handle: %hd", **data);
-    item = proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
-    for (i = 1; *data <= dataend; i++) {
-       size = (*data)[1] + 2;
+    const char     *string, *string1;
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    item = proto_tree_add_text(pt, tvb, offset, 1, "Handle: %u",
+       tvb_get_guint8(tvb, offset));
+    item = proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    msglen -= 4;
+    for (i = 1; msglen > 0; i++) {
+       option_length = tvb_get_guint8(tvb, offset+1);
+       size = option_length + 2;
        padding = 3 - ((size + 3) %4);
-       item = proto_tree_add_text(pt, NullTVB, *offset, size + padding, "Option number %d", i);
+       item = proto_tree_add_text(pt, tvb, offset, size + padding, "Option number %u", i);
        tree = proto_item_add_subtree (item, ett_gryphon_pgm_options);
-       option = **data;
-       option_length = (*data)[1];
+       option = tvb_get_guint8(tvb, offset);
        switch (option_length) {
        case 1:
-           option_value = (*data)[2];
+           option_value = tvb_get_guint8(tvb, offset+2);
            break;
        case 2:
-           option_value = pntohs ((unsigned short *)((*data)+2));
+           option_value = tvb_get_ntohs(tvb, offset+2);
            break;
        case 4:
-           option_value = pntohl ((unsigned int *)((*data)+2));
+           option_value = tvb_get_ntohl(tvb, offset+2);
            break;
        default:
            option_value = 0;
@@ -1496,188 +1873,384 @@ cmd_options (int src, const u_char **data, const u_char *dataend, int *offset, i
            }
            break;
        }
-       proto_tree_add_text(tree, NullTVB, *offset, 1, "%s", string);
-       proto_tree_add_text(tree, NullTVB, *offset+2, option_length, "%s", string1);
+       proto_tree_add_text(tree, tvb, offset, 1, "%s", string);
+       proto_tree_add_text(tree, tvb, offset+2, option_length, "%s", string1);
        if (padding)
-           proto_tree_add_text(tree, NullTVB, *offset+option_length+2, padding, "padding");
-       BUMP (*offset, *data, size + padding);
+           proto_tree_add_text(tree, tvb, offset+option_length+2, padding, "padding");
+       offset += size + padding;
+       msglen -= size + padding;
     }
+    return offset;
 }
 
-void
-cmd_files (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    u_char  *which, dir[256];
-    int     len;
-    
-    if ((*data)[0] == 0)
-       which = "First group of names";
+static int
+cmd_files(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int                 msglen;
+    const gchar  *which;
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    if (tvb_get_guint8(tvb, offset) == 0)
+       which = "First group of names";
     else
-       which = "Subsequent group of names";
-    
-    msglen -= 4;
-    len = msglen > 255 ? 255: msglen;
-    memset (dir, 0, 256);
-    strncpy (dir, (*data)+1, len);
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "%s", which);
-    proto_tree_add_text(pt, NullTVB, *offset+1, msglen-1, "Directory: %s", dir);
-    BUMP (*offset, *data, msglen);
+       which = "Subsequent group of names";
+
+    proto_tree_add_text(pt, tvb, offset, 1, "%s", which);
+    proto_tree_add_text(pt, tvb, offset+1, msglen-1, "Directory: %.*s",
+       msglen-1, tvb_get_ephemeral_string(tvb, offset+1, msglen-1));
+    offset += msglen;
+    return offset;
 }
 
-void
-resp_files (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    u_char     *flag;
-    
-    msglen -= 8;
-    flag = (*data)[0] ? "Yes": "No";
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "More filenames to return: %s", flag);
-    proto_tree_add_text(pt, NullTVB, *offset+1, msglen-1, "File and directory names");
-    BUMP (*offset, *data, msglen);
+static int
+resp_files(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int                        msglen;
+    const gchar        *flag;
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    flag = tvb_get_guint8(tvb, offset) ? "Yes": "No";
+    proto_tree_add_text(pt, tvb, offset, 1, "More filenames to return: %s", flag);
+    proto_tree_add_text(pt, tvb, offset+1, msglen-1, "File and directory names");
+    offset += msglen;
+    return offset;
 }
 
-void
-cmd_usdt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
+static int
+cmd_usdt(tvbuff_t *tvb, int offset, proto_tree *pt)
 {
-    u_char  *desc;
-    
-    if ((*data)[0])
-       desc = "Register with gusdt";
-    else
-       desc = "Unregister with gusdt";
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "%s", desc);
-    
-    if ((*data)[1])
-       desc = "Echo long transmit messages back to the client";
-    else
-       desc = "Do not echo long transmit messages back to the client";
-    proto_tree_add_text(pt, NullTVB, (*offset)+1, 1, "%s", desc);
-    
-    if ((*data)[2] == 2)
-       desc = "Assemble long received messages but do not send them to the client";
-    else if ((*data)[2])
-       desc = "Assemble long received messages and send them to the client";
+    int                ids, id, remain, size, i, j, bytes;
+    const gchar        *desc;
+    guint8     flags;
+    proto_tree *localTree;
+    proto_item *localItem;
+    const gchar        *actions[] = {
+       "Use 11 bit headers only",
+       "Use 29 bit headers only",
+       "Use both 11 & 29 bit headers",
+       "undefined"
+    };
+    const gchar *xmit_opts[] = {
+       "Pad messages with less than 8 data bytes with 0x00's",
+       "Pad messages with less than 8 data bytes with 0xFF's",
+       "Do not pad messages with less than 8 data bytes",
+       "undefined"
+    };
+    const gchar *recv_opts[] = {
+       "Do not verify the integrity of long received messages and do not send them to the client",
+       "Verify the integrity of long received messages and send them to the client",
+       "Verify the integrity of long received messages but do not send them to the client",
+       "undefined"
+    };
+    const gchar *block_desc[] = {"USDT request", "USDT response", "UUDT response"};
+
+    flags = tvb_get_guint8(tvb, offset);
+    if (flags & 1)
+       desc = "R";
     else
-       desc = "Do not assemble long received messages on behalf of the client";
-    proto_tree_add_text(pt, NullTVB, (*offset)+2, 1, "%s", desc);
-    
-    BUMP (*offset, *data, 4);
+       desc = "Unr";
+    proto_tree_add_text(pt, tvb, offset, 1, "%segister with gusdt", desc);
+
+    if (flags & 1) {
+        localItem = proto_tree_add_text(pt, tvb, offset, 1, "Action flags");
+        localTree = proto_item_add_subtree (localItem, ett_gryphon_flags);
+       proto_tree_add_text(localTree, tvb, offset, 1, "%s%s",
+           decode_boolean_bitfield (flags, 1, 8,
+               "R", "Unr"), "egister with gusdt");
+       proto_tree_add_text(localTree, tvb, offset, 1, "%s = %s",
+            decode_numeric_bitfield (flags, 6, 8, "%d"),
+            actions[(flags >> 1) & 3]);
+
+        flags = tvb_get_guint8(tvb, offset+1);
+        localItem = proto_tree_add_text(pt, tvb, offset+1, 1, "Transmit options");
+        localTree = proto_item_add_subtree (localItem, ett_gryphon_flags);
+       proto_tree_add_text(localTree, tvb, offset+1, 1, "%s%s",
+           decode_boolean_bitfield (flags, 1, 8,
+               "E", "Do not e"),
+                "cho long transmit messages back to the client");
+       proto_tree_add_text(localTree, tvb, offset+1, 1, "%s = %s",
+            decode_numeric_bitfield (flags, 6, 8, "%d"),
+            xmit_opts[(flags >> 1) & 3]);
+       proto_tree_add_text(localTree, tvb, offset+1, 1, "%s%s",
+           decode_boolean_bitfield (flags, 8, 8,
+               "S", "Do not s"),
+                "end a USDT_DONE event when the last frame of a multi-frame USDT message is transmitted");
+
+        flags = tvb_get_guint8(tvb, offset+2);
+        localItem = proto_tree_add_text(pt, tvb, offset+2, 1, "Receive options");
+        localTree = proto_item_add_subtree (localItem, ett_gryphon_flags);
+       proto_tree_add_text(localTree, tvb, offset+2, 1, "%s = %s",
+            decode_numeric_bitfield (flags, 3, 8, "%d"),
+            recv_opts[flags & 3]);
+       proto_tree_add_text(localTree, tvb, offset+2, 1, "%s%s",
+           decode_boolean_bitfield (flags, 4, 8,
+               "S", "Do not s"),
+                "end a USDT_FIRSTFRAME event when the first frame of a multi-frame USDT message is received");
+       proto_tree_add_text(localTree, tvb, offset+2, 1, "%s%s",
+           decode_boolean_bitfield (flags, 8, 8,
+               "S", "Do not s"),
+                "end a USDT_LASTFRAME event when the last frame of a multi-frame USDT message is received");
+
+        if ((ids = tvb_get_guint8(tvb, offset+3))) {
+            localItem = proto_tree_add_text(pt, tvb, offset+3, 1, "Using extended addressing for %d ID%s",
+                    ids, ids == 1?"":"s");
+            offset += 4;
+            localTree = proto_item_add_subtree (localItem, ett_gryphon_usdt_data);
+            while (ids) {
+                id = tvb_get_ntohl (tvb, offset);
+                proto_tree_add_text (localTree, tvb, offset, 4, "%04X", id);
+                offset += 4;
+                ids--;
+            }
+        } else {
+            proto_tree_add_text(pt, tvb, offset+3, 1, "Using extended addressing for the single, internally defined, ID");
+            offset += 4;
+        }
+        for (i = 0; i < 2; i++) {
+            bytes = tvb_reported_length_remaining (tvb, offset);
+            if (bytes <= 0)
+                break;
+            localItem = proto_tree_add_text(pt, tvb, offset, 16, "%s block of USDT/UUDT IDs", i==0?"First":"Second");
+            localTree = proto_item_add_subtree (localItem, ett_gryphon_usdt_data);
+            size = tvb_get_ntohl (tvb, offset);
+            if (size == 0) {
+                proto_tree_add_text (localTree, tvb, offset, 16, "No IDs in the block");
+                offset += 16;
+            } else if (size == 1) {
+                proto_tree_add_text (localTree, tvb, offset, 4, "1 ID in the block");
+                offset += 4;
+                for (j = 0; j < 3; j++){
+                    id = tvb_get_ntohl (tvb, offset);
+                    proto_tree_add_text (localTree, tvb, offset, 4,
+                            "%s ID: %04X", block_desc[j], id);
+                    offset += 4;
+                }
+            } else {
+                proto_tree_add_text (localTree, tvb, offset, 4, "%d IDs in the block", size);
+                offset += 4;
+                for (j = 0; j < 3; j++){
+                    id = tvb_get_ntohl (tvb, offset);
+                    proto_tree_add_text (localTree, tvb, offset, 4,
+                            "%s IDs from %04X through %04X", block_desc[j], id, id+size-1);
+                    offset += 4;
+                }
+            }
+        }
+    } else {
+        proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+        offset += 4;
+    }
+
+    if ((remain = tvb_reported_length_remaining(tvb, offset))) {
+        proto_tree_add_text(pt, tvb, offset, remain, "%d ignored byte%s",
+                remain, remain == 1 ? "" : "s");
+        offset += remain;
+    }
+
+    return offset;
 }
 
-void
-speed (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 1, "Baud rate index: %hd", (*data)[0]);
-    proto_tree_add_text(pt, NullTVB, *offset+1, 3, "reserved");
-    BUMP (*offset, *data, 4);
+static int
+cmd_bits_in (tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    proto_item *item;
+    proto_tree *tree;
+    unsigned int i;
+    int                msglen, mask, value;
+    const char  *decode[] = {"Input 1", "Input 2", "Input 3", "Pushbutton"};
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    value = tvb_get_guint8(tvb, offset);
+    if (value) {
+        item = proto_tree_add_text(pt, tvb, offset, 1, "Digital values set");
+        tree = proto_item_add_subtree (item, ett_gryphon_digital_data);
+        for (i = 0, mask = 1; i < SIZEOF (decode); mask <<= 1, i++) {
+            if (value & mask) {
+                proto_tree_add_text(tree, tvb, offset, 1, "%s is set",
+                        decode[i]);
+            }
+        }
+    } else {
+        proto_tree_add_text(pt, tvb, offset, 1, "No digital values are set");
+    }
+
+    offset++;
+    msglen--;
+    return offset;
 }
 
-void
-filter_block (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    int     length, type, i, operator, padding;
-    
-    proto_tree_add_text(pt, NullTVB, *offset, 2, "Filter field starts at byte %d", pntohs ((unsigned short *)(*data)));
-    length = pntohs ((unsigned short *)((*data)+2));
-    proto_tree_add_text(pt, NullTVB, *offset+2, 2, "Filter field is %d bytes long", length);
-    type = *((*data)+4);
-    for (i = 0; i < SIZEOF(filter_data_types); i++) {
-       if (filter_data_types[i].value == type)
-           break;
+static int
+cmd_bits_out (tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    proto_item *item;
+    proto_tree *tree;
+    unsigned int i;
+    int                msglen, mask, value;
+    const char  *decode[] = {"Output 1", "Output 2"};
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    value = tvb_get_guint8(tvb, offset);
+    if (value) {
+        item = proto_tree_add_text(pt, tvb, offset, 1, "Digital values set");
+        tree = proto_item_add_subtree (item, ett_gryphon_digital_data);
+        for (i = 0, mask = 1; i < SIZEOF (decode); mask <<= 1, i++) {
+            if (value & mask) {
+                proto_tree_add_text(tree, tvb, offset, 1, "%s is set",
+                        decode[i]);
+            }
+        }
+    } else {
+        proto_tree_add_text(pt, tvb, offset, 1, "No digital values are set");
     }
-    if (i >= SIZEOF(filter_data_types))
-       i = SIZEOF(filter_data_types) - 1;
-    proto_tree_add_text(pt, NullTVB, *offset+4, 1, "Filtering on %s", filter_data_types[i].strptr);
 
-    operator = *((*data)+5);
-    for (i = 0; i < SIZEOF(operators); i++) {
-       if (operators[i].value == operator)
-           break;
+    offset++;
+    msglen--;
+    return offset;
+}
+
+static int
+cmd_init_strat (tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    int            msglen, index;
+    float   value;
+
+    msglen = tvb_reported_length_remaining(tvb, offset);
+    proto_tree_add_text(pt, tvb, offset, 4, "Reset Limit = %u messages",
+       tvb_get_ntohl(tvb, offset));
+    offset += 4;
+    msglen -= 4;
+    for (index = 1; msglen; index++, offset++, msglen--) {
+        value = tvb_get_guint8(tvb, offset);
+        if (value) {
+            value /= 4;
+            proto_tree_add_text(pt, tvb, offset, 1, "Delay %d = %.2f seconds",
+               index, value);
+        } else {
+            proto_tree_add_text(pt, tvb, offset, 1, "Delay %d = infinite",
+               index);
+        }
     }
-    if (i >= SIZEOF(operators))
-       i = SIZEOF(operators) - 1;
-    proto_tree_add_text(pt, NullTVB, *offset+5, 1, "Type of comparison: %s", operators[i].strptr);
-    proto_tree_add_text(pt, NullTVB, *offset+6, 2, "reserved");
-    BUMP (*offset, *data, 8);
-    
+    return offset;
+}
+
+static int
+speed(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    proto_tree_add_text(pt, tvb, offset, 1, "Baud rate index: %u",
+       tvb_get_guint8(tvb, offset));
+    proto_tree_add_text(pt, tvb, offset+1, 3, "reserved");
+    offset += 4;
+    return offset;
+}
+
+static int
+filter_block(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    unsigned int    type, operator;
+    int     length, padding;
+
+    proto_tree_add_text(pt, tvb, offset, 2, "Filter field starts at byte %u",
+       tvb_get_ntohs(tvb, offset));
+    length = tvb_get_ntohs(tvb, offset+2);
+    proto_tree_add_text(pt, tvb, offset+2, 2, "Filter field is %d byte%s long",
+            length, length == 1 ? "" : "s");
+    type = tvb_get_guint8(tvb, offset+4);
+    proto_tree_add_text(pt, tvb, offset+4, 1, "Filtering on %s",
+       val_to_str(type, filter_data_types, "Unknown (0x%02x)"));
+
+    operator = tvb_get_guint8(tvb, offset+5);
+    proto_tree_add_text(pt, tvb, offset+5, 1, "Type of comparison: %s",
+       val_to_str(operator, operators, "Unknown (%u)"));
+    proto_tree_add_text(pt, tvb, offset+6, 2, "reserved");
+    offset += 8;
+
     if (operator == BIT_FIELD_CHECK) {
-       proto_tree_add_text(pt, NullTVB, *offset, length, "Pattern");
-       proto_tree_add_text(pt, NullTVB, *offset+length, length, "Mask");
+       proto_tree_add_text(pt, tvb, offset, length, "Pattern");
+       proto_tree_add_text(pt, tvb, offset+length, length, "Mask");
     } else {
-       switch (length) {
+       switch (length) {
        case 1:
-           proto_tree_add_text(pt, NullTVB, *offset, 1, "Value: %hd", **data);
+           proto_tree_add_text(pt, tvb, offset, 1, "Value: %u",
+               tvb_get_guint8(tvb, offset));
            break;
        case 2:
-           proto_tree_add_text(pt, NullTVB, *offset, 2, "Value: %d", pntohs ((unsigned short *)(*data)));
+           proto_tree_add_text(pt, tvb, offset, 2, "Value: %u",
+               tvb_get_ntohs(tvb, offset));
            break;
        case 4:
-           proto_tree_add_text(pt, NullTVB, *offset, 4, "Value: %dl", pntohl ((unsigned long *)(*data)));
+           proto_tree_add_text(pt, tvb, offset, 4, "Value: %u",
+               tvb_get_ntohl(tvb, offset));
            break;
        default:
-           proto_tree_add_text(pt, NullTVB, *offset, length, "Value");
+           proto_tree_add_text(pt, tvb, offset, length, "Value");
        }
     }
-    BUMP (*offset, *data, length * 2);
+    offset += length * 2;
     padding = 3 - (length * 2 + 3) % 4;
     if (padding) {
-       proto_tree_add_text(pt, NullTVB, *offset, padding, "padding");
-       BUMP (*offset, *data, padding);
+       proto_tree_add_text(pt, tvb, offset, padding, "padding");
+       offset += padding;
     }
+    return offset;
 }
 
-void
-blm_mode (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
-    
-    char    *mode, line[50];
+static int
+blm_mode(tvbuff_t *tvb, int offset, proto_tree *pt)
+{
+    const char    *mode;
+    char line[50];
     int     x, y, seconds;
-    
-    x = pntohl ((unsigned long *)(*data));
-    y = pntohl ((unsigned long *)((*data)+4));
+
+    x = tvb_get_ntohl(tvb, offset);
+    y = tvb_get_ntohl(tvb, offset+4);
     switch (x) {
     case 0:
        mode = "Off";
-       sprintf (line, "reserved");
+       g_snprintf (line, 50, "reserved");
        break;
     case 1:
        mode = "Average over time";
        seconds = y / 1000;
        y = y % 1000;
-       sprintf (line, "Averaging period: %d.%03d seconds", seconds, y);
+       g_snprintf (line, 50, "Averaging period: %d.%03d seconds", seconds, y);
        break;
     case 2:
        mode = "Average over frame count";
-       sprintf (line, "Averaging period: %d frames", y);
+       g_snprintf (line, 50, "Averaging period: %d frames", y);
        break;
     default:
        mode = "- unknown -";
-       sprintf (line, "reserved");
+       g_snprintf (line, 50, "reserved");
     }
-    proto_tree_add_text(pt, NullTVB, *offset, 4, "Mode: %s", mode);
-    BUMP (*offset, *data, 4);
-    proto_tree_add_text(pt, NullTVB, *offset, 4, line, NULL);
-    BUMP (*offset, *data, 4);
+    proto_tree_add_text(pt, tvb, offset, 4, "Mode: %s", mode);
+    offset += 4;
+    proto_tree_add_text(pt, tvb, offset, 4, line, NULL);
+    offset += 4;
+    return offset;
 }
 
-G_MODULE_EXPORT void
-plugin_init(plugin_address_table_t *pat)
+void
+proto_register_gryphon(void)
 {
     static hf_register_info hf[] = {
-       { &hf_gryph_src,
-       { "Source",           "gryph.src", FT_UINT8, BASE_DEC, NULL, 0x0,
-               "" }},
-       { &hf_gryph_srcchan,
-       { "Source channel",   "gryph.srcchan", FT_UINT8, BASE_DEC, NULL, 0x0,
-               "" }},
-       { &hf_gryph_dest,
-       { "Destination",      "gryph.dest", FT_UINT8, BASE_DEC, NULL, 0x0,
-               "" }},
-       { &hf_gryph_destchan,
-       { "Destination channel", "gryph.dstchan", FT_UINT8, BASE_DEC, NULL, 0x0,
-               "" }},
-       { &hf_gryph_type,
-       { "Frame type",       "gryph.type", FT_UINT8, BASE_DEC, NULL, 0x0,
-               "" }},
-       { &hf_gryph_cmd,
-       { "Command",          "gryph.cmd.cmd", FT_UINT8, BASE_DEC, NULL, 0x0,
-               "" }},
+       { &hf_gryphon_src,
+       { "Source",           "gryphon.src", FT_UINT8, BASE_HEX, VALS(src_dest), 0x0,
+               NULL, HFILL }},
+       { &hf_gryphon_srcchan,
+       { "Source channel",   "gryphon.srcchan", FT_UINT8, BASE_DEC, NULL, 0x0,
+               NULL, HFILL }},
+       { &hf_gryphon_dest,
+       { "Destination",      "gryphon.dest", FT_UINT8, BASE_HEX, VALS(src_dest), 0x0,
+               NULL, HFILL }},
+       { &hf_gryphon_destchan,
+       { "Destination channel", "gryphon.destchan", FT_UINT8, BASE_DEC, NULL, 0x0,
+               NULL, HFILL }},
+       { &hf_gryphon_type,
+       { "Frame type",       "gryphon.type", FT_UINT8, BASE_DEC, NULL, 0x0,
+               NULL, HFILL }},
+       { &hf_gryphon_cmd,
+       { "Command",          "gryphon.cmd", FT_UINT8, BASE_DEC, NULL, 0x0,
+               NULL, HFILL }},
     };
 
     static gint *ett[] = {
@@ -1698,23 +2271,30 @@ plugin_init(plugin_address_table_t *pat)
        &ett_gryphon_pgm_list,
        &ett_gryphon_pgm_status,
        &ett_gryphon_pgm_options,
+        &ett_gryphon_valid_headers,
+        &ett_gryphon_usdt_data,
+        &ett_gryphon_digital_data,
     };
-    plugin_address_table_init(pat);
-    if (proto_gryphon == -1) {
-       /* first activation */
-       proto_gryphon = proto_register_protocol("DG Gryphon Protocol",
-                                               "Gryphon",
-                                               "gryphon");
-       proto_register_field_array(proto_gryphon, hf, array_length(hf));
-       proto_register_subtree_array(ett, array_length(ett));
-    } else {
-       /* do nothing, this is in fact a re-activation with possibly 
-          a new filter */
-    }
+    module_t *gryphon_module;
+
+    proto_gryphon = proto_register_protocol("DG Gryphon Protocol",
+                                           "Gryphon",
+                                           "gryphon");
+    proto_register_field_array(proto_gryphon, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+
+    gryphon_module = prefs_register_protocol(proto_gryphon, NULL);
+    prefs_register_bool_preference(gryphon_module, "desegment",
+       "Desegment all Gryphon messages spanning multiple TCP segments",
+       "Whether the Gryphon dissector should desegment all messages spanning multiple TCP segments",
+       &gryphon_desegment);
 }
 
-G_MODULE_EXPORT void
-plugin_reg_handoff(void)
+void
+proto_reg_handoff_gryphon(void)
 {
-    old_dissector_add("tcp.port", 7000, &dissect_gryphon, proto_gryphon);
+    dissector_handle_t gryphon_handle;
+
+    gryphon_handle = create_dissector_handle(dissect_gryphon, proto_gryphon);
+    dissector_add_uint("tcp.port", 7000, gryphon_handle);
 }