Change proto_tree_add_ipv6() to take a struct e_in6_addr pointer
[metze/wireshark/wip.git] / epan / dissectors / packet-nfs.c
index 489105c6a616486df808437ab5c24442ae18b979..433408bc2a5622eaf55affdfb96a5e2afa8afc5b 100644 (file)
 #include "config.h"
 
 #include <stdio.h>
-#include <glib.h>
-#include "packet-rpc.h"
-#include "packet-nfs.h"
-#include <epan/prefs.h>
+
 #include <epan/packet.h>
+#include <epan/prefs.h>
 #include <epan/exceptions.h>
-#include <epan/wmem/wmem.h>
-#include <wsutil/crc16.h>
-#include <wsutil/crc32.h>
 #include <epan/expert.h>
 #include <epan/to_str.h>
+#include <epan/decode_as.h>
+#include <wsutil/crc16.h>
+#include <wsutil/crc32.h>
+#include "packet-nfs.h"
 
 void proto_register_nfs(void);
 void proto_reg_handoff_nfs(void);
 
 /* NON-NFS-version-specific hf variables */
 static int proto_nfs = -1;
+static int proto_nfs_unknown = -1;
+static int proto_nfs_svr4 = -1;
+static int proto_nfs_knfsd_le = -1;
+static int proto_nfs_nfsd_le = -1;
+static int proto_nfs_knfsd_new = -1;
+static int proto_nfs_ontap_v3 = -1;
+static int proto_nfs_ontap_v4 = -1;
+static int proto_nfs_ontap_gx_v3 = -1;
+static int proto_nfs_celerra_vnx = -1;
+static int proto_nfs_gluster = -1;
+static int proto_nfs_dcache = -1;
 static int hf_nfs_access_check  = -1;
 static int hf_nfs_access_supported  = -1;
 static int hf_nfs_access_rights = -1;
@@ -93,8 +103,12 @@ static int hf_nfs_fh_file_flag_private = -1;
 static int hf_nfs_fh_file_flag_next_gen = -1;
 static int hf_nfs_fh_gfid = -1;
 static int hf_nfs_fh_handle_type = -1;
-static int hf_nfs_fh_fsid_major = -1;
-static int hf_nfs_fh_fsid_minor = -1;
+static int hf_nfs_fh_fsid_major16_mask = -1;
+static int hf_nfs_fh_fsid_minor16_mask = -1;
+static int hf_nfs_fh_fsid_major16 = -1;
+static int hf_nfs_fh_fsid_minor16 = -1;
+static int hf_nfs_fh_fsid_major32 = -1;
+static int hf_nfs_fh_fsid_minor32 = -1;
 static int hf_nfs_fh_fsid_inode = -1;
 static int hf_nfs_fh_xfsid_major = -1;
 static int hf_nfs_fh_xfsid_minor = -1;
@@ -113,6 +127,7 @@ static int hf_nfs_fh_dentry = -1;
 static int hf_nfs_fh_dirinode = -1;
 static int hf_nfs_fh_pinode = -1;
 static int hf_nfs_fh_hp_len = -1;
+static int hf_nfs_fh_hp_key = -1;
 static int hf_nfs_fh_version = -1;
 static int hf_nfs_fh_auth_type = -1;
 static int hf_nfs_fh_fsid_type = -1;
@@ -133,6 +148,9 @@ static int hf_nfs_fh_ex_inode = -1;
 static int hf_nfs_fh_ex_gen = -1;
 static int hf_nfs_fh_flag = -1;
 static int hf_nfs_fh_endianness = -1;
+static int hf_nfs_fh_dc_opaque = -1;
+static int hf_nfs_fh_dc_exportid = -1;
+static int hf_nfs_fh_dc_handle_type = -1;
 static int hf_nfs_full_name = -1;
 static int hf_nfs_name = -1;
 static int hf_nfs_data = -1;
@@ -172,6 +190,8 @@ static int hf_nfs2_fattr_rdev = -1;
 static int hf_nfs2_fattr_blocks = -1;
 static int hf_nfs2_fattr_fsid = -1;
 static int hf_nfs2_fattr_fileid = -1;
+static int hf_nfs2_ftype = -1;
+static int hf_nfs2_mode = -1;
 static int hf_nfs2_mode_name = -1;
 static int hf_nfs2_mode_set_user_id = -1;
 static int hf_nfs2_mode_set_group_id = -1;
@@ -298,6 +318,12 @@ static int hf_nfs3_gxfh_spinfid = -1;
 static int hf_nfs3_gxfh_spinfuid = -1;
 static int hf_nfs3_gxfh_exportptid = -1;
 static int hf_nfs3_gxfh_exportptuid = -1;
+static int hf_nfs3_verifier = -1;
+static int hf_nfs3_specdata1 = -1;
+static int hf_nfs3_specdata2 = -1;
+static int hf_nfs3_attributes_follow = -1;
+static int hf_nfs3_handle_follow = -1;
+static int hf_nfs3_sattrguard3 = -1;
 
 
 /* NFSv4 RFC 5661 header format variables */
@@ -308,6 +334,7 @@ static int hf_nfs4_main_opcode = -1;
 static int hf_nfs4_linktext = -1;
 static int hf_nfs4_tag = -1;
 static int hf_nfs4_ops_count = -1;
+static int hf_nfs4_pathname_components = -1;
 static int hf_nfs4_component = -1;
 static int hf_nfs4_clientid = -1;
 /* static int hf_nfs4_ace = -1; */
@@ -331,7 +358,10 @@ static int hf_nfs4_lock_seqid = -1;
 static int hf_nfs4_reqd_attr = -1;
 static int hf_nfs4_reco_attr = -1;
 static int hf_nfs4_attr_mask = -1;
+static int hf_nfs4_attr_count = -1;
+static int hf_nfs4_set_it_value_follows = -1;
 static int hf_nfs4_time_how = -1;
+static int hf_nfs4_time_how4 = -1;
 static int hf_nfs4_fattr_link_support = -1;
 static int hf_nfs4_fattr_symlink_support = -1;
 static int hf_nfs4_fattr_named_attr = -1;
@@ -441,7 +471,10 @@ static int hf_nfs4_client_id = -1;
 static int hf_nfs4_stateid_other = -1;
 static int hf_nfs4_stateid_hash = -1;
 static int hf_nfs4_lock_reclaim = -1;
-static int hf_nfs4_acl = -1;
+static int hf_nfs4_aclflags = -1;
+static int hf_nfs4_aclflag_auto_inherit = -1;
+static int hf_nfs4_aclflag_protected = -1;
+static int hf_nfs4_aclflag_defaulted = -1;
 static int hf_nfs4_num_aces = -1;
 static int hf_nfs4_callback_ident = -1;
 static int hf_nfs4_r_netid = -1;
@@ -457,7 +490,7 @@ static int hf_nfs4_layout_return_type = -1;
 static int hf_nfs4_iomode = -1;
 /* static int hf_nfs4_stripetype = -1; */
 /* static int hf_nfs4_mdscommit = -1; */
-/* static int hf_nfs4_stripeunit = -1; */
+static int hf_nfs4_stripeunit = -1;
 static int hf_nfs4_newtime = -1;
 static int hf_nfs4_newoffset = -1;
 static int hf_nfs4_layout_avail = -1;
@@ -523,7 +556,11 @@ static int hf_nfs4_cachethis = -1;
 /* static int hf_nfs4_pattern_offset = -1; */
 static int hf_nfs4_notification_bitmap = -1;
 static int hf_nfs4_lrs_present = -1;
+static int hf_nfs4_nfl_mirrors = -1;
 static int hf_nfs4_nfl_util = -1;
+static int hf_nfs4_nfl_fhs = -1;
+static int hf_nfs4_mirror_index = -1;
+static int hf_nfs4_mirror_eff = -1;
 static int hf_nfs4_nfl_first_stripe_index = -1;
 static int hf_nfs4_lrf_body_content = -1;
 static int hf_nfs4_reclaim_one_fs = -1;
@@ -550,7 +587,63 @@ static int hf_nfs4_test_stateid_arg = -1;
 static int hf_nfs4_test_stateid_res = -1;
 static int hf_nfs4_seek_data_content = -1;
 /* static int hf_nfs4_impl_id_len = -1; */
-
+static int hf_nfs4_huge_bitmap_length = -1;
+static int hf_nfs4_universal_address_ipv4 = -1;
+static int hf_nfs4_universal_address_ipv6 = -1;
+static int hf_nfs4_getdevinfo = -1;
+static int hf_nfs4_ff_version = -1;
+static int hf_nfs4_ff_minorversion = -1;
+static int hf_nfs4_ff_tightly_coupled = -1;
+static int hf_nfs4_ff_rsize = -1;
+static int hf_nfs4_ff_wsize = -1;
+static int hf_nfs4_fattr_clone_blocksize = -1;
+static int hf_nfs4_fattr_space_freed = -1;
+static int hf_nfs4_fattr_change_attr_type = -1;
+static int hf_nfs4_ff_layout_flags = -1;
+static int hf_nfs4_ff_layout_flags_no_layoutcommit = -1;
+static int hf_nfs4_ff_synthetic_owner = -1;
+static int hf_nfs4_ff_synthetic_owner_group = -1;
+static int hf_nfs4_ff_bytes_completed = -1;
+static int hf_nfs4_ff_bytes_not_delivered = -1;
+static int hf_nfs4_ff_bytes_requested = -1;
+static int hf_nfs4_ff_local = -1;
+static int hf_nfs4_ff_ops_completed = -1;
+static int hf_nfs4_ff_ops_requested = -1;
+static int hf_nfs4_io_bytes = -1;
+static int hf_nfs4_io_count = -1;
+static int hf_nfs4_layoutstats = -1;
+static int hf_nfs4_callback_stateids = -1;
+static int hf_nfs4_callback_stateids_index = -1;
+static int hf_nfs4_consecutive = -1;
+static int hf_nfs4_netloc = -1;
+static int hf_nfs4_netloc_type = -1;
+static int hf_nfs4_nl_name = -1;
+static int hf_nfs4_nl_url = -1;
+static int hf_nfs4_source_server_index = -1;
+static int hf_nfs4_source_servers = -1;
+static int hf_nfs4_synchronous = -1;
+static int hf_nfs4_device_error_count = -1;
+static int hf_nfs4_device_errors_index = -1;
+static int hf_nfs4_ff_ioerrs_count = -1;
+static int hf_nfs4_ff_ioerrs_index = -1;
+static int hf_nfs4_ff_ioerrs_length = -1;
+static int hf_nfs4_ff_ioerrs_offset = -1;
+static int hf_nfs4_ff_iostats_count = -1;
+static int hf_nfs4_ff_iostats_index = -1;
+static int hf_nfs4_io_error_op = -1;
+static int hf_nfs4_io_hints_mask = -1;
+static int hf_nfs4_io_hint_count = -1;
+static int hf_nfs4_io_advise_hint = -1;
+static int hf_nfs4_bytes_copied = -1;
+static int hf_nfs4_read_plus_content_type = -1;
+static int hf_nfs4_read_plus_content_count = -1;
+static int hf_nfs4_read_plus_content_index = -1;
+static int hf_nfs4_block_size = -1;
+static int hf_nfs4_block_count = -1;
+static int hf_nfs4_reloff_blocknum = -1;
+static int hf_nfs4_blocknum = -1;
+static int hf_nfs4_reloff_pattern = -1;
+static int hf_nfs4_pattern_hash = -1;
 
 static gint ett_nfs = -1;
 static gint ett_nfs_fh_encoding = -1;
@@ -676,6 +769,7 @@ static gint ett_nfs4_secinfo_flavor_info = -1;
 static gint ett_nfs4_stateid = -1;
 static gint ett_nfs4_fattr_fh_expire_type = -1;
 static gint ett_nfs4_fattr_aclsupport = -1;
+static gint ett_nfs4_aclflag = -1;
 static gint ett_nfs4_ace = -1;
 static gint ett_nfs4_clientaddr = -1;
 static gint ett_nfs4_aceflag = -1;
@@ -724,7 +818,7 @@ static gint ett_nfs4_gid = -1;
 static gint ett_nfs4_service = -1;
 static gint ett_nfs4_sessionid = -1;
 static gint ett_nfs4_layoutseg = -1;
-static gint ett_nfs4_layoutseg_fh = -1;
+static gint ett_nfs4_layoutseg_sub = -1;
 static gint ett_nfs4_test_stateid = -1;
 static gint ett_nfs4_destroy_clientid = -1;
 static gint ett_nfs4_reclaim_complete = -1;
@@ -733,41 +827,36 @@ static gint ett_nfs4_deallocate = -1;
 static gint ett_nfs4_seek = -1;
 static gint ett_nfs4_chan_attrs = -1;
 static gint ett_nfs4_want_notify_flags = -1;
+static gint ett_nfs4_ff_layout_flags = -1;
+static gint ett_nfs4_layoutstats = -1;
+static gint ett_nfs4_io_info = -1;
+static gint ett_nfs4_io_latency = -1;
+static gint ett_nfs4_io_time = -1;
+static gint ett_nfs4_callback_stateids_sub = -1;
+static gint ett_nfs4_source_servers_sub = -1;
+static gint ett_nfs4_copy = -1;
+static gint ett_nfs4_copy_notify = -1;
+static gint ett_nfs4_device_errors_sub = -1;
+static gint ett_nfs4_layouterror = -1;
+static gint ett_nfs4_ff_ioerrs_sub = -1;
+static gint ett_nfs4_ff_iostats_sub = -1;
+static gint ett_nfs4_clone = -1;
+static gint ett_nfs4_offload_cancel = -1;
+static gint ett_nfs4_offload_status = -1;
+static gint ett_nfs4_io_advise = -1;
+static gint ett_nfs4_read_plus = -1;
+static gint ett_nfs4_read_plus_content_sub = -1;
+static gint ett_nfs4_write_same = -1;
 
 static expert_field ei_nfs_too_many_ops = EI_INIT;
 static expert_field ei_nfs_not_vnx_file = EI_INIT;
+static expert_field ei_protocol_violation = EI_INIT;
+static expert_field ei_nfs_too_many_bitmaps = EI_INIT;
 
 
 /* Types of fhandles we can dissect */
 static dissector_table_t nfs_fhandle_table;
 
-#define FHT_UNKNOWN          0
-#define FHT_SVR4             1
-#define FHT_LINUX_KNFSD_LE   2
-#define FHT_LINUX_NFSD_LE    3
-#define FHT_LINUX_KNFSD_NEW  4
-#define FHT_NETAPP           5
-#define FHT_NETAPP_V4        6
-#define FHT_NETAPP_GX_V3     7
-#define FHT_CELERRA_VNX      8
-#define FHT_GLUSTER          9
-
-static const enum_val_t nfs_fhandle_types[] = {
-       { "unknown",     "Unknown",     FHT_UNKNOWN },
-       { "svr4",        "SVR4",        FHT_SVR4 },
-       { "knfsd_le",    "KNFSD_LE",    FHT_LINUX_KNFSD_LE },
-       { "nfsd_le",     "NFSD_LE",     FHT_LINUX_NFSD_LE },
-       { "knfsd_new",   "KNFSD_NEW",   FHT_LINUX_KNFSD_NEW },
-       { "ontap_v3",    "ONTAP_V3",    FHT_NETAPP },
-       { "ontap_v4",    "ONTAP_V4",    FHT_NETAPP_V4},
-       { "ontap_gx_v3", "ONTAP_GX_V3", FHT_NETAPP_GX_V3},
-       { "celerra_vnx", "CELERRA_VNX", FHT_CELERRA_VNX },
-       { "gluster",     "GLUSTER",     FHT_GLUSTER },
-       { NULL, NULL, 0 }
-};
-/* decode all nfs filehandles as this type */
-static gint default_nfs_fhandle_type = FHT_UNKNOWN;
-
 typedef struct nfs_fhandle_data {
        int len;
        const unsigned char *fh;
@@ -819,7 +908,15 @@ static gboolean display_major_nfs4_ops = TRUE;
 
 static int dissect_nfs4_stateid(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *hash);
 
-static void reg_callback(int cbprog);
+static void nfs_prompt(packet_info *pinfo _U_, gchar* result)
+{
+       g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Decode NFS file handles as");
+}
+
+static gpointer nfs_value(packet_info *pinfo _U_)
+{
+       return 0;
+}
 
 /* This function will store one nfs filehandle in our global tree of
  * filehandles.
@@ -920,55 +1017,37 @@ nfs_name_snoop_unmatched_hash(gconstpointer k)
 }
 
 
-static gboolean
-nfs_name_snoop_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
+static void
+nfs_name_snoop_value_destroy(gpointer value)
 {
        nfs_name_snoop_t *nns = (nfs_name_snoop_t *)value;
 
-       if (nns->name) {
-               g_free((gpointer)nns->name);
-               nns->name = NULL;
-               nns->name_len = 0;
-       }
-       if (nns->full_name) {
-               g_free((gpointer)nns->full_name);
-               nns->full_name = NULL;
-               nns->full_name_len = 0;
-       }
-       if (nns->parent) {
-               g_free((gpointer)nns->parent);
-               nns->parent = NULL;
-               nns->parent_len = 0;
-       }
-       if (nns->fh) {
-               g_free((gpointer)nns->fh);
-               nns->fh = NULL;
-               nns->fh_length = 0;
-       }
+       g_free((gpointer)nns->name);
+       g_free((gpointer)nns->full_name);
+       g_free((gpointer)nns->parent);
+       g_free((gpointer)nns->fh);
        g_free(nns);
-       return TRUE;
 }
 
 
 static void
 nfs_name_snoop_init(void)
 {
-       if (nfs_name_snoop_unmatched != NULL) {
-               g_hash_table_foreach_remove(nfs_name_snoop_unmatched,
-                               nfs_name_snoop_unmatched_free_all, NULL);
-       } else {
-               /* The fragment table does not exist. Create it */
-               nfs_name_snoop_unmatched = g_hash_table_new(nfs_name_snoop_unmatched_hash,
-                       nfs_name_snoop_unmatched_equal);
-       }
-       if (nfs_name_snoop_matched != NULL) {
-               g_hash_table_foreach_remove(nfs_name_snoop_matched,
-                               nfs_name_snoop_unmatched_free_all, NULL);
-       } else {
-               /* The fragment table does not exist. Create it */
-               nfs_name_snoop_matched = g_hash_table_new(nfs_name_snoop_matched_hash,
-                       nfs_name_snoop_matched_equal);
-       }
+       nfs_name_snoop_unmatched =
+               g_hash_table_new_full(nfs_name_snoop_unmatched_hash,
+               nfs_name_snoop_unmatched_equal,
+               NULL, nfs_name_snoop_value_destroy);
+       nfs_name_snoop_matched =
+               g_hash_table_new_full(nfs_name_snoop_matched_hash,
+               nfs_name_snoop_matched_equal,
+               NULL, nfs_name_snoop_value_destroy);
+}
+
+static void
+nfs_name_snoop_cleanup(void)
+{
+       g_hash_table_destroy(nfs_name_snoop_unmatched);
+       g_hash_table_destroy(nfs_name_snoop_matched);
 }
 
 
@@ -1207,8 +1286,8 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
                                0, 0, nns->name);
                        PROTO_ITEM_SET_HIDDEN(fh_item);
                } else {
-                       fh_item = proto_tree_add_string_format_value(tree, hf_nfs_name, tvb,
-                               fh_offset, 0, nns->name, "%s", nns->name);
+                       fh_item = proto_tree_add_string(tree, hf_nfs_name, tvb,
+                               fh_offset, 0, nns->name);
                }
                PROTO_ITEM_SET_GENERATED(fh_item);
 
@@ -1229,45 +1308,37 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
 
 /* file handle dissection */
 
-static const value_string names_fhtype[] =
-{
-       {       FHT_UNKNOWN,            "unknown"                               },
-       {       FHT_SVR4,               "System V R4"                           },
-       {       FHT_LINUX_KNFSD_LE,     "Linux knfsd (little-endian)"           },
-       {       FHT_LINUX_NFSD_LE,      "Linux user-land nfsd (little-endian)"  },
-       {       FHT_LINUX_KNFSD_NEW,    "Linux knfsd (new)"                     },
-       {       FHT_NETAPP,             "ONTAP 7G nfs v3 file handle"           },
-       {       FHT_NETAPP_V4,          "ONTAP 7G nfs v4 file handle"           },
-       {       FHT_NETAPP_GX_V3,       "ONTAP GX nfs v3 file handle"           },
-       {       FHT_CELERRA_VNX,        "Celerra|VNX NFS file handle"           },
-       {       FHT_GLUSTER,            "GlusterFS/NFS file handle"             },
-       {       0,                      NULL                                    }
-};
-static value_string_ext names_fhtype_ext = VALUE_STRING_EXT_INIT(names_fhtype);
+static const true_false_string tfs_endianness = { "Little Endian", "Big Endian" };
+
+static void
+nfs_fmt_fsid( gchar *result, guint32 revision )
+{
+       guint32 fsid_major;
+       guint32 fsid_minor;
 
+       fsid_major = ( revision>>18 ) &  0x3fff; /* 14 bits */
+       fsid_minor = ( revision     ) & 0x3ffff; /* 18 bits */
 
-static const true_false_string tfs_endianness = { "Little Endian", "Big Endian" };
+   g_snprintf( result, ITEM_LABEL_LENGTH, "%d,%d", fsid_major, fsid_minor);
+}
 
 /* SVR4: checked with ReliantUNIX (5.43, 5.44, 5.45), OpenSolaris (build 101a) */
 static void
 dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       gboolean little_endian; /* We support little endian and big endian. */
-       gboolean have_flag;     /* The flag field at the end is optional. */
-       gboolean found;         /* Did we really detect the file handle format? */
+       guint encoding = ENC_BIG_ENDIAN;        /* We support little endian and big endian. Default is big endian*/
+       gboolean have_flag = FALSE;     /* The flag field at the end is optional. Assume no flag is there */
+       gboolean found = FALSE;         /* Did we really detect the file handle format? */
        guint32  nof = 0;
        guint32  len1;
        guint32  len2;
        guint32  fhlen;         /* File handle length. */
 
-       /* By default we assume big endianness. */
-       little_endian = FALSE;
-
-       /* By default, we aassume, that the flag is no there. */
-       have_flag = FALSE;
-
-       /* Not detected yet. */
-       found = FALSE;
+       static const int * fsid_fields[] = {
+               &hf_nfs_fh_fsid_major32,
+               &hf_nfs_fh_fsid_minor32,
+               NULL
+       };
 
        /* Somehow this is no calling argument, so we have to re-calculate it. */
        fhlen = tvb_reported_length(tvb);
@@ -1278,12 +1349,12 @@ dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tre
                len2 = tvb_get_letohs(tvb, 10+len1);
 
                if (12+len1+len2 == fhlen) {
-                       little_endian = TRUE;
+                       encoding = ENC_LITTLE_ENDIAN;
                        have_flag = FALSE;
                        found = TRUE;
                }
                if (16+len1+len2 == fhlen) {
-                       little_endian = TRUE;
+                       encoding = ENC_LITTLE_ENDIAN;
                        have_flag = TRUE;
                        found = TRUE;
                }
@@ -1296,81 +1367,27 @@ dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tre
                        len2 = tvb_get_ntohs(tvb, 10+len1);
 
                        if (12+len1+len2 == fhlen) {
-                               little_endian = FALSE;
                                have_flag = FALSE;
                        }
                        if (16+len1+len2 == fhlen) {
-                               little_endian = FALSE;
                                have_flag = TRUE;
                        }
                }
        }
 
-       proto_tree_add_boolean(tree, hf_nfs_fh_endianness, tvb, 0, fhlen, little_endian);
+       proto_tree_add_boolean(tree, hf_nfs_fh_endianness, tvb, 0, fhlen, (encoding == ENC_LITTLE_ENDIAN));
 
        /* We are fairly sure, that when found == FALSE, the following code will
        throw an exception. */
 
        /* file system id */
-       {
-               guint32 fsid_O;
-               guint32 fsid_L;
-               guint32 temp;
-               guint32 fsid_major;
-               guint32 fsid_minor;
-
-               fsid_O = nof;
-               fsid_L = 4;
-               if (little_endian)
-                       temp = tvb_get_letohl(tvb, fsid_O);
-               else
-                       temp = tvb_get_ntohl(tvb, fsid_O);
-               fsid_major = ( temp>>18 ) &  0x3fff; /* 14 bits */
-               fsid_minor = ( temp     ) & 0x3ffff; /* 18 bits */
-
-               if (tree) {
-                       proto_item *fsid_item = NULL;
-                       proto_tree *fsid_tree = NULL;
-
-                       fsid_item = proto_tree_add_text(tree, tvb,
-                                                       fsid_O, fsid_L,
-                                                       "file system ID: %d,%d", fsid_major, fsid_minor);
-                       fsid_tree = proto_item_add_subtree(fsid_item,
-                                                          ett_nfs_fh_fsid);
-                       if (little_endian) {
-                               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
-                                                   tvb, fsid_O+2, 2, fsid_major);
-                               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
-                                                   tvb, fsid_O,   3, fsid_minor);
-                       }
-                       else {
-                               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
-                                                   tvb, fsid_O,   2, fsid_major);
-                               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
-                                                   tvb, fsid_O+1, 3, fsid_minor);
-                       }
-               }
-               nof = fsid_O + fsid_L;
-       }
+       proto_tree_add_bitmask(tree, tvb, nof, hf_nfs_fh_fsid,
+                                       ett_nfs_fh_fsid, fsid_fields, encoding);
+       nof += 4;
 
        /* file system type */
-       {
-               guint32 fstype_O;
-               guint32 fstype_L;
-               guint32 fstype;
-
-               fstype_O = nof;
-               fstype_L = 4;
-               if (little_endian)
-                       fstype = tvb_get_letohl(tvb, fstype_O);
-               else
-                       fstype = tvb_get_ntohl(tvb, fstype_O);
-               if (tree) {
-                       proto_tree_add_uint(tree, hf_nfs_fh_fstype, tvb,
-                                           fstype_O, fstype_L, fstype);
-               }
-               nof = fstype_O + fstype_L;
-       }
+       proto_tree_add_item(tree, hf_nfs_fh_fstype, tvb, nof, 4, encoding);
+       nof += 4;
 
        /* file number */
        {
@@ -1390,26 +1407,14 @@ dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tre
                fn_O = nof;
                fn_len_O = fn_O;
                fn_len_L = 2;
-               if (little_endian)
-                       fn_len = tvb_get_letohs(tvb, fn_len_O);
-               else
-                       fn_len = tvb_get_ntohs(tvb, fn_len_O);
+               fn_len = tvb_get_guint16(tvb, fn_len_O, encoding);
                fn_data_O = fn_O + fn_len_L;
                fn_data_inode_O = fn_data_O + 2;
                fn_data_inode_L = 4;
-               if (little_endian)
-                       inode = tvb_get_letohl(tvb, fn_data_inode_O);
-               else
-                       inode = tvb_get_ntohl(tvb, fn_data_inode_O);
-               if (little_endian)
-                       fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
-               else
-                       fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
+               inode = tvb_get_guint32(tvb, fn_data_inode_O, encoding);
+               fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
                fn_data_gen_L = 4;
-               if (little_endian)
-                       gen = tvb_get_letohl(tvb, fn_data_gen_O);
-               else
-                       gen = tvb_get_ntohl(tvb, fn_data_gen_O);
+               gen = tvb_get_guint32(tvb, fn_data_gen_O, encoding);
                fn_L = fn_len_L + fn_len;
                if (tree) {
                        proto_item *fn_item = NULL;
@@ -1447,24 +1452,16 @@ dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tre
                xfn_O = nof;
                xfn_len_O = xfn_O;
                xfn_len_L = 2;
-               if (little_endian)
-                       xfn_len = tvb_get_letohs(tvb, xfn_len_O);
-               else
-                       xfn_len = tvb_get_ntohs(tvb, xfn_len_O);
+               xfn_len = tvb_get_guint16(tvb, xfn_len_O, encoding);
                xfn_data_O = xfn_O + xfn_len_L;
                xfn_data_inode_O = xfn_data_O + 2;
                xfn_data_inode_L = 4;
-               if (little_endian)
-                       xinode = tvb_get_letohl(tvb, xfn_data_inode_O);
-               else
-                       xinode = tvb_get_ntohl(tvb, xfn_data_inode_O);
+               xinode = tvb_get_guint32(tvb, xfn_data_inode_O, encoding);
                xfn_data_gen_O = xfn_data_inode_O + xfn_data_inode_L;
                xfn_data_gen_L = 4;
-               if (little_endian)
-                       xgen = tvb_get_letohl(tvb, xfn_data_gen_O);
-               else
-                       xgen = tvb_get_ntohl(tvb, xfn_data_gen_O);
+               xgen = tvb_get_guint32(tvb, xfn_data_gen_O, encoding);
                xfn_L = xfn_len_L + xfn_len;
+
                if (tree) {
                        proto_item *xfn_item = NULL;
                        proto_tree *xfn_tree = NULL;
@@ -1484,22 +1481,8 @@ dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tre
        }
 
        /* flag */
-       if (have_flag) {
-               guint32 flag_O;
-               guint32 flag_L;
-               guint32 flag_value;
-
-               flag_O = nof;
-               flag_L = 4;
-               if (little_endian)
-                       flag_value = tvb_get_letohl(tvb, flag_O);
-               else
-                       flag_value = tvb_get_ntohl(tvb, flag_O);
-               if (tree) {
-                       proto_tree_add_uint(tree, hf_nfs_fh_flag, tvb,
-                                           flag_O, flag_L, flag_value);
-               }
-       }
+       if (have_flag)
+               proto_tree_add_item(tree, hf_nfs_fh_flag, tvb, nof, 4, encoding);
 }
 
 
@@ -1510,35 +1493,22 @@ dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto
 {
        if (tree) {
                int     offset = 0;
-               guint32 dentry;
-               guint32 inode;
-               guint32 dirinode;
                guint32 temp;
                guint32 fsid_major;
                guint32 fsid_minor;
                guint32 xfsid_major;
                guint32 xfsid_minor;
-               guint32 xinode;
-               guint32 gen;
 
-               dentry      = tvb_get_letohl(tvb, offset+0);
-               inode       = tvb_get_letohl(tvb, offset+4);
-               dirinode    = tvb_get_letohl(tvb, offset+8);
                temp        = tvb_get_letohs (tvb, offset+12);
                fsid_major  = (temp >> 8) & 0xff;
                fsid_minor  = (temp     ) & 0xff;
                temp        = tvb_get_letohs(tvb, offset+16);
                xfsid_major = (temp >> 8) & 0xff;
                xfsid_minor = (temp     ) & 0xff;
-               xinode      = tvb_get_letohl(tvb, offset+20);
-               gen         = tvb_get_letohl(tvb, offset+24);
 
-               proto_tree_add_uint(tree, hf_nfs_fh_dentry,
-                                   tvb, offset+0, 4, dentry);
-               proto_tree_add_uint(tree, hf_nfs_fh_fn_inode,
-                                   tvb, offset+4, 4, inode);
-               proto_tree_add_uint(tree, hf_nfs_fh_dirinode,
-                                   tvb, offset+8, 4, dirinode);
+               proto_tree_add_item(tree, hf_nfs_fh_dentry, tvb, offset+0, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_nfs_fh_fn_inode, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_nfs_fh_dirinode, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
 
                /* file system id (device) */
                {
@@ -1548,10 +1518,8 @@ dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto
                                                        offset+12, 4, ett_nfs_fh_fsid, NULL,
                                                        "file system ID: %d,%d",
                                                        fsid_major, fsid_minor);
-                       proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
-                                           tvb, offset+13, 1, fsid_major);
-                       proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
-                                           tvb, offset+12, 1, fsid_minor);
+                       proto_tree_add_item(fsid_tree, hf_nfs_fh_fsid_major16_mask, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
+                       proto_tree_add_item(fsid_tree, hf_nfs_fh_fsid_minor16_mask, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
                }
 
                /* exported file system id (device) */
@@ -1561,16 +1529,12 @@ dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto
                        xfsid_tree = proto_tree_add_subtree_format(tree, tvb,
                                                         offset+16, 4, ett_nfs_fh_xfsid, NULL,
                                                         "exported file system ID: %d,%d", xfsid_major, xfsid_minor);
-                       proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_major,
-                                           tvb, offset+17, 1, xfsid_major);
-                       proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_minor,
-                                           tvb, offset+16, 1, xfsid_minor);
+                       proto_tree_add_item(xfsid_tree, hf_nfs_fh_xfsid_major, tvb, offset+16, 2, ENC_LITTLE_ENDIAN);
+                       proto_tree_add_item(xfsid_tree, hf_nfs_fh_xfsid_minor, tvb, offset+16, 2, ENC_LITTLE_ENDIAN);
                }
 
-               proto_tree_add_uint(tree, hf_nfs_fh_xfn_inode,
-                                   tvb, offset+20, 4, xinode);
-               proto_tree_add_uint(tree, hf_nfs_fh_fn_generation,
-                                   tvb, offset+24, 4, gen);
+               proto_tree_add_item(tree, hf_nfs_fh_xfn_inode, tvb, offset+20, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_nfs_fh_fn_generation, tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
        }
 }
 
@@ -1583,14 +1547,7 @@ dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_
        int offset = 0;
 
        /* pseudo inode */
-       {
-               guint32 pinode;
-               pinode   = tvb_get_letohl(tvb, offset+0);
-               if (tree) {
-                       proto_tree_add_uint(tree, hf_nfs_fh_pinode,
-                                           tvb, offset+0, 4, pinode);
-               }
-       }
+       proto_tree_add_item(tree, hf_nfs_fh_pinode, tvb, offset+0, 4, ENC_LITTLE_ENDIAN);
 
        /* hash path */
        {
@@ -1598,22 +1555,14 @@ dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_
 
                hashlen  = tvb_get_guint8(tvb, offset+4);
                if (tree) {
-                       proto_item *hash_item = NULL;
-                       proto_tree *hash_tree = NULL;
-
-                       hash_item = proto_tree_add_text(tree, tvb, offset+4,
-                                                       hashlen + 1,
-                                                       "hash path: %s",
-                                                       tvb_bytes_to_ep_str(tvb, offset+5, hashlen));
-                       hash_tree = proto_item_add_subtree(hash_item,
-                                                          ett_nfs_fh_hp);
+                       proto_tree *hash_tree;
+
+                       hash_tree = proto_tree_add_subtree_format(tree, tvb, offset+4, hashlen + 1, ett_nfs_fh_hp, NULL,
+                                                                       "hash path: %s", tvb_bytes_to_str(wmem_packet_scope(), tvb, offset+5, hashlen));
                        proto_tree_add_uint(hash_tree,
                                            hf_nfs_fh_hp_len, tvb, offset+4, 1,
                                            hashlen);
-                       proto_tree_add_text(hash_tree, tvb, offset+5,
-                                           hashlen,
-                                           "key: %s",
-                                           tvb_bytes_to_ep_str(tvb, offset+5, hashlen));
+                       proto_tree_add_item(hash_tree, hf_nfs_fh_hp_key, tvb, offset+5, hashlen, ENC_NA);
                }
        }
 }
@@ -1623,55 +1572,40 @@ static void
 dissect_fhandle_data_NETAPP(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        int offset = 0;
+       static const int * flags[] = {
+               &hf_nfs_fh_file_flag_mntpoint,
+               &hf_nfs_fh_file_flag_snapdir,
+               &hf_nfs_fh_file_flag_snapdir_ent,
+               &hf_nfs_fh_file_flag_empty,
+               &hf_nfs_fh_file_flag_vbn_access,
+               &hf_nfs_fh_file_flag_multivolume,
+               &hf_nfs_fh_file_flag_metadata,
+       };
 
        if (tree) {
                guint32 mount          = tvb_get_letohl(tvb, offset +  0);
-               guint32 mount_gen      = tvb_get_letohl(tvb, offset +  4);
-               guint16 flags          = tvb_get_letohs(tvb, offset +  8);
-               guint8  snapid         = tvb_get_guint8(tvb, offset + 10);
-               guint8  unused         = tvb_get_guint8(tvb, offset + 11);
+
                guint32 inum           = tvb_get_ntohl( tvb, offset + 12);
-               guint32 generation     = tvb_get_letohl(tvb, offset + 16);
-               guint32 fsid           = tvb_get_letohl(tvb, offset + 20);
                guint32 nfsexport      = tvb_get_letohl(tvb, offset + 24);
                guint32 export_snapgen = tvb_get_letohl(tvb, offset + 28);
 
                proto_tree *subtree = NULL;
-               char *flag_string;
-               static const char *strings[] = { " MNT_PNT", " SNAPDIR", " SNAPDIR_ENT",
-                                   " EMPTY", " VBN_ACCESS", " MULTIVOLUME",
-                                   " METADATA" };
-               guint16 bit = sizeof(strings) / sizeof(strings[0]);
-
-               flag_string = (char *)wmem_alloc(wmem_packet_scope(), 512);
-               flag_string[0] = 0;
-               while (bit--) {
-                       if (flags & (1<<bit)) {
-                               g_strlcat(flag_string, strings[bit], 512);
-                       }
-               }
+
                subtree = proto_tree_add_subtree_format(tree, tvb, offset + 0, 8,
                                           ett_nfs_fh_mount, NULL, "mount (inode %u)", mount);
                proto_tree_add_uint(subtree, hf_nfs_fh_mount_fileid,
                                           tvb, offset + 0, 4, mount);
-               proto_tree_add_uint(subtree, hf_nfs_fh_mount_generation,
-                                          tvb, offset + 4, 4, mount_gen);
+               proto_tree_add_item(subtree, hf_nfs_fh_mount_generation, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
                subtree = proto_tree_add_subtree_format(tree, tvb, offset + 8, 16,
                                           ett_nfs_fh_file, NULL, "file (inode %u)", inum);
-               proto_tree_add_uint_format(subtree, hf_nfs_fh_flags,
-                                                 tvb, offset + 8, 2, flags,
-                                                 "Flags: %#02x%s", flags,
-                                                 flag_string);
-               proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
-                                          offset + 10, 1, snapid);
-               proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
-                                          offset + 11, 1, unused);
-               proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
-                                          offset + 12, 4, inum);
-               proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
-                                          offset + 16, 4, generation);
-               proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
-                                          offset + 20, 4, fsid);
+
+               proto_tree_add_bitmask_with_flags(subtree, tvb, offset + 8, hf_nfs_fh_flags, ett_nfs4_fh_file_flags, flags, ENC_LITTLE_ENDIAN, BMT_NO_FALSE);
+
+               proto_tree_add_item(subtree, hf_nfs_fh_snapid, tvb, offset + 10, 1, ENC_NA);
+               proto_tree_add_item(subtree, hf_nfs_fh_unused, tvb, offset + 11, 1, ENC_NA);
+               proto_tree_add_item(subtree, hf_nfs_fh_fileid, tvb, offset + 12, 4, ENC_BIG_ENDIAN);
+               proto_tree_add_item(subtree, hf_nfs_fh_generation, tvb, offset + 16, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(subtree, hf_nfs_fh_fsid, tvb, offset + 20, 4, ENC_LITTLE_ENDIAN);
                subtree = proto_tree_add_subtree_format(tree, tvb, offset + 24, 8,
                                           ett_nfs_fh_export, NULL, "export (inode %u)", nfsexport);
                proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
@@ -1686,39 +1620,36 @@ dissect_fhandle_data_NETAPP(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *t
        }
 }
 
-static const value_string netapp_file_flag_vals[] =  {
-       { 0x0000,       "Not set"},
-       { 0x0001,       "Set"},
-       { 0,            NULL}
+static const value_string handle_type_strings[] = {
+       { 0, "NORMAL" },
+       { 1, "UNEXP" },
+       { 2, "VOLDIR" },
+       { 3, "ROOT" },
+       { 4, "ABSENT" },
+       { 0, NULL }
 };
 
 static void
 dissect_fhandle_data_NETAPP_V4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       static const char *handle_type_strings [] = { "NORMAL",
-                                                     "UNEXP",
-                                                     "VOLDIR",
-                                                     "ROOT",
-                                                     "ABSENT",
-                                                     "INVALID"
-       };
-
-       static const char *strings[] = { " MNT_PNT",
-                                        " SNAPDIR",
-                                        " SNAPDIR_ENT",
-                                        " EMPTY",
-                                        " VBN_ACCESS",
-                                        " MULTIVOLUME",
-                                        " METADATA",
-                                        " ORPHAN",
-                                        " FOSTER",
-                                        " NAMED_ATTR",
-                                        " EXP_SNAPDIR",
-                                        " VFILER",
-                                        " NS_AGGR",
-                                        " STRIPED",
-                                        " NS_PRIVATE",
-                                        " NEXT_GEN_FH"
+       static const int * flags[] = {
+               &hf_nfs_fh_file_flag_mntpoint,
+               &hf_nfs_fh_file_flag_snapdir,
+               &hf_nfs_fh_file_flag_snapdir_ent,
+               &hf_nfs_fh_file_flag_empty,
+               &hf_nfs_fh_file_flag_vbn_access,
+               &hf_nfs_fh_file_flag_multivolume,
+               &hf_nfs_fh_file_flag_metadata,
+               &hf_nfs_fh_file_flag_orphan,
+               &hf_nfs_fh_file_flag_foster,
+               &hf_nfs_fh_file_flag_named_attr,
+               &hf_nfs_fh_file_flag_exp_snapdir,
+               &hf_nfs_fh_file_flag_vfiler,
+               &hf_nfs_fh_file_flag_aggr,
+               &hf_nfs_fh_file_flag_striped,
+               &hf_nfs_fh_file_flag_private,
+               &hf_nfs_fh_file_flag_next_gen,
+               NULL
        };
 
        if (tree == NULL)
@@ -1726,93 +1657,35 @@ dissect_fhandle_data_NETAPP_V4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree
 
        {
                int         offset = 0;
-               proto_item *item;
                proto_tree *subtree;
-               guint8      snapid, unused;
-               guint16     flags;
-               guint32     fileid, snapgen, generation, fsid;
+               guint32     fileid;
                guint32     handle_type;
                guint32     inum;
-               char       *flag_string;
-               guint16     bit    = sizeof(strings) / sizeof(strings[0]);
-               proto_tree *flag_tree;
-               const char *handle_string;
+               guint encoding;
 
                handle_type = tvb_get_ntohl(tvb, offset + 24);
                inum        = tvb_get_ntohl(tvb, offset + 12);
 
-               flag_string = (char *)wmem_alloc(wmem_packet_scope(), 512);
-               flag_string[0] = '\0';
-
                if ( handle_type != 0 && handle_type <= 255) {
-                       fileid      = tvb_get_ntohl( tvb, offset +  0);
-                       snapgen     = tvb_get_ntohl( tvb, offset +  4);
-                       flags       = tvb_get_ntohs( tvb, offset +  8);
-                       snapid      = tvb_get_guint8(tvb, offset + 10);
-                       unused      = tvb_get_guint8(tvb, offset + 11);
-                       generation  = tvb_get_ntohl( tvb, offset + 16);
-                       fsid        = tvb_get_ntohl( tvb, offset + 20);
-               } else {
-                       fileid      = tvb_get_letohl(tvb, offset +  0);
-                       snapgen     = tvb_get_letohl(tvb, offset +  4);
-                       flags       = tvb_get_letohs(tvb, offset +  8);
-                       snapid      = tvb_get_guint8(tvb, offset + 10);
-                       unused      = tvb_get_guint8(tvb, offset + 11);
-                       generation  = tvb_get_letohl(tvb, offset + 16);
-                       fsid        = tvb_get_letohl(tvb, offset + 20);
-                       handle_type = tvb_get_letohl(tvb, offset + 24);
-               }
-
-               if (handle_type <= 4) {
-                       handle_string = handle_type_strings[handle_type];
+                       encoding = ENC_BIG_ENDIAN;
                } else {
-                       handle_string = handle_type_strings[5];
-               }
-
-               while (bit--) {
-                       if (flags & (1<<bit)) {
-                               g_strlcat(flag_string, strings[bit], 512);
-                       }
+                       encoding = ENC_LITTLE_ENDIAN;
                }
+        fileid = tvb_get_guint32(tvb, offset, encoding);
                subtree = proto_tree_add_subtree_format(tree, tvb, offset + 0, 8, ett_nfs4_fh_export, NULL, "export (inode %u)", fileid);
 
-               proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
-                                   tvb, offset + 0, 4, fileid);
-               proto_tree_add_uint(subtree, hf_nfs_fh_export_generation,
-                                   tvb, offset + 4, 4, snapgen);
+               proto_tree_add_item(subtree, hf_nfs_fh_export_fileid, tvb, offset + 0, 4, encoding);
+               proto_tree_add_item(subtree, hf_nfs_fh_export_generation, tvb, offset + 4, 4, encoding);
                subtree = proto_tree_add_subtree_format(tree, tvb, offset + 8, 16, ett_nfs4_fh_file, NULL, "file (inode %u)", inum);
-               item = proto_tree_add_uint_format_value(subtree, hf_nfs_fh_flags,
-                                                       tvb, offset + 8, 2, flags, "%#02x%s", flags, flag_string);
-               flag_tree = proto_item_add_subtree(item, ett_nfs4_fh_file_flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_mntpoint, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_snapdir, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_snapdir_ent, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_empty, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_vbn_access, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_multivolume, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_metadata, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_orphan, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_foster, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_named_attr, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_exp_snapdir, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_vfiler, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_aggr, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_striped, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_private, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_next_gen, tvb, offset+8, 2, flags);
-               proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
-                                   offset + 10, 1, snapid);
-               proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
-                                   offset + 11, 1, unused);
-               proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
-                                   offset + 12, 4, inum);
-               proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
-                                   offset + 16, 4, generation);
-               proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
-                                   offset + 20, 4, fsid);
-               proto_tree_add_uint_format_value(tree, hf_nfs_fh_handle_type,
-                                                tvb, offset+24, 4, handle_type,
-                                                "%s(%#02x)", handle_string, handle_type);
+
+               proto_tree_add_bitmask_with_flags(subtree, tvb, offset + 8, hf_nfs_fh_flags, ett_nfs4_fh_file_flags, flags, encoding, BMT_NO_FALSE);
+
+               proto_tree_add_item(subtree, hf_nfs_fh_snapid, tvb, offset + 10, 1, ENC_NA);
+               proto_tree_add_item(subtree, hf_nfs_fh_unused, tvb, offset + 11, 1, ENC_NA);
+               proto_tree_add_item(subtree, hf_nfs_fh_fileid, tvb, offset + 12, 4, encoding);
+               proto_tree_add_item(subtree, hf_nfs_fh_generation, tvb, offset + 16, 4, encoding);
+               proto_tree_add_item(subtree, hf_nfs_fh_fsid, tvb, offset + 20, 4, encoding);
+               proto_tree_add_item(tree, hf_nfs_fh_handle_type, tvb, offset+24, 4, encoding);
        }
 }
 
@@ -1835,14 +1708,8 @@ dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t* tvb, packet_info *pinfo _U_, proto_t
        if (tree) {
                proto_item *tf;
                proto_tree *field_tree;
-               guint16     epoch;
-               guint32     export_id;
-               guint32     export_uid;
                guint8      flags;
-               guint32     spinfile_id;
-               guint32     spinfile_uid;
                guint8      utility;
-               guint8      volcnt;
                guint32     offset = 0;
                static const int * fh_flags[] = {
                        &hf_nfs3_gxfh_sfhflags_resv1,
@@ -1895,15 +1762,11 @@ dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t* tvb, packet_info *pinfo _U_, proto_t
                                    offset, 1, utility);
 
                /* = volume count== */
-               volcnt = tvb_get_guint8(tvb, offset+1);
-               proto_tree_add_uint(tree, hf_nfs3_gxfh_volcnt, tvb, offset+1, 1, volcnt);
+               proto_tree_add_item(tree, hf_nfs3_gxfh_volcnt, tvb, offset+1, 1, ENC_NA);
                /* = epoch = */
-               epoch = tvb_get_letohs(tvb, offset+2);
-               proto_tree_add_uint(tree, hf_nfs3_gxfh_epoch, tvb, offset+2, 2, epoch);
+               proto_tree_add_item(tree, hf_nfs3_gxfh_epoch, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
                /* = spin file handle = */
                flags        = tvb_get_guint8(tvb, offset+11);
-               spinfile_id  = tvb_get_letohl(tvb, offset+12);
-               spinfile_uid = tvb_get_letohl(tvb, offset+16);
 
                field_tree = proto_tree_add_subtree(tree, tvb, offset+4, 16,
                                         ett_nfs3_gxfh_sfhfield, NULL, "  spin file handle");
@@ -1919,15 +1782,11 @@ dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t* tvb, packet_info *pinfo _U_, proto_t
                        proto_tree_add_bitmask(field_tree, tvb, offset+11, hf_nfs3_gxfh_sfhflags, ett_nfs3_gxfh_sfhflags, fh_flags, ENC_NA);
                }
 
-               proto_tree_add_uint(field_tree, hf_nfs3_gxfh_spinfid, tvb,
-                                          offset+12, 4, spinfile_id);
-               proto_tree_add_uint(field_tree, hf_nfs3_gxfh_spinfuid, tvb,
-                                          offset+16, 4, spinfile_uid);
+               proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfid, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfuid, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
 
                /* = spin file handle (mount point) = */
                flags        = tvb_get_guint8(tvb, offset+27);
-               spinfile_id  = tvb_get_letohl(tvb, offset+28);
-               spinfile_uid = tvb_get_letohl(tvb, offset+32);
 
                field_tree = proto_tree_add_subtree(tree, tvb, offset+20, 16,
                                         ett_nfs3_gxfh_sfhfield, NULL, "  spin (mount point) file handle");
@@ -1943,20 +1802,12 @@ dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t* tvb, packet_info *pinfo _U_, proto_t
                        proto_tree_add_bitmask(field_tree, tvb, offset+27, hf_nfs3_gxfh_sfhflags, ett_nfs3_gxfh_sfhflags, fh_flags, ENC_NA);
                }
 
-               proto_tree_add_uint(field_tree, hf_nfs3_gxfh_spinfid, tvb,
-                                          offset+28, 4, spinfile_id);
-               proto_tree_add_uint(field_tree, hf_nfs3_gxfh_spinfuid, tvb,
-                                          offset+32, 4, spinfile_uid);
+               proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfid, tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfuid, tvb, offset+32, 4, ENC_LITTLE_ENDIAN);
                /* = export point id  = */
-               export_id  = tvb_get_letohl(tvb, offset+36);
-               proto_tree_add_uint_format_value(tree, hf_nfs3_gxfh_exportptid, tvb,
-                                          offset+36, 4, spinfile_id,
-                                          "0x%08x (%u)", export_id, export_id);
+               proto_tree_add_item(tree, hf_nfs3_gxfh_exportptid, tvb, offset+36, 4, ENC_LITTLE_ENDIAN);
                /* = export point unique id  = */
-               export_uid = tvb_get_letohl(tvb, offset+40);
-               proto_tree_add_uint_format_value(tree, hf_nfs3_gxfh_exportptuid, tvb,
-                                          offset+40, 4, spinfile_id,
-                                          "0x%08x (%u)", export_uid, export_uid);
+               proto_tree_add_item(tree, hf_nfs3_gxfh_exportptuid, tvb, offset+40, 4, ENC_LITTLE_ENDIAN);
 
        }  /* end of (tree) */
 }
@@ -1990,16 +1841,14 @@ static void
 dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        int    offset = 0;
-       guint8 version;
-       guint8 auth_type;
+       guint32 version;
+       guint8 auth_type = 0;
        guint8 fsid_type;
        guint8 fileid_type;
+       proto_tree *fileid_tree;
+       proto_item *fileid_item;
 
-       version     = tvb_get_guint8(tvb, offset + 0);
-       if (tree) {
-               proto_tree_add_uint(tree, hf_nfs_fh_version,
-                       tvb, offset+0, 1, version);
-       }
+       proto_tree_add_item_ret_uint(tree, hf_nfs_fh_version, tvb, offset+0, 1, ENC_NA, &version);
 
        switch (version) {
                case 1:
@@ -2023,62 +1872,53 @@ dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, prot
                        break;
                default: {
                        /* unknown version */
-                       goto out;
+                       return;
                }
        }
 
-       switch (auth_type) {
-               case 0: {
-                       /* no authentication */
-                       if (tree) {
-                               proto_tree_add_text(tree, tvb,
-                                       offset + 0, 0,
-                                       "authentication: none");
-                       }
-               } break;
-               default: {
-                       /* unknown authentication type */
-                       goto out;
-               }
+       if (auth_type != 0)
+       {
+               /* unknown authentication type */
+               return;
        }
 
-       switch (fsid_type) {
-               case 0: {
-                       guint16 fsid_major;
-                       guint16 fsid_minor;
-                       guint32 fsid_inode;
+       if (fsid_type != 0)
+       {
+               /* unknown authentication type */
+               return;
+       }
 
-                       fsid_major = tvb_get_ntohs(tvb, offset + 0);
-                       fsid_minor = tvb_get_ntohs(tvb, offset + 2);
-                       fsid_inode = tvb_get_letohl(tvb, offset + 4);
-                       if (tree) {
-                               proto_tree *fsid_tree = proto_tree_add_subtree_format(tree, tvb,
-                                       offset+0, 8, ett_nfs_fh_fsid, NULL,
-                                       "file system ID: %u,%u (inode %u)",
-                                       fsid_major, fsid_minor, fsid_inode);
-
-                               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
-                                                       tvb, offset+0, 2, fsid_major);
-                               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
-                                                       tvb, offset+2, 2, fsid_minor);
-                               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_inode,
-                                                       tvb, offset+4, 4, fsid_inode);
-                       }
-                       offset += 8;
-               } break;
-               default: {
-                       /* unknown fsid type */
-                       goto out;
-               }
+       {
+       guint16 fsid_major;
+       guint16 fsid_minor;
+       guint32 fsid_inode;
+
+       fsid_major = tvb_get_ntohs(tvb, offset + 0);
+       fsid_minor = tvb_get_ntohs(tvb, offset + 2);
+       fsid_inode = tvb_get_letohl(tvb, offset + 4);
+       if (tree) {
+               proto_tree *fsid_tree = proto_tree_add_subtree_format(tree, tvb,
+                       offset+0, 8, ett_nfs_fh_fsid, NULL,
+                       "file system ID: %u,%u (inode %u)",
+                       fsid_major, fsid_minor, fsid_inode);
+
+               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major16,
+                                       tvb, offset+0, 2, fsid_major);
+               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor16,
+                                       tvb, offset+2, 2, fsid_minor);
+               proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_inode,
+                                       tvb, offset+4, 4, fsid_inode);
+       }
+
+       offset += 8;
        }
 
+       fileid_tree = proto_tree_add_subtree_format(tree, tvb,
+                                       offset, 0, ett_nfs_fh_fn, &fileid_item, "file ID");
+
        switch (fileid_type) {
                case 0: {
-                       if (tree) {
-                               proto_tree_add_text(tree, tvb,
-                                       offset+0, 0,
-                                       "file ID: root inode");
-                       }
+                       proto_item_append_text(fileid_item, ": root inode");
                } break;
                case 1: {
                        guint32 inode;
@@ -2088,10 +1928,8 @@ dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, prot
                        generation = tvb_get_letohl(tvb, offset + 4);
 
                        if (tree) {
-                               proto_tree *fileid_tree = proto_tree_add_subtree_format(tree, tvb,
-                                       offset+0, 8, ett_nfs_fh_fn, NULL,
-                                       "file ID: %u (%u)",
-                                       inode, generation);
+                               proto_item_append_text(fileid_item, ": %u (%u)", inode, generation);
+                               proto_item_set_len(fileid_item, 8);
 
                                proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
                                                tvb, offset+0, 4, inode);
@@ -2104,36 +1942,30 @@ dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, prot
                case 2: {
                        guint32 inode;
                        guint32 generation;
-                       guint32 parent_inode;
 
                        inode = tvb_get_letohl(tvb, offset + 0);
                        generation = tvb_get_letohl(tvb, offset + 4);
-                       parent_inode = tvb_get_letohl(tvb, offset + 8);
 
                        if (tree) {
-                                proto_tree *fileid_tree = proto_tree_add_subtree_format(tree, tvb,
-                                       offset+0, 8, ett_nfs_fh_fn, NULL,
-                                       "file ID: %u (%u)",
-                                       inode, generation);
+                               proto_item_append_text(fileid_item, ": %u (%u)", inode, generation);
+                               proto_item_set_len(fileid_item, 12);
 
                                proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
                                                tvb, offset+0, 4, inode);
                                proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
                                                tvb, offset+4, 4, generation);
-                               proto_tree_add_uint(fileid_tree, hf_nfs_fh_dirinode,
-                                               tvb, offset+8, 4, parent_inode);
+                               proto_tree_add_item(fileid_tree, hf_nfs_fh_dirinode,
+                                               tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
                        }
 
                        /*offset += 12;*/
                } break;
                default: {
+                       proto_item_append_text(fileid_item, ": unknown");
                        /* unknown fileid type */
-                       goto out;
+                       return;
                }
        }
-
-out:
-       ;
 }
 
 
@@ -2155,7 +1987,7 @@ dissect_fhandle_data_GLUSTER(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *
        if (fhlen != 36)
                return;
 
-       ident = tvb_get_string_enc(NULL, tvb, offset, 4, ENC_ASCII);
+       ident = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 4, ENC_ASCII);
        if (strncmp(":OGL", ident, 4))
                return;
        offset += 4;
@@ -2166,6 +1998,55 @@ dissect_fhandle_data_GLUSTER(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *
        /*offset += 16;*/
 }
 
+/*
+ * Dissect dCache NFS File Handle - dcache > 2.6
+ */
+
+#define DCACHE_MAGIC_MASK   0x00FFFFFF
+#define DCACHE_VERSION_MASK 0xFF000000
+#define DCACHE_MAGIC        0xCAFFEE
+
+static const value_string dcache_handle_types[] = {
+       { 0, "INODE" },
+       { 1, "TAG" },
+       { 2, "TAGS" },
+       { 3, "ID" },
+       { 4, "PATHOF" },
+       { 5, "PARENT" },
+       { 6, "NAMEOF" },
+       { 7, "PGET" },
+       { 8, "PSET" },
+       { 9, "CONST" },
+       { 0, NULL }
+};
+
+static void
+dissect_fhandle_data_DCACHE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       int offset = 0;
+       guint32 version;
+       guint32 magic;
+       guint8 obj_len;
+
+       if (!tree)
+               return;
+
+       version = (tvb_get_ntohl(tvb, offset) & DCACHE_VERSION_MASK) >> 24;
+       magic   = (tvb_get_ntohl(tvb, offset) & DCACHE_MAGIC_MASK);
+
+       if ((version != 1) || (magic != DCACHE_MAGIC)) {
+               /* unknown file handle */
+               return;
+       }
+
+       obj_len = tvb_get_guint8(tvb, offset + 16);
+
+       proto_tree_add_item(tree, hf_nfs_fh_version, tvb, offset, 1, ENC_BIG_ENDIAN);
+       proto_tree_add_item(tree, hf_nfs_fh_generation, tvb, offset+4, 4, ENC_BIG_ENDIAN);
+       proto_tree_add_item(tree, hf_nfs_fh_dc_exportid, tvb, offset+8, 4, ENC_BIG_ENDIAN);
+       proto_tree_add_item(tree, hf_nfs_fh_dc_handle_type, tvb, offset+15, 1, ENC_BIG_ENDIAN);
+       proto_tree_add_item(tree, hf_nfs_fh_dc_opaque, tvb, offset + 17, obj_len, ENC_NA);
+}
 
 /* Dissect EMC Celerra or VNX NFSv3/v4 File Handle */
 static void
@@ -2173,21 +2054,7 @@ dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tr
 {
        guint16 offset = 0;
        guint16 fhlen;
-       guint32 obj_fsid;
-       guint16 obj_kindid;
-       guint16 obj_treeid;
-       guint32 obj_inode;
-       guint32 obj_gen;
-       guint32 ex_fsid;
-       guint16 ex_kindid;
-       guint16 ex_treeid;
-       guint32 ex_inode;
-       guint32 ex_gen;
        guint32 obj_id;
-       guint32 ro_node;
-
-       if (!tree)
-               return;
 
        fhlen = tvb_reported_length(tvb);
 
@@ -2200,19 +2067,18 @@ dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tr
                {
                proto_item *obj_item;
                proto_tree *obj_tree;
+
+               if (!tree)
+                       return;
+
                obj_item = proto_tree_add_item(tree, hf_nfs_fh_obj, tvb, offset+0, 16, ENC_NA );
                obj_tree = proto_item_add_subtree(obj_item, ett_nfs_fh_obj);
 
-               obj_fsid   = tvb_get_letohl(tvb, offset+0);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_fsid,   tvb,  offset+0, 4, obj_fsid);
-               obj_kindid = tvb_get_letohs(tvb, offset+4);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_kindid, tvb,  offset+4, 2, obj_kindid);
-               obj_treeid = tvb_get_letohs(tvb, offset+6);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_treeid, tvb,  offset+6, 2, obj_treeid);
-               obj_inode  = tvb_get_letohl(tvb, offset+8);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_inode,  tvb,  offset+8, 4, obj_inode);
-               obj_gen   = tvb_get_letohl(tvb, offset+12);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+12, 4, obj_gen);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_fsid,   tvb,  offset+0, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_kindid, tvb,  offset+4, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_treeid, tvb,  offset+6, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_inode,  tvb,  offset+8, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
                }
                {
                /* Create "Export" subtree (NFSv3: Bytes 16 thru 31 of the 32-byte file handle  */
@@ -2221,16 +2087,11 @@ dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tr
                ex_item = proto_tree_add_item(tree, hf_nfs_fh_ex, tvb,  offset+16, 16, ENC_NA );
                ex_tree = proto_item_add_subtree(ex_item, ett_nfs_fh_ex);
 
-               ex_fsid   = tvb_get_letohl(tvb, offset+16);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_fsid,     tvb, offset+16, 4, ex_fsid);
-               ex_kindid = tvb_get_letohs(tvb, offset+20);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_kindid,   tvb, offset+20, 2, ex_kindid);
-               ex_treeid = tvb_get_letohs(tvb, offset+22);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_treeid,   tvb, offset+22, 2, ex_treeid);
-               ex_inode  = tvb_get_letohl(tvb, offset+24);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_inode,    tvb, offset+24, 4, ex_inode);
-               ex_gen    = tvb_get_letohl(tvb, offset+28);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_gen,      tvb, offset+28, 4, ex_gen);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_fsid,     tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_kindid,   tvb, offset+20, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_treeid,   tvb, offset+22, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_inode,    tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_gen,      tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
                }
        } else if (fhlen == 40) {
                /*
@@ -2241,14 +2102,16 @@ dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tr
                the *export* info followed by 16 bytes containing the *file/dir* info.
                */
 
+               if (!tree)
+                       return;
+
                /* "Named Attribute ID" or "Object ID" (bytes 0 thru 3) */
                obj_id = tvb_get_letohl(tvb, offset+0);
                if (obj_id <= 0 || obj_id > 9) obj_id = 1;
                proto_tree_add_uint(tree, hf_nfs_fh_obj_id,         tvb,  offset+0, 4, obj_id);
 
                /* "RO_Node" boolean (bytes 4 thru 7) */
-               ro_node = tvb_get_letohl(tvb, offset+4);
-               proto_tree_add_boolean(tree, hf_nfs_fh_ro_node,     tvb,  offset+4, 4, ro_node);
+               proto_tree_add_item(tree, hf_nfs_fh_ro_node,     tvb,  offset+4, 4, ENC_LITTLE_ENDIAN);
 
                /* Create "Export" subtree (bytes 8 thru 23 of the 40-byte file handle  */
                {
@@ -2257,16 +2120,11 @@ dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tr
                ex_item = proto_tree_add_item(tree, hf_nfs_fh_ex,  tvb,  offset+8, 16, ENC_NA );
                ex_tree = proto_item_add_subtree(ex_item, ett_nfs_fh_ex);
 
-               ex_fsid   = tvb_get_letohl(tvb, offset+8);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_fsid,    tvb,  offset+8,  4, ex_fsid);
-               ex_kindid = tvb_get_letohs(tvb, offset+12);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_kindid,  tvb, offset+12,  2, ex_kindid);
-               ex_treeid = tvb_get_letohs(tvb, offset+14);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_treeid,  tvb, offset+14,  2, ex_treeid);
-               ex_inode  = tvb_get_letohl(tvb, offset+16);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_inode,   tvb, offset+16,  4, ex_inode);
-               ex_gen    = tvb_get_letohl(tvb, offset+20);
-               proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_gen,     tvb, offset+20,  4, ex_gen);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_fsid,    tvb,  offset+8,  4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_kindid,  tvb, offset+12,  2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_treeid,  tvb, offset+14,  2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_inode,   tvb, offset+16,  4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(ex_tree, hf_nfs_fh_ex_gen,     tvb, offset+20,  4, ENC_LITTLE_ENDIAN);
                }
                /* Create a "File/Dir/Object" subtree (bytes 24 thru 39 of the 40-byte file handle) */
                {
@@ -2275,16 +2133,11 @@ dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tr
                obj_item = proto_tree_add_item(tree, hf_nfs_fh_obj, tvb, offset+24, 16, ENC_NA);
                obj_tree = proto_item_add_subtree(obj_item, ett_nfs_fh_obj);
 
-               obj_fsid   = tvb_get_letohl(tvb, offset+24);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_fsid,   tvb, offset+24,  4, obj_fsid);
-               obj_kindid = tvb_get_letohs(tvb, offset+28);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_kindid, tvb, offset+28,  2, obj_kindid);
-               obj_treeid = tvb_get_letohs(tvb, offset+30);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_treeid, tvb, offset+30,  2, obj_treeid);
-               obj_inode  = tvb_get_letohl(tvb, offset+32);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_inode,  tvb, offset+32,  4, obj_inode);
-               obj_gen   = tvb_get_letohl(tvb, offset+36);
-               proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+36,  4, obj_gen);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_fsid,   tvb, offset+24,  4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_kindid, tvb, offset+28,  2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_treeid, tvb, offset+30,  2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_inode,  tvb, offset+32,  4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+36,  4, ENC_LITTLE_ENDIAN);
                }
        } else {
                /* This is not a Celerra|VNX file handle.  Display a warning. */
@@ -2299,7 +2152,7 @@ dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tr
 static void
 dissect_fhandle_data_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       guint fhlen = tvb_length(tvb);
+       guint fhlen = tvb_reported_length(tvb);
 
        proto_tree_add_item(tree, hf_nfs_fh_fhandle_data, tvb, 0, fhlen, ENC_NA);
 }
@@ -2339,9 +2192,8 @@ dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *
                guint8 *fh_array;
                proto_item *fh_item = NULL;
 
-               fh_array = tvb_get_string_enc(NULL, tvb, offset, fhlen, ENC_ASCII);
+               fh_array = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset, fhlen);
                fhhash = crc32_ccitt(fh_array, fhlen);
-               g_free(fh_array);
 
                if (hidden) {
                        fh_item = proto_tree_add_uint(tree, hf_nfs_fh_hash, NULL, 0,
@@ -2362,17 +2214,11 @@ dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *
 
        if (!hidden) {
                tvbuff_t *fh_tvb;
-               int real_length;
-
-               proto_tree_add_text(tree, tvb, offset, 0, "decode type as: %s",
-                       val_to_str_ext_const(default_nfs_fhandle_type, &names_fhtype_ext, "Unknown"));
-
-               real_length = fhlen;
-               if (default_nfs_fhandle_type != FHT_UNKNOWN && real_length < tvb_length_remaining(tvb, offset))
-                       real_length = tvb_length_remaining(tvb, offset);
 
-               fh_tvb = tvb_new_subset(tvb, offset, real_length, fhlen);
-               if (!dissector_try_uint(nfs_fhandle_table, default_nfs_fhandle_type, fh_tvb, pinfo, tree))
+               /* Functionality for choosing subdissector is controlled through Decode As as NFS doesn't
+                  have a unique identifier to determine subdissector */
+               fh_tvb = tvb_new_subset(tvb, offset, fhlen, fhlen);
+               if (!dissector_try_uint(nfs_fhandle_table, 0, fh_tvb, pinfo, tree))
                        dissect_fhandle_data_unknown(fh_tvb, pinfo, tree);
        }
 }
@@ -2486,16 +2332,11 @@ static int
 dissect_nfs2_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *status)
 {
        guint32     stat;
+       proto_item *stat_item;
 
-       stat = tvb_get_ntohl(tvb, offset+0);
-
-       if (tree) {
-               proto_item *stat_item;
-
-               proto_tree_add_uint(tree, hf_nfs2_status, tvb, offset+0, 4, stat);
-               stat_item = proto_tree_add_uint(tree, hf_nfs_status, tvb, offset+0, 4, stat);
-               PROTO_ITEM_SET_HIDDEN(stat_item);
-       }
+       proto_tree_add_item_ret_uint(tree, hf_nfs2_status, tvb, offset+0, 4, ENC_BIG_ENDIAN, &stat);
+       stat_item = proto_tree_add_uint(tree, hf_nfs_status, tvb, offset+0, 4, stat);
+       PROTO_ITEM_SET_HIDDEN(stat_item);
 
        offset += 4;
 
@@ -2508,10 +2349,11 @@ dissect_nfs2_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *status
 
 /* NFSv2 RFC 1094, Page 12..14 */
 static int
-dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_rmdir_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -2529,10 +2371,11 @@ dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, prot
 
 
 static int
-dissect_nfs2_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_symlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -2550,10 +2393,11 @@ dissect_nfs2_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, pr
 
 
 static int
-dissect_nfs2_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_link_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -2571,10 +2415,11 @@ dissect_nfs2_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto
 
 
 static int
-dissect_nfs2_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_rename_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -2592,10 +2437,11 @@ dissect_nfs2_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, pro
 
 
 static int
-dissect_nfs2_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_remove_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -2626,21 +2472,9 @@ static const value_string nfs2_ftype[] =
 static value_string_ext nfs2_ftype_ext = VALUE_STRING_EXT_INIT(nfs2_ftype);
 
 static int
-dissect_nfs2_ftype(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
+dissect_nfs2_ftype(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       guint32     ftype;
-
-       ftype = tvb_get_ntohl(tvb, offset+0);
-
-       if (tree) {
-               const char *ftype_name_p;
-
-               ftype_name_p = val_to_str_ext(ftype, &nfs2_ftype_ext, "%u");
-
-               proto_tree_add_text(tree, tvb, offset, 4,
-                       "%s: %s (%u)", name, ftype_name_p, ftype);
-       }
-
+       proto_tree_add_item(tree, hf_nfs2_ftype, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
        return offset;
 }
@@ -2690,9 +2524,10 @@ dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
 
 /* NFSv2 RFC 1094, Page 15 */
 static int
-dissect_nfs2_statfs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_statfs_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -2704,9 +2539,10 @@ dissect_nfs2_statfs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
 
 
 static int
-dissect_nfs2_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_readlink_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -2718,9 +2554,10 @@ dissect_nfs2_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_
 
 
 static int
-dissect_nfs2_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_getattr_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -2775,33 +2612,26 @@ static const value_string nfs2_mode_names[] = {
 };
 
 static int
-dissect_nfs2_mode(tvbuff_t *tvb, int offset, proto_tree *tree, const char *label)
-{
-
+dissect_nfs2_mode(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       static const int *modes[] = {
+               &hf_nfs2_mode_name,
+               &hf_nfs2_mode_set_user_id,
+               &hf_nfs2_mode_set_group_id,
+               &hf_nfs2_mode_save_swap_text,
+               &hf_nfs2_mode_read_owner,
+               &hf_nfs2_mode_write_owner,
+               &hf_nfs2_mode_exec_owner,
+               &hf_nfs2_mode_read_group,
+               &hf_nfs2_mode_write_group,
+               &hf_nfs2_mode_exec_group,
+               &hf_nfs2_mode_read_other,
+               &hf_nfs2_mode_write_other,
+               &hf_nfs2_mode_exec_other,
+               NULL
+       };
 
-       if (tree) {
-               guint32     mode;
-               proto_item *mode_item;
-               proto_tree *mode_tree;
-
-               mode = tvb_get_ntohl(tvb, offset+0);
-               mode_item = proto_tree_add_text(tree, tvb, offset, 4, "%s: 0%o", label, mode);
-               mode_tree = proto_item_add_subtree(mode_item, ett_nfs2_mode);
-
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_name, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_set_user_id, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_set_group_id, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_save_swap_text, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_read_owner, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_write_owner, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_exec_owner, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_read_group, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_write_group, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_exec_group, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_read_other, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_write_other, tvb, offset, 4, ENC_BIG_ENDIAN);
-               proto_tree_add_item(mode_tree, hf_nfs2_mode_exec_other, tvb, offset, 4, ENC_BIG_ENDIAN);
-       }
+       proto_tree_add_bitmask(tree, tvb, offset, hf_nfs2_mode, ett_nfs2_mode, modes, ENC_BIG_ENDIAN);
 
        offset += 4;
        return offset;
@@ -2819,8 +2649,8 @@ dissect_nfs2_fattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name
        fattr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
                        ett_nfs_fattr, &fattr_item, name);
 
-       offset = dissect_nfs2_ftype(tvb, offset, fattr_tree, "type");
-       offset = dissect_nfs2_mode(tvb, offset, fattr_tree, "mode");
+       offset = dissect_nfs2_ftype(tvb, offset, fattr_tree);
+       offset = dissect_nfs2_mode(tvb, offset, fattr_tree);
        offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_nlink, offset);
        offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_uid, offset);
        offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_gid, offset);
@@ -2857,9 +2687,9 @@ dissect_nfs2_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name
                                        ett_nfs2_sattr, &sattr_item, name);
 
        if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
-               offset = dissect_nfs2_mode(tvb, offset, sattr_tree, "mode");
+               offset = dissect_nfs2_mode(tvb, offset, sattr_tree);
        else {
-               proto_tree_add_text(sattr_tree, tvb, offset, 4, "mode: no value");
+               proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_mode, tvb, offset, 4, 0xffffffff, "no value");
                offset += 4;
        }
 
@@ -2867,7 +2697,7 @@ dissect_nfs2_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name
                offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs2_fattr_uid,
                        offset);
        else {
-               proto_tree_add_text(sattr_tree, tvb, offset, 4, "uid: no value");
+               proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_fattr_uid, tvb, offset, 4, 0xffffffff, "no value");
                offset += 4;
        }
 
@@ -2875,7 +2705,7 @@ dissect_nfs2_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name
                offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs2_fattr_gid,
                        offset);
        else {
-               proto_tree_add_text(sattr_tree, tvb, offset, 4, "gid: no value");
+               proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_fattr_gid, tvb, offset, 4, 0xffffffff, "no value");
                offset += 4;
        }
 
@@ -2883,7 +2713,7 @@ dissect_nfs2_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name
                offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs2_fattr_size,
                        offset);
        else {
-               proto_tree_add_text(sattr_tree, tvb, offset, 4, "size: no value");
+               proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_fattr_size, tvb, offset, 4, 0xffffffff, "no value");
                offset += 4;
        }
 
@@ -2891,7 +2721,12 @@ dissect_nfs2_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name
                offset = dissect_timeval(tvb, offset, sattr_tree,
                        hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
        } else {
-               proto_tree_add_text(sattr_tree, tvb, offset, 8, "atime: no value");
+               nstime_t    ts;
+
+               ts.secs  = 0xffffffff;
+               ts.nsecs = 0;
+
+               proto_tree_add_time_format_value(sattr_tree, hf_nfs_atime, tvb, offset, 8, &ts, "no value");
                offset += 8;
        }
 
@@ -2899,7 +2734,12 @@ dissect_nfs2_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name
                offset = dissect_timeval(tvb, offset, sattr_tree,
                        hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
        } else {
-               proto_tree_add_text(sattr_tree, tvb, offset, 8, "mtime: no value");
+               nstime_t    ts;
+
+               ts.secs  = 0xffffffff;
+               ts.nsecs = 0;
+
+               proto_tree_add_time_format_value(sattr_tree, hf_nfs_mtime, tvb, offset, 8, &ts, "no value");
                offset += 8;
        }
 
@@ -2956,31 +2796,25 @@ dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
 
 /* NFSv2 RFC 1094, Page 17,18 */
 static int
-dissect_nfs2_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_write_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
-       offset = dissect_attrstat(tvb, offset, tree, pinfo, "WRITE");
-
-       return offset;
+       return dissect_attrstat(tvb, 0, tree, pinfo, "WRITE");
 }
 
 
 /* NFSv2 RFC 1094, Page 18 */
 static int
-dissect_nfs2_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_setattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
-       offset = dissect_attrstat(tvb, offset, tree, pinfo, "SETATTR");
-
-       return offset;
+       return dissect_attrstat(tvb, 0, tree, pinfo, "SETATTR");
 }
 
 
 /* NFSv2 RFC 1094, Page 18 */
 static int
-dissect_nfs2_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_getattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
-       offset = dissect_attrstat(tvb, offset, tree, pinfo, "GETATTR");
-
-       return offset;
+       return dissect_attrstat(tvb, 0, tree, pinfo, "GETATTR");
 }
 
 
@@ -3023,10 +2857,11 @@ dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
 
 /* NFSv2 RFC 1094, Page 18 */
 static int
-dissect_nfs2_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_rmdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     hash;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
 
@@ -3039,10 +2874,11 @@ dissect_nfs2_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
 
 /* NFSv2 RFC 1094, Page 18 */
 static int
-dissect_nfs2_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_remove_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     hash;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
 
@@ -3055,10 +2891,11 @@ dissect_nfs2_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
 
 /* NFSv2 RFC 1094, Page 18 */
 static int
-dissect_nfs2_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_lookup_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     hash;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
 
@@ -3108,38 +2945,36 @@ dissect_nfsdata(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
 
 /* NFSv2 RFC 1094, Page 18 */
 static int
-dissect_nfs2_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_mkdir_reply(tvbuff_t *tvb, packet_info *pinfo,
                         proto_tree *tree, void *data)
 {
-       offset = dissect_diropres(tvb, offset, pinfo, tree, "MKDIR", (rpc_call_info_value*)data);
-       return offset;
+       return dissect_diropres(tvb, 0, pinfo, tree, "MKDIR", (rpc_call_info_value*)data);
 }
 
 
 static int
-dissect_nfs2_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_create_reply(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data _U_)
 {
-       offset = dissect_diropres(tvb, offset, pinfo, tree, "CREATE", (rpc_call_info_value*)data);
-       return offset;
+       return dissect_diropres(tvb, 0, pinfo, tree, "CREATE", (rpc_call_info_value*)data);
 }
 
 
 static int
-dissect_nfs2_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_lookup_reply(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data _U_)
 {
-       offset = dissect_diropres(tvb, offset, pinfo, tree, "LOOKUP", (rpc_call_info_value*)data);
-       return offset;
+       return dissect_diropres(tvb, 0, pinfo, tree, "LOOKUP", (rpc_call_info_value*)data);
 }
 
 
 /* RFC 1094, Page 6 */
 static int
-dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_setattr_call(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data)
 {
        guint32 hash;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
        offset = dissect_nfs2_sattr  (tvb, offset,        tree, "attributes");
@@ -3152,12 +2987,13 @@ dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 6 */
 static int
-dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs2_readlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                            proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -3179,26 +3015,22 @@ dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv2 RFC 1094, Page 7 */
 static int
-dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_read_call(tvbuff_t *tvb, packet_info *pinfo,
                       proto_tree *tree, void *data)
 {
        guint32 offset_value;
        guint32 count;
        guint32 totalcount;
        guint32 hash;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
-       offset_value = tvb_get_ntohl(tvb, offset+0);
-       count        = tvb_get_ntohl(tvb, offset+4);
-       totalcount   = tvb_get_ntohl(tvb, offset+8);
-       if (tree) {
-               proto_tree_add_uint(tree, hf_nfs2_read_offset, tvb,
-               offset+0, 4, offset_value);
-               proto_tree_add_uint(tree, hf_nfs2_read_count, tvb,
-               offset+4, 4, count);
-               proto_tree_add_uint(tree, hf_nfs2_read_totalcount, tvb,
-               offset+8, 4, totalcount);
-       }
+       proto_tree_add_item_ret_uint(tree, hf_nfs2_read_offset, tvb,
+               offset+0, 4, ENC_BIG_ENDIAN, &offset_value);
+       proto_tree_add_item_ret_uint(tree, hf_nfs2_read_count, tvb,
+               offset+4, 4, ENC_BIG_ENDIAN, &count);
+       proto_tree_add_item_ret_uint(tree, hf_nfs2_read_totalcount, tvb,
+               offset+8, 4, ENC_BIG_ENDIAN, &totalcount);
        offset += 12;
 
        col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x Offset: %d Count: %d TotalCount: %d",
@@ -3212,11 +3044,12 @@ dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 7 */
 static int
-dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs2_read_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                        proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -3238,26 +3071,23 @@ dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv2 RFC 1094, Page 8 */
 static int
-dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_write_call(tvbuff_t *tvb, packet_info *pinfo,
                        proto_tree *tree, void *data)
 {
        guint32 beginoffset;
        guint32 offset_value;
        guint32 totalcount;
        guint32 hash;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
-       beginoffset  = tvb_get_ntohl(tvb, offset+0);
-       offset_value = tvb_get_ntohl(tvb, offset+4);
-       totalcount   = tvb_get_ntohl(tvb, offset+8);
-       if (tree) {
-               proto_tree_add_uint(tree, hf_nfs2_write_beginoffset, tvb,
-               offset+0, 4, beginoffset);
-               proto_tree_add_uint(tree, hf_nfs2_write_offset, tvb,
-               offset+4, 4, offset_value);
-               proto_tree_add_uint(tree, hf_nfs2_write_totalcount, tvb,
-               offset+8, 4, totalcount);
-       }
+
+       proto_tree_add_item_ret_uint(tree, hf_nfs2_write_beginoffset, tvb,
+               offset+0, 4, ENC_BIG_ENDIAN, &beginoffset);
+       proto_tree_add_item_ret_uint(tree, hf_nfs2_write_offset, tvb,
+               offset+4, 4, ENC_BIG_ENDIAN, &offset_value);
+       proto_tree_add_item_ret_uint(tree, hf_nfs2_write_totalcount, tvb,
+               offset+8, 4, ENC_BIG_ENDIAN, &totalcount);
        offset += 12;
 
        col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x BeginOffset: %d Offset: %d TotalCount: %d",
@@ -3273,11 +3103,12 @@ dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 8 */
 static int
-dissect_nfs2_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_mkdir_call(tvbuff_t *tvb, packet_info *pinfo,
                        proto_tree *tree, void *data)
 {
        guint32     hash;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
        offset = dissect_nfs2_sattr    (tvb, offset,        tree, "attributes");
@@ -3289,11 +3120,12 @@ dissect_nfs2_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 }
 
 static int
-dissect_nfs2_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_create_call(tvbuff_t *tvb, packet_info *pinfo,
                         proto_tree *tree, void *data)
 {
        guint32     hash;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
        offset = dissect_nfs2_sattr    (tvb, offset,        tree, "attributes");
@@ -3307,13 +3139,14 @@ dissect_nfs2_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 9 */
 static int
-dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_rename_call(tvbuff_t *tvb, packet_info *pinfo,
                         proto_tree *tree, void *data)
 {
        guint32     from_hash;
        const char *from_name = NULL;
        guint32     to_hash;
        const char *to_name   = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
@@ -3329,12 +3162,13 @@ dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 9 */
 static int
-dissect_nfs2_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_link_call(tvbuff_t *tvb, packet_info *pinfo,
                       proto_tree *tree, void *data)
 {
        guint32     from_hash;
        guint32     to_hash;
        const char *to_name = NULL;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "from", &from_hash, (rpc_call_info_value*)data);
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
@@ -3350,12 +3184,13 @@ dissect_nfs2_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 10 */
 static int
-dissect_nfs2_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_symlink_call(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data)
 {
        guint32     from_hash;
        const char *from_name = NULL;
        const char *to_name   = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
        offset = dissect_path(tvb, offset, tree, hf_nfs_symlink_to, &to_name);
@@ -3372,22 +3207,16 @@ dissect_nfs2_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 11 */
 static int
-dissect_nfs2_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_readdir_call(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data)
 {
-       guint32 cookie;
-       guint32 count;
        guint32 hash;
+       int offset = 0;
 
        offset = dissect_fhandle(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
-       cookie  = tvb_get_ntohl(tvb, offset+ 0);
-       count = tvb_get_ntohl(tvb, offset+ 4);
-       if (tree) {
-               proto_tree_add_uint(tree, hf_nfs2_readdir_cookie, tvb,
-                       offset+ 0, 4, cookie);
-               proto_tree_add_uint(tree, hf_nfs2_readdir_count, tvb,
-                       offset+ 4, 4, count);
-       }
+
+       proto_tree_add_item(tree, hf_nfs2_readdir_cookie, tvb, offset+ 0, 4, ENC_BIG_ENDIAN);
+       proto_tree_add_item(tree, hf_nfs2_readdir_count, tvb, offset+ 4, 4, ENC_BIG_ENDIAN);
        offset += 8;
 
        col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
@@ -3406,7 +3235,6 @@ dissect_readdir_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree *entry_tree = NULL;
        int         old_offset = offset;
        guint32     fileid;
-       guint32     cookie;
        const char *name;
 
        if (tree) {
@@ -3415,22 +3243,16 @@ dissect_readdir_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
                entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
        }
 
-       fileid = tvb_get_ntohl(tvb, offset + 0);
-       if (entry_tree)
-               proto_tree_add_uint(entry_tree, hf_nfs2_readdir_entry_fileid, tvb,
-                       offset+0, 4, fileid);
+       proto_tree_add_item_ret_uint(entry_tree, hf_nfs2_readdir_entry_fileid, tvb,
+                       offset, 4, ENC_BIG_ENDIAN, &fileid);
        offset += 4;
 
        offset = dissect_filename(tvb, offset, entry_tree,
                hf_nfs2_readdir_entry_name, &name);
        if (entry_item)
-               proto_item_set_text(entry_item, "Entry: file ID %u, name %s",
-               fileid, name);
+               proto_item_set_text(entry_item, "Entry: file ID %u, name %s", fileid, name);
 
-       cookie = tvb_get_ntohl(tvb, offset + 0);
-       if (entry_tree)
-               proto_tree_add_uint(entry_tree, hf_nfs2_readdir_entry_cookie, tvb,
-                       offset+0, 4, cookie);
+       proto_tree_add_item(entry_tree, hf_nfs2_readdir_entry_cookie, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
 
        /* now we know, that a readdir entry is shorter */
@@ -3444,12 +3266,13 @@ dissect_readdir_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv2 RFC 1094, Page 11 */
 static int
-dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_readdir_reply(tvbuff_t *tvb, packet_info *pinfo,
                           proto_tree *tree, void *data _U_)
 {
        guint32     status;
        guint32     eof_value;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
@@ -3458,10 +3281,8 @@ dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
                        offset = dissect_rpc_list(tvb, pinfo, tree, offset,
                                dissect_readdir_entry, NULL);
-                       eof_value = tvb_get_ntohl(tvb, offset+0);
-                       if (tree)
-                               proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
-                                       offset+ 0, 4, eof_value);
+                       proto_tree_add_item_ret_uint(tree, hf_nfs_readdir_eof, tvb,
+                                       offset, 4, ENC_BIG_ENDIAN, &eof_value);
                        offset += 4;
                break;
                default:
@@ -3477,37 +3298,21 @@ dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv2 RFC 1094, Page 12 */
 static int
-dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs2_statfs_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                          proto_tree *tree, void *data _U_)
 {
        guint32     status;
-       guint32     tsize;
-       guint32     bsize;
-       guint32     blocks;
-       guint32     bfree;
-       guint32     bavail;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs2_status(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       tsize  = tvb_get_ntohl(tvb, offset+ 0);
-                       bsize  = tvb_get_ntohl(tvb, offset+ 4);
-                       blocks = tvb_get_ntohl(tvb, offset+ 8);
-                       bfree  = tvb_get_ntohl(tvb, offset+12);
-                       bavail = tvb_get_ntohl(tvb, offset+16);
-                       if (tree) {
-                               proto_tree_add_uint(tree, hf_nfs2_statfs_tsize, tvb,
-                                       offset+ 0, 4, tsize);
-                               proto_tree_add_uint(tree, hf_nfs2_statfs_bsize, tvb,
-                                       offset+ 4, 4, bsize);
-                               proto_tree_add_uint(tree, hf_nfs2_statfs_blocks, tvb,
-                                       offset+ 8, 4, blocks);
-                               proto_tree_add_uint(tree, hf_nfs2_statfs_bfree, tvb,
-                                       offset+12, 4, bfree);
-                               proto_tree_add_uint(tree, hf_nfs2_statfs_bavail, tvb,
-                                       offset+16, 4, bavail);
-                       }
+                       proto_tree_add_item(tree, hf_nfs2_statfs_tsize, tvb, offset+ 0, 4, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tree, hf_nfs2_statfs_bsize, tvb, offset+ 4, 4, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tree, hf_nfs2_statfs_blocks, tvb, offset+ 8, 4, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tree, hf_nfs2_statfs_bfree, tvb, offset+12, 4, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tree, hf_nfs2_statfs_bavail, tvb, offset+16, 4, ENC_BIG_ENDIAN);
                        offset += 20;
                        proto_item_append_text(tree, ", STATFS Reply");
                break;
@@ -3523,16 +3328,15 @@ dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 
 /* proc number, "proc name", dissect_request, dissect_reply */
-/* NULL as function pointer means: type of arguments is "void". */
 static const vsff nfs2_proc[] = {
        { 0,    "NULL",         /* OK */
-       NULL,                           NULL },
+       dissect_rpc_void,               dissect_rpc_void },
        { 1,    "GETATTR",      /* OK */
        dissect_nfs2_getattr_call,      dissect_nfs2_getattr_reply },
        { 2,    "SETATTR",      /* OK */
        dissect_nfs2_setattr_call,      dissect_nfs2_setattr_reply },
        { 3,    "ROOT",         /* OK */
-       NULL,                           NULL },
+       dissect_rpc_void,               dissect_rpc_void },
        { 4,    "LOOKUP",       /* OK */
        dissect_nfs2_lookup_call,       dissect_nfs2_lookup_reply },
        { 5,    "READLINK",     /* OK */
@@ -3540,7 +3344,7 @@ static const vsff nfs2_proc[] = {
        { 6,    "READ",         /* OK */
        dissect_nfs2_read_call,         dissect_nfs2_read_reply },
        { 7,    "WRITECACHE",   /* OK */
-       NULL,                           NULL },
+       dissect_rpc_void,               dissect_rpc_void },
        { 8,    "WRITE",        /* OK */
        dissect_nfs2_write_call,        dissect_nfs2_write_reply },
        { 9,    "CREATE",       /* OK */
@@ -3616,8 +3420,7 @@ dissect_nfs3_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, const cha
 static int
 dissect_nfs3_cookie_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       proto_tree_add_text(tree, tvb, offset, NFS3_COOKIEVERFSIZE,
-               "Verifier: Opaque Data");
+       proto_tree_add_bytes_format_value(tree, hf_nfs3_verifier, tvb, offset, NFS3_COOKIEVERFSIZE, NULL, "Opaque Data");
        offset += NFS3_COOKIEVERFSIZE;
        return offset;
 }
@@ -3627,8 +3430,7 @@ dissect_nfs3_cookie_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
 static int
 dissect_nfs3_create_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       proto_tree_add_text(tree, tvb, offset, NFS3_CREATEVERFSIZE,
-               "Verifier: Opaque Data");
+       proto_tree_add_bytes_format_value(tree, hf_nfs3_verifier, tvb, offset, NFS3_CREATEVERFSIZE, NULL, "Opaque Data");
        offset += NFS3_CREATEVERFSIZE;
        return offset;
 }
@@ -3638,8 +3440,7 @@ dissect_nfs3_create_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
 static int
 dissect_nfs3_write_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       proto_tree_add_text(tree, tvb, offset, NFS3_WRITEVERFSIZE,
-               "Verifier: Opaque Data");
+       proto_tree_add_bytes_format_value(tree, hf_nfs3_verifier, tvb, offset, NFS3_WRITEVERFSIZE, NULL, "Opaque Data");
        offset += NFS3_WRITEVERFSIZE;
        return offset;
 }
@@ -3782,10 +3583,8 @@ dissect_nfs3_specdata(tvbuff_t *tvb, int offset, proto_tree *tree, const char *n
                specdata3_tree = proto_tree_add_subtree_format(tree, tvb, offset, 8,
                        ett_nfs3_specdata, NULL, "%s: %u,%u", name, specdata1, specdata2);
 
-               proto_tree_add_text(specdata3_tree, tvb, offset+0, 4,
-                                   "specdata1: %u", specdata1);
-               proto_tree_add_text(specdata3_tree, tvb, offset+4, 4,
-                                   "specdata2: %u", specdata2);
+               proto_tree_add_uint(specdata3_tree, hf_nfs3_specdata1, tvb, offset+0, 4, specdata1);
+               proto_tree_add_uint(specdata3_tree, hf_nfs3_specdata2, tvb, offset+4, 4, specdata2);
        }
 
        offset += 8;
@@ -4007,9 +3806,7 @@ dissect_nfs3_post_op_attr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_t
        post_op_attr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
                        ett_nfs3_post_op_attr, &post_op_attr_item, name);
 
-       proto_tree_add_text(post_op_attr_tree, tvb, offset, 4,
-                       "attributes_follow: %s (%u)",
-               val_to_str_const(attributes_follow, value_follows, "Unknown"), attributes_follow);
+       proto_tree_add_uint(post_op_attr_tree, hf_nfs3_attributes_follow, tvb, offset, 4, attributes_follow);
 
        offset += 4;
        switch (attributes_follow) {
@@ -4066,10 +3863,7 @@ dissect_pre_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *nam
        pre_op_attr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
                        ett_nfs3_pre_op_attr, &pre_op_attr_item, name);
 
-       attributes_follow = tvb_get_ntohl(tvb, offset+0);
-       proto_tree_add_text(pre_op_attr_tree, tvb, offset, 4,
-               "attributes_follow: %s (%u)",
-               val_to_str_const(attributes_follow, value_follows, "Unknown"), attributes_follow);
+       proto_tree_add_item_ret_uint(pre_op_attr_tree, hf_nfs3_attributes_follow, tvb, offset, 4, ENC_BIG_ENDIAN, &attributes_follow);
        offset += 4;
        switch (attributes_follow) {
                case TRUE:
@@ -4122,10 +3916,7 @@ dissect_nfs3_post_op_fh(tvbuff_t *tvb, int offset, packet_info *pinfo,
        post_op_fh3_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
                        ett_nfs3_post_op_fh, &post_op_fh3_item, name);
 
-       handle_follows = tvb_get_ntohl(tvb, offset+0);
-       proto_tree_add_text(post_op_fh3_tree, tvb, offset, 4,
-               "handle_follows: %s (%u)",
-               val_to_str_const(handle_follows, value_follows, "Unknown"), handle_follows);
+       proto_tree_add_item_ret_uint(post_op_fh3_tree, hf_nfs3_handle_follow, tvb, offset, 4, ENC_BIG_ENDIAN, &handle_follows);
        offset += 4;
        switch (handle_follows) {
                case TRUE:
@@ -4163,8 +3954,7 @@ dissect_set_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
        set_mode3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
                        ett_nfs3_set_mode, &set_mode3_item, "%s: %s", name, set_it_name);
 
-       proto_tree_add_text(set_mode3_tree, tvb, offset, 4,
-                       "set_it: %s (%u)", set_it_name, set_it);
+       proto_tree_add_uint(set_mode3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
 
        offset += 4;
 
@@ -4202,8 +3992,7 @@ dissect_set_uid3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
        set_uid3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
                        ett_nfs3_set_uid, &set_uid3_item, "%s: %s", name, set_it_name);
 
-       proto_tree_add_text(set_uid3_tree, tvb, offset, 4,
-                       "set_it: %s (%u)", set_it_name, set_it);
+       proto_tree_add_uint(set_uid3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
        offset += 4;
 
        switch (set_it) {
@@ -4239,8 +4028,7 @@ dissect_set_gid3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
        set_gid3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
                        ett_nfs3_set_gid, &set_gid3_item, "%s: %s", name, set_it_name);
 
-       proto_tree_add_text(set_gid3_tree, tvb, offset, 4,
-                       "set_it: %s (%u)", set_it_name, set_it);
+       proto_tree_add_uint(set_gid3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
 
        offset += 4;
 
@@ -4277,8 +4065,7 @@ dissect_set_size3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
 
        set_size3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
                        ett_nfs3_set_size, &set_size3_item, "%s: %s", name, set_it_name);
-       proto_tree_add_text(set_size3_tree, tvb, offset, 4,
-                       "set_it: %s (%u)", set_it_name, set_it);
+       proto_tree_add_uint(set_size3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
 
        offset += 4;
 
@@ -4330,8 +4117,7 @@ dissect_set_atime(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
        set_atime_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
                        ett_nfs3_set_atime, &set_atime_item, "%s: %s", name, set_it_name);
 
-       proto_tree_add_text(set_atime_tree, tvb, offset, 4,
-                       "set_it: %s (%u)", set_it_name, set_it);
+       proto_tree_add_uint(set_atime_tree, hf_nfs4_time_how, tvb, offset, 4, set_it);
        offset += 4;
 
        switch (set_it) {
@@ -4369,8 +4155,7 @@ dissect_set_mtime(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
 
        set_mtime_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
                        ett_nfs3_set_mtime, &set_mtime_item, "%s: %s", name, set_it_name);
-       proto_tree_add_text(set_mtime_tree, tvb, offset, 4,
-                               "set_it: %s (%u)", set_it_name, set_it);
+       proto_tree_add_uint(set_mtime_tree, hf_nfs4_time_how, tvb, offset, 4, set_it);
 
        offset += 4;
 
@@ -4463,11 +4248,12 @@ dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tr
 
 
 static int
-dissect_nfs3_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_remove_call(tvbuff_t *tvb, packet_info *pinfo,
                         proto_tree *tree, void *data)
 {
        guint32     hash = 0;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name, (rpc_call_info_value*)data);
 
@@ -4479,31 +4265,32 @@ dissect_nfs3_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_null_call(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
+dissect_nfs3_null_call(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
                       proto_tree *tree, void *data _U_)
 {
        proto_item_append_text(tree, ", NULL Call");
 
-       return offset;
+       return 0;
 }
 
 
 static int
-dissect_nfs3_null_reply(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
+dissect_nfs3_null_reply(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
                        proto_tree *tree, void *data _U_)
 {
        proto_item_append_text(tree, ", NULL Reply");
 
-       return offset;
+       return 0;
 }
 
 
 static int
-dissect_nfs3_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_rmdir_call(tvbuff_t *tvb, packet_info *pinfo,
        proto_tree *tree, void *data)
 {
        guint32     hash = 0;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name, (rpc_call_info_value*)data);
 
@@ -4516,10 +4303,11 @@ dissect_nfs3_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 32,33 */
 static int
-dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_getattr_call(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -4532,11 +4320,12 @@ dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 32,33 */
 static int
-dissect_nfs3_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_getattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                           proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        proto_item_append_text(tree, ", GETATTR Reply");
 
@@ -4573,8 +4362,7 @@ dissect_sattrguard3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *nam
        sattrguard3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
                        ett_nfs3_sattrguard, &sattrguard3_item, "%s: %s", name, check_name);
 
-       proto_tree_add_text(sattrguard3_tree, tvb, offset, 4,
-                       "check: %s (%u)", check_name, check);
+       proto_tree_add_uint(sattrguard3_tree, hf_nfs3_sattrguard3, tvb, offset, 4, check);
 
 
        offset += 4;
@@ -4598,10 +4386,11 @@ dissect_sattrguard3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *nam
 
 /* NFSv3 RFC 1813, Page 33..36 */
 static int
-dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_setattr_call(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh    (tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
        offset = dissect_nfs3_sattr     (tvb, offset,        tree, "new_attributes");
@@ -4616,11 +4405,12 @@ dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 33..36 */
 static int
-dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_setattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                           proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -4643,11 +4433,12 @@ dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 37..39 */
 static int
-dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_lookup_call(tvbuff_t *tvb, packet_info *pinfo,
                         proto_tree *tree, void *data)
 {
        guint32     hash = 0;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what", &hash, &name, (rpc_call_info_value*)data);
 
@@ -4660,12 +4451,13 @@ dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 37..39 */
 static int
-dissect_nfs3_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_lookup_reply(tvbuff_t *tvb, packet_info *pinfo,
                          proto_tree *tree, void *data)
 {
        guint32     status;
        const char *err;
        guint32     hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -4887,8 +4679,9 @@ dissect_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *
 
 /* NFSv3 RFC 1813, Page 40..43 */
 static int
-dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs3_access_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
+       int offset = 0;
        guint32 fhhash = 0, *acc_request, amask;
        rpc_call_info_value *civ = (rpc_call_info_value*)data;
 
@@ -4912,11 +4705,12 @@ dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
 
 /* NFSv3 RFC 1813, Page 40..43 */
 static int
-dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_access_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                          proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
@@ -4936,10 +4730,11 @@ dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 44,45 */
 static int
-dissect_nfs3_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_readlink_call(tvbuff_t *tvb, packet_info *pinfo,
                           proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -4951,12 +4746,13 @@ dissect_nfs3_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_readlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                            proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -4985,12 +4781,13 @@ dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 46..48 */
 static int
-dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_read_call(tvbuff_t *tvb, packet_info *pinfo,
                       proto_tree *tree, void *data)
 {
        guint64 off;
        guint32 len;
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
 
@@ -5012,12 +4809,13 @@ dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 46..48 */
 static int
-dissect_nfs3_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_read_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                        proto_tree *tree, void *data _U_)
 {
        guint32     status;
        guint32     len;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5071,13 +4869,13 @@ dissect_stable_how(tvbuff_t *tvb, int offset, proto_tree *tree, int hfindex)
 
 /* NFSv3 RFC 1813, Page 49..54 */
 static int
-dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                       proto_tree *tree, void *data)
+dissect_nfs3_write_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint64 off;
        guint32 len;
        guint32 stable;
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
 
@@ -5103,13 +4901,13 @@ dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 49..54 */
 static int
-dissect_nfs3_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                        proto_tree *tree, void *data _U_)
+dissect_nfs3_write_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        guint32     len;
        guint32     stable;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5167,12 +4965,12 @@ dissect_createmode3(tvbuff_t *tvb, int offset, proto_tree *tree, guint32* mode)
 
 /* NFSv3 RFC 1813, Page 54..58 */
 static int
-dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                        proto_tree *tree, void *data)
+dissect_nfs3_create_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     mode;
        guint32     hash = 0;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
        offset = dissect_createmode3(tvb, offset, tree, &mode);
@@ -5197,11 +4995,11 @@ dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 54..58 */
 static int
-dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                         proto_tree *tree, void *data)
+dissect_nfs3_create_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5227,11 +5025,11 @@ dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 58..60 */
 static int
-dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                       proto_tree *tree, void *data)
+dissect_nfs3_mkdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     hash = 0;
        const char *name = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
        offset = dissect_nfs3_sattr    (tvb, offset, tree, "attributes");
@@ -5244,11 +5042,11 @@ dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                        proto_tree *tree, void *data)
+dissect_nfs3_mkdir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5274,12 +5072,12 @@ dissect_nfs3_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 61..63 */
 static int
-dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                         proto_tree *tree, void *data)
+dissect_nfs3_symlink_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     from_hash = 0;
        const char *from_name = NULL;
        const char *to_name   = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &from_hash, &from_name, (rpc_call_info_value*)data);
        offset = dissect_nfs3_sattr    (tvb, offset,        tree, "symlink_attributes");
@@ -5295,11 +5093,11 @@ dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                          proto_tree *tree, void *data)
+dissect_nfs3_symlink_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5325,13 +5123,13 @@ dissect_nfs3_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 63..66 */
 static int
-dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                       proto_tree *tree, void *data)
+dissect_nfs3_mknod_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     type;
        guint32     hash = 0;
        const char *name = NULL;
        const char *type_str;
+       int offset = 0;
 
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
        offset = dissect_ftype3(tvb, offset, tree, hf_nfs3_ftype, &type);
@@ -5359,11 +5157,11 @@ dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_mknod_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                        proto_tree *tree, void *data)
+dissect_nfs3_mknod_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5389,11 +5187,11 @@ dissect_nfs3_mknod_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 67..69 */
 static int
-dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                         proto_tree *tree, void *data _U_)
+dissect_nfs3_remove_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5414,11 +5212,11 @@ dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 
 static int
-dissect_nfs3_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                        proto_tree *tree, void *data _U_)
+dissect_nfs3_rmdir_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5440,13 +5238,13 @@ dissect_nfs3_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 71..74 */
 static int
-dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                        proto_tree *tree, void *data)
+dissect_nfs3_rename_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     from_hash = 0;
        const char *from_name = NULL;
        guint32     to_hash   = 0;
        const char *to_name   = NULL;
+       int offset = 0;
 
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
@@ -5462,11 +5260,12 @@ dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 71..74 */
 static int
-dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_rename_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
                          proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5491,12 +5290,12 @@ dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 74..76 */
 static int
-dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                      proto_tree *tree, void *data)
+dissect_nfs3_link_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     from_hash = 0;
        guint32     to_hash   = 0;
        const char *to_name   = NULL;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &from_hash, (rpc_call_info_value*)data);
        offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link", &to_hash, &to_name, (rpc_call_info_value*)data);
@@ -5512,11 +5311,11 @@ dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 74..76 */
 static int
-dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                       proto_tree *tree, void *data _U_)
+dissect_nfs3_link_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5543,10 +5342,10 @@ dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 76..80 */
 static int
-dissect_nfs3_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                         proto_tree *tree, void *data)
+dissect_nfs3_readdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_cookie, offset);
@@ -5596,12 +5395,13 @@ dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 76..80 */
 static int
-dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_readdir_reply(tvbuff_t *tvb, packet_info *pinfo,
                           proto_tree *tree, void *data _U_)
 {
        guint32     status;
        guint32     eof_value;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5635,10 +5435,11 @@ dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 80..83 */
 static int
-dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_readdirplus_call(tvbuff_t *tvb, packet_info *pinfo,
                              proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_cookie, offset);
@@ -5712,12 +5513,12 @@ dissect_nfs3_entryplus(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 80..83 */
 static int
-dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                              proto_tree *tree, void *data)
+dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32     status;
        guint32     eof_value;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5751,10 +5552,10 @@ dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 84..86 */
 static int
-dissect_nfs3_fsstat_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                        proto_tree *tree, void *data)
+dissect_nfs3_fsstat_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -5765,12 +5566,12 @@ dissect_nfs3_fsstat_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                         proto_tree *tree, void *data _U_)
+dissect_nfs3_fsstat_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        guint32     invarsec;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5822,10 +5623,10 @@ static const true_false_string tfs_nfs_pathconf =
 
 /* NFSv3 RFC 1813, Page 86..90 */
 static int
-dissect_nfs3_fsinfo_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                        proto_tree *tree, void *data)
+dissect_nfs3_fsinfo_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -5836,10 +5637,17 @@ dissect_nfs3_fsinfo_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                         proto_tree *tree, void *data _U_)
+dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
+       static const int *properties[] = {
+               &hf_nfs3_fsinfo_properties_setattr,
+               &hf_nfs3_fsinfo_properties_pathconf,
+               &hf_nfs3_fsinfo_properties_symlinks,
+               &hf_nfs3_fsinfo_properties_hardlinks,
+               NULL
+       };
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5865,24 +5673,7 @@ dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
                        offset = dissect_nfstime3(tvb, offset, tree, hf_nfs_dtime, hf_nfs_dtime_sec,
                                hf_nfs_dtime_nsec);
 
-                       if (tree) {
-                               proto_item *properties_item;
-                               proto_tree *properties_tree;
-
-                               properties_item = proto_tree_add_item(tree, hf_nfs3_fsinfo_properties,
-                                   tvb, offset, 4, ENC_BIG_ENDIAN);
-
-                               properties_tree = proto_item_add_subtree(properties_item, ett_nfs3_fsinfo_properties);
-
-                               proto_tree_add_item(properties_tree, hf_nfs3_fsinfo_properties_setattr, tvb,
-                                       offset, 4, ENC_BIG_ENDIAN);
-                               proto_tree_add_item(properties_tree, hf_nfs3_fsinfo_properties_pathconf, tvb,
-                                       offset, 4, ENC_BIG_ENDIAN);
-                               proto_tree_add_item(properties_tree, hf_nfs3_fsinfo_properties_symlinks, tvb,
-                                       offset, 4, ENC_BIG_ENDIAN);
-                               proto_tree_add_item(properties_tree, hf_nfs3_fsinfo_properties_hardlinks, tvb,
-                                       offset, 4, ENC_BIG_ENDIAN);
-                       }
+                       proto_tree_add_bitmask(tree, tvb, offset, hf_nfs3_fsinfo_properties, ett_nfs3_fsinfo_properties, properties, ENC_BIG_ENDIAN);
                        offset += 4;
 
                        proto_item_append_text(tree, ", FSINFO Reply");
@@ -5907,10 +5698,10 @@ dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 90..92 */
 static int
-dissect_nfs3_pathconf_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                          proto_tree *tree, void *data)
+dissect_nfs3_pathconf_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
 
@@ -5921,13 +5712,13 @@ dissect_nfs3_pathconf_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 static int
-dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                           proto_tree *tree, void *data _U_)
+dissect_nfs3_pathconf_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        guint32     linkmax;
        guint32     name_max;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -5971,10 +5762,10 @@ dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* NFSv3 RFC 1813, Page 92..95 */
 static int
-dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                        proto_tree *tree, void *data)
+dissect_nfs3_commit_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        guint32 hash = 0;
+       int offset = 0;
 
        offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_offset, offset);
@@ -5989,11 +5780,11 @@ dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* NFSv3 RFC 1813, Page 92..95 */
 static int
-dissect_nfs3_commit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                         proto_tree *tree, void *data _U_)
+dissect_nfs3_commit_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *err;
+       int offset = 0;
 
        offset = dissect_nfs3_status(tvb, offset, tree, &status);
        switch (status) {
@@ -6128,19 +5919,190 @@ static const value_string names_nfs4_status[] = {
        {       10085,  "NFS4ERR_REJECT_DELEG"              },
        {       10086,  "NFS4ERR_RETURNCONFLICT"            },
        {       10087,  "NFS4ERR_DELEG_REVOKED"             },
+       {       10088,  "NFS4ERR_PARTNER_NOTSUPP"           },
+       {       10089,  "NFS4ERR_PARTNER_NO_AUTH"           },
+       {       10090,  "NFS4ERR_UNION_NOTSUPP"             },
+       {       10091,  "NFS4ERR_OFFLOAD_DENIED"            },
+       {       10092,  "NFS4ERR_WRONG_LFS"                 },
+       {       10093,  "NFS4ERR_BADLABEL"                  },
+       {       10094,  "NFS4ERR_OFFLOAD_NO_REQS"           },
        {       0,      NULL }
 };
 static value_string_ext names_nfs4_status_ext = VALUE_STRING_EXT_INIT(names_nfs4_status);
 
+static const value_string fattr4_names[] = {
+#define FATTR4_SUPPORTED_ATTRS     0
+       {       FATTR4_SUPPORTED_ATTRS,    "Supported_Attrs"    },
+#define FATTR4_TYPE                1
+       {       FATTR4_TYPE,               "Type"},
+#define FATTR4_FH_EXPIRE_TYPE      2
+       {       FATTR4_FH_EXPIRE_TYPE,     "FH_Expire_Type"     },
+#define FATTR4_CHANGE              3
+       {       FATTR4_CHANGE,             "Change"},
+#define FATTR4_SIZE                4
+       {       FATTR4_SIZE,               "Size"       },
+#define FATTR4_LINK_SUPPORT        5
+       {       FATTR4_LINK_SUPPORT,       "Link_Support"       },
+#define FATTR4_SYMLINK_SUPPORT     6
+       {       FATTR4_SYMLINK_SUPPORT,    "Symlink_Support"    },
+#define FATTR4_NAMED_ATTR          7
+       {       FATTR4_NAMED_ATTR,         "Named_Attr" },
+#define FATTR4_FSID                8
+       {       FATTR4_FSID,               "FSID"       },
+#define FATTR4_UNIQUE_HANDLES      9
+       {       FATTR4_UNIQUE_HANDLES,     "Unique_Handles"     },
+#define FATTR4_LEASE_TIME          10
+       {       FATTR4_LEASE_TIME,         "Lease_Time" },
+#define FATTR4_RDATTR_ERROR        11
+       {       FATTR4_RDATTR_ERROR,       "RDAttr_Error"       },
+#define FATTR4_ACL                 12
+       {       FATTR4_ACL,                "ACL"        },
+#define FATTR4_ACLSUPPORT          13
+       {       FATTR4_ACLSUPPORT,         "ACLSupport" },
+#define FATTR4_ARCHIVE             14
+       {       FATTR4_ARCHIVE,            "Archive"    },
+#define FATTR4_CANSETTIME          15
+       {       FATTR4_CANSETTIME,         "CanSetTime" },
+#define FATTR4_CASE_INSENSITIVE    16
+       {       FATTR4_CASE_INSENSITIVE,   "Case_Insensitive"   },
+#define FATTR4_CASE_PRESERVING     17
+       {       FATTR4_CASE_PRESERVING,    "Case_Preserving"    },
+#define FATTR4_CHOWN_RESTRICTED    18
+       {       FATTR4_CHOWN_RESTRICTED,   "Chown_Restricted"   },
+#define FATTR4_FILEHANDLE          19
+       {       FATTR4_FILEHANDLE,         "Filehandle" },
+#define FATTR4_FILEID              20
+       {       FATTR4_FILEID,             "FileId"     },
+#define FATTR4_FILES_AVAIL         21
+       {       FATTR4_FILES_AVAIL,        "Files_Avail"        },
+#define FATTR4_FILES_FREE          22
+       {       FATTR4_FILES_FREE,         "Files_Free" },
+#define FATTR4_FILES_TOTAL         23
+       {       FATTR4_FILES_TOTAL,        "Files_Total"        },
+#define FATTR4_FS_LOCATIONS        24
+       {       FATTR4_FS_LOCATIONS,       "FS_Locations"       },
+#define FATTR4_HIDDEN              25
+       {       FATTR4_HIDDEN,             "Hidden"     },
+#define FATTR4_HOMOGENEOUS         26
+       {       FATTR4_HOMOGENEOUS,        "Homogeneous"        },
+#define FATTR4_MAXFILESIZE         27
+       {       FATTR4_MAXFILESIZE,        "MaxFileSize"        },
+#define FATTR4_MAXLINK             28
+       {       FATTR4_MAXLINK,            "MaxLink"    },
+#define FATTR4_MAXNAME             29
+       {       FATTR4_MAXNAME,            "MaxName"    },
+#define FATTR4_MAXREAD             30
+       {       FATTR4_MAXREAD,            "MaxRead"    },
+#define FATTR4_MAXWRITE            31
+       {       FATTR4_MAXWRITE,           "MaxWrite"   },
+#define FATTR4_MIMETYPE            32
+       {       FATTR4_MIMETYPE,           "MimeType"   },
+#define FATTR4_MODE                33
+       {       FATTR4_MODE,               "Mode"       },
+#define FATTR4_NO_TRUNC            34
+       {       FATTR4_NO_TRUNC,           "No_Trunc"   },
+#define FATTR4_NUMLINKS            35
+       {       FATTR4_NUMLINKS,           "NumLinks"   },
+#define FATTR4_OWNER               36
+       {       FATTR4_OWNER,              "Owner"      },
+#define FATTR4_OWNER_GROUP         37
+       {       FATTR4_OWNER_GROUP,        "Owner_Group"        },
+#define FATTR4_QUOTA_AVAIL_HARD    38
+       {       FATTR4_QUOTA_AVAIL_HARD,   "Quota_Avail_Hard"   },
+#define FATTR4_QUOTA_AVAIL_SOFT    39
+       {       FATTR4_QUOTA_AVAIL_SOFT,   "Quota_Avail_Soft"   },
+#define FATTR4_QUOTA_USED          40
+       {       FATTR4_QUOTA_USED,         "Quota_Used" },
+#define FATTR4_RAWDEV              41
+       {       FATTR4_RAWDEV,             "RawDev"     },
+#define FATTR4_SPACE_AVAIL         42
+       {       FATTR4_SPACE_AVAIL,        "Space_Avail"        },
+#define FATTR4_SPACE_FREE          43
+       {       FATTR4_SPACE_FREE,         "Space_Free" },
+#define FATTR4_SPACE_TOTAL         44
+       {       FATTR4_SPACE_TOTAL,        "Space_Total"        },
+#define FATTR4_SPACE_USED          45
+       {       FATTR4_SPACE_USED,         "Space_Used" },
+#define FATTR4_SYSTEM              46
+       {       FATTR4_SYSTEM,             "System"     },
+#define FATTR4_TIME_ACCESS         47
+       {       FATTR4_TIME_ACCESS,        "Time_Access"        },
+#define FATTR4_TIME_ACCESS_SET     48
+       {       FATTR4_TIME_ACCESS_SET,    "Time_Access_Set"    },
+#define FATTR4_TIME_BACKUP         49
+       {       FATTR4_TIME_BACKUP,        "Time_Backup"        },
+#define FATTR4_TIME_CREATE         50
+       {       FATTR4_TIME_CREATE,        "Time_Create"        },
+#define FATTR4_TIME_DELTA          51
+       {       FATTR4_TIME_DELTA,         "Time_Delta" },
+#define FATTR4_TIME_METADATA       52
+       {       FATTR4_TIME_METADATA,      "Time_Metadata"      },
+#define FATTR4_TIME_MODIFY         53
+       {       FATTR4_TIME_MODIFY,        "Time_Modify"        },
+#define FATTR4_TIME_MODIFY_SET     54
+       {       FATTR4_TIME_MODIFY_SET,    "Time_Modify_Set"    },
+#define FATTR4_MOUNTED_ON_FILEID   55
+       {       FATTR4_MOUNTED_ON_FILEID,  "Mounted_on_FileId"  },
+#define FATTR4_DIR_NOTIF_DELAY     56
+       {       FATTR4_DIR_NOTIF_DELAY,    "Dir_Notif_Delay"    },
+#define FATTR4_DIRENT_NOTIF_DELAY  57
+#define FATTR4_DACL                58
+       {       FATTR4_DACL,               "DACL"                },
+#define FATTR4_SACL                59
+       {       FATTR4_SACL,               "SACL"                },
+#define FATTR4_CHANGE_POLICY       60
+       {       FATTR4_CHANGE_POLICY,      "Change_Policy"              },
+#define FATTR4_FS_STATUS           61
+       {       FATTR4_FS_STATUS,          "FS_Status"                  },
+#define FATTR4_FS_LAYOUT_TYPE      62
+       {       FATTR4_FS_LAYOUT_TYPE,     "FS_Layout_Type"             },
+#define FATTR4_LAYOUT_HINT         63
+       {       FATTR4_LAYOUT_HINT,        "Layout_hint"                },
+#define FATTR4_LAYOUT_TYPE         64
+       {       FATTR4_LAYOUT_TYPE,        "Layout_type"                },
+#define FATTR4_LAYOUT_BLKSIZE      65
+       {       FATTR4_LAYOUT_BLKSIZE,     "Layout_blksize"             },
+#define FATTR4_LAYOUT_ALIGNMENT    66
+       {       FATTR4_LAYOUT_ALIGNMENT,   "Layout_alignment"   },
+#define FATTR4_FS_LOCATIONS_INFO   67
+       {       FATTR4_FS_LOCATIONS_INFO,  "FS_Locations_info"  },
+#define FATTR4_MDSTHRESHOLD        68
+       {       FATTR4_MDSTHRESHOLD,       "MDS_Threshold"              },
+#define FATTR4_RETENTION_GET       69
+       {       FATTR4_RETENTION_GET,      "Retention_Get"              },
+#define FATTR4_RETENTION_SET       70
+       {       FATTR4_RETENTION_SET,      "Retention_Set"              },
+#define FATTR4_RETENTEVT_GET       71
+       {       FATTR4_RETENTEVT_GET,      "RetentEvt_Get"              },
+#define FATTR4_RETENTEVT_SET       72
+       {       FATTR4_RETENTEVT_SET,      "RetentEvt_Set"              },
+#define FATTR4_RETENTION_HOLD      73
+       {       FATTR4_RETENTION_HOLD,     "Retention_Hold"             },
+#define FATTR4_MODE_SET_MASKED     74
+       {       FATTR4_MODE_SET_MASKED,    "Mode_Set_Masked"    },
+#define FATTR4_SUPPATTR_EXCLCREAT  75
+       {       FATTR4_SUPPATTR_EXCLCREAT, "Suppattr_ExclCreat" },
+#define FATTR4_FS_CHARSET_CAP      76
+       {       FATTR4_FS_CHARSET_CAP,     "FS_Charset_Cap"             },
+#define FATTR4_CLONE_BLOCKSIZE     77
+       {       FATTR4_CLONE_BLOCKSIZE,    "Clone_Block_Size"           },
+#define FATTR4_SPACE_FREED         78
+       {       FATTR4_SPACE_FREED,        "Space_Freed"                },
+#define FATTR4_CHANGE_ATTR_TYPE    79
+       {       FATTR4_CHANGE_ATTR_TYPE,   "Change_Attr_Type"           },
+#define FATTR4_SECURITY_LABEL      80
+       {       FATTR4_SECURITY_LABEL,     "Security_Label"             },
+       {       0,      NULL    }
+};
+static value_string_ext fattr4_names_ext = VALUE_STRING_EXT_INIT(fattr4_names);
+
 static int
 dissect_nfs4_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *status)
 {
        guint32     stat;
        proto_item *stat_item;
 
-       stat = tvb_get_ntohl(tvb, offset+0);
-
-       proto_tree_add_uint(tree, hf_nfs4_status, tvb, offset+0, 4, stat);
+       proto_tree_add_item_ret_uint(tree, hf_nfs4_status, tvb, offset+0, 4, ENC_BIG_ENDIAN, &stat);
        stat_item = proto_tree_add_uint(tree, hf_nfs_status, tvb, offset+0, 4, stat);
        PROTO_ITEM_SET_HIDDEN(stat_item);
 
@@ -6220,9 +6182,7 @@ dissect_nfs4_pathname(tvbuff_t *tvb, int offset, proto_tree *tree)
        proto_item *fitem;
        proto_tree *newftree;
 
-       comp_count = tvb_get_ntohl(tvb, offset);
-       fitem = proto_tree_add_text(tree, tvb, offset, 4,
-               "pathname components (%u)", comp_count);
+       fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_pathname_components, tvb, offset, 4, ENC_BIG_ENDIAN, &comp_count);
        offset += 4;
 
        newftree = proto_item_add_subtree(fitem, ett_nfs4_pathname);
@@ -6257,8 +6217,7 @@ dissect_nfs4_settime(tvbuff_t *tvb, int offset,
 {
        guint32 set_it;
 
-       set_it = tvb_get_ntohl(tvb, offset);
-       proto_tree_add_uint(tree, hf_nfs4_time_how, tvb, offset+0, 4, set_it);
+       proto_tree_add_item_ret_uint(tree, hf_nfs4_time_how4, tvb, offset+0, 4, ENC_BIG_ENDIAN, &set_it);
        offset += 4;
 
        if (set_it == SET_TO_CLIENT_TIME4)
@@ -6530,19 +6489,36 @@ dissect_nfs4_ace(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,     proto_tree *
        return offset;
 }
 
+#define ACL4_AUTO_INHERIT      0x00000001
+#define ACL4_PROTECTED         0x00000002
+#define ACL4_DEFAULTED         0x00000004
+
+static const int *aclflags_fields[] = {
+       &hf_nfs4_aclflag_auto_inherit,
+       &hf_nfs4_aclflag_protected,
+       &hf_nfs4_aclflag_defaulted,
+       NULL
+};
+
+static int
+dissect_nfs4_aclflags(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_aclflags,
+               ett_nfs4_aclflag, aclflags_fields, ENC_BIG_ENDIAN);
+       offset += 4;
+
+       return offset;
+}
 
 static int
 dissect_nfs4_fattr_acl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_item *attr_item,
-                      proto_tree *tree, guint32 obj_type)
+                      proto_tree *tree, guint32 obj_type, guint32 attr_num)
 {
        guint32 num_aces;
        guint32 ace_number;
 
-       if (tree) {
-               proto_item *acl_item;
-               acl_item = proto_tree_add_none_format(tree, hf_nfs4_acl, tvb, 0, 0, "ACL");
-               PROTO_ITEM_SET_HIDDEN(acl_item);
-       }
+       if (attr_num != FATTR4_ACL)
+               offset = dissect_nfs4_aclflags(tvb, offset, tree);
 
        num_aces = tvb_get_ntohl(tvb, offset);
        if (tree && num_aces > 0) {
@@ -6629,10 +6605,9 @@ dissect_nfs4_fs_locations(tvbuff_t *tvb, packet_info *pinfo, int offset,
 
 
 static int
-dissect_nfs4_mode(tvbuff_t *tvb, int offset,
-                 proto_tree *tree, const char *name)
+dissect_nfs4_mode(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       return dissect_nfs2_mode(tvb, offset, tree, name);
+       return dissect_nfs2_mode(tvb, offset, tree);
 }
 
 #define FH4_PERSISTENT 0x00000000
@@ -6701,178 +6676,32 @@ dissect_nfs4_security_label(tvbuff_t *tvb, proto_tree *tree, int offset)
        return offset;
 }
 
-static const value_string fattr4_names[] = {
-#define FATTR4_SUPPORTED_ATTRS     0
-       {       FATTR4_SUPPORTED_ATTRS,    "Supported_Attrs"    },
-#define FATTR4_TYPE                1
-       {       FATTR4_TYPE,               "Type"},
-#define FATTR4_FH_EXPIRE_TYPE      2
-       {       FATTR4_FH_EXPIRE_TYPE,     "FH_Expire_Type"     },
-#define FATTR4_CHANGE              3
-       {       FATTR4_CHANGE,             "Change"},
-#define FATTR4_SIZE                4
-       {       FATTR4_SIZE,               "Size"       },
-#define FATTR4_LINK_SUPPORT        5
-       {       FATTR4_LINK_SUPPORT,       "Link_Support"       },
-#define FATTR4_SYMLINK_SUPPORT     6
-       {       FATTR4_SYMLINK_SUPPORT,    "Symlink_Support"    },
-#define FATTR4_NAMED_ATTR          7
-       {       FATTR4_NAMED_ATTR,         "Named_Attr" },
-#define FATTR4_FSID                8
-       {       FATTR4_FSID,               "FSID"       },
-#define FATTR4_UNIQUE_HANDLES      9
-       {       FATTR4_UNIQUE_HANDLES,     "Unique_Handles"     },
-#define FATTR4_LEASE_TIME          10
-       {       FATTR4_LEASE_TIME,         "Lease_Time" },
-#define FATTR4_RDATTR_ERROR        11
-       {       FATTR4_RDATTR_ERROR,       "RDAttr_Error"       },
-#define FATTR4_ACL                 12
-       {       FATTR4_ACL,                "ACL"        },
-#define FATTR4_ACLSUPPORT          13
-       {       FATTR4_ACLSUPPORT,         "ACLSupport" },
-#define FATTR4_ARCHIVE             14
-       {       FATTR4_ARCHIVE,            "Archive"    },
-#define FATTR4_CANSETTIME          15
-       {       FATTR4_CANSETTIME,         "CanSetTime" },
-#define FATTR4_CASE_INSENSITIVE    16
-       {       FATTR4_CASE_INSENSITIVE,   "Case_Insensitive"   },
-#define FATTR4_CASE_PRESERVING     17
-       {       FATTR4_CASE_PRESERVING,    "Case_Preserving"    },
-#define FATTR4_CHOWN_RESTRICTED    18
-       {       FATTR4_CHOWN_RESTRICTED,   "Chown_Restricted"   },
-#define FATTR4_FILEHANDLE          19
-       {       FATTR4_FILEHANDLE,         "Filehandle" },
-#define FATTR4_FILEID              20
-       {       FATTR4_FILEID,             "FileId"     },
-#define FATTR4_FILES_AVAIL         21
-       {       FATTR4_FILES_AVAIL,        "Files_Avail"        },
-#define FATTR4_FILES_FREE          22
-       {       FATTR4_FILES_FREE,         "Files_Free" },
-#define FATTR4_FILES_TOTAL         23
-       {       FATTR4_FILES_TOTAL,        "Files_Total"        },
-#define FATTR4_FS_LOCATIONS        24
-       {       FATTR4_FS_LOCATIONS,       "FS_Locations"       },
-#define FATTR4_HIDDEN              25
-       {       FATTR4_HIDDEN,             "Hidden"     },
-#define FATTR4_HOMOGENEOUS         26
-       {       FATTR4_HOMOGENEOUS,        "Homogeneous"        },
-#define FATTR4_MAXFILESIZE         27
-       {       FATTR4_MAXFILESIZE,        "MaxFileSize"        },
-#define FATTR4_MAXLINK             28
-       {       FATTR4_MAXLINK,            "MaxLink"    },
-#define FATTR4_MAXNAME             29
-       {       FATTR4_MAXNAME,            "MaxName"    },
-#define FATTR4_MAXREAD             30
-       {       FATTR4_MAXREAD,            "MaxRead"    },
-#define FATTR4_MAXWRITE            31
-       {       FATTR4_MAXWRITE,           "MaxWrite"   },
-#define FATTR4_MIMETYPE            32
-       {       FATTR4_MIMETYPE,           "MimeType"   },
-#define FATTR4_MODE                33
-       {       FATTR4_MODE,               "Mode"       },
-#define FATTR4_NO_TRUNC            34
-       {       FATTR4_NO_TRUNC,           "No_Trunc"   },
-#define FATTR4_NUMLINKS            35
-       {       FATTR4_NUMLINKS,           "NumLinks"   },
-#define FATTR4_OWNER               36
-       {       FATTR4_OWNER,              "Owner"      },
-#define FATTR4_OWNER_GROUP         37
-       {       FATTR4_OWNER_GROUP,        "Owner_Group"        },
-#define FATTR4_QUOTA_AVAIL_HARD    38
-       {       FATTR4_QUOTA_AVAIL_HARD,   "Quota_Avail_Hard"   },
-#define FATTR4_QUOTA_AVAIL_SOFT    39
-       {       FATTR4_QUOTA_AVAIL_SOFT,   "Quota_Avail_Soft"   },
-#define FATTR4_QUOTA_USED          40
-       {       FATTR4_QUOTA_USED,         "Quota_Used" },
-#define FATTR4_RAWDEV              41
-       {       FATTR4_RAWDEV,             "RawDev"     },
-#define FATTR4_SPACE_AVAIL         42
-       {       FATTR4_SPACE_AVAIL,        "Space_Avail"        },
-#define FATTR4_SPACE_FREE          43
-       {       FATTR4_SPACE_FREE,         "Space_Free" },
-#define FATTR4_SPACE_TOTAL         44
-       {       FATTR4_SPACE_TOTAL,        "Space_Total"        },
-#define FATTR4_SPACE_USED          45
-       {       FATTR4_SPACE_USED,         "Space_Used" },
-#define FATTR4_SYSTEM              46
-       {       FATTR4_SYSTEM,             "System"     },
-#define FATTR4_TIME_ACCESS         47
-       {       FATTR4_TIME_ACCESS,        "Time_Access"        },
-#define FATTR4_TIME_ACCESS_SET     48
-       {       FATTR4_TIME_ACCESS_SET,    "Time_Access_Set"    },
-#define FATTR4_TIME_BACKUP         49
-       {       FATTR4_TIME_BACKUP,        "Time_Backup"        },
-#define FATTR4_TIME_CREATE         50
-       {       FATTR4_TIME_CREATE,        "Time_Create"        },
-#define FATTR4_TIME_DELTA          51
-       {       FATTR4_TIME_DELTA,         "Time_Delta" },
-#define FATTR4_TIME_METADATA       52
-       {       FATTR4_TIME_METADATA,      "Time_Metadata"      },
-#define FATTR4_TIME_MODIFY         53
-       {       FATTR4_TIME_MODIFY,        "Time_Modify"        },
-#define FATTR4_TIME_MODIFY_SET     54
-       {       FATTR4_TIME_MODIFY_SET,    "Time_Modify_Set"    },
-#define FATTR4_MOUNTED_ON_FILEID   55
-       {       FATTR4_MOUNTED_ON_FILEID,  "Mounted_on_FileId"  },
-#define FATTR4_DIR_NOTIF_DELAY     56
-       {       FATTR4_DIR_NOTIF_DELAY,    "Dir_Notif_Delay"    },
-#define FATTR4_DIRENT_NOTIF_DELAY  57
-#define FATTR4_DACL                58
-       {       FATTR4_DACL,               "DACL"                },
-#define FATTR4_SACL                59
-       {       FATTR4_SACL,               "SACL"                },
-#define FATTR4_CHANGE_POLICY       60
-       {       FATTR4_CHANGE_POLICY,      "Change_Policy"              },
-#define FATTR4_FS_STATUS           61
-       {       FATTR4_FS_STATUS,          "FS_Status"                  },
-#define FATTR4_FS_LAYOUT_TYPE      62
-       {       FATTR4_FS_LAYOUT_TYPE,     "FS_Layout_Type"             },
-#define FATTR4_LAYOUT_HINT         63
-       {       FATTR4_LAYOUT_HINT,        "Layout_hint"                },
-#define FATTR4_LAYOUT_TYPE         64
-       {       FATTR4_LAYOUT_TYPE,        "Layout_type"                },
-#define FATTR4_LAYOUT_BLKSIZE      65
-       {       FATTR4_LAYOUT_BLKSIZE,     "Layout_blksize"             },
-#define FATTR4_LAYOUT_ALIGNMENT    66
-       {       FATTR4_LAYOUT_ALIGNMENT,   "Layout_alignment"   },
-#define FATTR4_FS_LOCATIONS_INFO   67
-       {       FATTR4_FS_LOCATIONS_INFO,  "FS_Locations_info"  },
-#define FATTR4_MDSTHRESHOLD        68
-       {       FATTR4_MDSTHRESHOLD,       "MDS_Threshold"              },
-#define FATTR4_RETENTION_GET       69
-       {       FATTR4_RETENTION_GET,      "Retention_Get"              },
-#define FATTR4_RETENTION_SET       70
-       {       FATTR4_RETENTION_SET,      "Retention_Set"              },
-#define FATTR4_RETENTEVT_GET       71
-       {       FATTR4_RETENTEVT_GET,      "RetentEvt_Get"              },
-#define FATTR4_RETENTEVT_SET       72
-       {       FATTR4_RETENTEVT_SET,      "RetentEvt_Set"              },
-#define FATTR4_RETENTION_HOLD      73
-       {       FATTR4_RETENTION_HOLD,     "Retention_Hold"             },
-#define FATTR4_MODE_SET_MASKED     74
-       {       FATTR4_MODE_SET_MASKED,    "Mode_Set_Masked"    },
-#define FATTR4_SUPPATTR_EXCLCREAT  75
-       {       FATTR4_SUPPATTR_EXCLCREAT, "Suppattr_ExclCreat" },
-#define FATTR4_FS_CHARSET_CAP      76
-       {       FATTR4_FS_CHARSET_CAP,     "FS_Charset_Cap"             },
-#define FATTR4_SECURITY_LABEL      80
-       {       FATTR4_SECURITY_LABEL,     "Security_Label"             },
-       {       0,      NULL    }
-};
-static value_string_ext fattr4_names_ext = VALUE_STRING_EXT_INIT(fattr4_names);
-
 #define FATTR4_BITMAP_ONLY 0
 #define FATTR4_DISSECT_VALUES 1
 
-/* As of NFSv4.1 (RFC 5661) The maximum number of attribute bitmaps is 3 in that NFSv4.1 introduced
-*  attribute numbers in excess of 63 (e.g., FATTR4_FS_CHARSET_CAP = 76):
- *
- *                      1          2          3
- *  +-------------+----------+----------+----------+
- *  | num_bitmaps | 31 .. 0  | 63 .. 32 | 95 .. 64 |
- *  +-------------+----------+----------+----------+
+/*
+ * Bitmaps are currently used for attributes and state_protect bits.
+ * Currently we don't expect more than 4 words, but future protocol
+ * revisions might add more bits, and in theory an implementation
+ * might legally zero-pad a bitmask out to something longer.  We keep
+ * a generous maximum here just as a sanity check:
  */
-#define MAX_BITMAPS 3
+#define MAX_BITMAPS 100
+
+static const value_string names_nfs_change_attr_types[] =
+{
+#define CHANGE_TYPE_IS_MONOTONIC_INCR 1
+       {       CHANGE_TYPE_IS_MONOTONIC_INCR,  "CHANGE_TYPE_IS_MONOTONIC_INCR" },
+#define CHANGE_TYPE_IS_VERSION_COUNTER 2
+       {       CHANGE_TYPE_IS_VERSION_COUNTER, "CHANGE_TYPE_IS_VERSION_COUNTER"        },
+#define CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS 3
+       {       CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS,  "CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS" },
+#define CHANGE_TYPE_IS_TIME_METADATA 4
+       {       CHANGE_TYPE_IS_TIME_METADATA,   "CHANGE_TYPE_IS_TIME_METADATA"  },
+#define CHANGE_TYPE_IS_UNDEFINED 5
+       {       CHANGE_TYPE_IS_UNDEFINED,       "CHANGE_TYPE_IS_UNDEFINED"      },
+       {       0,      NULL    }
+};
 
 /* Display each attrmask bitmap and optionally dissect the value.
 */
@@ -6880,9 +6709,9 @@ static int
 dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, rpc_call_info_value *civ)
 {
        int       attr_mask_offset = 0;
-       guint   i, j;
-       guint   num_bitmaps;
-       guint   count            = 0;
+       guint32   i, j;
+       guint32   num_bitmaps;
+       guint32   count            = 0;
        guint32   attr_num;
        guint32  *bitmaps          = NULL;
        guint32   bitmap, sl;
@@ -6892,21 +6721,19 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
 
        proto_item *bitmap_item = NULL;
        proto_tree *bitmap_tree = NULL;
-       proto_item *hitem       = NULL;
-       proto_item *attr_item   = NULL;
+       proto_item *hitem = NULL;
+       proto_item *attr_item = NULL;
        proto_tree *attr_tree   = NULL;
 
        num_bitmaps = tvb_get_ntohl(tvb, offset);
        offset += 4;
 
-       if (num_bitmaps > MAX_BITMAPS) {
-               if (tree)
-                       proto_tree_add_text(tree, tvb, offset, 4, "Huge bitmap length: %u", num_bitmaps);
-               THROW(ReportedBoundsError);
-       }
-       tvb_ensure_bytes_exist(tvb, offset, num_bitmaps * 4);
-
        if (num_bitmaps) {
+               if (num_bitmaps > MAX_BITMAPS) {
+                       proto_tree_add_uint(tree, hf_nfs4_huge_bitmap_length, tvb, offset, 4, num_bitmaps);
+                       THROW(ReportedBoundsError);
+               }
+
                bitmaps = (guint32 *)wmem_alloc(wmem_packet_scope(), num_bitmaps * sizeof(guint32));
                attr_mask_offset = offset;
 
@@ -6924,6 +6751,10 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
                *  attr_bitmap fields and the 4-byte 'total bytes in the values section field';
                *  otherwise, just skip the bitmaps and offset will be returned. */
                offset += (num_bitmaps * 4) + (type == FATTR4_DISSECT_VALUES ? 4 : 0);
+
+       } else if (type == FATTR4_DISSECT_VALUES) {
+               expert_add_info(pinfo, tree, &ei_protocol_violation);
+               return offset += 4;
        }
 
        if (!tree
@@ -6952,9 +6783,9 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
                                for (count=0; bitmap; bitmap >>= 1)
                                        count += (bitmap & 1);
                                bitmap = bitmaps[i];
-                               hitem = proto_tree_add_text(bitmap_tree, tvb, attr_mask_offset, 4, "[%u attribute%s]", count,
-                                       plurality(count, "", "s"));
+                               hitem = proto_tree_add_uint_format(bitmap_tree, hf_nfs4_attr_count, tvb, attr_mask_offset, 4, count, "%u attribute%s", count, plurality(count, "", "s"));
                                PROTO_ITEM_SET_HIDDEN(hitem);
+                               PROTO_ITEM_SET_GENERATED(hitem);
                        }
                } else {
                        attr_mask_offset += 4;
@@ -6976,11 +6807,16 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
 
                                        /* Display label: reqd_attr: or reco_attr: */
                                        attr_item = proto_tree_add_uint(bitmap_tree,
-                                               ((attr_num <= 11 || attr_num == 19 || attr_num == 75) ? hf_nfs4_reqd_attr: hf_nfs4_reco_attr),
-                                               tvb, attr_mask_offset, 4, attr_num);
+                                               (attr_num <= FATTR4_RDATTR_ERROR ||
+                                                attr_num == FATTR4_FILEHANDLE ||
+                                                attr_num == FATTR4_SUPPATTR_EXCLCREAT) ?
+                                               hf_nfs4_reqd_attr: hf_nfs4_reco_attr,
+                                               tvb, offset, 0, attr_num);
                                }
                                if (type == FATTR4_DISSECT_VALUES)
                                {
+                                       int attr_offset = offset;
+
                                        /* Decode the value of this attribute */
                                        if (attr_item)
                                                attr_tree = proto_item_add_subtree(attr_item, ett_nfs4_bitmap);
@@ -7041,8 +6877,10 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
                                                break;
 
                                        case FATTR4_ACL:
+                                       case FATTR4_DACL:
+                                       case FATTR4_SACL:
                                                offset = dissect_nfs4_fattr_acl(tvb, offset, pinfo, attr_item, attr_tree,
-                                                       obj_type);
+                                                       obj_type, attr_num);
                                                break;
 
                                        case FATTR4_ACLSUPPORT:
@@ -7128,7 +6966,7 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
                                                break;
 
                                        case FATTR4_MODE:
-                                               offset = dissect_nfs4_mode(tvb, offset, attr_tree, "fattr4_mode");
+                                               offset = dissect_nfs4_mode(tvb, offset, attr_tree);
                                                break;
 
                                        case FATTR4_NO_TRUNC:
@@ -7219,6 +7057,21 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
                                                                        offset);
                                                break;
 
+                                       case FATTR4_CLONE_BLOCKSIZE:
+                                               offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_clone_blocksize,
+                                                                       offset);
+                                               break;
+
+                                       case FATTR4_SPACE_FREED:
+                                               offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_space_freed,
+                                                                       offset);
+                                               break;
+
+                                       case FATTR4_CHANGE_ATTR_TYPE:
+                                               offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_change_attr_type,
+                                                                       offset);
+                                               break;
+
                                        case FATTR4_SECURITY_LABEL:
                                                offset = dissect_nfs4_security_label(tvb, attr_tree, offset);
                                                break;
@@ -7226,6 +7079,9 @@ dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
                                        default:
                                                break;
                                        }
+
+                                       if (attr_item)
+                                               proto_item_set_len(attr_item, offset - attr_offset);
                                }
                        }
                        sl <<= 1;
@@ -7312,11 +7168,7 @@ static const value_string names_open4_share_deny[] = {
 static int
 dissect_nfs4_open_share_deny(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       guint deny_access;
-
-       deny_access = tvb_get_ntohl(tvb, offset);
-       proto_tree_add_uint(tree, hf_nfs4_open_share_deny, tvb, offset, 4,
-               deny_access);
+       proto_tree_add_item(tree, hf_nfs4_open_share_deny, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
 
        return offset;
@@ -7504,6 +7356,10 @@ dissect_nfs4_clientaddr(tvbuff_t *tvb, int offset, proto_tree *tree)
        guint   b1, b2, b3, b4, b5, b6, b7, b8, b9, b10;
        guint16 port;
        int     addr_offset;
+       guint32 ipv4;
+       struct e_in6_addr ipv6;
+       address addr;
+       proto_item* ti;
 
        offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_netid, offset, &protocol);
        addr_offset = offset;
@@ -7514,24 +7370,31 @@ dissect_nfs4_clientaddr(tvbuff_t *tvb, int offset, proto_tree *tree)
                                                   &b1, &b2, &b3, &b4, &b5, &b6) == 6) {
                        /* IPv4: h1.h2.h3.h4.p1.p2 */
                        port = (b5<<8) | b6;
-                       proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset,
-                               "[IPv4 address %u.%u.%u.%u, protocol=%s, port=%u]",
-                               b1, b2, b3, b4, protocol, port);
+                       ipv4 = g_htonl((b1<<24) | (b2<<16) | (b3<<8) | b4);
+                       SET_ADDRESS(&addr, AT_IPv4, 4, &ipv4);
+                       ti = proto_tree_add_ipv4_format(tree, hf_nfs4_universal_address_ipv4, tvb, addr_offset, offset-addr_offset, ipv4, "IPv4 address %s, protocol=%s, port=%u",
+                               address_to_str(wmem_packet_scope(), &addr), protocol, port);
+                       PROTO_ITEM_SET_GENERATED(ti);
                } else if (universal_ip_address && sscanf(universal_ip_address, "%u.%u",
                                                   &b1, &b2) == 2) {
                        /* Some clients (linux) sometimes send only the port. */
                        port = (b1<<8) | b2;
-                       proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset,
-                               "[ip address NOT SPECIFIED, protocol=%s, port=%u]", protocol, port);
+                       ti = proto_tree_add_ipv4_format(tree, hf_nfs4_universal_address_ipv4, tvb, addr_offset, offset-addr_offset, 0, "ip address NOT SPECIFIED, protocol=%s, port=%u", protocol, port);
+                       PROTO_ITEM_SET_GENERATED(ti);
                } else if (universal_ip_address && sscanf(universal_ip_address,
                                                "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x.%u.%u",
                                                &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &b9, &b10) == 10) {
                        port = (b9<<8) | b10;
-                       proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset,
-                               "[IPv6 address %2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x, protocol=%s, port=%u]",
-                               b1, b2, b3, b4, b5, b6, b7, b8, protocol, port);
+                       memset(&ipv6, 0, sizeof(ipv6));
+                       ipv6.bytes[0] = b1; ipv6.bytes[1] = b2; ipv6.bytes[2] = b3; ipv6.bytes[3] = b4;
+                       ipv6.bytes[4] = b5; ipv6.bytes[5] = b6; ipv6.bytes[6] = b7; ipv6.bytes[7] = b8;
+                       SET_ADDRESS(&addr, AT_IPv6, 16, &ipv6);
+                       ti = proto_tree_add_ipv6_format(tree, hf_nfs4_universal_address_ipv6, tvb, addr_offset, offset-addr_offset, &ipv6, "IPv6 address %s, protocol=%s, port=%u",
+                               address_to_str(wmem_packet_scope(), &addr), protocol, port);
+                       PROTO_ITEM_SET_GENERATED(ti);
                } else {
-                       proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset, "[Invalid address]");
+                       ti = proto_tree_add_ipv4_format(tree, hf_nfs4_universal_address_ipv4, tvb, addr_offset, offset-addr_offset, 0, "Invalid address");
+                       PROTO_ITEM_SET_GENERATED(ti);
                }
        }
        return offset;
@@ -7543,10 +7406,8 @@ dissect_nfs4_cb_client4(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
        proto_tree *cb_location;
        proto_item *fitem;
-       int         cbprog, old_offset;
+       int         old_offset;
 
-       cbprog = tvb_get_ntohl(tvb, offset);
-       reg_callback(cbprog);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_cb_program, offset);
        old_offset = offset;
        cb_location = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "cb_location");
@@ -7647,8 +7508,18 @@ static const value_string names_nfs4_operation[] = {
        {       NFS4_OP_DESTROY_CLIENTID,      "DESTROY_CLIENTID"  },
        {       NFS4_OP_RECLAIM_COMPLETE,      "RECLAIM_COMPLETE"  },
        {       NFS4_OP_ALLOCATE,              "ALLOCATE"  },
+       {       NFS4_OP_COPY,                  "COPY"  },
+       {       NFS4_OP_COPY_NOTIFY,           "COPY_NOTIFY"  },
        {       NFS4_OP_DEALLOCATE,            "DEALLOCATE"  },
-       {       NFS4_OP_SEEK,                  "SEEK"  },
+       {       NFS4_OP_IO_ADVISE,             "IO_ADVISE"  },
+       {       NFS4_OP_LAYOUTERROR,           "LAYOUTERROR"  },
+       {       NFS4_OP_LAYOUTSTATS,           "LAYOUTSTATS"  },
+       {       NFS4_OP_OFFLOAD_CANCEL,        "OFFLOAD_CANCEL"  },
+       {       NFS4_OP_OFFLOAD_STATUS,        "OFFLOAD_STATUS"  },
+       {       NFS4_OP_READ_PLUS,             "READ_PLUS"  },
+       {       NFS4_OP_SEEK,                  "SEEK"  },
+       {       NFS4_OP_WRITE_SAME,            "WRITE_SAME"  },
+       {       NFS4_OP_CLONE,                 "CLONE"  },
        {       NFS4_OP_ILLEGAL,               "ILLEGAL"  },
        {       0, NULL  }
 };
@@ -7716,16 +7587,18 @@ static gint *nfs4_operation_ett[] =
         &ett_nfs4_destroy_clientid,
         &ett_nfs4_reclaim_complete,
         &ett_nfs4_allocate,
-        NULL,
-        NULL,
+        &ett_nfs4_copy,
+        &ett_nfs4_copy_notify,
         &ett_nfs4_deallocate,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
+        &ett_nfs4_io_advise,
+        &ett_nfs4_layouterror,
+        &ett_nfs4_layoutstats,
+        &ett_nfs4_offload_cancel,
+        &ett_nfs4_offload_status,
+        &ett_nfs4_read_plus,
         &ett_nfs4_seek,
+        &ett_nfs4_write_same,
+        &ett_nfs4_clone,
 };
 
 
@@ -7791,7 +7664,6 @@ dissect_nfs4_dirlist(tvbuff_t *tvb, int offset, packet_info *pinfo,
        return offset;
 }
 
-
 static int
 dissect_nfs4_change_info(tvbuff_t *tvb, int offset,
                         proto_tree *tree, const char *name)
@@ -7853,8 +7725,7 @@ static const int *open4_result_flag_fields[] = {
 static int
 dissect_nfs4_open_rflags(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       if (tree)
-               proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_open_rflags,
+       proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_open_rflags,
                        ett_nfs4_open_result_flags, open4_result_flag_fields, ENC_BIG_ENDIAN);
        offset += 4;
 
@@ -7874,9 +7745,8 @@ dissect_nfs4_stateid(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *hash)
 
        newftree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_nfs4_stateid, &fitem, "stateid");
 
-       sidh_array = tvb_get_string_enc(NULL, tvb, offset, 16, ENC_ASCII);
+       sidh_array = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 16, ENC_ASCII);
        sid_hash = crc16_ccitt(sidh_array, 16);
-       g_free(sidh_array);
 
        sh_item = proto_tree_add_uint(newftree, hf_nfs4_stateid_hash, tvb, offset, 16, sid_hash);
        PROTO_ITEM_SET_GENERATED(sh_item);
@@ -7932,11 +7802,9 @@ dissect_nfs4_state_protect_bitmap(tvbuff_t *tvb, int offset,
 
        num_bitmaps = tvb_get_ntohl(tvb, offset);
        if (num_bitmaps > MAX_BITMAPS) {
-               proto_tree_add_text(tree, tvb, offset, 4,
-                               "Huge bitmap length: %u", num_bitmaps);
+               proto_tree_add_uint(tree, hf_nfs4_huge_bitmap_length, tvb, offset, 4, num_bitmaps);
                THROW(ReportedBoundsError);
        }
-       tvb_ensure_bytes_exist(tvb, offset, 4 + num_bitmaps * 4);
        newftree = proto_tree_add_subtree(tree, tvb, offset, 4 + num_bitmaps * 4,
                                    ett_nfs4_bitmap, NULL, "operation mask");
        offset += 4;
@@ -8011,8 +7879,7 @@ dissect_nfs4_state_protect_a(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
        guint stateprotect;
 
-       stateprotect = tvb_get_ntohl(tvb, offset);
-       proto_tree_add_uint(tree, hf_nfs4_state_protect_how, tvb, offset+0, 4, stateprotect);
+       proto_tree_add_item_ret_uint(tree, hf_nfs4_state_protect_how, tvb, offset+0, 4, ENC_BIG_ENDIAN, &stateprotect);
        offset += 4;
 
        switch (stateprotect) {
@@ -8036,9 +7903,8 @@ dissect_nfs4_state_protect_r(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
        guint stateprotect;
 
-       stateprotect = tvb_get_ntohl(tvb, offset);
-       proto_tree_add_uint(tree, hf_nfs4_state_protect_how, tvb, offset+0, 4,
-                           stateprotect);
+       proto_tree_add_item_ret_uint(tree, hf_nfs4_state_protect_how, tvb, offset+0, 4,
+                           ENC_BIG_ENDIAN, &stateprotect);
        offset += 4;
 
        switch (stateprotect) {
@@ -8071,8 +7937,7 @@ dissect_nfs4_space_limit(tvbuff_t *tvb, int offset,
 {
        guint limitby;
 
-       limitby = tvb_get_ntohl(tvb, offset);
-       proto_tree_add_uint(tree, hf_nfs4_limit_by, tvb, offset+0, 4, limitby);
+       proto_tree_add_item_ret_uint(tree, hf_nfs4_limit_by, tvb, offset+0, 4, ENC_BIG_ENDIAN, &limitby);
        offset += 4;
 
        switch (limitby)
@@ -8146,15 +8011,13 @@ dissect_nfs4_open_delegation(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
        guint delegation_type;
-       proto_tree *newftree = NULL;
-       proto_item *fitem = NULL;
-
-       delegation_type = tvb_get_ntohl(tvb, offset);
-       fitem = proto_tree_add_uint(tree, hf_nfs4_open_delegation_type, tvb,
-               offset+0, 4, delegation_type);
-       offset += 4;
+       proto_tree *newftree;
+       proto_item *fitem;
 
+       fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_open_delegation_type, tvb,
+               offset+0, 4, ENC_BIG_ENDIAN, &delegation_type);
        newftree = proto_item_add_subtree(fitem, ett_nfs4_open_delegation);
+       offset += 4;
 
        switch (delegation_type)
        {
@@ -8231,6 +8094,60 @@ dissect_nfs4_locker(tvbuff_t *tvb, int offset, proto_tree *tree)
        return offset;
 }
 
+static const value_string read_plus_content_names[] = {
+#define NFS4_CONTENT_DATA                 0
+       {       NFS4_CONTENT_DATA,    "Data"    },
+#define NFS4_CONTENT_HOLE             1
+       {       NFS4_CONTENT_HOLE,    "Hole"    },
+       {       0,      NULL    }
+};
+static value_string_ext read_plus_content_names_ext = VALUE_STRING_EXT_INIT(read_plus_content_names);
+
+static int
+dissect_nfs4_read_plus_content(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       proto_item *sub_fitem;
+       proto_tree *ss_tree;
+       proto_tree *subtree;
+       proto_item *ss_fitem;
+       guint       i;
+       guint       count;
+       guint       type;
+
+       count = tvb_get_ntohl(tvb, offset);
+       sub_fitem = proto_tree_add_item(tree, hf_nfs4_read_plus_content_count,
+                                       tvb, offset, 4, ENC_BIG_ENDIAN);
+       offset += 4;
+
+       subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_read_plus_content_sub);
+       for (i = 0; i < count; i++) {
+               ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_read_plus_content_index,
+                                                       tvb, offset+0, 4, i, "Content [%u]", i);
+               ss_tree = proto_item_add_subtree(ss_fitem,
+                                                ett_nfs4_read_plus_content_sub);
+               offset += 4;
+
+               type = tvb_get_ntohl(tvb, offset);
+               proto_tree_add_uint(ss_tree, hf_nfs4_read_plus_content_type, tvb, offset, 0, type);
+               offset += 4;
+
+               switch (type) {
+               case NFS4_CONTENT_DATA:
+                       offset = dissect_rpc_uint64(tvb, ss_tree, hf_nfs4_offset, offset);
+                       dissect_rpc_uint32(tvb, ss_tree, hf_nfs4_read_data_length, offset); /* don't change offset */
+                       offset = dissect_nfsdata(tvb, offset, ss_tree, hf_nfs_data);
+                       break;
+               case NFS4_CONTENT_HOLE:
+                       offset = dissect_rpc_uint64(tvb, ss_tree, hf_nfs4_offset, offset);
+                       offset = dissect_rpc_uint32(tvb, ss_tree, hf_nfs4_count, offset);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return offset;
+}
 
 static int
 dissect_nfs4_client_id(tvbuff_t *tvb, int offset, proto_tree *tree)
@@ -8289,77 +8206,449 @@ dissect_nfs4_newoffset(tvbuff_t *tvb, int offset, proto_tree *tree)
        return offset;
 }
 
+static const value_string io_advise_names[] = {
+#define IO_ADVISE4_NORMAL                 0
+       {       IO_ADVISE4_NORMAL,    "Normal"  },
+#define IO_ADVISE4_SEQUENTIAL             1
+       {       IO_ADVISE4_SEQUENTIAL,    "Sequential"  },
+#define IO_ADVISE4_SEQUENTIAL_BACKWARDS   2
+       {       IO_ADVISE4_SEQUENTIAL_BACKWARDS,    "Sequential Backwards"      },
+#define IO_ADVISE4_RANDOM                 3
+       {       IO_ADVISE4_RANDOM,    "Random"  },
+#define IO_ADVISE4_WILLNEED               4
+       {       IO_ADVISE4_WILLNEED,    "Will Need"     },
+#define IO_ADVISE4_WILLNEED_OPPORTUNISTIC 5
+       {       IO_ADVISE4_WILLNEED_OPPORTUNISTIC,    "Will Need Opportunistic" },
+#define IO_ADVISE4_DONTNEED               6
+       {       IO_ADVISE4_DONTNEED,    "Don't Need"    },
+#define IO_ADVISE4_NOREUSE                7
+       {       IO_ADVISE4_NOREUSE,    "No Reuse"       },
+#define IO_ADVISE4_READ                   8
+       {       IO_ADVISE4_READ,    "Read"      },
+#define IO_ADVISE4_WRITE                  9
+       {       IO_ADVISE4_WRITE,    "Write"    },
+#define IO_ADVISE4_INIT_PROXIMITY         10
+       {       IO_ADVISE4_INIT_PROXIMITY,    "Init Proximity"  },
+       {       0,      NULL    }
+};
+static value_string_ext io_advise_names_ext = VALUE_STRING_EXT_INIT(io_advise_names);
 
 static int
-dissect_nfs4_layoutreturn(tvbuff_t *tvb, int offset, proto_tree *tree)
+dissect_nfs4_io_hints(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       guint returntype;
+       int       hints_mask_offset = 0;
+       guint32   i, j;
+       guint32   num_bitmaps;
+       guint32   count            = 0;
+       guint32   hint_num;
+       guint32  *bitmaps          = NULL;
+       guint32   bitmap, sl;
+       gboolean  first_hint       = TRUE;
+       gboolean  no_idx           = FALSE;
 
-       returntype = tvb_get_ntohl(tvb, offset);
-       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_return_type, offset);
-       if (returntype == 1) { /* RETURN_FILE */
-               offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
-               offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
-               offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
-               offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_lrf_body_content);
-       }
+       proto_item *bitmap_item = NULL;
+       proto_tree *bitmap_tree = NULL;
+       proto_item *hitem = NULL;
 
-       return offset;
-}
+       num_bitmaps = tvb_get_ntohl(tvb, offset);
+       offset += 4;
 
+       if (!num_bitmaps)
+               return offset;
 
-static int
-dissect_nfs_layoutreturn_stateid(tvbuff_t *tvb, proto_tree *tree, int offset)
-{
-       guint lrs_present;
+       if (num_bitmaps > MAX_BITMAPS) {
+               proto_tree_add_uint(tree, hf_nfs4_huge_bitmap_length, tvb, offset, 4, num_bitmaps);
+               expert_add_info(pinfo, tree, &ei_nfs_too_many_bitmaps);
+               return offset;
+       }
 
-       lrs_present = tvb_get_ntohl(tvb, offset);
-       offset = dissect_rpc_bool(tvb, tree, hf_nfs4_lrs_present, offset);
+       bitmaps = (guint32 *)wmem_alloc(wmem_packet_scope(), num_bitmaps * sizeof(guint32));
+       hints_mask_offset = offset;
 
-       if (lrs_present) {
-               offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+       /* Load the array with the bitmap(s) */
+       for (i = 0; i < num_bitmaps; i++) {
+               bitmaps[i] = tvb_get_ntohl(tvb, hints_mask_offset + (i*4));
+               if (bitmaps[i] > 0)
+                       count++;
        }
 
-       return offset;
-}
+       /* If there is only one non-zero bitmap, don't display the bitmap index "[x]". */
+       if (count <= 1)
+               no_idx = TRUE;
 
+       offset += (num_bitmaps * 4);
 
-static int
-dissect_nfs4_notification_bitmap(tvbuff_t *tvb, proto_tree *tree, int offset)
-{
-       guint32 bitmap_num;
-       guint i;
+       for (i = 0; i < num_bitmaps; i++) {
+               bitmap = bitmaps[i];
 
-       bitmap_num = tvb_get_ntohl(tvb, offset);
-       offset += 4;
+               if (bitmap) {
+                       if (tree) {
+                               /*
+                               * Display the current Attr_mask bitmap (as of RFC 5661 NVSv4.1, there are up to 3) */
+                               if (no_idx)
+                                       bitmap_item = proto_tree_add_uint_format_value(tree, hf_nfs4_io_hints_mask, tvb,
+                                               hints_mask_offset, 4, bitmap, "0x%08x", bitmap);
+                               else
+                                       bitmap_item = proto_tree_add_uint_format(tree, hf_nfs4_io_hints_mask, tvb,
+                                               hints_mask_offset, 4, bitmap, "Hints mask[%u]: 0x%08x", i, bitmap);
 
-       /* https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8611 */
-       if (!tree) {
-               if ((guint)offset > offset + (bitmap_num * 4)) {
-                       return tvb_reported_length(tvb);
-               }
-               else {
-                       return offset + (bitmap_num * 4);
+                               bitmap_tree = proto_item_add_subtree(bitmap_item, ett_nfs4_bitmap);
+                               first_hint = TRUE;
+
+                               /* Count the number of hint bits set */
+                               for (count=0; bitmap; bitmap >>= 1)
+                                       count += (bitmap & 1);
+                               bitmap = bitmaps[i];
+                               hitem = proto_tree_add_uint_format(bitmap_tree, hf_nfs4_io_hint_count, tvb, hints_mask_offset, 4, count, "%u hint%s", count, plurality(count, "", "s"));
+                               PROTO_ITEM_SET_HIDDEN(hitem);
+                               PROTO_ITEM_SET_GENERATED(hitem);
+                       }
+               } else {
+                       hints_mask_offset += 4;
+                       continue;
                }
-       }
 
-       for (i = 0; i < bitmap_num; i++) {
-               offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_notification_bitmap, offset);
+               sl = 0x00000001;
+
+               for (j = 0; j < 32; j++) {
+                       hint_num = 32*i + j;
+
+                       if (bitmap & sl) {
+                               if (bitmap_tree) {
+                                       /*
+                                       * Append this attribute name to the 'Hints mask' header line */
+                                       proto_item_append_text (bitmap_tree, (first_hint ? " (%s" : ", %s"),
+                                               val_to_str_ext(hint_num, &io_advise_names_ext, "Unknown: %u"));
+                                       first_hint = FALSE;
+
+                                       proto_tree_add_uint(bitmap_tree, hf_nfs4_io_advise_hint, tvb, offset, 0, hint_num);
+                               }
+                       }
+                       sl <<= 1;
+               } /* End of inner loop: test the next bit in this mask */
+
+               if (bitmap_tree)
+                       proto_item_append_text(bitmap_tree, ")");
+               hints_mask_offset += 4;
+       } /* End of outer loop, read the next mask */
+
+       return offset;
+}
+
+static int
+dissect_nfs4_app_data_block(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *hash)
+{
+       proto_item *fitem;
+
+       guint32     pattern_hash;
+        guint8     *pattern_array;
+        guint       pattern_len;
+
+
+       offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_block_size, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_block_count, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_reloff_blocknum, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_blocknum, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_reloff_pattern, offset);
+
+       pattern_len = tvb_get_ntohl(tvb, offset);
+       offset += 4;
+
+       pattern_array = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, pattern_len, ENC_ASCII);
+       pattern_hash = crc32_ccitt(pattern_array, pattern_len);
+       fitem = proto_tree_add_uint(tree, hf_nfs4_pattern_hash, tvb, offset, pattern_len, pattern_hash);
+       PROTO_ITEM_SET_GENERATED(fitem);
+       proto_item_set_len(fitem, pattern_len);
+
+       offset += pattern_len;
+
+       if (hash)
+               *hash = pattern_hash;
+
+       return offset;
+}
+
+static int
+dissect_nfs4_io_time(tvbuff_t *tvb, int offset, proto_tree *tree, const char *timer_mode)
+{
+       proto_tree *newtree;
+
+       newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_time, NULL, "%s", timer_mode);
+       offset = dissect_nfs4_nfstime(tvb, offset, newtree);
+
+       return offset;
+}
+
+static int
+dissect_nfs4_io_latency(tvbuff_t *tvb, int offset, proto_tree *tree, const char *io_mode)
+{
+       proto_tree *newtree;
+
+       newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_latency, NULL, "%s Latency", io_mode);
+
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ops_requested, offset);
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_requested, offset);
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ops_completed, offset);
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_completed, offset);
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_not_delivered, offset);
+
+       offset = dissect_nfs4_io_time(tvb, offset, newtree, "Busy time");
+       offset = dissect_nfs4_io_time(tvb, offset, newtree, "Completion time");
+
+       return offset;
+}
+
+static int
+dissect_nfs4_io_info(tvbuff_t *tvb, int offset, proto_tree *tree, const char *io_mode)
+{
+       proto_tree *newtree;
+
+       newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_info, NULL, "%s Info", io_mode);
+
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_io_count, offset);
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_io_bytes, offset);
+
+       return offset;
+}
+
+static int
+dissect_nfs4_layoutstats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ, gboolean has_layout_type)
+{
+       guint       layout_type = LAYOUT4_NO_LAYOUT_TYPE;
+       proto_tree *netaddr;
+       proto_item *fitem;
+       int         old_offset;
+       guint32     last_fh_hash    = 0;
+
+       /* FIXME: Are these here or in the caller? Check for layoutcommit */
+       offset = dissect_nfs4_io_info(tvb, offset, tree, "Read");
+       offset = dissect_nfs4_io_info(tvb, offset, tree, "Write");
+       offset = dissect_nfs4_deviceid(tvb, offset, tree);
+
+       if (has_layout_type) {
+               layout_type = tvb_get_ntohl(tvb, offset);
+               offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
+       }
+
+       /* If not flex files layout type eat the rest and move on.. */
+       if (!has_layout_type || layout_type == LAYOUT4_FLEX_FILES) {
+
+               /* NFS Flex Files */
+               if (has_layout_type)
+                       offset += 4; /* Skip past opaque count */
+
+               /* The netaddr */
+               old_offset = offset;
+               netaddr = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "DS address");
+
+               offset = dissect_nfs4_clientaddr(tvb, offset, netaddr);
+               proto_item_set_len(fitem, offset - old_offset);
+
+               /* The file handle */
+               offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "Filehandle", &last_fh_hash, civ);
+
+               /* Read Latency */
+               offset = dissect_nfs4_io_latency(tvb, offset, tree, "Read");
+
+               /* Write Latency */
+               offset = dissect_nfs4_io_latency(tvb, offset, tree, "Write");
+
+               /* Duration */
+               offset = dissect_nfs4_io_time(tvb, offset, tree, "Duration");
+
+               /* Local? */
+               offset = dissect_rpc_bool(tvb, tree, hf_nfs4_ff_local, offset);
+       } else {
+               offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_layoutstats);
        }
 
        return offset;
 }
 
+static int
+dissect_nfs4_ff_io_stats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
+{
+       offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
+       offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
+       offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+
+       /* Note that we've already determined that we are in the Flex File Layout Type */
+       offset = dissect_nfs4_layoutstats(tvb, offset, pinfo, tree, civ, FALSE);
+
+       return offset;
+}
 
 static int
-dissect_nfs4_devices(tvbuff_t *tvb, int offset, proto_tree *tree)
+dissect_nfs4_device_errors(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       guint i, j;
-       guint32 num_indices, num_multipath, num_addr;
+       proto_item *sub_fitem;
+       proto_tree *ss_tree;
+       proto_tree *subtree;
+       proto_item *ss_fitem;
+       guint       i;
+       guint       count;
+
+       guint       opcode;
+
+       count = tvb_get_ntohl(tvb, offset);
+       sub_fitem = proto_tree_add_item(tree, hf_nfs4_device_error_count,
+                                       tvb, offset, 4, ENC_BIG_ENDIAN);
+       offset += 4;
+
+       subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_device_errors_sub);
+       for (i = 0; i < count; i++) {
+               ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_device_errors_index,
+                                                       tvb, offset+0, 4, i, "Error [%u]", i);
+               ss_tree = proto_item_add_subtree(ss_fitem,
+                                                ett_nfs4_device_errors_sub);
+               offset = dissect_nfs4_deviceid(tvb, offset, ss_tree);
+               offset = dissect_nfs4_status(tvb, offset, ss_tree, NULL);
+
+               opcode = tvb_get_ntohl(tvb, offset);
+               proto_tree_add_uint(ss_tree, hf_nfs4_io_error_op, tvb, offset, 4, opcode);
+               offset += 4;
+       }
+
+       return offset;
+}
+
+static int
+dissect_nfs4_ff_io_error(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       proto_tree *newtree;
+
+       /* FIXME */
+       newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_latency, NULL, "IO errors");
+
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ioerrs_offset, offset);
+       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ioerrs_length, offset);
+       offset = dissect_nfs4_stateid(tvb, offset, newtree, NULL);
+
+       offset = dissect_nfs4_device_errors(tvb, offset, newtree);
+
+       return offset;
+}
+
+static int
+dissect_nfs4_layoutreturn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
+{
+       guint returntype;
+       guint layout_type;
+
+       proto_item *sub_fitem;
+       proto_tree *ss_tree;
+       proto_tree *subtree;
+       proto_item *ss_fitem;
+       guint       i;
+       guint       count;
+
+       offset = dissect_rpc_bool(tvb, tree, hf_nfs4_reclaim, offset);
+
+       layout_type = tvb_get_ntohl(tvb, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
+
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_iomode, offset);
+
+       returntype = tvb_get_ntohl(tvb, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_return_type, offset);
+       if (returntype == 1) { /* RETURN_FILE */
+               offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
+               offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
+               offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+
+               /* If not flex files layout type eat the rest and move on.. */
+               if (layout_type == LAYOUT4_FLEX_FILES) {
+                       offset += 4; /* Skip past opaque count */
+
+                       /* Get the errors */
+                       count = tvb_get_ntohl(tvb, offset);
+                       sub_fitem = proto_tree_add_item(tree, hf_nfs4_ff_ioerrs_count,
+                                                       tvb, offset, 4, ENC_BIG_ENDIAN);
+                       offset += 4;
+
+                       subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_ff_ioerrs_sub);
+                       for (i = 0; i < count; i++) {
+                               ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_ff_ioerrs_index,
+                                                                       tvb, offset+0, 4, i, "IO Error [%u]", i);
+                               ss_tree = proto_item_add_subtree(ss_fitem,
+                                                                ett_nfs4_ff_ioerrs_sub);
+
+                               offset = dissect_nfs4_ff_io_error(tvb, offset, ss_tree);
+                       }
+
+                       /* Get the stats */
+                       count = tvb_get_ntohl(tvb, offset);
+                       sub_fitem = proto_tree_add_item(tree, hf_nfs4_ff_iostats_count,
+                                                       tvb, offset, 4, ENC_BIG_ENDIAN);
+                       offset += 4;
+
+                       subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_ff_iostats_sub);
+                       for (i = 0; i < count; i++) {
+                               ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_ff_iostats_index,
+                                                                       tvb, offset+0, 4, i, "IO Stat [%u]", i);
+                               ss_tree = proto_item_add_subtree(ss_fitem,
+                                                                ett_nfs4_ff_iostats_sub);
+
+                               offset = dissect_nfs4_ff_io_stats(tvb, offset, pinfo, ss_tree, civ);
+                       }
+
+               } else {
+                       offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_lrf_body_content);
+               }
+       }
+
+       return offset;
+}
+
+static int
+dissect_nfs_layoutreturn_stateid(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+       guint lrs_present;
+
+       lrs_present = tvb_get_ntohl(tvb, offset);
+       offset = dissect_rpc_bool(tvb, tree, hf_nfs4_lrs_present, offset);
+
+       if (lrs_present) {
+               offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+       }
+
+       return offset;
+}
+
+
+static int
+dissect_nfs4_notification_bitmap(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+       guint32 bitmap_num;
+       guint i;
+
+       bitmap_num = tvb_get_ntohl(tvb, offset);
+       offset += 4;
+
+       /* https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8611 */
+       if (!tree) {
+               if ((guint)offset > offset + (bitmap_num * 4)) {
+                       return tvb_reported_length(tvb);
+               }
+               else {
+                       return offset + (bitmap_num * 4);
+               }
+       }
+
+       for (i = 0; i < bitmap_num; i++) {
+               offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_notification_bitmap, offset);
+       }
+
+       return offset;
+}
 
-       /* No layout type - argh */
 
-       /* Assume file layout for now */
+static int
+dissect_nfs4_devices_file(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       guint i, j;
+       guint32 num_indices, num_multipath, num_addr;
 
        /* disect indices */
        num_indices = tvb_get_ntohl(tvb, offset);
@@ -8382,6 +8671,40 @@ dissect_nfs4_devices(tvbuff_t *tvb, int offset, proto_tree *tree)
        return offset;
 }
 
+static int
+dissect_nfs4_devices_flexfile(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       guint i;
+       guint32 num_addr;
+       guint32 num_vers;
+
+       /* disect indices */
+       num_addr = tvb_get_ntohl(tvb, offset);
+       offset += 4;
+       for (i = 0; i < num_addr; i++) {
+               offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_netid, offset,
+                                           NULL);
+               offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_addr, offset,
+                                           NULL);
+       }
+
+       num_vers = tvb_get_ntohl(tvb, offset);
+       offset += 4;
+
+       for (i = 0; i < num_vers; i++) {
+               offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_version, offset);
+               offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_minorversion,
+                                   offset);
+               offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_rsize,
+                                   offset);
+               offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_wsize,
+                                   offset);
+               offset = dissect_rpc_bool(tvb, tree, hf_nfs4_ff_tightly_coupled,
+                                 offset);
+       }
+
+       return offset;
+}
 
 static int
 dissect_nfs4_test_stateid_arg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
@@ -8396,18 +8719,142 @@ dissect_nfs4_test_stateid_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        return dissect_nfs4_status(tvb, offset, tree, NULL);
 }
 
+static int
+dissect_nfs4_netloc(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       guint netloc_type;
+       proto_tree *netaddr;
+       int old_offset;
+       proto_item *fitem;
+
+       /* netloc type */
+       netloc_type = tvb_get_ntohl(tvb, offset);
+       offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_netloc_type, offset);
+
+       switch (netloc_type) {
+       case NL4_NAME:
+               offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_nl_name, NULL);
+               break;
+       case NL4_URL:
+               offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_nl_url, NULL);
+               break;
+       case NL4_NETADDR:
+               old_offset = offset;
+               netaddr = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "netaddr");
+
+               offset = dissect_nfs4_clientaddr(tvb, offset, netaddr);
+               proto_item_set_len(fitem, offset - old_offset);
+               break;
+       default:
+               /* back up to re-read the length field when treating as
+                * opaque */
+               offset -= 4;
+               offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_netloc);
+               break;
+       }
+
+       return offset;
+}
+
+static int
+dissect_nfs4_copy_reqs(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       offset = dissect_rpc_bool(tvb, tree, hf_nfs4_consecutive, offset);
+       offset = dissect_rpc_bool(tvb, tree, hf_nfs4_synchronous, offset);
+
+       return offset;
+}
+
+static int
+dissect_nfs4_write_response(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       proto_item *sub_fitem;
+       proto_tree *ss_tree;
+       proto_tree *subtree;
+       proto_item *ss_fitem;
+       guint       i;
+       guint32     count;
+
+       /* Number of callback stateids */
+       sub_fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_callback_stateids,
+                       tvb, offset, 4, ENC_BIG_ENDIAN, &count);
+       offset += 4;
+
+       subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_callback_stateids_sub);
+       for (i = 0; i < count; i++) {
+               ss_fitem = proto_tree_add_item(subtree,
+                               hf_nfs4_callback_stateids_index,
+                               tvb, offset, 4, i);
+
+               ss_tree = proto_item_add_subtree(ss_fitem,
+                               ett_nfs4_callback_stateids_sub);
+
+               offset = dissect_nfs4_netloc(tvb, offset, ss_tree);
+       }
+
+       offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
+       offset = dissect_nfs4_stable_how(tvb, offset, tree, "committed");
+       offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_verifier, offset);
+
+       return offset;
+}
+
+static int
+dissect_nfs4_source_servers(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       proto_item *sub_fitem;
+       proto_tree *ss_tree;
+       proto_tree *subtree;
+       proto_item *ss_fitem;
+       guint       i;
+       guint32     source_servers;
+
+       /* Number of source servers */
+       sub_fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_source_servers,
+                       tvb, offset, 4, ENC_BIG_ENDIAN, &source_servers);
+       offset += 4;
+
+       subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_source_servers_sub);
+       for (i = 0; i < source_servers; i++) {
+               ss_fitem = proto_tree_add_item(subtree,
+                               hf_nfs4_source_server_index,
+                               tvb, offset, 4, i);
+
+               ss_tree = proto_item_add_subtree(ss_fitem,
+                               ett_nfs4_source_servers_sub);
+
+               offset = dissect_nfs4_netloc(tvb, offset, ss_tree);
+       }
+
+       return offset;
+}
 
 static int
 dissect_nfs4_deviceaddr(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
+       guint layout_type;
 
        /* layout type */
+       layout_type = tvb_get_ntohl(tvb, offset);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
 
-       /* skip da_addr_body size */
+       /* skip length */
        offset+=4;
 
-       offset = dissect_nfs4_devices(tvb, offset, tree);
+       switch (layout_type) {
+       case LAYOUT4_NFSV4_1_FILES:
+               offset = dissect_nfs4_devices_file(tvb, offset, tree);
+               break;
+       case LAYOUT4_FLEX_FILES:
+               offset = dissect_nfs4_devices_flexfile(tvb, offset, tree);
+               break;
+       default:
+               /* back up to re-read the length field when treating as
+                * opaque */
+               offset -= 4;
+               offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_getdevinfo);
+               break;
+       }
 
        return offset;
 }
@@ -8525,16 +8972,21 @@ dissect_rpc_secparms4(tvbuff_t *tvb, int offset, proto_tree *tree)
        return offset;
 }
 
-
 static int
-dissect_nfs4_layout(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
+dissect_nfs4_layoutget(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
 {
        guint       layout_type;
-       guint       fh_num;
+       guint       sub_num;
        guint       lo_seg_count;
-       guint       i, lo_seg;
+       guint       i, j, k, lo_seg;
        proto_tree *newtree;
-       proto_tree *fh_tree;
+       proto_item *sub_fitem;
+       proto_tree *subtree;
+
+       static const int * layout_flags[] = {
+               &hf_nfs4_ff_layout_flags_no_layoutcommit,
+               NULL
+       };
 
        lo_seg_count = tvb_get_ntohl(tvb, offset);
 
@@ -8552,28 +9004,95 @@ dissect_nfs4_layout(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
                offset = dissect_rpc_uint32(tvb, newtree, hf_nfs4_layout_type, offset);
 
                /* If not files layout type eat the rest and move on.. */
-               if (layout_type != LAYOUT4_NFSV4_1_FILES) {
-                       offset = dissect_nfsdata(tvb, offset, newtree, hf_nfs4_layout);
-                       continue;
-               }
+               if (layout_type == LAYOUT4_NFSV4_1_FILES) {
+                       /* NFS Files */
+                       offset += 4; /* Skip past opaque count */
 
-               /* NFS Files */
-               offset += 4; /* Skip past opaque count */
+                       offset = dissect_nfs4_deviceid(tvb, offset, newtree);
 
-               offset = dissect_nfs4_deviceid(tvb, offset, newtree);
+                       offset = dissect_rpc_uint32(tvb, newtree,
+                                       hf_nfs4_nfl_util, offset);
+                       offset = dissect_rpc_uint32(tvb, newtree,
+                                       hf_nfs4_nfl_first_stripe_index, offset);
+                       offset = dissect_rpc_uint64(tvb, newtree,
+                                       hf_nfs4_offset, offset);
 
-               offset = dissect_rpc_uint32(tvb, newtree, hf_nfs4_nfl_util, offset);
-               offset = dissect_rpc_uint32(tvb, newtree, hf_nfs4_nfl_first_stripe_index, offset);
-               offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_offset, offset);
+                       sub_num = tvb_get_ntohl(tvb, offset); /* Len of FH list */
 
-               fh_num = tvb_get_ntohl(tvb, offset); /* Len of FH list */
+                       sub_fitem = proto_tree_add_item(newtree, hf_nfs4_nfl_fhs,
+                                       tvb, offset, 4, ENC_BIG_ENDIAN);
+                       offset += 4;
 
-               fh_tree = proto_tree_add_subtree_format(newtree, tvb, offset, 4,
-                                               ett_nfs4_layoutseg_fh, NULL, "File Handles (count: %u)", fh_num);
-               offset += 4;
+                       subtree = proto_item_add_subtree(sub_fitem,
+                                       ett_nfs4_layoutseg_sub);
+                       for (i = 0; i < sub_num; i++)
+                               offset = dissect_nfs4_fh(tvb, offset, pinfo,
+                                               subtree, "lo_filehandle", NULL,
+                                               civ);
+               } else if (layout_type == LAYOUT4_FLEX_FILES) {
+                       guint   ds_count, fh_count;
+                       proto_tree *ds_tree;
+                       proto_item *ds_fitem;
+
+                       /* NFS Flex Files */
+                       offset += 4; /* Skip past opaque count */
+
+                       /* stripe unit */
+                       offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_stripeunit, offset);
+
+                       /* Len of mirror list */
+                       sub_num = tvb_get_ntohl(tvb, offset);
+                       offset += 4;
+
+                       for (i = 0; i < sub_num; i++) {
+                               sub_fitem = proto_tree_add_item(newtree,
+                                               hf_nfs4_nfl_mirrors, tvb,
+                                               offset, 4, i);
+
+                               /* data server count */
+                               ds_count = tvb_get_ntohl(tvb, offset);
+                               offset += 4;
+
+                               subtree = proto_item_add_subtree(sub_fitem,
+                                               ett_nfs4_layoutseg_sub);
+
+                               for (j = 0; j < ds_count; j++) {
+                                       ds_fitem = proto_tree_add_item(subtree,
+                                                       hf_nfs4_mirror_index, tvb,
+                                                       offset, 4, j);
+
+                                       ds_tree = proto_item_add_subtree(ds_fitem,
+                                                       ett_nfs4_layoutseg_sub);
+
+                                       offset = dissect_nfs4_deviceid(tvb, offset,
+                                                       ds_tree);
+                                       offset = dissect_rpc_uint32(tvb, ds_tree,
+                                                       hf_nfs4_mirror_eff, offset);
+                                       offset = dissect_nfs4_stateid(tvb, offset,
+                                                       ds_tree, NULL);
+
+                                       fh_count = tvb_get_ntohl(tvb, offset);
+                                       offset += 4;
 
-               for (i = 0; i < fh_num; i++)
-                       offset = dissect_nfs4_fh(tvb, offset, pinfo, fh_tree, "lo_filehandle", NULL, civ);
+                                       for (k = 0; k < fh_count; k++)
+                                               offset = dissect_nfs4_fh(tvb, offset,
+                                                       pinfo, ds_tree, "fh", NULL, civ);
+
+                                       offset = dissect_nfs_utf8string(tvb, offset,
+                                                       ds_tree, hf_nfs4_ff_synthetic_owner,
+                                                       NULL);
+                                       offset = dissect_nfs_utf8string(tvb, offset,
+                                                       ds_tree, hf_nfs4_ff_synthetic_owner_group,
+                                                       NULL);
+                               }
+                       }
+
+                       proto_tree_add_bitmask(newtree, tvb, offset, hf_nfs4_ff_layout_flags,
+                                               ett_nfs4_ff_layout_flags, layout_flags, ENC_BIG_ENDIAN);
+               } else {
+                       offset = dissect_nfsdata(tvb, offset, newtree, hf_nfs4_layout);
+                       continue;
+               }
        }
        return offset;
 }
@@ -8582,17 +9101,14 @@ dissect_nfs4_layout(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
 static int
 dissect_nfs_create_session_flags(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_csa)
 {
-       proto_tree *csa_flags_item;
-       proto_tree *csa_flags_tree;
-
-       csa_flags_item = proto_tree_add_item(tree, hf_csa, tvb, offset, 4, ENC_BIG_ENDIAN);
-       csa_flags_tree = proto_item_add_subtree(csa_flags_item, ett_nfs4_create_session_flags);
-       proto_tree_add_item(csa_flags_tree, hf_nfs4_create_session_flags_persist, tvb, offset, 4,
-               ENC_BIG_ENDIAN);
-       proto_tree_add_item(csa_flags_tree, hf_nfs4_create_session_flags_conn_back_chan, tvb, offset, 4,
-               ENC_BIG_ENDIAN);
-       proto_tree_add_item(csa_flags_tree, hf_nfs4_create_session_flags_conn_rdma, tvb, offset, 4,
-               ENC_BIG_ENDIAN);
+       const int * flags[] = {
+               &hf_nfs4_create_session_flags_persist,
+               &hf_nfs4_create_session_flags_conn_back_chan,
+               &hf_nfs4_create_session_flags_conn_rdma,
+               NULL
+       };
+
+       proto_tree_add_bitmask(tree, tvb, offset, hf_csa, ett_nfs4_create_session_flags, flags, ENC_BIG_ENDIAN);
        offset += 4;
 
        return offset;
@@ -8726,13 +9242,35 @@ static int nfs4_operation_tiers[] = {
                 1 /* 58, NFS4_OP_RECLAIM_COMPLETE */,
                        /* Minor version 2 */
                 1 /* 59, NFS4_OP_ALLOCATE */,
+                1 /* 60, NFS4_OP_COPY */,
+                1 /* 61, NFS4_OP_COPY_NOTIFY */,
                 1 /* 62, NFS4_OP_DEALLOCATE */,
+                1 /* 63, NFS4_OP_IO_ADVISE */,
+                1 /* 64, NFS4_OP_LAYOUTERROR */,
+                1 /* 65, NFS4_OP_LAYOUTSTATS */,
+                1 /* 66, NFS4_OP_OFFLOAD_CANCEL */,
+                1 /* 67, NFS4_OP_OFFLOAD_STATUS */,
+                1 /* 68, NFS4_OP_READ_PLUS */,
                 1 /* 69, NFS4_OP_SEEK */,
+                1 /* 70, NFS4_OP_WRITE_SAME */,
+                1 /* 71, NFS4_OP_CLONE */,
 };
 
 #define NFS4_OPERATION_TIER(op) \
        ((op) < G_N_ELEMENTS(nfs4_operation_tiers) ? nfs4_operation_tiers[(op)] : 0)
 
+static const int * nfs4_exchid_flags[] = {
+       &hf_nfs4_exchid_flags_confirmed_r,
+       &hf_nfs4_exchid_flags_upd_conf_rec_a,
+       &hf_nfs4_exchid_flags_pnfs_ds,
+       &hf_nfs4_exchid_flags_pnfs_mds,
+       &hf_nfs4_exchid_flags_non_pnfs,
+       &hf_nfs4_exchid_flags_bind_princ,
+       &hf_nfs4_exchid_flags_moved_migr,
+       &hf_nfs4_exchid_flags_moved_refer,
+       NULL
+};
+
 static int
 dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
 {
@@ -8740,7 +9278,6 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
        const char *source_name     = NULL;
        const char *dest_name       = NULL;
        const char *opname          = NULL;
-       int         cbprog;
        guint       opcode;
        guint       highest_tier    = 5;
        guint       current_tier    = 5;
@@ -8756,12 +9293,15 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
        guint32     last_fh_hash    = 0;
        guint32     saved_fh_hash   = 0;
        guint32     length;
+       guint32     hash;
        guint64     length64;
        guint64     file_offset;
        proto_item *fitem;
        proto_tree *ftree;
        proto_tree *newftree        = NULL;
        nfs4_operation_summary *op_summary;
+       guint16     dst_sid_hash;
+       guint64     dst_file_offset;
 
        ops = tvb_get_ntohl(tvb, offset+0);
 
@@ -9159,31 +9699,12 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                case NFS4_OP_EXCHANGE_ID:
                        {
                        proto_tree *eia_clientowner_tree;
-                       proto_tree *eia_flags_tree = NULL;
 
                        eia_clientowner_tree = proto_tree_add_subtree(newftree, tvb, offset, 0, ett_nfs4_clientowner, NULL, "eia_clientowner");
                        offset = dissect_rpc_uint64(tvb, eia_clientowner_tree, hf_nfs4_verifier, offset);
                        offset = dissect_nfsdata(tvb, offset, eia_clientowner_tree, hf_nfs_data);
 
-                       fitem = proto_tree_add_item(newftree, hf_nfs4_exchid_call_flags, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       eia_flags_tree = proto_item_add_subtree(fitem, ett_nfs4_exchangeid_call_flags);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_confirmed_r, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_upd_conf_rec_a, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_pnfs_ds, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_pnfs_mds, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_non_pnfs, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_bind_princ, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_moved_migr, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
-                       proto_tree_add_item(eia_flags_tree, hf_nfs4_exchid_flags_moved_refer, tvb, offset, 4,
-                               ENC_BIG_ENDIAN);
+                       proto_tree_add_bitmask(eia_clientowner_tree, tvb, offset, hf_nfs4_exchid_call_flags, ett_nfs4_exchangeid_call_flags, nfs4_exchid_flags, ENC_BIG_ENDIAN);
                        offset += 4;
 
                        offset = dissect_nfs4_state_protect_a(tvb, offset, newftree);
@@ -9198,8 +9719,6 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                                hf_nfs4_create_session_flags_csa);
                        offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csa_fore_chan_attrs");
                        offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csa_back_chan_attrs");
-                       cbprog = tvb_get_ntohl(tvb, offset);
-                       reg_callback(cbprog);
                        offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_cb_program, offset);
                        offset = dissect_rpc_secparms4(tvb, offset, newftree);
                        break;
@@ -9237,10 +9756,7 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                        break;
 
                case NFS4_OP_LAYOUTRETURN:
-                       offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_reclaim, offset);
-                       offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_layout_type, offset);
-                       offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_iomode, offset);
-                       offset = dissect_nfs4_layoutreturn(tvb, offset, newftree);
+                       offset = dissect_nfs4_layoutreturn(tvb, offset, pinfo, newftree, civ);
                        break;
 
                case NFS4_OP_GETDEVINFO:
@@ -9265,32 +9781,143 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                        offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_cachethis, offset);
                        break;
 
-               case NFS4_OP_ALLOCATE:
+               case NFS4_OP_ALLOCATE:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       length64 = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " StateID: 0x%04x"
+                                       " Offset: %" G_GINT64_MODIFIER "u"
+                                       " Len: %" G_GINT64_MODIFIER "u",
+                                       sid_hash, file_offset, length64);
+                       break;
+
+               case NFS4_OP_COPY:
+
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &dst_sid_hash);
+                       file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       dst_file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       length64 = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " Src StateID: 0x%04x"
+                                       " Offset: %" G_GINT64_MODIFIER "u"
+                                       " Len: %" G_GINT64_MODIFIER "u",
+                                       sid_hash, file_offset, length64);
+
+                       offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_consecutive, offset);
+                       offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_synchronous, offset);
+
+                       /* FIXME: Report consecutive and sync? */
+
+                       if (dst_sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " Dst StateID: 0x%04x"
+                                       " Offset: %" G_GINT64_MODIFIER "u",
+                                       dst_sid_hash, dst_file_offset);
+
+                       offset = dissect_nfs4_source_servers(tvb, offset, newftree);
+                       break;
+
+               case NFS4_OP_COPY_NOTIFY:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " StateID: 0x%04x",
+                                       sid_hash);
+
+                       offset = dissect_nfs4_netloc(tvb, offset, newftree);
+
+                       break;
+
+               case NFS4_OP_DEALLOCATE:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       length64 = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " StateID: 0x%04x"
+                                       " Offset: %" G_GINT64_MODIFIER "u"
+                                       " Len: %" G_GINT64_MODIFIER "u",
+                                       sid_hash, file_offset, length64);
+                       break;
+
+               case NFS4_OP_IO_ADVISE:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       length64 = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " StateID: 0x%04x"
+                                       " Offset: %" G_GINT64_MODIFIER "u"
+                                       " Len: %" G_GINT64_MODIFIER "u",
+                                       sid_hash, file_offset, length64);
+                       offset = dissect_nfs4_io_hints(tvb, offset, pinfo, tree);
+                       break;
+
+               case NFS4_OP_OFFLOAD_CANCEL:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " StateID: 0x%04x",
+                                       sid_hash);
+                       break;
+
+               case NFS4_OP_OFFLOAD_STATUS:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " StateID: 0x%04x",
+                                       sid_hash);
+                       break;
+
+               case NFS4_OP_READ_PLUS:
                        offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
                        file_offset = tvb_get_ntoh64(tvb, offset);
                        offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
-                       length64 = tvb_get_ntoh64(tvb, offset);
-                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+                       length = tvb_get_ntohl(tvb, offset);
+                       offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count, offset);
                        if (sid_hash != 0)
                                wmem_strbuf_append_printf (op_summary[ops_counter].optext,
-                                       " StateID: 0x%04x"
-                                       " Offset: %" G_GINT64_MODIFIER "u"
-                                       " Len: %" G_GINT64_MODIFIER "u",
-                                       sid_hash, file_offset, length64);
+                                       " StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
+                                       sid_hash, file_offset, length);
                        break;
 
-               case NFS4_OP_DEALLOCATE:
+               case NFS4_OP_LAYOUTERROR:
+                       file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       length = tvb_get_ntohl(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
                        offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
+                                       sid_hash, file_offset, length);
+                       offset = dissect_nfs4_device_errors(tvb, offset, newftree);
+                       break;
+
+               case NFS4_OP_LAYOUTSTATS:
                        file_offset = tvb_get_ntoh64(tvb, offset);
                        offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
-                       length64 = tvb_get_ntoh64(tvb, offset);
+                       length = tvb_get_ntohl(tvb, offset);
                        offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
                        if (sid_hash != 0)
                                wmem_strbuf_append_printf (op_summary[ops_counter].optext,
-                                       " StateID: 0x%04x"
-                                       " Offset: %" G_GINT64_MODIFIER "u"
-                                       " Len: %" G_GINT64_MODIFIER "u",
-                                       sid_hash, file_offset, length64);
+                                       " StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
+                                       sid_hash, file_offset, length);
+                       offset = dissect_nfs4_layoutstats(tvb, offset, pinfo, newftree, civ, TRUE);
                        break;
 
                case NFS4_OP_SEEK:
@@ -9306,6 +9933,38 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                                        sid_hash, file_offset);
                        break;
 
+               case NFS4_OP_WRITE_SAME:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       offset = dissect_nfs4_stable_how(tvb, offset, newftree, "stable");
+                       offset = dissect_nfs4_app_data_block(tvb, offset, newftree, &hash);
+                       wmem_strbuf_append_printf(op_summary[ops_counter].optext,
+                               "Pattern Hash: 0x%08x", hash);
+
+                       break;
+
+               case NFS4_OP_CLONE:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, &dst_sid_hash);
+                       file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       dst_file_offset = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+                       length64 = tvb_get_ntoh64(tvb, offset);
+                       offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+                       if (sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " Src StateID: 0x%04x"
+                                       " Offset: %" G_GINT64_MODIFIER "u"
+                                       " Len: %" G_GINT64_MODIFIER "u",
+                                       sid_hash, file_offset, length64);
+
+                       if (dst_sid_hash != 0)
+                               wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+                                       " Dst StateID: 0x%04x"
+                                       " Offset: %" G_GINT64_MODIFIER "u",
+                                       dst_sid_hash, dst_file_offset);
+                       break;
+
                /* In theory, it's possible to get this opcode */
                case NFS4_OP_ILLEGAL:
                        break;
@@ -9362,9 +10021,10 @@ dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
 
 
 static int
-dissect_nfs4_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs4_compound_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        const char *tag = NULL;
+       int offset = 0;
 
        offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
        /*
@@ -9388,9 +10048,8 @@ dissect_nfs4_secinfo_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_item *fitem;
        proto_tree *secftree;
 
-       flavor = tvb_get_ntohl(tvb, offset);
-       fitem = proto_tree_add_uint(tree, hf_nfs4_secinfo_flavor, tvb, offset, 4,
-               flavor);
+       fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_secinfo_flavor, tvb, offset, 4,
+               ENC_BIG_ENDIAN, &flavor);
        offset += 4;
 
        switch (flavor)
@@ -9479,14 +10138,15 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
 
                /*
                 * With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT,
-                * NFS4_OP_SETATTR, and NFS4_OP_SETCLIENTID, all other
+                * NFS4_OP_SETATTR, NFS4_OP_SETCLIENTID, and NFS4_OP_COPY, all other
                 * ops do *not* return data with the failed status code.
                 */
                if (status != NFS4_OK
                && opcode != NFS4_OP_LOCK
                && opcode != NFS4_OP_LOCKT
                && opcode != NFS4_OP_SETATTR
-               && opcode != NFS4_OP_SETCLIENTID) {
+               && opcode != NFS4_OP_SETCLIENTID
+               && opcode != NFS4_OP_COPY) {
                        op_summary[ops_counter].iserror = TRUE;
                        continue;
                }
@@ -9624,31 +10284,12 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
                        break;
 
                case NFS4_OP_EXCHANGE_ID: {
-                               proto_tree *eir_flags_tree = NULL;
                                proto_tree *eir_server_owner_tree = NULL;
 
                                offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
                                offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
 
-                               fitem = proto_tree_add_item(newftree, hf_nfs4_exchid_reply_flags, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               eir_flags_tree = proto_item_add_subtree(fitem, ett_nfs4_exchangeid_reply_flags);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_confirmed_r, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_upd_conf_rec_a, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_pnfs_ds, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_pnfs_mds, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_non_pnfs, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_bind_princ, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_moved_migr, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
-                               proto_tree_add_item(eir_flags_tree, hf_nfs4_exchid_flags_moved_refer, tvb, offset, 4,
-                                       ENC_BIG_ENDIAN);
+                               proto_tree_add_bitmask(newftree, tvb, offset, hf_nfs4_exchid_reply_flags, ett_nfs4_exchangeid_reply_flags, nfs4_exchid_flags, ENC_BIG_ENDIAN);
                                offset += 4;
 
                                offset = dissect_nfs4_state_protect_r(tvb, offset, newftree);
@@ -9681,7 +10322,7 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
                        offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_return_on_close,
                                                                          offset);
                        offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
-                       offset = dissect_nfs4_layout(tvb, offset, pinfo, newftree, civ);
+                       offset = dissect_nfs4_layoutget(tvb, offset, pinfo, newftree, civ);
                        break;
 
                case NFS4_OP_LAYOUTCOMMIT:
@@ -9706,42 +10347,29 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
 
                case NFS4_OP_SEQUENCE:
                        {
-                       proto_tree *sf_tree = NULL;
+                       static const int * sequence_flags[] = {
+                               &hf_nfs4_sequence_status_flags_cb_path_down,
+                               &hf_nfs4_sequence_status_flags_cb_gss_contexts_expiring,
+                               &hf_nfs4_sequence_status_flags_cb_gss_contexts_expired,
+                               &hf_nfs4_sequence_status_flags_expired_all_state_revoked,
+                               &hf_nfs4_sequence_status_flags_expired_some_state_revoked,
+                               &hf_nfs4_sequence_status_flags_admin_state_revoked,
+                               &hf_nfs4_sequence_status_flags_recallable_state_revoked,
+                               &hf_nfs4_sequence_status_flags_lease_moved,
+                               &hf_nfs4_sequence_status_flags_restart_reclaim_needed,
+                               &hf_nfs4_sequence_status_flags_cb_path_down_session,
+                               &hf_nfs4_sequence_status_flags_backchannel_fault,
+                               &hf_nfs4_sequence_status_flags_devid_changed,
+                               &hf_nfs4_sequence_status_flags_devid_deleted,
+                               NULL
+                       };
 
                        offset = dissect_nfs4_sessionid(tvb, offset, newftree);
                        offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
                        offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_slotid, offset);
                        offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_high_slotid, offset);
                        offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_target_high_slotid, offset);
-                       fitem = proto_tree_add_item(newftree, hf_nfs4_sequence_status_flags,
-                                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       sf_tree = proto_item_add_subtree(fitem, ett_nfs4_sequence_status_flags);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_cb_path_down,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_cb_gss_contexts_expiring,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_cb_gss_contexts_expired,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_expired_all_state_revoked,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_expired_some_state_revoked,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_admin_state_revoked,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_recallable_state_revoked,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_lease_moved,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_restart_reclaim_needed,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_cb_path_down_session,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_backchannel_fault,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_devid_changed,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
-                       proto_tree_add_item(sf_tree, hf_nfs4_sequence_status_flags_devid_deleted,
-                               tvb, offset, 4, ENC_BIG_ENDIAN);
+                       proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_sequence_status_flags, ett_nfs4_sequence_status_flags, sequence_flags, ENC_BIG_ENDIAN);
                        offset += 4;
                        }
                        break;
@@ -9749,14 +10377,65 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
                case NFS4_OP_ALLOCATE:
                        break;
 
+               case NFS4_OP_COPY:
+
+                       if (status == NFS4_OK) {
+                               offset = dissect_nfs4_write_response(tvb, offset, newftree);
+                               offset = dissect_nfs4_copy_reqs(tvb, offset, newftree);
+                       } else if (status == NFS4ERR_OFFLOAD_NO_REQS)
+                               offset = dissect_nfs4_copy_reqs(tvb, offset, newftree);
+
+                       break;
+
+               case NFS4_OP_COPY_NOTIFY:
+
+                       offset = dissect_nfs4_nfstime(tvb, offset, newftree);
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
+                       offset = dissect_nfs4_source_servers(tvb, offset, newftree);
+
+                       break;
+
                case NFS4_OP_DEALLOCATE:
                        break;
 
+               case NFS4_OP_OFFLOAD_CANCEL:
+                       break;
+
+               case NFS4_OP_IO_ADVISE:
+                       offset = dissect_nfs4_io_hints(tvb, offset, pinfo, tree);
+                       break;
+
+               case NFS4_OP_OFFLOAD_STATUS:
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
+                       break;
+
+               case NFS4_OP_READ_PLUS:
+                       if (status == NFS4_OK) {
+                               offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
+                               offset = dissect_nfs4_read_plus_content(tvb, offset, newftree);
+                       }
+                       break;
+
+               case NFS4_OP_LAYOUTERROR:
+                       break;
+
+               case NFS4_OP_LAYOUTSTATS:
+                       break;
+
                case NFS4_OP_SEEK:
                        offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
                        offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
                        break;
 
+               case NFS4_OP_WRITE_SAME:
+                       if (status == NFS4_OK) {
+                               offset = dissect_nfs4_write_response(tvb, offset, newftree);
+                       }
+                       break;
+
+               case NFS4_OP_CLONE:
+                       break;
+
                default:
                        break;
                }
@@ -9812,11 +10491,12 @@ dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
 
 
 static int
-dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs4_compound_reply(tvbuff_t *tvb, packet_info *pinfo,
        proto_tree *tree, void *data)
 {
        guint32     status;
        const char *tag = NULL;
+       int offset = 0;
 
        offset = dissect_nfs4_status(tvb, offset, tree, &status);
        offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
@@ -9837,7 +10517,6 @@ dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 /* proc number, "proc name", dissect_request, dissect_reply */
-/* NULL as function pointer means: type of arguments is "void". */
 static const vsff nfs3_proc[] = {
        { 0,    "NULL",         /* OK */
        dissect_nfs3_null_call,         dissect_nfs3_null_reply },
@@ -9933,6 +10612,12 @@ static const value_string nfs4_proc_vals[] = {
        { 0, NULL }
 };
 
+static const rpc_prog_vers_info nfs_vers_info[] = {
+       { 2, nfs2_proc, &hf_nfs2_procedure },
+       { 3, nfs3_proc, &hf_nfs3_procedure },
+       { 4, nfs4_proc, &hf_nfs4_procedure },
+};
+
 /*
  * Union of the NFSv2, NFSv3, and NFSv4 status codes.
  * Used for the "nfs.status" hidden field and in packet-nfsacl.c.
@@ -10050,6 +10735,13 @@ static const value_string names_nfs_nfsstat[] = {
        { 10085, "ERR_REJECT_DELEG"                  },
        { 10086, "ERR_RETURNCONFLICT"                },
        { 10087, "ERR_DELEG_REVOKED"                 },
+       { 10088, "ERR_PARTNER_NOTSUPP"               },
+       { 10089, "ERR_PARTNER_NO_AUTH"               },
+       { 10090, "ERR_UNION_NOTSUPP"                 },
+       { 10091, "ERR_OFFLOAD_DENIED"                },
+       { 10092, "ERR_WRONG_LFS"                     },
+       { 10093, "ERR_BADLABEL"                      },
+       { 10094, "ERR_OFFLOAD_NO_REQS"               },
        { 0,    NULL }
 };
 static value_string_ext names_nfs_nfsstat_ext = VALUE_STRING_EXT_INIT(names_nfs_nfsstat);
@@ -10069,10 +10761,18 @@ static const value_string stripetype_names[] = {
 };
 #endif
 
+static const value_string netloctype_names[] = {
+       { NL4_NAME, "NL4_NAME" },
+       { NL4_URL, "NL4_URL"  },
+       { NL4_NETADDR, "NL4_NETADDR"  },
+       { 0, NULL }
+};
+
 static const value_string layouttype_names[] = {
        { 1, "LAYOUT4_NFSV4_1_FILES" },
        { 2, "LAYOUT4_OSD2_OBJECTS"  },
        { 3, "LAYOUT4_BLOCK_VOLUME"  },
+       { 4, "LAYOUT4_FLEX_FILES"  },
        { 0, NULL }
 };
 
@@ -10146,6 +10846,7 @@ static const value_string names_nfs_cb_operation[] = {
        { NFS4_OP_CB_WANTS_CANCELLED,      "CB_WANTS_CANCELLED" },
        { NFS4_OP_CB_NOTIFY_LOCK,          "CB_NOTIFY_LOCK" },
        { NFS4_OP_CB_NOTIFY_DEVICEID,      "CB_NOTIFY_DEVICEID" },
+       { NFS4_OP_CB_OFFLOAD,              "CB_OFFLOAD" },
        { NFS4_OP_CB_ILLEGAL,              "CB_ILLEGAL"},
        { 0,    NULL }
 };
@@ -10224,6 +10925,7 @@ static int
 dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
 {
        guint32     ops, ops_counter;
+       guint32     status;
        guint       opcode;
        proto_item *fitem;
        proto_tree *ftree;
@@ -10244,7 +10946,7 @@ dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                offset += 4;
 
        /* the opcodes are not contiguous */
-               if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) &&
+               if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_OFFLOAD) &&
                    (opcode != NFS4_OP_CB_ILLEGAL))
                        break;
 
@@ -10285,6 +10987,16 @@ dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                case NFS4_OP_CB_NOTIFY_LOCK:
                case NFS4_OP_CB_NOTIFY_DEVICEID:
                        break;
+               case NFS4_OP_CB_OFFLOAD:
+                       offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "filehandle", NULL, civ);
+                       offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
+                       offset = dissect_nfs4_status(tvb, offset, newftree, &status);
+                       if (status == NFS4_OK) {
+                               offset = dissect_nfs4_write_response(tvb, offset, newftree);
+                       } else {
+                               offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_bytes_copied, offset);
+                       }
+                       break;
                case NFS4_OP_ILLEGAL:
                        break;
                default:
@@ -10297,9 +11009,10 @@ dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
 
 
 static int
-dissect_nfs4_cb_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs4_cb_compound_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
        const char *tag = NULL;
+       int offset = 0;
 
        offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
 
@@ -10316,7 +11029,7 @@ dissect_nfs4_cb_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, pro
 static int
 dissect_nfs4_cb_resp_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       guint32     ops, ops_counter;
+       guint32     ops, ops_counter;
        guint32     opcode;
        proto_item *fitem;
        proto_tree *ftree;
@@ -10332,7 +11045,7 @@ dissect_nfs4_cb_resp_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                opcode = tvb_get_ntohl(tvb, offset);
 
                /* sanity check for bogus packets */
-               if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) &&
+               if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_OFFLOAD) &&
                        (opcode != NFS4_OP_ILLEGAL))
                        break;
 
@@ -10380,6 +11093,7 @@ dissect_nfs4_cb_resp_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
                case NFS4_OP_CB_WANTS_CANCELLED:
                case NFS4_OP_CB_NOTIFY_LOCK:
                case NFS4_OP_CB_NOTIFY_DEVICEID:
+               case NFS4_OP_CB_OFFLOAD:
                        break;
                case NFS4_OP_ILLEGAL:
                        break;
@@ -10393,11 +11107,12 @@ dissect_nfs4_cb_resp_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
 
 
 static int
-dissect_nfs4_cb_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs4_cb_compound_reply(tvbuff_t *tvb, packet_info *pinfo,
                              proto_tree *tree, void *data _U_)
 {
        guint32     status;
        const char *tag = NULL;
+       int offset = 0;
 
        offset = dissect_nfs4_status(tvb, offset, tree, &status);
        offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
@@ -10423,19 +11138,14 @@ static const value_string nfs_cb_proc_vals[] = {
        { 0, NULL }
 };
 
-void reg_callback(int cbprog)
-{
-       /* Register the protocol as RPC */
-       rpc_init_prog(proto_nfs, cbprog, ett_nfs);
-
-       /*
-        * Register the procedure tables.  The version should be 4,
-        * but some Linux kernels set this field to 1.  "Temporarily",
-        * accommodate these servers.
-        */
-       rpc_init_proc_table(cbprog, 1, nfs_cb_proc, hf_nfs4_cb_procedure);
-       rpc_init_proc_table(cbprog, 4, nfs_cb_proc, hf_nfs4_cb_procedure);
-}
+/*
+ * The version should be 4, but some Linux kernels set this field to 1.
+ * "Temporarily" accommodate these servers.
+ */
+static const rpc_prog_vers_info nfs_cb_vers_info[] = {
+       { 1, nfs_cb_proc, &hf_nfs4_cb_procedure },
+       { 4, nfs_cb_proc, &hf_nfs4_cb_procedure },
+};
 
 void
 proto_register_nfs(void)
@@ -10461,6 +11171,8 @@ proto_register_nfs(void)
                { &hf_nfs_fh_hash, {
                        "hash (CRC-32)", "nfs.fh.hash", FT_UINT32, BASE_HEX,
                        NULL, 0, "file handle hash", HFILL }},
+
+
                { &hf_nfs_fh_mount_fileid, {
                        "fileid", "nfs.fh.mount.fileid", FT_UINT32, BASE_DEC,
                        NULL, 0, "mount point fileid", HFILL }},
@@ -10483,8 +11195,8 @@ proto_register_nfs(void)
                        "generation", "nfs.fh.generation", FT_UINT32, BASE_HEX,
                        NULL, 0, "inode generation", HFILL }},
                { &hf_nfs_fh_fsid, {
-                       "fsid", "nfs.fh.fsid", FT_UINT32, BASE_HEX,
-                       NULL, 0, "file system ID", HFILL }},
+                       "file system ID", "nfs.fh.fsid", FT_UINT32, BASE_CUSTOM,
+                       CF_FUNC(nfs_fmt_fsid), 0, NULL, HFILL }},
                { &hf_nfs_fh_export_fileid, {
                        "fileid", "nfs.fh.export.fileid", FT_UINT32, BASE_DEC,
                        NULL, 0, "export point fileid", HFILL }},
@@ -10499,61 +11211,73 @@ proto_register_nfs(void)
                        NULL, 0, "Gluster/NFS exportid", HFILL }},
                { &hf_nfs_fh_handle_type, {
                        "Handle type", "nfs.fh.handletype", FT_UINT32, BASE_DEC,
-                       NULL, 0, "v4 handle type", HFILL }},
+                       VALS(handle_type_strings), 0, "v4 handle type", HFILL }},
                { &hf_nfs_fh_file_flag_mntpoint, {
-                       "mount point", "nfs.fh.file.flag.mntpoint", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0001, "file flag: mountpoint", HFILL }},
+                       "mount point", "nfs.fh.file.flag.mntpoint", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0001, "file flag: mountpoint", HFILL }},
                { &hf_nfs_fh_file_flag_snapdir, {
-                       "snapdir", "nfs.fh.file.flag.snapdir", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0002, "file flag: snapdir", HFILL }},
+                       "snapdir", "nfs.fh.file.flag.snapdir", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0002, "file flag: snapdir", HFILL }},
                { &hf_nfs_fh_file_flag_snapdir_ent, {
-                       "snapdir_ent", "nfs.fh.file.flag.snadir_ent", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0004, "file flag: snapdir_ent", HFILL }},
+                       "snapdir_ent", "nfs.fh.file.flag.snadir_ent", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0004, "file flag: snapdir_ent", HFILL }},
                { &hf_nfs_fh_file_flag_empty, {
-                       "empty", "nfs.fh.file.flag.empty", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0008, "file flag: empty", HFILL }},
+                       "empty", "nfs.fh.file.flag.empty", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0008, "file flag: empty", HFILL }},
                { &hf_nfs_fh_file_flag_vbn_access, {
-                       "vbn_access", "nfs.fh.file.flag.vbn_access", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0010, "file flag: vbn_access", HFILL }},
+                       "vbn_access", "nfs.fh.file.flag.vbn_access", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0010, "file flag: vbn_access", HFILL }},
                { &hf_nfs_fh_file_flag_multivolume, {
-                       "multivolume", "nfs.fh.file.flag.multivolume", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0020, "file flag: multivolume", HFILL }},
+                       "multivolume", "nfs.fh.file.flag.multivolume", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0020, "file flag: multivolume", HFILL }},
                { &hf_nfs_fh_file_flag_metadata, {
-                       "metadata", "nfs.fh.file.flag.metadata", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0040, "file flag: metadata", HFILL }},
+                       "metadata", "nfs.fh.file.flag.metadata", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0040, "file flag: metadata", HFILL }},
                { &hf_nfs_fh_file_flag_orphan, {
-                       "orphan", "nfs.fh.file.flag.orphan", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0080, "file flag: orphan", HFILL }},
+                       "orphan", "nfs.fh.file.flag.orphan", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0080, "file flag: orphan", HFILL }},
                { &hf_nfs_fh_file_flag_foster, {
-                       "foster", "nfs.fh.file.flag.foster", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0100, "file flag: foster", HFILL }},
+                       "foster", "nfs.fh.file.flag.foster", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0100, "file flag: foster", HFILL }},
                { &hf_nfs_fh_file_flag_named_attr, {
-                       "named_attr", "nfs.fh.file.flag.named_attr", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0200, "file flag: named_attr", HFILL }},
+                       "named_attr", "nfs.fh.file.flag.named_attr", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0200, "file flag: named_attr", HFILL }},
                { &hf_nfs_fh_file_flag_exp_snapdir, {
-                       "exp_snapdir", "nfs.fh.file.flag.exp_snapdir", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0400, "file flag: exp_snapdir", HFILL }},
+                       "exp_snapdir", "nfs.fh.file.flag.exp_snapdir", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0400, "file flag: exp_snapdir", HFILL }},
                { &hf_nfs_fh_file_flag_vfiler, {
-                       "vfiler", "nfs.fh.file.flag.vfiler", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x0800, "file flag: vfiler", HFILL }},
+                       "vfiler", "nfs.fh.file.flag.vfiler", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x0800, "file flag: vfiler", HFILL }},
                { &hf_nfs_fh_file_flag_aggr, {
-                       "aggr", "nfs.fh.file.flag.aggr", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x1000, "file flag: aggr", HFILL }},
+                       "aggr", "nfs.fh.file.flag.aggr", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x1000, "file flag: aggr", HFILL }},
                { &hf_nfs_fh_file_flag_striped, {
-                       "striped", "nfs.fh.file.flag.striped", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x2000, "file flag: striped", HFILL }},
+                       "striped", "nfs.fh.file.flag.striped", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x2000, "file flag: striped", HFILL }},
                { &hf_nfs_fh_file_flag_private, {
-                       "private", "nfs.fh.file.flag.private", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x4000, "file flag: private", HFILL }},
+                       "private", "nfs.fh.file.flag.private", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x4000, "file flag: private", HFILL }},
                { &hf_nfs_fh_file_flag_next_gen, {
-                       "next_gen", "nfs.fh.file.flag.next_gen", FT_UINT16, BASE_HEX,
-                       VALS(netapp_file_flag_vals), 0x8000, "file flag: next_gen", HFILL }},
-               { &hf_nfs_fh_fsid_major, {
+                       "next_gen", "nfs.fh.file.flag.next_gen", FT_BOOLEAN, 16,
+                       TFS(&tfs_set_notset), 0x8000, "file flag: next_gen", HFILL }},
+               { &hf_nfs_fh_fsid_major16_mask, {
+                       "major", "nfs.fh.fsid.major", FT_UINT16, BASE_DEC,
+                       NULL, 0xFF00, "major file system ID", HFILL }},
+               { &hf_nfs_fh_fsid_minor16_mask, {
+                       "minor", "nfs.fh.fsid.minor", FT_UINT16, BASE_DEC,
+                       NULL, 0x00FF, "minor file system ID", HFILL }},
+               { &hf_nfs_fh_fsid_major16, {
+                       "major", "nfs.fh.fsid.major", FT_UINT16, BASE_DEC,
+                       NULL, 0x0, "major file system ID", HFILL }},
+               { &hf_nfs_fh_fsid_minor16, {
+                       "minor", "nfs.fh.fsid.minor", FT_UINT16, BASE_DEC,
+                       NULL, 0x0, "minor file system ID", HFILL }},
+               { &hf_nfs_fh_fsid_major32, {
                        "major", "nfs.fh.fsid.major", FT_UINT32, BASE_DEC,
-                       NULL, 0, "major file system ID", HFILL }},
-               { &hf_nfs_fh_fsid_minor, {
+                       NULL, 0xfffc, "major file system ID", HFILL }},
+               { &hf_nfs_fh_fsid_minor32, {
                        "minor", "nfs.fh.fsid.minor", FT_UINT32, BASE_DEC,
-                       NULL, 0, "minor file system ID", HFILL }},
+                       NULL, 0x3ffff, "minor file system ID", HFILL }},
                { &hf_nfs_fh_fsid_inode, {
                        "inode", "nfs.fh.fsid.inode", FT_UINT32, BASE_DEC,
                        NULL, 0, "file system inode", HFILL }},
@@ -10561,11 +11285,11 @@ proto_register_nfs(void)
                        "gfid", "nfs.fh.gfid", FT_GUID, BASE_NONE,
                        NULL, 0, "Gluster/NFS GFID", HFILL }},
                { &hf_nfs_fh_xfsid_major, {
-                       "exported major", "nfs.fh.xfsid.major", FT_UINT32, BASE_DEC,
-                       NULL, 0, "exported major file system ID", HFILL }},
+                       "exported major", "nfs.fh.xfsid.major", FT_UINT16, BASE_DEC,
+                       NULL, 0xFF00, "exported major file system ID", HFILL }},
                { &hf_nfs_fh_xfsid_minor, {
-                       "exported minor", "nfs.fh.xfsid.minor", FT_UINT32, BASE_DEC,
-                       NULL, 0, "exported minor file system ID", HFILL }},
+                       "exported minor", "nfs.fh.xfsid.minor", FT_UINT16, BASE_DEC,
+                       NULL, 0x00FF, "exported minor file system ID", HFILL }},
                { &hf_nfs_fh_fstype, {
                        "file system type", "nfs.fh.fstype", FT_UINT32, BASE_DEC,
                        NULL, 0, NULL, HFILL }},
@@ -10615,6 +11339,9 @@ proto_register_nfs(void)
                { &hf_nfs_fh_hp_len, {
                        "length", "nfs.fh.hp.len", FT_UINT32, BASE_DEC,
                        NULL, 0, "hash path length", HFILL }},
+               { &hf_nfs_fh_hp_key, {
+                       "key", "nfs.fh.hp.key", FT_BYTES, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
                { &hf_nfs_fh_version, {
                        "version", "nfs.fh.version", FT_UINT8, BASE_DEC,
                        NULL, 0, "file handle layout version", HFILL }},
@@ -10675,6 +11402,15 @@ proto_register_nfs(void)
                { &hf_nfs_fh_endianness, {
                        "endianness", "nfs.fh.endianness", FT_BOOLEAN, BASE_NONE,
                        TFS(&tfs_endianness), 0x0, "server native endianness", HFILL }},
+               { &hf_nfs_fh_dc_opaque, {
+                       "fh opaque data", "nfs.fh.dc.opaque", FT_BYTES, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+               { &hf_nfs_fh_dc_exportid, {
+                       "export_id", "nfs.fh.dc.exportid", FT_UINT32, BASE_HEX,
+                       NULL, 0, NULL, HFILL }},
+               { &hf_nfs_fh_dc_handle_type, {
+                       "fh type", "nfs.fh.dc.type", FT_UINT8, BASE_DEC,
+                       VALS(dcache_handle_types), 0, NULL, HFILL }},
                { &hf_nfs2_status, {
                        "Status", "nfs.status2", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
                        &names_nfs2_stat_ext, 0, "Reply status", HFILL }},
@@ -11024,6 +11760,10 @@ proto_register_nfs(void)
                        "Name", "nfs.entry_name", FT_STRING, BASE_NONE,
                        NULL, 0, "Directory entry name", HFILL }},
 
+               { &hf_nfs4_pathname_components, {
+                       "pathname components", "nfs.pathname.component.count", FT_UINT32, BASE_DEC,
+                       NULL, 0, "Number of Pathname component", HFILL }},
+
                { &hf_nfs4_component, {
                        "Name", "nfs.pathname.component", FT_STRING, BASE_NONE,
                        NULL, 0, "Pathname component", HFILL }},
@@ -11132,7 +11872,19 @@ proto_register_nfs(void)
                        "Attr mask", "nfs.attr_mask", FT_UINT32, BASE_HEX,
                        NULL, 0, "ACL attribute mask", HFILL }},
 
+               { &hf_nfs4_attr_count, {
+                       "Attr count", "nfs.attr_count", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_set_it_value_follows,        {
+                       "set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
+                       VALS(value_follows), 0, "How To Set Time", HFILL }},
+
                { &hf_nfs4_time_how,    {
+                       "set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
+                       VALS(time_how), 0, "How To Set Time", HFILL }},
+
+               { &hf_nfs4_time_how4,   {
                        "set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
                        VALS(names_time_how4), 0, "How To Set Time", HFILL }},
 
@@ -11639,8 +12391,21 @@ proto_register_nfs(void)
                        "StateID Hash", "nfs.stateid4.hash", FT_UINT16, BASE_HEX,
                        NULL, 0, NULL, HFILL }},
 
-               { &hf_nfs4_acl, {
-                       "ACL", "nfs.acl", FT_NONE, BASE_NONE, NULL, 0, "Access Control List", HFILL }},
+               { &hf_nfs4_aclflags, {
+                       "ACL flags", "nfs.acl.flags", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_aclflag_auto_inherit, {
+                       "AUTO_INHERIT", "nfs.acl.flags.auto_inherit", FT_BOOLEAN, 32,
+                       NULL, ACL4_AUTO_INHERIT, NULL, HFILL }},
+
+               { &hf_nfs4_aclflag_protected, {
+                       "PROTECTED", "nfs.acl.flags.protected", FT_BOOLEAN, 32,
+                       NULL, ACL4_PROTECTED, NULL, HFILL }},
+
+               { &hf_nfs4_aclflag_defaulted, {
+                       "DEFAULTED", "nfs.acl.flags.defaulted", FT_BOOLEAN, 32,
+                       NULL, ACL4_DEFAULTED, NULL, HFILL }},
 
                { &hf_nfs4_num_aces, {
                        "ACE count", "nfs.num_aces", FT_UINT32, BASE_DEC,
@@ -11770,6 +12535,30 @@ proto_register_nfs(void)
                        "export point unique id", "nfs.gxfh3.exportptuid", FT_UINT32, BASE_HEX_DEC,
                        NULL, 0, NULL, HFILL }},
 
+               { &hf_nfs3_verifier, {
+                       "Verifier", "nfs.verifier", FT_BYTES, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs3_specdata1, {
+                       "specdata1", "nfs.specdata1", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs3_specdata2, {
+                       "specdata2", "nfs.specdata2", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs3_attributes_follow, {
+                       "attributes_follow", "nfs.attributes_follow", FT_UINT32, BASE_DEC,
+                       VALS(value_follows), 0, NULL, HFILL }},
+
+               { &hf_nfs3_handle_follow, {
+                       "handle_follow", "nfs.handle_follow", FT_UINT32, BASE_DEC,
+                       VALS(value_follows), 0, NULL, HFILL }},
+
+               { &hf_nfs3_sattrguard3, {
+                       "check", "nfs.sattrguard3", FT_UINT32, BASE_DEC,
+                       VALS(value_follows), 0, NULL, HFILL }},
+
                { &hf_nfs4_length_minlength, {
                        "min length", "nfs.minlength4", FT_UINT64, BASE_DEC,
                        NULL, 0, NULL, HFILL }},
@@ -11796,11 +12585,9 @@ proto_register_nfs(void)
                        VALS(stripetype_names), 0, NULL, HFILL }},
 #endif
 
-#if 0
                { &hf_nfs4_stripeunit, {
                        "stripe unit", "nfs.stripeunit", FT_UINT64, BASE_DEC,
                        NULL, 0, NULL, HFILL }},
-#endif
 
 #if 0
                { &hf_nfs4_util, {
@@ -11889,10 +12676,26 @@ proto_register_nfs(void)
                        "return on close?", "nfs.retclose4", FT_BOOLEAN, BASE_NONE,
                        TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
 
+               { &hf_nfs4_nfl_mirrors, {
+                       "Mirror", "nfs.nfl_mirrors", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
                { &hf_nfs4_nfl_util, {
                        "nfl_util", "nfs.nfl_util", FT_UINT32, BASE_HEX,
                        NULL, 0, NULL, HFILL }},
 
+               { &hf_nfs4_nfl_fhs, {
+                       "file handles", "nfs.nfl_fhs", FT_UINT32, BASE_HEX,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_mirror_index, {
+                       "Data Server", "nfs.nff_mirror_index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_mirror_eff, {
+                       "mirror efficiency", "nfs.nff_mirror_eff", FT_UINT32, BASE_HEX,
+                       NULL, 0, NULL, HFILL }},
+
                { &hf_nfs4_nfl_first_stripe_index, {
                        "first stripe to use index", "nfs.nfl_first_stripe_index", FT_UINT32, BASE_DEC,
                        NULL, 0, NULL, HFILL }},
@@ -12248,6 +13051,14 @@ proto_register_nfs(void)
                        "S_IXOTH", "nfs.mode3.xoth", FT_BOOLEAN, 32,
                        TFS(&tfs_yes_no), 0x001, NULL, HFILL }},
 
+               { &hf_nfs2_ftype, {
+                       "type", "nfs.ftype", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
+                       &nfs2_ftype_ext, 0, NULL, HFILL }},
+
+               { &hf_nfs2_mode, {
+                       "mode", "nfs.mode", FT_UINT32, BASE_OCT,
+                       NULL, 0, NULL, HFILL }},
+
                { &hf_nfs2_mode_name, {
                        "Name", "nfs.mode.name", FT_UINT32, BASE_DEC,
                        VALS(nfs2_mode_names), 0160000, NULL, HFILL }},
@@ -12372,6 +13183,234 @@ proto_register_nfs(void)
                        "data content", "nfs.data_content", FT_UINT32, BASE_DEC,
                        VALS(names_data_content), 0, NULL, HFILL }},
 
+               { &hf_nfs4_huge_bitmap_length, {
+                       "Huge bitmap length", "nfs.huge_bitmap_length", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_universal_address_ipv4, {
+                       "universal_address", "nfs.universal_address.ipv4", FT_IPv4, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_universal_address_ipv6, {
+                       "universal_address", "nfs.universal_address.ipv6", FT_IPv6, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_getdevinfo, {
+                       "dev info", "nfs.devinfo", FT_BYTES,
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_version, {
+                       "version", "nfs.ff.version", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_minorversion, {
+                       "minorversion", "nfs.ff.minorversion", FT_UINT32,
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_rsize, {
+                       "max_rsize", "nfs.ff.rsize", FT_UINT32,
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_wsize, {
+                       "max_wsize", "nfs.ff.wsize", FT_UINT32,
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_tightly_coupled, {
+                        "tightly coupled", "nfs.ff.tightly_coupled",
+                       FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
+                       NULL, HFILL }},
+
+               { &hf_nfs4_ff_layout_flags, {
+                       "layout flags", "nfs.ff.layout_flags", FT_UINT32, BASE_HEX,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_synthetic_owner, {
+                       "synthetic owner", "nfs.ff.synthetic_owner", FT_STRING, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_synthetic_owner_group, {
+                       "synthetic group", "nfs.ff.synthetic_owner_group", FT_STRING, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_layout_flags_no_layoutcommit, {
+                       "FLAG_NO_LAYOUTCOMMIT", "nfs.ff.layout_flags.no_layoutcommit", FT_BOOLEAN, 32,
+                       TFS(&tfs_set_notset), 0x00000001, NULL, HFILL}},
+
+               { &hf_nfs4_fattr_clone_blocksize, {
+                       "clone block size", "nfs.fattr4.clone_block_size", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_fattr_space_freed, {
+                       "space freed", "nfs.fattr4.space_freed", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_fattr_change_attr_type, {
+                       "change attr type", "nfs.fattr4.change_attr_type", FT_UINT32, BASE_DEC,
+                       VALS(names_nfs_change_attr_types), 0, NULL, HFILL }},
+
+               { &hf_nfs4_callback_stateids, {
+                       "Callback StateIds", "nfs.callback_ids", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_callback_stateids_index, {
+                       "Callback Id", "nfs.ff.callback_id_index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_consecutive, {
+                       "copy consecutively?", "nfs.consecutive", FT_BOOLEAN, BASE_NONE,
+                       TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
+
+               { &hf_nfs4_netloc, {
+                       "net loc", "nfs.netloc", FT_BYTES,
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_netloc_type, {
+                       "netloc type", "nfs.netloctype", FT_UINT32, BASE_DEC,
+                       VALS(netloctype_names), 0, NULL, HFILL }},
+
+               { &hf_nfs4_nl_name, {
+                       "net loc name", "nfs.nl_name", FT_STRING, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_nl_url, {
+                       "net loc url", "nfs.nl_url", FT_STRING, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_source_servers, {
+                       "Source Server count", "nfs.source_servers", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_source_server_index, {
+                       "Source Server", "nfs.ff.source_server_index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_synchronous, {
+                       "copy synchronous?", "nfs.synchronous", FT_BOOLEAN, BASE_NONE,
+                       TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
+
+               { &hf_nfs4_io_hints_mask, {
+                       "Hint mask", "nfs.hint.mask", FT_UINT32, BASE_HEX,
+                       NULL, 0, "ACL attribute mask", HFILL }},
+
+               { &hf_nfs4_io_hint_count, {
+                       "Hint count", "nfs.hint.count", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_io_advise_hint, {
+                       "Hint", "nfs.hint.hint", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
+                       &io_advise_names_ext, 0, NULL, HFILL }},
+
+               { &hf_nfs4_bytes_copied, {
+                       "bytes copied", "nfs.bytes_copied", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_read_plus_content_type, {
+                       "Content Type", "nfs.content.type", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
+                       &read_plus_content_names_ext, 0, NULL, HFILL }},
+
+               { &hf_nfs4_read_plus_content_count, {
+                       "Content count", "nfs.content.count", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_read_plus_content_index, {
+                       "Content index", "nfs.content.index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_block_size, {
+                       "Content index", "nfs.content.index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_block_count, {
+                       "Number of Blocks", "nfs.adb.block.count", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_reloff_blocknum, {
+                       "Relative Offset Block Number", "nfs.adb.block.reloff_num", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_blocknum, {
+                       "Block Number", "nfs.adb.block.num", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_reloff_pattern, {
+                       "Relative Offset Pattern", "nfs.adb.pattern.reloff", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_pattern_hash, {
+                       "hash (CRC-32)", "nfs.adb.pattern_hash", FT_UINT32, BASE_HEX,
+                       NULL, 0, "ADB pattern hash", HFILL }},
+
+               { &hf_nfs4_ff_local, {
+                       "client used cache?", "nfs.ff.local", FT_BOOLEAN, BASE_NONE,
+                       TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
+
+               { &hf_nfs4_io_count, {
+                       "count", "nfs.io_count", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_io_bytes, {
+                       "bytes", "nfs.io_bytes", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_ops_requested, {
+                       "ops requested", "nfs.ff.ops_requested", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_bytes_requested, {
+                       "bytes requested", "nfs.ff.bytes_requested", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_ops_completed, {
+                       "ops completed", "nfs.ff.ops_completed", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_bytes_completed, {
+                       "bytes completed", "nfs.ff.bytes_completed", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_bytes_not_delivered, {
+                       "bytes not delivered", "nfs.ff.bytes_not_delivered", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_layoutstats, {
+                       "Layout Stats", "nfs.layoutstats", FT_BYTES, BASE_NONE,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_device_error_count, {
+                       "Device Error count", "nfs.device_error_count", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_device_errors_index, {
+                       "Device Error index", "nfs.device_errors_index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_ioerrs_count, {
+                       "IO Errors count", "nfs.ff.ioerrs_count", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_ioerrs_index, {
+                       "IO Errors index", "nfs.ff.ioerrs_index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_ioerrs_length, {
+                       "length", "nfs.ff.ioerrs_length", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_ioerrs_offset, {
+                       "offset", "nfs.ff.ioerrs_offset", FT_UINT64, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_iostats_count, {
+                       "IO Stats count", "nfs.ff.iostats_count", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_ff_iostats_index, {
+                       "IO Stats index", "nfs.ff.iostats_index", FT_UINT32, BASE_DEC,
+                       NULL, 0, NULL, HFILL }},
+
+               { &hf_nfs4_io_error_op, {
+                       "OP", "nfs.ff_ioerrs_op", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
+                       &names_nfs4_operation_ext, 0, NULL, HFILL }},
 
        /* Hidden field for v2, v3, and v4 status */
                { &hf_nfs_status, {
@@ -12525,6 +13564,7 @@ proto_register_nfs(void)
                &ett_nfs4_stateid,
                &ett_nfs4_fattr_fh_expire_type,
                &ett_nfs4_fattr_aclsupport,
+               &ett_nfs4_aclflag,
                &ett_nfs4_ace,
                &ett_nfs4_clientaddr,
                &ett_nfs4_aceflag,
@@ -12556,7 +13596,7 @@ proto_register_nfs(void)
                &ett_nfs4_service,
                &ett_nfs4_sessionid,
                &ett_nfs4_layoutseg,
-               &ett_nfs4_layoutseg_fh,
+               &ett_nfs4_layoutseg_sub,
                &ett_nfs4_cb_request_op,
                &ett_nfs4_cb_resop,
                &ett_nfs4_cb_getattr,
@@ -12577,18 +13617,61 @@ proto_register_nfs(void)
                &ett_nfs4_chan_attrs,
                &ett_nfs4_create_session_flags,
                &ett_nfs4_sequence_status_flags,
-               &ett_nfs4_want_notify_flags
+               &ett_nfs4_want_notify_flags,
+               &ett_nfs4_ff_layout_flags,
+               &ett_nfs4_layoutstats,
+               &ett_nfs4_io_info,
+               &ett_nfs4_io_latency,
+               &ett_nfs4_io_time,
+               &ett_nfs4_callback_stateids_sub,
+               &ett_nfs4_source_servers_sub,
+               &ett_nfs4_copy,
+               &ett_nfs4_copy_notify,
+               &ett_nfs4_device_errors_sub,
+               &ett_nfs4_layouterror,
+               &ett_nfs4_ff_ioerrs_sub,
+               &ett_nfs4_ff_iostats_sub,
+               &ett_nfs4_clone,
+               &ett_nfs4_offload_cancel,
+               &ett_nfs4_offload_status,
+               &ett_nfs4_io_advise,
+               &ett_nfs4_read_plus,
+               &ett_nfs4_read_plus_content_sub,
+               &ett_nfs4_write_same
        };
 
        static ei_register_info ei[] = {
                { &ei_nfs_too_many_ops, { "nfs.too_many_ops", PI_PROTOCOL, PI_NOTE, "Too many operations", EXPFILL }},
                { &ei_nfs_not_vnx_file, { "nfs.not_vnx_file", PI_UNDECODED, PI_WARN, "Not a Celerra|VNX file handle", EXPFILL }},
+               { &ei_protocol_violation, { "nfs.protocol_violation", PI_PROTOCOL, PI_WARN,
+                       "Per RFCs 3530 and 5661 an attribute mask is required but was not provided.", EXPFILL }},
+               { &ei_nfs_too_many_bitmaps, { "nfs.too_many_bitmaps", PI_PROTOCOL, PI_NOTE, "Too many bitmap array items", EXPFILL }},
        };
 
        module_t *nfs_module;
        expert_module_t* expert_nfs;
 
+       /* Decode As handling */
+       static build_valid_func nfs_da_build_value[1] = {nfs_value};
+       static decode_as_value_t nfs_da_values = {nfs_prompt, 1, nfs_da_build_value};
+       static decode_as_t nfs_da = {"nfs", "NFS File Handle", "nfs_fhandle.type", 1, 0, &nfs_da_values, NULL, NULL,
+                                                                       decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
+
        proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs");
+
+       /* "protocols" registered just for Decode As */
+       proto_nfs_unknown = proto_register_protocol("Unknown", "unknown", "nfs.unknown");
+       proto_nfs_svr4 = proto_register_protocol("SVR4", "svr4", "nfs.svr4");
+       proto_nfs_knfsd_le = proto_register_protocol("KNFSD_LE", "knfsd_le", "nfs.knfsd_le");
+       proto_nfs_nfsd_le = proto_register_protocol("NFSD_LE", "nfsd_le", "nfs.nfsd_le");
+       proto_nfs_knfsd_new = proto_register_protocol("KNFSD_NEW", "knfsd_new", "nfs.knfsd_new");
+       proto_nfs_ontap_v3 = proto_register_protocol("ONTAP_V3", "ontap_v3", "nfs.ontap_v3");
+       proto_nfs_ontap_v4 = proto_register_protocol("ONTAP_V4", "ontap_v4", "nfs.ontap_v4");
+       proto_nfs_ontap_gx_v3 = proto_register_protocol("ONTAP_GX_V3", "ontap_gx_v3", "nfs.ontap_gx_v3");
+       proto_nfs_celerra_vnx = proto_register_protocol("CELERRA_VNX", "celerra_vnx", "nfs.celerra_vnx");
+       proto_nfs_gluster = proto_register_protocol("GLUSTER", "gluster", "nfs.gluster");
+       proto_nfs_dcache = proto_register_protocol("dCache", "dcache", "nfs.dcache");
+
        proto_register_field_array(proto_nfs, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
        expert_nfs = expert_register_protocol(proto_nfs);
@@ -12626,18 +13709,15 @@ proto_register_nfs(void)
        nfs_fhandle_table = register_dissector_table("nfs_fhandle.type",
            "NFS Filehandle types", FT_UINT8, BASE_HEX);
 
-       prefs_register_enum_preference(nfs_module,
-               "default_fhandle_type",
-               "Decode NFS file handles as",
-               "Decode all NFS file handles as if they are of this type",
-               &default_nfs_fhandle_type,
-               nfs_fhandle_types,
-               FALSE);
+       prefs_register_obsolete_preference(nfs_module, "default_fhandle_type");
 
        nfs_name_snoop_known    = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
        nfs_file_handles        = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
        nfs_fhandle_frame_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
        register_init_routine(nfs_name_snoop_init);
+       register_cleanup_routine(nfs_name_snoop_cleanup);
+
+       register_decode_as(&nfs_da);
 }
 
 
@@ -12647,42 +13727,45 @@ proto_reg_handoff_nfs(void)
        dissector_handle_t fhandle_handle;
 
        /* Register the protocol as RPC */
-       rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
+       rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs,
+           G_N_ELEMENTS(nfs_vers_info), nfs_vers_info);
+
+       /* Register the CB protocol as RPC */
+       rpc_init_prog(proto_nfs, NFS_CB_PROGRAM, ett_nfs,
+           G_N_ELEMENTS(nfs_cb_vers_info), nfs_cb_vers_info);
 
-       /* Register the procedure tables */
-       rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc, hf_nfs2_procedure);
-       rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc, hf_nfs3_procedure);
-       rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc, hf_nfs4_procedure);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_SVR4, proto_nfs_svr4);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_SVR4, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_SVR4, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_LE, proto_nfs_knfsd_le);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_LE, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_LINUX_KNFSD_LE, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_NFSD_LE, proto_nfs_nfsd_le);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_NFSD_LE, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_LINUX_NFSD_LE, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_NEW, proto_nfs_knfsd_new);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_NEW, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_LINUX_KNFSD_NEW, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP, proto_nfs_ontap_v3);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_NETAPP, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_V4, proto_nfs_ontap_v4);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_V4, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_NETAPP_V4, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_GX_v3, proto_nfs_ontap_gx_v3);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_GX_v3, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_NETAPP_GX_V3, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_CELERRA_VNX, proto_nfs_celerra_vnx);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_CELERRA_VNX, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_CELERRA_VNX, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_GLUSTER, proto_nfs_gluster);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_GLUSTER, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_GLUSTER, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_DCACHE, proto_nfs_dcache);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 
-       fhandle_handle = create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs);
-       dissector_add_uint("nfs_fhandle.type", FHT_UNKNOWN, fhandle_handle);
+       fhandle_handle = create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs_unknown);
+       dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
 }
 
 /*