Add a Mac OS X icon file, for possible future use.
[obnox/wireshark/wip.git] / packet-ndmp.c
index 48de9e82983fe27ba4c058c8871a2af451bad117..f0ee37b8fadb645045e17e7467b26b9dbb78e0cb 100644 (file)
@@ -2,39 +2,35 @@
  * Routines for NDMP dissection
  * 2001 Ronnie Sahlberg (see AUTHORS for email)
  *
- * $Id: packet-ndmp.c,v 1.15 2002/02/13 01:17:58 guy Exp $
+ * $Id: packet-ndmp.c,v 1.25 2003/12/27 04:01:17 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 /* see www.ndmp.org for protocol specifications.
-   this file implements version 3 of ndmp 
+   this file implements version 3 of ndmp
 */
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
 #include <stdio.h>
 #include <string.h>
 #include <glib.h>
 #include "packet-scsi.h"
 #include "packet-frame.h"
 #include "prefs.h"
+#include "reassemble.h"
+#include "rpc_defrag.h"
 
 #define TCP_PORT_NDMP 10000
 
-#define NDMP_FRAGLEN 0x7fffffffL
-
 static int proto_ndmp = -1;
 static int hf_ndmp_version = -1;
-static int hf_ndmp_size = -1;
 static int hf_ndmp_header = -1;
 static int hf_ndmp_sequence = -1;
 static int hf_ndmp_reply_sequence = -1;
@@ -244,7 +239,8 @@ struct ndmp_header {
 /* desegmentation of NDMP packets */
 static gboolean ndmp_desegment = TRUE;
 
-
+/* defragmentation of fragmented NDMP records */
+static gboolean ndmp_defragment = FALSE;
 
 #define NDMP_MESSAGE_REQUEST   0x00
 #define NDMP_MESSAGE_REPLY     0x01
@@ -425,10 +421,9 @@ static const value_string msg_vals[] = {
        {0, NULL}
 };
 
-
 static int
-dissect_connect_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_connect_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* version number */
        proto_tree_add_item(tree, hf_ndmp_version, tvb, offset, 4, FALSE);
@@ -438,8 +433,8 @@ dissect_connect_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_error(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
-    guint32 seq)
+dissect_error(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -449,27 +444,27 @@ dissect_error(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
 }
 
 static int
-dissect_ndmp_get_host_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_ndmp_get_host_info_reply(tvbuff_t *tvb, int offset,
+    packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* hostname */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_hostname, offset, NULL);
 
        /* os type */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_os_type, offset, NULL);
 
        /* os version */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_os_vers, offset, NULL);
 
        /* hostid */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_hostid, offset, NULL);
 
        return offset;
@@ -488,7 +483,8 @@ static const value_string addr_type_vals[] = {
 };
 
 static int
-dissect_ndmp_addr_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_ndmp_addr_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
        offset += 4;
@@ -498,7 +494,7 @@ dissect_ndmp_addr_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
 
 static int
 dissect_ndmp_addr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /*address type*/
        return dissect_ndmp_addr_type(tvb, offset, pinfo, tree);
@@ -506,7 +502,7 @@ dissect_ndmp_addr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 static int
 dissect_ndmp_config_get_connection_type_reply(tvbuff_t *tvb, int offset,
-    packet_info *pinfo, proto_tree *tree, guint32 seq)
+    packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -529,7 +525,8 @@ static const value_string auth_type_vals[] = {
        {0,NULL}
 };
 static int
-dissect_auth_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_auth_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
        offset += 4;
@@ -539,18 +536,18 @@ dissect_auth_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
 
 static int
 dissect_get_auth_type_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* auth type */
        return dissect_auth_type(tvb, offset, pinfo, tree);
 }
 
 static int
-dissect_auth_attr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_auth_attr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        guint type;
-       
+
        type=tvb_get_ntohl(tvb,offset);
 
        /* auth type */
@@ -563,7 +560,7 @@ dissect_auth_attr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
        case NDMP_AUTH_TEXT:
                break;
        case NDMP_AUTH_MD5:
-               proto_tree_add_item(tree, hf_ndmp_auth_challenge, 
+               proto_tree_add_item(tree, hf_ndmp_auth_challenge,
                        tvb, offset, 64, FALSE);
                offset+=64;
        }
@@ -572,14 +569,15 @@ dissect_auth_attr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_default_env(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_default_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree)
 {
        /* name */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_butype_env_name, offset, NULL);
 
        /* value */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_butype_env_value, offset, NULL);
 
        return offset;
@@ -623,7 +621,8 @@ static const true_false_string tfs_butype_attr_recover_utf8 = {
        "Normal recover. Do NOT use utf8"
 };
 static int
-dissect_butype_attrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_butype_attrs(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -663,7 +662,7 @@ static int
 dissect_butype_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
        /*butype name*/
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_butype_name, offset, NULL);
 
        /* default env */
@@ -678,7 +677,7 @@ dissect_butype_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
 
 static int
 dissect_get_butype_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -712,7 +711,8 @@ static const true_false_string tfs_fs_invalid_used_inodes = {
        "Used inode count is VALID"
 };
 static int
-dissect_fs_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_fs_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -741,14 +741,15 @@ dissect_fs_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *pa
 }
 
 static int
-dissect_fs_env(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_fs_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree)
 {
        /* name */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_fs_env_name, offset, NULL);
 
        /* value */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_fs_env_value, offset, NULL);
 
        return offset;
@@ -761,35 +762,35 @@ dissect_fs_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
        offset=dissect_fs_invalid(tvb, offset, pinfo, tree);
 
        /* fs type */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_fs_fs_type, offset, NULL);
 
        /* fs logical device */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_fs_logical_device, offset, NULL);
 
        /* fs physical device */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_fs_physical_device, offset, NULL);
 
        /*total_size*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_fs_total_size,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_size,
                        offset);
 
        /*used_size*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_fs_used_size,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_size,
                        offset);
 
        /*avail_size*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_fs_avail_size,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_avail_size,
                        offset);
 
        /*total_inodes*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_fs_total_inodes,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_inodes,
                        offset);
 
        /*used_inodes*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_fs_used_inodes,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_inodes,
                        offset);
 
        /* env */
@@ -797,7 +798,7 @@ dissect_fs_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
                        dissect_fs_env, hf_ndmp_fs_env);
 
        /* status */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_fs_status, offset, NULL);
 
        return offset;
@@ -805,7 +806,7 @@ dissect_fs_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 
 static int
 dissect_get_fs_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -827,7 +828,8 @@ static const true_false_string tfs_tape_attr_unload = {
        "Device does NOT support unload"
 };
 static int
-dissect_tape_attr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_tape_attr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -850,14 +852,15 @@ dissect_tape_attr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *par
 }
 
 static int
-dissect_tape_capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_tape_capability(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree)
 {
        /* name */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_tape_capability_name, offset, NULL);
 
        /* value */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_tape_capability_value, offset, NULL);
 
        return offset;
@@ -867,7 +870,7 @@ static int
 dissect_tape_dev_cap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
        /* device */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_tape_device, offset, NULL);
 
        /* tape attributes */
@@ -884,7 +887,7 @@ static int
 dissect_tape_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
        /* model */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_tape_model, offset, NULL);
 
        /* device capabilites */
@@ -896,7 +899,7 @@ dissect_tape_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
 
 static int
 dissect_get_tape_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -913,7 +916,7 @@ static int
 dissect_scsi_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
        /* model */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_scsi_model, offset, NULL);
 
        /* device capabilites */
@@ -925,7 +928,7 @@ dissect_scsi_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
 
 static int
 dissect_get_scsi_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -940,22 +943,22 @@ dissect_get_scsi_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 static int
 dissect_get_server_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* vendor */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_server_vendor, offset, NULL);
 
        /* product */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_server_product, offset, NULL);
 
        /* revision */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_server_revision, offset, NULL);
 
 
@@ -967,19 +970,19 @@ dissect_get_server_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_scsi_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_scsi_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* device */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_scsi_device, offset, NULL);
 
        return offset;
 }
 
 static int
-dissect_scsi_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_scsi_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -1001,11 +1004,11 @@ dissect_scsi_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_scsi_set_state_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_scsi_set_state_request(tvbuff_t *tvb, int offset,
+    packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
 {
        /* device */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_scsi_device, offset, NULL);
 
        /* controller */
@@ -1024,7 +1027,8 @@ dissect_scsi_set_state_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -1036,7 +1040,7 @@ dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_t
                                "Flags: 0x%08x", flags);
                tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_flags);
        }
-       
+
        proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_in,
                                tvb, offset, 4, flags);
        proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_out,
@@ -1046,7 +1050,8 @@ dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_t
 }
 
 static int
-dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo,
+    proto_tree *parent_tree, gint devtype)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -1055,7 +1060,7 @@ dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
 
        cdb_len = tvb_get_ntohl(tvb, offset);
        cdb_len_full = rpc_roundup(cdb_len);
-       
+
        if (parent_tree) {
                item = proto_tree_add_text(parent_tree, tvb, offset,
                                4+cdb_len_full, "CDB");
@@ -1067,7 +1072,7 @@ dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
        offset += 4;
 
        if (cdb_len != 0) {
-               dissect_scsi_cdb(tvb, pinfo, tree, offset, cdb_len);
+               dissect_scsi_cdb(tvb, pinfo, tree, offset, cdb_len, devtype);
                offset += cdb_len_full;
        }
 
@@ -1086,7 +1091,7 @@ dissect_execute_cdb_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto
 
        payload_len = tvb_get_ntohl(tvb, offset);
        payload_len_full = rpc_roundup(payload_len);
-       
+
        if (parent_tree) {
                item = proto_tree_add_text(parent_tree, tvb, offset,
                                4+payload_len_full, "%s", name);
@@ -1106,9 +1111,24 @@ dissect_execute_cdb_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto
        return offset;
 }
 
+/*
+ * XXX - we assume that NDMP_SCSI_EXECUTE_CDB requests only go to SCSI Media
+ * Changer devices and NDMP_TAPE_EXECUTE_CDB only go to SCSI Sequential
+ * Access devices.
+ *
+ * If that's not the case, we'll have to use the SCSI dissector's mechanisms
+ * for saving inquiry data for devices, and use inquiry data when available.
+ * Unfortunately, that means we need to save the name of the device, and
+ * use it as a device identifier; as the name isn't available in the
+ * NDMP_SCSI_EXECUTE_CDB or NDMP_TAPE_EXECUTE_CDB messages, that means
+ * we need to remember the currently-opened "SCSI" and "TAPE" devices
+ * from NDMP_SCSI_OPEN and NDMP_TAPE_OPEN, and attach to all frames
+ * that are the ones that trigger the dissection of NDMP_SCSI_EXECUTE_CDB
+ * or NDMP_TAPE_EXECUTE_CDB requests pointers to those names.
+ */
 static int
 dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq, gint devtype)
 {
        conversation_t *conversation;
        scsi_task_id_t task_key;
@@ -1127,8 +1147,8 @@ dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
        }
        task_key.conv_id = conversation->index;
        task_key.task_id = seq;
-        pinfo->private_data = &task_key;
-        
+       pinfo->private_data = &task_key;
+
        /* flags */
        offset = dissect_execute_cdb_flags(tvb, offset, pinfo, tree);
 
@@ -1141,7 +1161,7 @@ dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
        offset += 4;
 
        /* CDB */
-       offset = dissect_execute_cdb_cdb(tvb, offset, pinfo, tree);
+       offset = dissect_execute_cdb_cdb(tvb, offset, pinfo, tree, devtype);
 
        /* dataout */
        offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
@@ -1150,6 +1170,22 @@ dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
        return offset;
 }
 
+static int
+dissect_execute_cdb_request_mc(tvbuff_t *tvb, int offset, packet_info *pinfo,
+    proto_tree *tree, guint32 seq)
+{
+       return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
+           SCSI_DEV_SMC);
+}
+
+static int
+dissect_execute_cdb_request_tape(tvbuff_t *tvb, int offset, packet_info *pinfo,
+    proto_tree *tree, guint32 seq)
+{
+       return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
+           SCSI_DEV_SSC);
+}
+
 static int
 dissect_execute_cdb_sns(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
 {
@@ -1160,7 +1196,7 @@ dissect_execute_cdb_sns(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
 
        sns_len = tvb_get_ntohl(tvb, offset);
        sns_len_full = rpc_roundup(sns_len);
-       
+
        if (parent_tree) {
                item = proto_tree_add_text(parent_tree, tvb, offset,
                                4+sns_len_full, "Sense data");
@@ -1202,7 +1238,7 @@ dissect_execute_cdb_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
                /* no conversation, meaning we didn't see the request */
                pinfo->private_data = NULL;
        }
-        
+
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
        offset += 4;
@@ -1234,11 +1270,11 @@ static const value_string tape_open_mode_vals[] = {
 };
 
 static int
-dissect_tape_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_tape_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* device */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_tape_device, offset, NULL);
 
        /* open mode */
@@ -1278,7 +1314,8 @@ static const true_false_string tfs_ndmp_tape_invalid_partition = {
        "Partition is valid"
 };
 static int
-dissect_tape_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_tape_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -1327,7 +1364,8 @@ static const true_false_string tfs_ndmp_tape_flags_unload = {
        "This device does NOT support unload"
 };
 static int
-dissect_tape_flags(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_tape_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -1356,7 +1394,7 @@ dissect_tape_flags(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *pa
 
 static int
 dissect_tape_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* invalid bits */
        offset=dissect_tape_invalid(tvb, offset, pinfo, tree);
@@ -1385,11 +1423,11 @@ dissect_tape_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        offset += 4;
 
        /* total_space */
-       offset = dissect_rpc_uint64(tvb, pinfo, tree,hf_ndmp_tape_total_space,
+       offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_total_space,
                        offset);
 
        /* space_remain */
-       offset = dissect_rpc_uint64(tvb, pinfo, tree,hf_ndmp_tape_space_remain,
+       offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_space_remain,
                        offset);
 
        /* partition */
@@ -1418,8 +1456,8 @@ static const value_string tape_mtio_vals[] = {
 };
 
 static int
-dissect_tape_mtio_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_tape_mtio_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* op */
        proto_tree_add_item(tree, hf_ndmp_tape_mtio_op, tvb, offset, 4, FALSE);
@@ -1433,8 +1471,8 @@ dissect_tape_mtio_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_tape_mtio_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_tape_mtio_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -1492,7 +1530,8 @@ static const value_string halt_vals[] = {
 };
 
 static int
-dissect_ndmp_addr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_ndmp_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -1517,11 +1556,11 @@ dissect_ndmp_addr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *par
                /* IP addr */
                proto_tree_add_item(tree, hf_ndmp_addr_ip, tvb, offset, 4, FALSE);
                offset+=4;
-               
+
                /* TCP port */
                proto_tree_add_item(tree, hf_ndmp_addr_tcp, tvb, offset, 4, FALSE);
                offset+=4;
-               
+
                break;
        case NDMP_ADDR_FC:
                /* FCAL loop id */
@@ -1531,16 +1570,16 @@ dissect_ndmp_addr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *par
                break;
        case NDMP_ADDR_IPC:
                /* IPC address */
-               offset = dissect_rpc_data(tvb, pinfo, tree, hf_ndmp_addr_ipc, offset);
+               offset = dissect_rpc_data(tvb, tree, hf_ndmp_addr_ipc, offset);
                break;
        }
 
        return offset;
 }
-               
+
 static int
 dissect_mover_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -1601,8 +1640,8 @@ static const value_string mover_mode_vals[] = {
 };
 
 static int
-dissect_mover_listen_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_mover_listen_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* mode */
        proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
@@ -1617,7 +1656,7 @@ dissect_mover_listen_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 static int
 dissect_mover_listen_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -1630,8 +1669,8 @@ dissect_mover_listen_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_mover_set_window_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_mover_set_window_request(tvbuff_t *tvb, int offset,
+    packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
 {
        /* window offset */
        proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
@@ -1645,8 +1684,8 @@ dissect_mover_set_window_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_mover_set_record_size_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_mover_set_record_size_request(tvbuff_t *tvb, int offset,
+    packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
 {
        /* record size */
        proto_tree_add_item(tree, hf_ndmp_record_size, tvb, offset, 4, FALSE);
@@ -1657,7 +1696,7 @@ dissect_mover_set_record_size_request(tvbuff_t *tvb, int offset, packet_info *pi
 
 static int
 dissect_mover_connect_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* mode */
        proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
@@ -1670,11 +1709,11 @@ dissect_mover_connect_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_log_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_log_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* file */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_file_name, offset, NULL);
 
        /* error */
@@ -1697,8 +1736,8 @@ static const value_string log_type_vals[] = {
 };
 
 static int
-dissect_log_message_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_log_message_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* type */
        proto_tree_add_item(tree, hf_ndmp_log_type, tvb, offset, 4, FALSE);
@@ -1709,7 +1748,7 @@ dissect_log_message_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
        offset += 4;
 
        /* message */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_log_message, offset, NULL);
 
        return offset;
@@ -1717,14 +1756,14 @@ dissect_log_message_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 static int
 dissect_notify_data_halted_request(tvbuff_t *tvb, int offset,
-    packet_info *pinfo, proto_tree *tree, guint32 seq)
+    packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
 {
        /* halt */
        proto_tree_add_item(tree, hf_ndmp_halt, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* reason */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_halt_reason, offset, NULL);
 
        return offset;
@@ -1741,8 +1780,8 @@ static const value_string connected_vals[] = {
 };
 
 static int
-dissect_notify_connected_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_notify_connected_request(tvbuff_t *tvb, int offset,
+    packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
 {
        /* connected */
        proto_tree_add_item(tree, hf_ndmp_connected, tvb, offset, 4, FALSE);
@@ -1753,7 +1792,7 @@ dissect_notify_connected_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
        offset += 4;
 
        /* reason */
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_connected_reason, offset, NULL);
 
        return offset;
@@ -1762,7 +1801,7 @@ dissect_notify_connected_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 static int
 dissect_notify_mover_paused_request(tvbuff_t *tvb, int offset,
-    packet_info *pinfo, proto_tree *tree, guint32 seq)
+    packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
 {
        /* mover pause */
        proto_tree_add_item(tree, hf_ndmp_mover_pause, tvb, offset, 4, FALSE);
@@ -1776,10 +1815,11 @@ dissect_notify_mover_paused_request(tvbuff_t *tvb, int offset,
 }
 
 static int
-dissect_auth_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_auth_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree)
 {
        guint type;
-       
+
        type=tvb_get_ntohl(tvb,offset);
 
        /* auth type */
@@ -1791,22 +1831,22 @@ dissect_auth_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
                break;
        case NDMP_AUTH_TEXT:
                /* auth id */
-               offset = dissect_rpc_string(tvb, pinfo, tree,
+               offset = dissect_rpc_string(tvb, tree,
                                hf_ndmp_auth_id, offset, NULL);
 
                /* auth password */
-               offset = dissect_rpc_string(tvb, pinfo, tree,
+               offset = dissect_rpc_string(tvb, tree,
                                hf_ndmp_auth_password, offset, NULL);
 
-               
+
                break;
        case NDMP_AUTH_MD5:
                /* auth id */
-               offset = dissect_rpc_string(tvb, pinfo, tree,
+               offset = dissect_rpc_string(tvb, tree,
                                hf_ndmp_auth_id, offset, NULL);
 
                /* digest */
-               proto_tree_add_item(tree, hf_ndmp_auth_digest, 
+               proto_tree_add_item(tree, hf_ndmp_auth_digest,
                        tvb, offset, 16, FALSE);
                offset+=16;
        }
@@ -1816,14 +1856,14 @@ dissect_auth_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
 
 static int
 dissect_connect_client_auth_request(tvbuff_t *tvb, int offset,
-    packet_info *pinfo, proto_tree *tree, guint32 seq)
+    packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
 {
        return dissect_auth_data(tvb, offset, pinfo, tree);
 }
 
 static int
 dissect_connect_server_auth_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -1836,18 +1876,18 @@ dissect_connect_server_auth_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_tape_write_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_tape_write_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* data */
-       offset = dissect_rpc_data(tvb, pinfo, tree, hf_ndmp_data, offset);
+       offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
 
        return offset;
 }
 
 static int
-dissect_tape_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_tape_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -1861,8 +1901,8 @@ dissect_tape_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_tape_read_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_tape_read_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* count */
        proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
@@ -1872,15 +1912,15 @@ dissect_tape_read_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_tape_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+dissect_tape_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
        offset += 4;
 
        /* data */
-       offset = dissect_rpc_data(tvb, pinfo, tree, hf_ndmp_data, offset);
+       offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
 
        return offset;
 }
@@ -1918,39 +1958,39 @@ dissect_file_name(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *par
        switch(type){
        case NDMP_FS_UNIX:
                /* file */
-               offset = dissect_rpc_string(tvb, pinfo, tree,
+               offset = dissect_rpc_string(tvb, tree,
                                hf_ndmp_file_name, offset, &name);
                if (check_col(pinfo->cinfo, COL_INFO)){
-                       col_append_fstr(pinfo->cinfo, COL_INFO, " %s ", name);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
                }
                break;
        case NDMP_FS_NT:
                /* nt file */
-               offset = dissect_rpc_string(tvb, pinfo, tree,
+               offset = dissect_rpc_string(tvb, tree,
                                hf_ndmp_nt_file_name, offset, &name);
                if (check_col(pinfo->cinfo, COL_INFO)){
-                       col_append_fstr(pinfo->cinfo, COL_INFO, " %s ", name);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
                }
 
                /* dos file */
-               offset = dissect_rpc_string(tvb, pinfo, tree,
+               offset = dissect_rpc_string(tvb, tree,
                                hf_ndmp_dos_file_name, offset, NULL);
                break;
        default:
                /* file */
-               offset = dissect_rpc_string(tvb, pinfo, tree,
+               offset = dissect_rpc_string(tvb, tree,
                                hf_ndmp_file_name, offset, &name);
                if (check_col(pinfo->cinfo, COL_INFO)){
-                       col_append_fstr(pinfo->cinfo, COL_INFO, " %s ", name);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
                }
        }
 
        if (check_col(pinfo->cinfo, COL_INFO)){
-               col_append_fstr(pinfo->cinfo, COL_INFO, "(%s)",
+               col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
                        val_to_str(type, file_fs_type_vals, "Unknown type") );
        }
 
-       proto_item_set_len(item, offset-old_offset);    
+       proto_item_set_len(item, offset-old_offset);
        return offset;
 }
 
@@ -1968,7 +2008,8 @@ static const true_false_string tfs_ndmp_file_invalid_group = {
        "Group is valid"
 };
 static int
-dissect_file_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_file_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -2072,14 +2113,14 @@ dissect_file_stats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *pa
        offset += 4;
 
        /*file size*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_file_size,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_file_size,
                        offset);
 
        /* links */
        proto_tree_add_item(tree, hf_ndmp_file_links, tvb, offset, 4, FALSE);
        offset += 4;
 
-       proto_item_set_len(item, offset-old_offset);    
+       proto_item_set_len(item, offset-old_offset);
        return offset;
 }
 
@@ -2113,13 +2154,13 @@ dissect_file(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_t
        proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
        offset += 8;
 
-       proto_item_set_len(item, offset-old_offset);    
+       proto_item_set_len(item, offset-old_offset);
        return offset;
 }
 
 static int
 dissect_fh_add_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* files */
        offset = dissect_rpc_array(tvb, pinfo, tree, offset,
@@ -2148,7 +2189,7 @@ dissect_dir(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 
 static int
 dissect_fh_add_dir_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* dirs */
        offset = dissect_rpc_array(tvb, pinfo, tree, offset,
@@ -2178,7 +2219,7 @@ dissect_node(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 
 static int
 dissect_fh_add_node_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* node */
        offset = dissect_rpc_array(tvb, pinfo, tree, offset,
@@ -2189,10 +2230,10 @@ dissect_fh_add_node_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 static int
 dissect_data_start_backup_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /*butype name*/
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_butype_name, offset, NULL);
 
        /* default env */
@@ -2203,22 +2244,23 @@ dissect_data_start_backup_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_nlist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_nlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *tree)
 {
        /*original path*/
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_bu_original_path, offset, NULL);
 
        /*destination dir*/
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_bu_destination_dir, offset, NULL);
 
        /*new name*/
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_bu_new_name, offset, NULL);
 
        /*other name*/
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_bu_other_name, offset, NULL);
 
        /* node */
@@ -2235,7 +2277,7 @@ dissect_nlist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 
 static int
 dissect_data_start_recover_request(tvbuff_t *tvb, int offset,
-    packet_info *pinfo, proto_tree *tree, guint32 seq)
+    packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
 {
        /* default env */
        offset = dissect_rpc_array(tvb, pinfo, tree, offset,
@@ -2246,7 +2288,7 @@ dissect_data_start_recover_request(tvbuff_t *tvb, int offset,
                        dissect_nlist, hf_ndmp_nlist);
 
        /*butype name*/
-       offset = dissect_rpc_string(tvb, pinfo, tree,
+       offset = dissect_rpc_string(tvb, tree,
                        hf_ndmp_butype_name, offset, NULL);
 
        return offset;
@@ -2254,7 +2296,7 @@ dissect_data_start_recover_request(tvbuff_t *tvb, int offset,
 
 static int
 dissect_data_get_env_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        /* error */
        proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
@@ -2277,7 +2319,8 @@ static const true_false_string tfs_ndmp_state_invalid_etr = {
        "Estimated Time Remaining is valid"
 };
 static int
-dissect_state_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+dissect_state_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+    proto_tree *parent_tree)
 {
        proto_item* item = NULL;
        proto_tree* tree = NULL;
@@ -2339,7 +2382,7 @@ static const value_string data_halted_vals[] = {
 
 static int
 dissect_data_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, guint32 seq)
+    proto_tree *tree, guint32 seq _U_)
 {
        nstime_t ns;
 
@@ -2363,11 +2406,11 @@ dissect_data_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        offset += 4;
 
        /*bytes processed*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_data_bytes_processed,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_bytes_processed,
                        offset);
 
        /*est bytes remain*/
-       offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_ndmp_data_est_bytes_remain,
+       offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_est_bytes_remain,
                        offset);
 
        /* est time remain */
@@ -2400,51 +2443,51 @@ typedef struct _ndmp_command {
 } ndmp_command;
 
 static const ndmp_command ndmp_commands[] = {
-       {NDMP_CONFIG_GET_HOST_INFO,    
+       {NDMP_CONFIG_GET_HOST_INFO,
                NULL, dissect_ndmp_get_host_info_reply},
-       {NDMP_CONFIG_GET_CONNECTION_TYPE, 
+       {NDMP_CONFIG_GET_CONNECTION_TYPE,
                NULL, dissect_ndmp_config_get_connection_type_reply},
-       {NDMP_CONFIG_GET_AUTH_ATTR, 
+       {NDMP_CONFIG_GET_AUTH_ATTR,
                dissect_get_auth_type_request, dissect_auth_attr_msg},
-       {NDMP_CONFIG_GET_BUTYPE_INFO,   
+       {NDMP_CONFIG_GET_BUTYPE_INFO,
                NULL, dissect_get_butype_info_reply},
-       {NDMP_CONFIG_GET_FS_INFO,       
+       {NDMP_CONFIG_GET_FS_INFO,
                NULL, dissect_get_fs_info_reply},
-       {NDMP_CONFIG_GET_TAPE_INFO,     
+       {NDMP_CONFIG_GET_TAPE_INFO,
                NULL, dissect_get_tape_info_reply},
-       {NDMP_CONFIG_GET_SCSI_INFO,     
+       {NDMP_CONFIG_GET_SCSI_INFO,
                NULL, dissect_get_scsi_info_reply},
-       {NDMP_CONFIG_GET_SERVER_INFO,   
+       {NDMP_CONFIG_GET_SERVER_INFO,
                NULL, dissect_get_server_info_reply},
-       {NDMP_SCSI_OPEN,                
+       {NDMP_SCSI_OPEN,
                dissect_scsi_open_request, dissect_error},
-       {NDMP_SCSI_CLOSE,               
+       {NDMP_SCSI_CLOSE,
                NULL, dissect_error},
-       {NDMP_SCSI_GET_STATE,           
+       {NDMP_SCSI_GET_STATE,
                NULL, dissect_scsi_get_state_reply},
-       {NDMP_SCSI_SET_TARGET,          
+       {NDMP_SCSI_SET_TARGET,
                dissect_scsi_set_state_request, dissect_error},
-       {NDMP_SCSI_RESET_DEVICE,        
+       {NDMP_SCSI_RESET_DEVICE,
                NULL, dissect_error},
-       {NDMP_SCSI_RESET_BUS,           
+       {NDMP_SCSI_RESET_BUS,
                NULL, dissect_error},
        {NDMP_SCSI_EXECUTE_CDB,
-               dissect_execute_cdb_request, dissect_execute_cdb_reply},
-       {NDMP_TAPE_OPEN,                
+               dissect_execute_cdb_request_mc, dissect_execute_cdb_reply},
+       {NDMP_TAPE_OPEN,
                dissect_tape_open_request, dissect_error},
-       {NDMP_TAPE_CLOSE,               
+       {NDMP_TAPE_CLOSE,
                NULL, dissect_error},
-       {NDMP_TAPE_GET_STATE,           
+       {NDMP_TAPE_GET_STATE,
                NULL, dissect_tape_get_state_reply},
-       {NDMP_TAPE_MTIO,                
+       {NDMP_TAPE_MTIO,
                dissect_tape_mtio_request, dissect_tape_mtio_reply},
-       {NDMP_TAPE_WRITE,               
+       {NDMP_TAPE_WRITE,
                dissect_tape_write_request, dissect_tape_write_reply},
-       {NDMP_TAPE_READ,        
+       {NDMP_TAPE_READ,
                dissect_tape_read_request, dissect_tape_read_reply},
        {NDMP_TAPE_EXECUTE_CDB,
-               dissect_execute_cdb_request, dissect_execute_cdb_reply},
-       {NDMP_DATA_GET_STATE,           
+               dissect_execute_cdb_request_tape, dissect_execute_cdb_reply},
+       {NDMP_DATA_GET_STATE,
                NULL, dissect_data_get_state_reply},
        {NDMP_DATA_START_BACKUP,
                dissect_data_start_backup_request, dissect_error },
@@ -2452,61 +2495,61 @@ static const ndmp_command ndmp_commands[] = {
                dissect_data_start_recover_request, dissect_error },
        {NDMP_DATA_ABORT,
                NULL, dissect_error},
-       {NDMP_DATA_GET_ENV, 
+       {NDMP_DATA_GET_ENV,
                NULL, dissect_data_get_env_reply},
-       {NDMP_DATA_STOP, 
+       {NDMP_DATA_STOP,
                NULL, dissect_error},
-       {NDMP_DATA_LISTEN, 
+       {NDMP_DATA_LISTEN,
                dissect_ndmp_addr_msg, dissect_mover_listen_reply},
-       {NDMP_DATA_CONNECT,             
+       {NDMP_DATA_CONNECT,
                dissect_ndmp_addr_msg, dissect_error},
-       {NDMP_NOTIFY_DATA_HALTED,       
+       {NDMP_NOTIFY_DATA_HALTED,
                dissect_notify_data_halted_request, NULL},
-       {NDMP_NOTIFY_CONNECTED,         
+       {NDMP_NOTIFY_CONNECTED,
                dissect_notify_connected_request, NULL},
-       {NDMP_NOTIFY_MOVER_HALTED, 
+       {NDMP_NOTIFY_MOVER_HALTED,
                dissect_notify_data_halted_request, NULL},
-       {NDMP_NOTIFY_MOVER_PAUSED, 
+       {NDMP_NOTIFY_MOVER_PAUSED,
                dissect_notify_mover_paused_request, NULL},
-       {NDMP_NOTIFY_DATA_READ,         
+       {NDMP_NOTIFY_DATA_READ,
                dissect_mover_set_window_request, NULL},
-       {NDMP_LOG_FILE,                 
+       {NDMP_LOG_FILE,
                dissect_log_file_request, NULL},
-       {NDMP_LOG_MESSAGE,      
+       {NDMP_LOG_MESSAGE,
                dissect_log_message_request, NULL},
-       {NDMP_FH_ADD_FILE, 
+       {NDMP_FH_ADD_FILE,
                dissect_fh_add_file_request, NULL},
-       {NDMP_FH_ADD_DIR,               
+       {NDMP_FH_ADD_DIR,
                dissect_fh_add_dir_request, NULL},
-       {NDMP_FH_ADD_NODE, 
+       {NDMP_FH_ADD_NODE,
                dissect_fh_add_node_request, NULL},
-       {NDMP_CONNECT_OPEN,             
+       {NDMP_CONNECT_OPEN,
                dissect_connect_open_request, dissect_error},
-       {NDMP_CONNECT_CLIENT_AUTH, 
+       {NDMP_CONNECT_CLIENT_AUTH,
                dissect_connect_client_auth_request, dissect_error},
-       {NDMP_CONNECT_CLOSE,            
+       {NDMP_CONNECT_CLOSE,
                NULL,NULL},
-       {NDMP_CONNECT_SERVER_AUTH, 
+       {NDMP_CONNECT_SERVER_AUTH,
                dissect_auth_attr_msg, dissect_connect_server_auth_reply},
-       {NDMP_MOVER_GET_STATE,          
+       {NDMP_MOVER_GET_STATE,
                NULL, dissect_mover_get_state_reply},
-       {NDMP_MOVER_LISTEN,             
+       {NDMP_MOVER_LISTEN,
                dissect_mover_listen_request, dissect_mover_listen_reply},
-       {NDMP_MOVER_CONTINUE,           
+       {NDMP_MOVER_CONTINUE,
                NULL, dissect_error},
-       {NDMP_MOVER_ABORT,              
+       {NDMP_MOVER_ABORT,
                NULL, dissect_error},
-       {NDMP_MOVER_STOP,               
+       {NDMP_MOVER_STOP,
                NULL, dissect_error},
-       {NDMP_MOVER_SET_WINDOW,         
+       {NDMP_MOVER_SET_WINDOW,
                dissect_mover_set_window_request, dissect_error},
-       {NDMP_MOVER_READ, 
+       {NDMP_MOVER_READ,
                dissect_mover_set_window_request, dissect_error},
-       {NDMP_MOVER_CLOSE,              
+       {NDMP_MOVER_CLOSE,
                NULL, dissect_error},
-       {NDMP_MOVER_SET_RECORD_SIZE, 
+       {NDMP_MOVER_SET_RECORD_SIZE,
                dissect_mover_set_record_size_request, dissect_error},
-       {NDMP_MOVER_CONNECT,    
+       {NDMP_MOVER_CONNECT,
                dissect_mover_connect_request, dissect_error},
        {0, NULL,NULL}
 };
@@ -2552,7 +2595,7 @@ dissect_ndmp_header(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *p
        offset += 4;
 
        if (check_col(pinfo->cinfo, COL_INFO)){
-               col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s  ",
+               col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
                        val_to_str(nh->msg, msg_vals, "Unknown Message (0x%02x)"),
                        val_to_str(nh->type, msg_type_vals, "Unknown Type (0x%02x)")
                        );
@@ -2568,12 +2611,6 @@ dissect_ndmp_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree
        int i;
        proto_item *cmd_item=NULL;
        proto_tree *cmd_tree=NULL;
-       guint32 size;
-
-       /* the size of the current PDU */
-       size = tvb_get_ntohl(tvb, offset);      
-       proto_tree_add_uint(tree, hf_ndmp_size, tvb, offset, 4, size&NDMP_FRAGLEN);
-       offset += 4;
 
        offset=dissect_ndmp_header(tvb, offset, pinfo, tree, nh);
 
@@ -2591,10 +2628,12 @@ dissect_ndmp_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree
                return offset;
        }
 
-       if(tree){
-               cmd_item = proto_tree_add_text(tree, tvb, offset, -1, 
-                       msg_vals[i].strptr);
-               cmd_tree = proto_item_add_subtree(cmd_item, ett_ndmp);
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               if(tree){
+                       cmd_item = proto_tree_add_text(tree, tvb, offset, -1,
+                               msg_vals[i].strptr);
+                       cmd_tree = proto_item_add_subtree(cmd_item, ett_ndmp);
+               }
        }
 
        if(nh->type==NDMP_MESSAGE_REQUEST){
@@ -2612,121 +2651,123 @@ dissect_ndmp_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree
        return offset;
 }
 
-static void
-dissect_ndmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+static gboolean
+dissect_ndmp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+    tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
+    guint32 rpc_rm, gboolean first_pdu)
 {
-       volatile gboolean first = TRUE;
-       volatile int offset = 0;
-       guint32 size, available_bytes;
+       int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
+       guint32 size;
        struct ndmp_header nh;
-       proto_item *item=NULL;
-       proto_tree *volatile tree=NULL;
-       const char *saved_proto;
-
-       /* loop through the packet, dissecting multiple NDMP pdus*/
-       do {
-               available_bytes = tvb_length_remaining(tvb, offset);
-
-               /* size of this NDMP PDU */
-               size = (tvb_get_ntohl(tvb, offset)&NDMP_FRAGLEN) + 4;   
-               if(size<28){
-                       /* too short to be NDMP */
-                       return;
-               }
+       proto_item *ndmp_item = NULL;
+       proto_tree *ndmp_tree = NULL;
+
+       /* size of this NDMP PDU */
+       size = tvb_length_remaining(tvb, offset);
+       if (size < 24) {
+               /* too short to be NDMP */
+               return FALSE;
+       }
 
-               /* desegmentation */
-               if(ndmp_desegment){
-                       if(pinfo->can_desegment
-                       && size>available_bytes) {
-                               pinfo->desegment_offset = offset;
-                               pinfo->desegment_len = size-available_bytes;
-                               return;
-                       }
-               }
+       /*
+        * Check the NDMP header, if we have it.
+        */
+       nh.seq = tvb_get_ntohl(tvb, offset);
+       nh.time = tvb_get_ntohl(tvb, offset+4);
+       nh.type = tvb_get_ntohl(tvb, offset+8);
+       nh.msg = tvb_get_ntohl(tvb, offset+12);
+       nh.rep_seq = tvb_get_ntohl(tvb, offset+16);
+       nh.err = tvb_get_ntohl(tvb, offset+20);
+
+       if (nh.type > 1)
+               return FALSE;
+       if (nh.msg > 0xa09 || nh.msg == 0)
+               return FALSE;
+       if (nh.err > 0x17)
+               return FALSE;
 
-               /* check the ndmp header, if we have it */
-               if(available_bytes<28){
-                       /* We don't have enough data */
-                       return;
-               }
-               nh.seq=tvb_get_ntohl(tvb, offset+4);
-               nh.time=tvb_get_ntohl(tvb, offset+8);
-               nh.type=tvb_get_ntohl(tvb, offset+12);
-               nh.msg=tvb_get_ntohl(tvb, offset+16);
-               nh.rep_seq=tvb_get_ntohl(tvb, offset+20);
-               nh.err=tvb_get_ntohl(tvb, offset+24);
-
-               if(nh.type>1){
-                       return;
-               }
-               if((nh.msg>0xa09)||(nh.msg==0)){
-                       return;
-               }
-               if(nh.err>0x17){
-                       return;
-               }
+       /*
+        * Check if this is the last fragment.
+        */
+       if (!(rpc_rm & RPC_RM_LASTFRAG)) {
+               /*
+                * This isn't the last fragment.
+                * If we're doing reassembly, just return
+                * TRUE to indicate that this looks like
+                * the beginning of an NDMP message,
+                * and let them do reassembly.
+                */
+               if (ndmp_defragment)
+                       return TRUE;
+       }
 
-               if (first) {
-                       if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
-                               col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDMP");
-                       if (check_col(pinfo->cinfo, COL_INFO)) 
-                               col_clear(pinfo->cinfo, COL_INFO);
-                       first = FALSE;
-               }
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDMP");
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               if (first_pdu)
+                       col_clear(pinfo->cinfo, COL_INFO);
+               else
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "; ");
+       }
+
+       if (tree) {
+               ndmp_item = proto_tree_add_item(tree, proto_ndmp,
+                   tvb, 0, -1, FALSE);
+               ndmp_tree = proto_item_add_subtree(ndmp_item, ett_ndmp);
 
-               if(parent_tree){
-                       item = proto_tree_add_item(parent_tree, proto_ndmp, tvb, offset, size, FALSE);
-                       tree = proto_item_add_subtree(item, ett_ndmp);
+               if (is_tcp) {
+                       show_rpc_fraginfo(tvb, frag_tvb, ndmp_tree, rpc_rm,
+                           ipfd_head, pinfo);
                }
+       }
+
+       /*
+        * We cannot trust what dissect_ndmp_cmd() tells us, as there
+        * are implementations which pad some additional data after
+        * the PDU.  We MUST use size.
+        */
+       dissect_ndmp_cmd(tvb, offset, pinfo, ndmp_tree, &nh);
+       return TRUE;
+}
+
+static void
+dissect_ndmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       int offset = 0;
+       int len;
+       gboolean first_pdu = TRUE;
 
+       while (tvb_reported_length_remaining(tvb, offset) != 0) {
                /*
-                * Catch the ReportedBoundsError exception; if this
-                * particular message happens to get a ReportedBoundsError
-                * exception, that doesn't mean that we should stop
-                * dissecting NDMP messages within this frame or chunk
-                * of reassembled data.
-                *
-                * If it gets a BoundsError, we can stop, as there's
-                * nothing more to see, so we just re-throw it.
+                * Process this fragment.
                 */
-               saved_proto = pinfo->current_proto;
-               TRY {
-                       /* We cannot trust what dissect_ndmp_cmd() tells us
-                          since there are implementations which pads some
-                          additional data after the PDU. We MUST use size.
-                       */
-                       dissect_ndmp_cmd(tvb, offset, pinfo, tree, &nh);
-               }
-               CATCH(BoundsError) {
-                       RETHROW;
+               len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
+                   dissect_ndmp_message, FALSE, proto_ndmp, ett_ndmp,
+                   ndmp_defragment, first_pdu);
+               first_pdu = FALSE;
+               if (len < 0) {
+                       /*
+                        * We need more data from the TCP stream for
+                        * this fragment.
+                        */
+                       return;
                }
-               CATCH(ReportedBoundsError) {
-                       if (check_col(pinfo->cinfo, COL_INFO)) {
-                               col_append_str(pinfo->cinfo, COL_INFO,
-                                   "[Malformed Packet]");
-                       }
-                       proto_tree_add_protocol_format(parent_tree,
-                           proto_malformed, tvb, 0, 0,
-                           "[Malformed Packet: %s]", pinfo->current_proto);
-                       pinfo->current_proto = saved_proto;
+               if (len == 0) {
+                       /*
+                        * It's not NDMP.  Stop processing.
+                        */
+                       break;
                }
-               ENDTRY;
-               offset += size;
-       } while(offset<(int)tvb_reported_length(tvb));
-}
-
-
 
+               offset += len;
+       }
+}
 
 void
 proto_register_ndmp(void)
 {
 
   static hf_register_info hf_ndmp[] = {
-       { &hf_ndmp_size, {
-               "Size", "ndmp.size", FT_UINT32, BASE_DEC,
-               NULL, 0, "Size of this NDMP PDU", HFILL }},
-
        { &hf_ndmp_header, {
                "NDMP Header", "ndmp.header", FT_NONE, 0,
                NULL, 0, "NDMP Header", HFILL }},
@@ -3370,9 +3411,6 @@ proto_register_ndmp(void)
        { &hf_ndmp_data_est_time_remain, {
                "Est Time Remain", "ndmp.data.est_time_remain", FT_RELATIVE_TIME, BASE_DEC,
                NULL, 0, "Estimated time remaining", HFILL }},
-
-
-
   };
 
   static gint *ett[] = {
@@ -3390,6 +3428,7 @@ proto_register_ndmp(void)
     &ett_ndmp_addr,
     &ett_ndmp_file,
     &ett_ndmp_file_name,
+    &ett_ndmp_file_stats,
     &ett_ndmp_file_invalids,
     &ett_ndmp_state_invalids,
   };
@@ -3398,13 +3437,19 @@ proto_register_ndmp(void)
 
   proto_ndmp = proto_register_protocol("Network Data Management Protocol", "NDMP", "ndmp");
   proto_register_field_array(proto_ndmp, hf_ndmp, array_length(hf_ndmp));
-  
+
   proto_register_subtree_array(ett, array_length(ett));
 
   /* desegmentation */
   ndmp_module = prefs_register_protocol(proto_ndmp, NULL);
-  prefs_register_bool_preference(ndmp_module, "desegment", "Desegment all NDMP messages spanning multiple TCP segments", "Whether the dissector should desegment NDMP over TCP PDUs or not", &ndmp_desegment);
-
+  prefs_register_bool_preference(ndmp_module, "desegment",
+       "Desegment all NDMP messages spanning multiple TCP segments",
+       "Whether the dissector should desegment NDMP messages",
+       &ndmp_desegment);
+  prefs_register_bool_preference(ndmp_module, "defragment",
+       "Defragment all multi-fragment NDMP messages",
+       "Whether the dissector should defragment multi-fragment NDMP messages",
+       &ndmp_defragment);
 }
 
 void