sensitivity of packet range options fine tuning:
[obnox/wireshark/wip.git] / packet-nfs.c
index e1fd85bd7fabbd5f82a43a7f39778615a5de8192..28dec3cb6d857bc6a9dce38b967f8db3b3d033d5 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for nfs dissection
  * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
  * Copyright 2000-2002, Mike Frisch <frisch@hummingbird.com> (NFSv4 decoding)
- * $Id: packet-nfs.c,v 1.81 2002/10/14 17:08:53 guy Exp $
+ * $Id: packet-nfs.c,v 1.94 2003/09/28 01:52:57 sahlberg Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "packet-rpc.h"
 #include "packet-nfs.h"
 #include "prefs.h"
-
+#include "epan/int-64bit.h"
 
 static int proto_nfs = -1;
 
+static int hf_nfs_procedure_v2 = -1;
+static int hf_nfs_procedure_v3 = -1;
+static int hf_nfs_procedure_v4 = -1;
 static int hf_nfs_fh_length = -1;
 static int hf_nfs_fh_hash = -1;
 static int hf_nfs_fh_fsid_major = -1;
@@ -252,6 +255,7 @@ static int hf_nfs_aceflag4 = -1;
 static int hf_nfs_acemask4 = -1;
 static int hf_nfs_delegate_type = -1;
 static int hf_nfs_secinfo_flavor = -1;
+static int hf_nfs_secinfo_arr4 = -1;
 static int hf_nfs_num_blocks = -1;
 static int hf_nfs_bytes_per_block = -1;
 static int hf_nfs_eof = -1;
@@ -397,8 +401,8 @@ GHashTable *nfs_fhandle_frame_table = NULL;
 static gint
 nfs_fhandle_data_equal(gconstpointer k1, gconstpointer k2)
 {
-       nfs_fhandle_data_t *key1 = (nfs_fhandle_data_t *)k1;
-       nfs_fhandle_data_t *key2 = (nfs_fhandle_data_t *)k2;
+       const nfs_fhandle_data_t *key1 = (const nfs_fhandle_data_t *)k1;
+       const nfs_fhandle_data_t *key2 = (const nfs_fhandle_data_t *)k2;
 
        return (key1->len==key2->len)
             &&(!memcmp(key1->fh, key2->fh, key1->len));
@@ -406,7 +410,7 @@ nfs_fhandle_data_equal(gconstpointer k1, gconstpointer k2)
 static guint
 nfs_fhandle_data_hash(gconstpointer k)
 {
-       nfs_fhandle_data_t *key = (nfs_fhandle_data_t *)k;
+       const nfs_fhandle_data_t *key = (const nfs_fhandle_data_t *)k;
        int i;
        int hash;
 
@@ -503,7 +507,7 @@ typedef struct nfs_name_snoop {
 typedef struct nfs_name_snoop_key {
        int key;
        int fh_length;
-       unsigned char *fh;
+       const unsigned char *fh;
 } nfs_name_snoop_key_t;
 
 static GMemChunk *nfs_name_snoop_chunk = NULL;
@@ -519,8 +523,8 @@ static GHashTable *nfs_name_snoop_known = NULL;
 static gint
 nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer k2)
 {
-       nfs_name_snoop_key_t *key1 = (nfs_name_snoop_key_t *)k1;
-       nfs_name_snoop_key_t *key2 = (nfs_name_snoop_key_t *)k2;
+       const nfs_name_snoop_key_t *key1 = (const nfs_name_snoop_key_t *)k1;
+       const nfs_name_snoop_key_t *key2 = (const nfs_name_snoop_key_t *)k2;
 
        return (key1->key==key2->key)
             &&(key1->fh_length==key2->fh_length)
@@ -529,7 +533,7 @@ nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer k2)
 static guint
 nfs_name_snoop_matched_hash(gconstpointer k)
 {
-       nfs_name_snoop_key_t *key = (nfs_name_snoop_key_t *)k;
+       const nfs_name_snoop_key_t *key = (const nfs_name_snoop_key_t *)k;
        int i;
        guint hash;
 
@@ -636,11 +640,11 @@ void
 nfs_name_snoop_add_name(int xid, tvbuff_t *tvb, int name_offset, int name_len, int parent_offset, int parent_len, unsigned char *name)
 {
        nfs_name_snoop_t *nns, *old_nns;
-       unsigned char *ptr=NULL;
+       const unsigned char *ptr=NULL;
 
        /* filter out all '.' and '..' names */
        if(!name){
-               ptr=(unsigned char *)tvb_get_ptr(tvb, name_offset, name_len);
+               ptr=(const unsigned char *)tvb_get_ptr(tvb, name_offset, name_len);
                if(ptr[0]=='.'){
                        if(ptr[1]==0){
                                return;
@@ -704,6 +708,7 @@ nfs_name_snoop_add_name(int xid, tvbuff_t *tvb, int name_offset, int name_len, i
 static void
 nfs_name_snoop_add_fh(int xid, tvbuff_t *tvb, int fh_offset, int fh_length)
 {
+       unsigned char *fh;
        nfs_name_snoop_t *nns, *old_nns;
        nfs_name_snoop_key_t *key;
 
@@ -720,8 +725,9 @@ nfs_name_snoop_add_fh(int xid, tvbuff_t *tvb, int fh_offset, int fh_length)
        }
 
        /* oki, we have a new entry */
-       nns->fh=g_malloc(fh_length);
-       memcpy(nns->fh, tvb_get_ptr(tvb, fh_offset, fh_length), fh_length);
+       fh=g_malloc(fh_length);
+       memcpy(fh, tvb_get_ptr(tvb, fh_offset, fh_length), fh_length);
+       nns->fh=fh;
        nns->fh_length=fh_length;
 
        key=g_mem_chunk_alloc(nfs_name_snoop_key_chunk);
@@ -797,7 +803,7 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
        if(!pinfo->fd->flags.visited){
                key.key=0;
                key.fh_length=fh_length;
-               key.fh=(unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
+               key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
 
                nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
                if(nns){
@@ -825,7 +831,7 @@ nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_of
        if(!nns){
                key.key=pinfo->fd->num;
                key.fh_length=fh_length;
-               key.fh=(unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
+               key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
 
                nns=g_hash_table_lookup(nfs_name_snoop_known, &key);
        }
@@ -1347,10 +1353,10 @@ out:
 
 static void
 dissect_fhandle_data_unknown(tvbuff_t *tvb, int offset, proto_tree *tree,
-    int fhlen)
+    guint fhlen)
 {
-       int sublen;
-       int bytes_left;
+       guint sublen;
+       guint bytes_left;
        gboolean first_line;
 
        bytes_left = fhlen;
@@ -1373,7 +1379,7 @@ dissect_fhandle_data_unknown(tvbuff_t *tvb, int offset, proto_tree *tree,
 
 static void
 dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, unsigned int fhlen, gboolean hidden)
+    proto_tree *tree, unsigned int fhlen, gboolean hidden, guint32 *hash)
 {
        unsigned int fhtype = FHT_UNKNOWN;
 
@@ -1387,21 +1393,23 @@ dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
           of an RPC call */
        if(nfs_fhandle_reqrep_matching && (!hidden) ){
                nfs_fhandle_data_t *old_fhd=NULL;
+               unsigned char *fh;
 
                if( !pinfo->fd->flags.visited ){
                        nfs_fhandle_data_t fhd;
 
                        /* first check if we have seen this fhandle before */
                        fhd.len=fhlen;
-                       fhd.fh=(unsigned char *)tvb_get_ptr(tvb, offset, fhlen);
+                       fhd.fh=(const unsigned char *)tvb_get_ptr(tvb, offset, fhlen);
                        old_fhd=g_hash_table_lookup(nfs_fhandle_data_table,
                                (gconstpointer)&fhd);
                        if(!old_fhd){
                                /* oh, a new fhandle, alloc struct and store it in the table*/
                                old_fhd=g_mem_chunk_alloc(nfs_fhandle_data_chunk);
                                old_fhd->len=fhlen;
-                               old_fhd->fh=g_malloc(fhlen);
-                               memcpy(old_fhd->fh, fhd.fh, fhlen);
+                               fh=g_malloc(fhlen);
+                               memcpy(fh, fhd.fh, fhlen);
+                               old_fhd->fh=fh;
                                old_fhd->tvb=tvb_new_real_data(old_fhd->fh, old_fhd->len, old_fhd->len);
                                g_hash_table_insert(nfs_fhandle_data_table,
                                        (gpointer)old_fhd, (gpointer)old_fhd);
@@ -1438,6 +1446,9 @@ dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        proto_tree_add_uint(tree, hf_nfs_fh_hash, tvb, offset,
                                fhlen, fhhash);
                }
+               if(hash){
+                       *hash=fhhash;
+               }
        }
        if(nfs_file_name_snooping){
                nfs_name_snoop_fh(pinfo, tree, tvb, offset, fhlen, hidden);
@@ -1537,7 +1548,7 @@ void
 dissect_fhandle_hidden(packet_info *pinfo, proto_tree *tree, nfs_fhandle_data_t *nfd)
 {
        if(nfd && nfd->len){
-               dissect_fhandle_data(nfd->tvb, 0, pinfo, tree, nfd->len, TRUE);
+               dissect_fhandle_data(nfd->tvb, 0, pinfo, tree, nfd->len, TRUE, NULL);
        }
 }
 
@@ -1636,6 +1647,15 @@ static const value_string names_nfs_stat4[] = {
        {       10037,  "NFS4ERR_LOCKS_HELD"                            },
        {       10038,  "NFS4ERR_OPENMODE"      },
        {       10039,  "NFS4ERR_BADOWNER"      },
+       {       10040,  "NFS4ERR_BADCHAR"               },
+       {       10041,  "NFS4ERR_BADNAME"    },
+       {       10042,  "NFS4ERR_BAD_RANGE"     },
+       {       10043,  "NFS4ERR_LOCK_NOTSUPP"  },
+       {       10044,  "NFS4ERR_OP_ILLEGAL"    },
+       {       10045,  "NFS4ERR_DEADLOCK"      },
+       {       10046,  "NFS4ERR_FILE_OPEN"     },
+       {       10047,  "NFS4ERR_ADMIN_REVOKED" },
+       {       10048,  "NFS4ERR_CB_PATH_DOWN"  },
        { 0, NULL }
 };
 
@@ -1679,11 +1699,111 @@ dissect_stat(tvbuff_t *tvb, int offset, proto_tree *tree,
 
 /* RFC 1094, Page 12..14 */
 static int
-dissect_nfs2_stat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_stat(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       proto_item_append_text(tree, ", RMDIR Reply");
+                       break;
+               default:
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", RMDIR Reply  Error:%s", err);
+       }
+
+       return offset;
+}
+
+static int
+dissect_nfs2_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_stat(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       proto_item_append_text(tree, ", SYMLINK Reply");
+                       break;
+               default:
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", SYMLINK Reply  Error:%s", err);
+       }
+
+       return offset;
+}
+
+static int
+dissect_nfs2_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       proto_item_append_text(tree, ", LINK Reply");
+                       break;
+               default:
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", LINK Reply  Error:%s", err);
+       }
+
+       return offset;
+}
+
+static int
+dissect_nfs2_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_stat(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       proto_item_append_text(tree, ", RENAME Reply");
+                       break;
+               default:
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", RENAME Reply  Error:%s", err);
+       }
+
+       return offset;
+}
+
+static int
+dissect_nfs2_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_stat(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       proto_item_append_text(tree, ", REMOVE Reply");
+                       break;
+               default:
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", REMOVE Reply  Error:%s", err);
+       }
 
        return offset;
 }
@@ -1731,7 +1851,7 @@ dissect_ftype(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
 /* RFC 1094, Page 15 */
 int
 dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
-    char *name)
+    char *name, guint32 *hash)
 {
        proto_item* fitem;
        proto_tree* ftree = NULL;
@@ -1768,7 +1888,7 @@ dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
                }
        }
 
-       dissect_fhandle_data(tvb, offset, pinfo, ftree, FHSIZE, FALSE);
+       dissect_fhandle_data(tvb, offset, pinfo, ftree, FHSIZE, FALSE, hash);
 
        offset += FHSIZE;
        return offset;
@@ -1776,9 +1896,46 @@ dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
 
 /* RFC 1094, Page 15 */
 static int
-dissect_nfs2_fhandle_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_nfs2_statfs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+       guint32 hash;
+
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", STATFS Call FH:0x%08x", hash);
+
+       return offset;
+}
+
+static int
+dissect_nfs2_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       offset = dissect_fhandle(tvb, offset, pinfo, tree, "object");
+       guint32 hash;
+
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
+
+       return offset;
+}
+
+static int
+dissect_nfs2_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+       guint32 hash;
+
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
 
        return offset;
 }
@@ -1881,7 +2038,7 @@ dissect_mode(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
 
 
 /* RFC 1094, Page 15 */
-static int
+int
 dissect_fattr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
 {
        proto_item* fattr_item = NULL;
@@ -1999,26 +2156,32 @@ dissect_filename(tvbuff_t *tvb, int offset,
 
 /* RFC 1094, Page 17 */
 static int
-dissect_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
+dissect_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
 {
-       offset = dissect_rpc_string(tvb, tree, hf, offset, NULL);
+       offset = dissect_rpc_string(tvb, tree, hf, offset, name);
        return offset;
 }
 
 
 /* RFC 1094, Page 17,18 */
 static int
-dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree)
+dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, char *funcname)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_fattr(tvb, offset, tree, "attributes");
+                       proto_item_append_text(tree, ", %s Reply", funcname);
                break;
                default:
-                       /* do nothing */
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", %s Reply  Error:%s", funcname, err);
                break;
        }
 
@@ -2028,9 +2191,25 @@ dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree)
 
 /* RFC 1094, Page 17,18 */
 static int
-dissect_nfs2_attrstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+dissect_nfs2_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
 {
-       offset = dissect_attrstat(tvb, offset, tree);
+       offset = dissect_attrstat(tvb, offset, tree, pinfo, "WRITE");
+
+       return offset;
+}
+
+static int
+dissect_nfs2_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+       offset = dissect_attrstat(tvb, offset, tree, pinfo, "SETATTR");
+
+       return offset;
+}
+
+static int
+dissect_nfs2_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+       offset = dissect_attrstat(tvb, offset, tree, pinfo, "GETATTR");
 
        return offset;
 }
@@ -2038,7 +2217,7 @@ dissect_nfs2_attrstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, p
 
 /* RFC 1094, Page 18 */
 static int
-dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char* name)
+dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char* label, guint32 *hash, char **name)
 {
        proto_item* diropargs_item = NULL;
        proto_tree* diropargs_tree = NULL;
@@ -2046,7 +2225,7 @@ dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
 
        if (tree) {
                diropargs_item = proto_tree_add_text(tree, tvb, offset, -1,
-                       "%s", name);
+                       "%s", label);
                diropargs_tree = proto_item_add_subtree(diropargs_item, ett_nfs_diropargs);
        }
 
@@ -2066,8 +2245,8 @@ dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
                }
        }
 
-       offset = dissect_fhandle (tvb,offset,pinfo,diropargs_tree,"dir");
-       offset = dissect_filename(tvb,offset,      diropargs_tree,hf_nfs_name,NULL);
+       offset = dissect_fhandle(tvb, offset, pinfo, diropargs_tree, "dir", hash);
+       offset = dissect_filename(tvb, offset, diropargs_tree, hf_nfs_name, name);
 
        /* now we know, that diropargs is shorter */
        if (diropargs_item) {
@@ -2080,9 +2259,52 @@ dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
 
 /* RFC 1094, Page 18 */
 static int
-dissect_nfs2_diropargs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_nfs2_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
+       return offset;
+}
+
+static int
+dissect_nfs2_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       offset = dissect_diropargs(tvb, offset, pinfo, tree, "where");
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
+       return offset;
+}
+
+static int
+dissect_nfs2_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
+       g_free(name);
 
        return offset;
 }
@@ -2090,18 +2312,28 @@ dissect_nfs2_diropargs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto
 
 /* RFC 1094, Page 18 */
 static int
-dissect_diropres(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_diropres(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char *funcname)
 {
        guint32 status;
+       guint32 hash;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file");
+                       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
                        offset = dissect_fattr  (tvb, offset, tree, "attributes");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+                       }
+                       proto_item_append_text(tree, ", %s Reply FH:0x%08x", funcname, hash);
                break;
                default:
-                       /* do nothing */
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", %s Reply  Error:%s", funcname, err);
                break;
        }
 
@@ -2120,10 +2352,26 @@ dissect_nfsdata(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
 
 /* RFC 1094, Page 18 */
 static int
-dissect_nfs2_diropres_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_diropres(tvb, offset, pinfo, tree);
+       offset = dissect_diropres(tvb, offset, pinfo, tree, "MKDIR");
+       return offset;
+}
+
+static int
+dissect_nfs2_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       offset = dissect_diropres(tvb, offset, pinfo, tree, "CREATE");
+       return offset;
+}
+
+static int
+dissect_nfs2_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       offset = dissect_diropres(tvb, offset, pinfo, tree, "LOOKUP");
        return offset;
 }
 
@@ -2133,9 +2381,15 @@ static int
 dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file"      );
+       guint32 hash;
+
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
        offset = dissect_sattr  (tvb, offset,        tree, "attributes");
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
        return offset;
 }
 
@@ -2146,14 +2400,25 @@ dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree *tree)
 {
        guint32 status;
+       char *err;
+       char *name=NULL;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_path(tvb, offset, tree, hf_nfs_readlink_data);
+                       offset = dissect_path(tvb, offset, tree, hf_nfs_readlink_data, &name);
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
+                       }
+                       proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
+                       g_free(name);
                break;
                default:
-                       /* do nothing */
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", READLINK Reply  Error:%s", err);
                break;
        }
 
@@ -2169,8 +2434,9 @@ dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        guint32 offset_value;
        guint32 count;
        guint32 totalcount;
+       guint32 hash;
 
-       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file"      );
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
        offset_value = tvb_get_ntohl(tvb, offset+0);
        count        = tvb_get_ntohl(tvb, offset+4);
        totalcount   = tvb_get_ntohl(tvb, offset+8);
@@ -2184,6 +2450,11 @@ dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        }
        offset += 12;
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
+       }
+       proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
+
        return offset;
 }
 
@@ -2194,15 +2465,21 @@ dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_fattr(tvb, offset, tree, "attributes");
+                       proto_item_append_text(tree, ", READ Reply");
                        offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
                break;
                default:
-                       /* do nothing */
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", READ Reply  Error:%s", err);
                break;
        }
 
@@ -2218,8 +2495,9 @@ dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        guint32 beginoffset;
        guint32 offset_value;
        guint32 totalcount;
+       guint32 hash;
 
-       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file"      );
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
        beginoffset  = tvb_get_ntohl(tvb, offset+0);
        offset_value = tvb_get_ntohl(tvb, offset+4);
        totalcount   = tvb_get_ntohl(tvb, offset+8);
@@ -2233,6 +2511,11 @@ dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        }
        offset += 12;
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
+       }
+       proto_item_append_text(tree, ", WRITE Call FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
+
        offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
 
        return offset;
@@ -2241,12 +2524,40 @@ dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 /* RFC 1094, Page 8 */
 static int
-dissect_nfs2_createargs_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree *tree)
+{
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+       offset = dissect_sattr    (tvb, offset,        tree, "attributes");
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
+       return offset;
+}
+
+static int
+dissect_nfs2_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_diropargs(tvb, offset, pinfo, tree, "where"     );
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
        offset = dissect_sattr    (tvb, offset,        tree, "attributes");
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
        return offset;
 }
 
@@ -2256,9 +2567,21 @@ static int
 dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_diropargs(tvb, offset, pinfo, tree, "from");
-       offset = dissect_diropargs(tvb, offset, pinfo, tree, "to"  );
+       guint32 from_hash;
+       char *from_name=NULL;
+       guint32 to_hash;
+       char *to_name=NULL;
 
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+       }
+       proto_item_append_text(tree, ", RENAME Call From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+
+       g_free(from_name);
+       g_free(to_name);
        return offset;
 }
 
@@ -2268,9 +2591,19 @@ static int
 dissect_nfs2_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_fhandle  (tvb, offset, pinfo, tree, "from");
-       offset = dissect_diropargs(tvb, offset, pinfo, tree, "to"  );
+       guint32 from_hash;
+       guint32 to_hash;
+       char *to_name=NULL;
+
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "from", &from_hash);
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+       }
+       proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+
+       g_free(to_name);
        return offset;
 }
 
@@ -2280,9 +2613,20 @@ static int
 dissect_nfs2_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_diropargs(tvb, offset, pinfo, tree, "from"           );
-       offset = dissect_path     (tvb, offset,        tree, hf_nfs_symlink_to);
-       offset = dissect_sattr    (tvb, offset,        tree, "attributes"     );
+       guint32 from_hash;
+       char *from_name=NULL;
+       char *to_name=NULL;
+
+       offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
+       offset = dissect_path(tvb, offset, tree, hf_nfs_symlink_to, &to_name);
+       offset = dissect_sattr(tvb, offset, tree, "attributes");
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+       }
+       proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+       g_free(from_name);
+       g_free(to_name);
 
        return offset;
 }
@@ -2295,8 +2639,9 @@ dissect_nfs2_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
 {
        guint32 cookie;
        guint32 count;
+       guint32 hash;
 
-       offset = dissect_fhandle (tvb, offset, pinfo, tree, "dir");
+       offset = dissect_fhandle(tvb, offset, pinfo, tree, "dir", &hash);
        cookie  = tvb_get_ntohl(tvb, offset+ 0);
        count = tvb_get_ntohl(tvb, offset+ 4);
        if (tree) {
@@ -2307,6 +2652,11 @@ dissect_nfs2_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        }
        offset += 8;
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
+
        return offset;
 }
 
@@ -2363,10 +2713,13 @@ dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 {
        guint32 status;
        guint32 eof_value;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
                case 0:
+                       proto_item_append_text(tree, ", READDIR Reply");
+
                        offset = dissect_rpc_list(tvb, pinfo, tree, offset,
                                dissect_readdir_entry);
                        eof_value = tvb_get_ntohl(tvb, offset+0);
@@ -2376,7 +2729,11 @@ dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        offset += 4;
                break;
                default:
-                       /* do nothing */
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", READDIR Reply  Error:%s", err);
                break;
        }
 
@@ -2395,6 +2752,7 @@ dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        guint32 blocks;
        guint32 bfree;
        guint32 bavail;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
@@ -2417,9 +2775,14 @@ dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
                                        offset+16, 4, bavail);
                        }
                        offset += 20;
+                       proto_item_append_text(tree, ", STATFS Reply");
                break;
                default:
-                       /* do nothing */
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", STATFS Reply  Error:%s", err);
                break;
        }
 
@@ -2433,41 +2796,64 @@ static const vsff nfs2_proc[] = {
        { 0,    "NULL",         /* OK */
        NULL,                           NULL },
        { 1,    "GETATTR",      /* OK */
-       dissect_nfs2_fhandle_call,      dissect_nfs2_attrstat_reply },
+       dissect_nfs2_getattr_call,      dissect_nfs2_getattr_reply },
        { 2,    "SETATTR",      /* OK */
-       dissect_nfs2_setattr_call,      dissect_nfs2_attrstat_reply },
+       dissect_nfs2_setattr_call,      dissect_nfs2_setattr_reply },
        { 3,    "ROOT",         /* OK */
        NULL,                           NULL },
        { 4,    "LOOKUP",       /* OK */
-       dissect_nfs2_diropargs_call,    dissect_nfs2_diropres_reply },
+       dissect_nfs2_lookup_call,       dissect_nfs2_lookup_reply },
        { 5,    "READLINK",     /* OK */
-       dissect_nfs2_fhandle_call,      dissect_nfs2_readlink_reply },
+       dissect_nfs2_readlink_call,     dissect_nfs2_readlink_reply },
        { 6,    "READ",         /* OK */
        dissect_nfs2_read_call,         dissect_nfs2_read_reply },
        { 7,    "WRITECACHE",   /* OK */
        NULL,                           NULL },
        { 8,    "WRITE",        /* OK */
-       dissect_nfs2_write_call,        dissect_nfs2_attrstat_reply },
+       dissect_nfs2_write_call,        dissect_nfs2_write_reply },
        { 9,    "CREATE",       /* OK */
-       dissect_nfs2_createargs_call,   dissect_nfs2_diropres_reply },
+       dissect_nfs2_create_call,       dissect_nfs2_create_reply },
        { 10,   "REMOVE",       /* OK */
-       dissect_nfs2_diropargs_call,    dissect_nfs2_stat_reply },
+       dissect_nfs2_remove_call,       dissect_nfs2_remove_reply },
        { 11,   "RENAME",       /* OK */
-       dissect_nfs2_rename_call,       dissect_nfs2_stat_reply },
+       dissect_nfs2_rename_call,       dissect_nfs2_rename_reply },
        { 12,   "LINK",         /* OK */
-       dissect_nfs2_link_call,         dissect_nfs2_stat_reply },
+       dissect_nfs2_link_call,         dissect_nfs2_link_reply },
        { 13,   "SYMLINK",      /* OK */
-       dissect_nfs2_symlink_call,      dissect_nfs2_stat_reply },
+       dissect_nfs2_symlink_call,      dissect_nfs2_symlink_reply },
        { 14,   "MKDIR",        /* OK */
-       dissect_nfs2_createargs_call,   dissect_nfs2_diropres_reply },
+       dissect_nfs2_mkdir_call,        dissect_nfs2_mkdir_reply },
        { 15,   "RMDIR",        /* OK */
-       dissect_nfs2_diropargs_call,    dissect_nfs2_stat_reply },
+       dissect_nfs2_rmdir_call,        dissect_nfs2_rmdir_reply },
        { 16,   "READDIR",      /* OK */
        dissect_nfs2_readdir_call,      dissect_nfs2_readdir_reply },
        { 17,   "STATFS",       /* OK */
-       dissect_nfs2_fhandle_call,      dissect_nfs2_statfs_reply },
+       dissect_nfs2_statfs_call,       dissect_nfs2_statfs_reply },
        { 0,NULL,NULL,NULL }
 };
+
+static const value_string nfsv2_proc_vals[] = {
+       { 0,    "NULL" },
+       { 1,    "GETATTR" },
+       { 2,    "SETATTR" },
+       { 3,    "ROOT" },
+       { 4,    "LOOKUP" },
+       { 5,    "READLINK" },
+       { 6,    "READ" },
+       { 7,    "WRITECACHE" },
+       { 8,    "WRITE" },
+       { 9,    "CREATE" },
+       { 10,   "REMOVE" },
+       { 11,   "RENAME" },
+       { 12,   "LINK" },
+       { 13,   "SYMLINK" },
+       { 14,   "MKDIR" },
+       { 15,   "RMDIR" },
+       { 16,   "READDIR" },
+       { 17,   "STATFS" },
+       { 0,    NULL }
+};
+
 /* end of NFS Version 2 */
 
 
@@ -2488,9 +2874,9 @@ dissect_filename3(tvbuff_t *tvb, int offset,
 
 /* RFC 1813, Page 15 */
 static int
-dissect_nfspath3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
+dissect_nfspath3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
 {
-       offset = dissect_rpc_string(tvb, tree, hf, offset, NULL);
+       offset = dissect_rpc_string(tvb, tree, hf, offset, name);
        return offset;
 }
 
@@ -2699,7 +3085,7 @@ dissect_specdata3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
 /* RFC 1813, Page 21 */
 int
 dissect_nfs_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
-       proto_tree *tree, char *name)
+       proto_tree *tree, char *name, guint32 *hash)
 {
        guint fh3_len;
        guint fh3_len_full;
@@ -2750,9 +3136,17 @@ dissect_nfs_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
        proto_tree_add_uint(ftree, hf_nfs_fh_length, tvb, offset+0, 4,
                        fh3_len);
-       dissect_fhandle_data(tvb, offset+4, pinfo, ftree, fh3_len, FALSE);
 
-       offset += 4 + fh3_len_full;
+       /* Handle WebNFS requests where filehandle may be 0 length */
+       if (fh3_len > 0)
+       {
+               dissect_fhandle_data(tvb, offset+4, pinfo, ftree, fh3_len, FALSE, hash);
+
+               offset += fh3_len_full;
+       }
+
+       offset += 4;
+
        return offset;
 }
 
@@ -2793,8 +3187,8 @@ dissect_nfstime3(tvbuff_t *tvb, int offset,
 
 
 /* RFC 1813, Page 22 */
-static int
-dissect_fattr3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+int
+dissect_nfs_fattr3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
 {
        proto_item* fattr3_item = NULL;
        proto_tree* fattr3_tree = NULL;
@@ -2846,8 +3240,9 @@ static const value_string value_follows[] =
 
 
 /* RFC 1813, Page 23 */
-static int
-dissect_post_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+int
+dissect_nfs_post_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, 
+               char* name)
 {
        proto_item* post_op_attr_item = NULL;
        proto_tree* post_op_attr_tree = NULL;
@@ -2868,7 +3263,7 @@ dissect_post_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
        offset += 4;
        switch (attributes_follow) {
                case TRUE:
-                       offset = dissect_fattr3(tvb, offset, post_op_attr_tree,
+                       offset = dissect_nfs_fattr3(tvb, offset, post_op_attr_tree,
                                        "attributes");
                break;
                case FALSE:
@@ -2969,7 +3364,7 @@ dissect_wcc_data(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
        }
 
        offset = dissect_pre_op_attr (tvb, offset, wcc_data_tree, "before");
-       offset = dissect_post_op_attr(tvb, offset, wcc_data_tree, "after" );
+       offset = dissect_nfs_post_op_attr(tvb, offset, wcc_data_tree, "after" );
 
        /* now we know, that wcc_data is shorter */
        if (wcc_data_item) {
@@ -3005,7 +3400,7 @@ dissect_post_op_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
        switch (handle_follows) {
                case TRUE:
                        offset = dissect_nfs_fh3(tvb, offset, pinfo, post_op_fh3_tree,
-                                       "handle");
+                                       "handle", NULL);
                break;
                case FALSE:
                        /* void */
@@ -3342,7 +3737,7 @@ dissect_sattr3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
 /* RFC 1813, Page 27 */
 static int
 dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo,
-       proto_tree *tree, char* name)
+       proto_tree *tree, char* label, guint32 *hash, char **name)
 {
        proto_item* diropargs3_item = NULL;
        proto_tree* diropargs3_tree = NULL;
@@ -3352,18 +3747,18 @@ dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
        if (tree) {
                diropargs3_item = proto_tree_add_text(tree, tvb, offset, -1,
-                       "%s", name);
+                       "%s", label);
                diropargs3_tree = proto_item_add_subtree(diropargs3_item,
                        ett_nfs_diropargs3);
        }
 
        parent_offset=offset+4;
        parent_len=tvb_get_ntohl(tvb, offset);
-       offset = dissect_nfs_fh3(tvb, offset, pinfo, diropargs3_tree, "dir");
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, diropargs3_tree, "dir", hash);
        name_offset=offset+4;
        name_len=tvb_get_ntohl(tvb, offset);
        offset = dissect_filename3(tvb, offset, diropargs3_tree,
-               hf_nfs_name, NULL);
+               hf_nfs_name, name);
 
        /* are we snooping fh to filenames ?*/
        if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
@@ -3390,20 +3785,63 @@ dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo,
        return offset;
 }
 
+static int
+dissect_nfs3_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree *tree)
+{
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
+       return offset;
+}
 
-/* RFC 1813, Page 27 */
 static int
-dissect_nfs3_diropargs3_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_null_call(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
        proto_tree *tree)
 {
-       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object");
+       proto_item_append_text(tree, ", NULL Call");
 
        return offset;
 }
 
+static int
+dissect_nfs3_null_reply(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
+       proto_tree *tree)
+{
+       proto_item_append_text(tree, ", NULL Reply");
+
+       return offset;
+}
 
-/* RFC 1813, Page 40 */
 static int
+dissect_nfs3_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree *tree)
+{
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
+       return offset;
+}
+
+
+/* RFC 1813, Page 40 */
+int
 dissect_access(tvbuff_t *tvb, int offset, proto_tree *tree,
        char* name)
 {
@@ -3440,22 +3878,20 @@ dissect_access(tvbuff_t *tvb, int offset, proto_tree *tree,
 }
 
 
-/* NFS3 file handle dissector */
-static int
-dissect_nfs3_nfs_fh3_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
-       proto_tree* tree)
-{
-       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
-       return offset;
-}
-
-
 /* RFC 1813, Page 32,33 */
 static int
 dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
+
        return offset;
 }
 
@@ -3466,14 +3902,22 @@ dissect_nfs3_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_fattr3(tvb, offset, tree, "obj_attributes");
+                       offset = dissect_nfs_fattr3(tvb, offset, tree, "obj_attributes");
+                       proto_item_append_text(tree, ", GETATTR Reply");
                break;
                default:
                        /* void */
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", GETATTR Reply  Error:%s", err);
                break;
        }
 
@@ -3531,9 +3975,17 @@ static int
 dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "object");
+       guint32 hash;
+
+       offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "object", &hash);
        offset = dissect_sattr3     (tvb, offset,        tree, "new_attributes");
        offset = dissect_sattrguard3(tvb, offset,        tree, "guard");
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
+
        return offset;
 }
 
@@ -3544,14 +3996,22 @@ dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_wcc_data(tvb, offset, tree, "obj_wcc");
+                       proto_item_append_text(tree, ", SETATTR Reply");
                break;
                default:
                        offset = dissect_wcc_data(tvb, offset, tree, "obj_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", SETATTR Reply  Error:%s", err);
                break;
        }
 
@@ -3564,7 +4024,17 @@ static int
 dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what");
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what", &hash, &name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
        return offset;
 }
 
@@ -3575,19 +4045,32 @@ dissect_nfs3_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
+       guint32 hash;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "dir_attributes");
+
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+                       }
+                       proto_item_append_text(tree, ", LOOKUP Reply FH:0x%08x", hash);
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "dir_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", LOOKUP Reply  Error:%s", err);
                break;
        }
 
@@ -3600,9 +4083,16 @@ static int
 dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
        offset = dissect_access (tvb, offset,        tree, "access");
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", ACCESS Call FH:0x%08x", hash);
+
        return offset;
 }
 
@@ -3613,17 +4103,26 @@ dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
                        offset = dissect_access(tvb, offset, tree, "access");
+
+                       proto_item_append_text(tree, ", ACCESS Reply");
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", ACCESS Reply  Error:%s", err);
                break;
        }
 
@@ -3633,22 +4132,51 @@ dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* RFC 1813, Page 44,45 */
 static int
+dissect_nfs3_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
+
+       return offset;
+}
+static int
 dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
+       char *name=NULL;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "symlink_attributes");
                        offset = dissect_nfspath3(tvb, offset, tree,
-                               hf_nfs_readlink_data);
+                               hf_nfs_readlink_data, &name);
+
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
+                       }
+                       proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
+                       g_free(name);
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "symlink_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", READLINK Reply  Error:%s", err);
                break;
        }
 
@@ -3661,10 +4189,24 @@ static int
 dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file");
+       unsigned char *off;
+       guint32 len;
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
+
+       off=u64toa(tvb_get_ptr(tvb, offset, 8));
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
+
+       len=tvb_get_ntohl(tvb, offset);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
 
+       
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%s Len:%d", hash, off, len);
+       }
+       proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%s Len:%d", hash, off, len);
+
        return offset;
 }
 
@@ -3675,21 +4217,34 @@ dissect_nfs3_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       guint32 len;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "file_attributes");
+                       len=tvb_get_ntohl(tvb, offset);
                        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
                                offset);
                        offset = dissect_rpc_bool(tvb, tree, hf_nfs_read_eof,
                                offset);
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d", len);
+                       }
+                       proto_item_append_text(tree, ", READ Reply Len:%d", len);
                        offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "file_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", READ Reply  Error:%s", err);
                break;
        }
 
@@ -3728,10 +4283,27 @@ static int
 dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file");
+       unsigned char *off;
+       guint32 len;
+       guint32 stable;
+       guint32 hash;
+
+       offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file", &hash);
+
+       off=u64toa(tvb_get_ptr(tvb, offset, 8));
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
+
+       len=tvb_get_ntohl(tvb, offset);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
+
+       stable=tvb_get_ntohl(tvb, offset);
        offset = dissect_stable_how(tvb, offset, tree, hf_nfs_write_stable);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%s Len:%d %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
+       }
+       proto_item_append_text(tree, ", WRITE Call FH:0x%08x Offset:%s Len:%d %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
+
        offset = dissect_nfsdata   (tvb, offset, tree, hf_nfs_data);
 
        return offset;
@@ -3744,19 +4316,35 @@ dissect_nfs3_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       guint32 len;
+       guint32 stable;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_wcc_data  (tvb, offset, tree, "file_wcc");
+                       len=tvb_get_ntohl(tvb, offset);
                        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
                                offset);
+                       stable=tvb_get_ntohl(tvb, offset);
                        offset = dissect_stable_how(tvb, offset, tree,
                                hf_nfs_write_committed);
                        offset = dissect_writeverf3(tvb, offset, tree);
+
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
+                       }
+                       proto_item_append_text(tree, ", WRITE Reply Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
                break;
                default:
                        offset = dissect_wcc_data(tvb, offset, tree, "file_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", WRITE Reply  Error:%s", err);
                break;
        }
 
@@ -3797,8 +4385,10 @@ dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
        guint32 mode;
+       guint32 hash;
+       char *name=NULL;
 
-       offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where");
+       offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where", &hash, &name);
        offset = dissect_createmode3(tvb, offset, tree, &mode);
        switch (mode) {
                case UNCHECKED:
@@ -3810,6 +4400,12 @@ dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
                break;
        }
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
+       }
+       proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
+       g_free(name);
+
        return offset;
 }
 
@@ -3820,17 +4416,25 @@ dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
                        offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       proto_item_append_text(tree, ", CREATE Reply");
                break;
                default:
                        offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", CREATE Reply  Error:%s", err);
                break;
        }
 
@@ -3843,9 +4447,48 @@ static int
 dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where");
+       guint32 hash;
+       char *name=NULL;
+
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
        offset = dissect_sattr3    (tvb, offset, tree, "attributes");
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+       }
+       proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
+       g_free(name);
+
+       return offset;
+}
+
+static int
+dissect_nfs3_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_nfsstat3(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+                               "obj_attributes");
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       proto_item_append_text(tree, ", MKDIR Reply");
+               break;
+               default:
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", MKDIR Reply  Error:%s", err);
+               break;
+       }
+
        return offset;
 }
 
@@ -3855,9 +4498,49 @@ static int
 dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where");
+       guint32 from_hash;
+       char *from_name=NULL;
+       char *to_name=NULL;
+
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &from_hash, &from_name);
        offset = dissect_sattr3    (tvb, offset,        tree, "symlink_attributes");
-       offset = dissect_nfspath3  (tvb, offset,        tree, hf_nfs_symlink_to);
+       offset = dissect_nfspath3  (tvb, offset,        tree, hf_nfs_symlink_to, &to_name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+       }
+       proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+       g_free(from_name);
+       g_free(to_name);
+
+       return offset;
+}
+static int
+dissect_nfs3_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_nfsstat3(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+                               "obj_attributes");
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       proto_item_append_text(tree, ", SYMLINK Reply");
+               break;
+               default:
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", SYMLINK Reply  Error:%s", err);
+               break;
+       }
 
        return offset;
 }
@@ -3869,8 +4552,11 @@ dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
        guint32 type;
+       guint32 hash;
+       char *name=NULL;
+       char *type_str;
 
-       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where");
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
        offset = dissect_ftype3(tvb, offset, tree, hf_nfs_ftype3, &type);
        switch (type) {
                case NF3CHR:
@@ -3887,6 +4573,42 @@ dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
                break;
        }
 
+       type_str=val_to_str(type, names_nfs_ftype3, "Unknown type:%u");
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x/%s %s", hash, name, type_str);
+       }
+       proto_item_append_text(tree, ", MKNOD Call FH:0x%08x/%s %s", hash, name, type_str);
+       g_free(name);
+
+       return offset;
+}
+static int
+dissect_nfs3_mknod_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_nfsstat3(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+                               "obj_attributes");
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       proto_item_append_text(tree, ", MKNOD Reply");
+               break;
+               default:
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", MKNOD Reply  Error:%s", err);
+               break;
+       }
+
        return offset;
 }
 
@@ -3897,14 +4619,46 @@ dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       proto_item_append_text(tree, ", REMOVE Reply");
                break;
                default:
                        offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", REMOVE Reply  Error:%s", err);
+               break;
+       }
+
+       return offset;
+}
+static int
+dissect_nfs3_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+       proto_tree* tree)
+{
+       guint32 status;
+       char *err;
+
+       offset = dissect_nfsstat3(tvb, offset, tree, &status);
+       switch (status) {
+               case 0:
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       proto_item_append_text(tree, ", RMDIR Reply");
+               break;
+               default:
+                       offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", RMDIR Reply  Error:%s", err);
                break;
        }
 
@@ -3917,9 +4671,21 @@ static int
 dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from");
-       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to");
+       guint32 from_hash;
+       char *from_name=NULL;
+       guint32 to_hash;
+       char *to_name=NULL;
 
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+       }
+       proto_item_append_text(tree, ", RENAME Call From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+
+       g_free(from_name);
+       g_free(to_name);
        return offset;
 }
 
@@ -3930,16 +4696,24 @@ dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_wcc_data(tvb, offset, tree, "fromdir_wcc");
                        offset = dissect_wcc_data(tvb, offset, tree, "todir_wcc");
+                       proto_item_append_text(tree, ", RENAME Reply");
                break;
                default:
                        offset = dissect_wcc_data(tvb, offset, tree, "fromdir_wcc");
                        offset = dissect_wcc_data(tvb, offset, tree, "todir_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", RENAME Reply  Error:%s", err);
                break;
        }
 
@@ -3952,9 +4726,19 @@ static int
 dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file");
-       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link");
+       guint32 from_hash;
+       guint32 to_hash;
+       char *to_name=NULL;
 
+       offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file", &from_hash);
+       offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link", &to_hash, &to_name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+       }
+       proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+
+       g_free(to_name);
        return offset;
 }
 
@@ -3965,18 +4749,26 @@ dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "file_attributes");
                        offset = dissect_wcc_data(tvb, offset, tree, "linkdir_wcc");
+                       proto_item_append_text(tree, ", LINK Reply");
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "file_attributes");
                        offset = dissect_wcc_data(tvb, offset, tree, "linkdir_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", LINK Reply  Error:%s", err);
                break;
        }
 
@@ -3989,11 +4781,18 @@ static int
 dissect_nfs3_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir");
+       guint32 hash;
+
+       offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir", &hash);
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
        offset = dissect_cookieverf3(tvb, offset, tree);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
+
        return offset;
 }
 
@@ -4006,7 +4805,7 @@ dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_item* entry_item = NULL;
        proto_tree* entry_tree = NULL;
        int old_offset = offset;
-       char *name;
+       char *name=NULL;
 
        if (tree) {
                entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
@@ -4021,6 +4820,10 @@ dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
                hf_nfs_readdir_entry3_name, &name);
        if (entry_item)
                proto_item_set_text(entry_item, "Entry: name %s", name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
+       }
        g_free(name);
 
        offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdir_entry3_cookie,
@@ -4042,11 +4845,14 @@ dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 {
        guint32 status;
        guint32 eof_value;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       proto_item_append_text(tree, ", READDIR Reply");
+
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "dir_attributes");
                        offset = dissect_cookieverf3(tvb, offset, tree);
                        offset = dissect_rpc_list(tvb, pinfo, tree, offset,
@@ -4058,8 +4864,14 @@ dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        offset += 4;
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "dir_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", READDIR Reply  Error:%s", err);
                break;
        }
 
@@ -4072,7 +4884,9 @@ static int
 dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir");
+       guint32 hash;
+
+       offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir", &hash);
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
        offset = dissect_cookieverf3(tvb, offset, tree);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_dircount,
@@ -4080,6 +4894,11 @@ dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_maxcount,
                offset);
 
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", READDIRPLUS Call FH:0x%08x", hash);
+
        return offset;
 }
 
@@ -4092,7 +4911,7 @@ dissect_entryplus3(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_item* entry_item = NULL;
        proto_tree* entry_tree = NULL;
        int old_offset = offset;
-       char *name;
+       char *name=NULL;
 
        if (tree) {
                entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
@@ -4107,12 +4926,16 @@ dissect_entryplus3(tvbuff_t *tvb, int offset, packet_info *pinfo,
                hf_nfs_readdirplus_entry_name, &name);
        if (entry_item)
                proto_item_set_text(entry_item, "Entry: name %s", name);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
+       }
        g_free(name);
 
        offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdirplus_entry_cookie,
                offset);
 
-       offset = dissect_post_op_attr(tvb, offset, entry_tree,
+       offset = dissect_nfs_post_op_attr(tvb, offset, entry_tree,
                "name_attributes");
        offset = dissect_post_op_fh3(tvb, offset, pinfo, entry_tree, "name_handle");
 
@@ -4132,11 +4955,14 @@ dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 {
        guint32 status;
        guint32 eof_value;
+       char *err;
 
        offset = dissect_stat(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       proto_item_append_text(tree, ", READDIRPLUS Reply");
+
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "dir_attributes");
                        offset = dissect_cookieverf3(tvb, offset, tree);
                        offset = dissect_rpc_list(tvb, pinfo, tree, offset,
@@ -4148,8 +4974,14 @@ dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        offset += 4;
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "dir_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", READDIRPLUS Reply  Error:%s", err);
                break;
        }
 
@@ -4158,17 +4990,34 @@ dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 /* RFC 1813, Page 84..86 */
+static int
+dissect_nfs3_fsstat_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", FSSTAT Call DH:0x%08x", hash);
+       return offset;
+}
+
+
 static int
 dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
        guint32 invarsec;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
                        offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_tbytes,
                                offset);
@@ -4187,10 +5036,18 @@ dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
                                proto_tree_add_uint(tree, hf_nfs_fsstat_invarsec, tvb,
                                offset+0, 4, invarsec);
                        offset += 4;
+
+                       proto_item_append_text(tree, ", FSSTAT Reply");
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", FSSTAT Reply  Error:%s", err);
                break;
        }
 
@@ -4206,6 +5063,20 @@ dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* RFC 1813, Page 86..90 */
 static int
+dissect_nfs3_fsinfo_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", FSINFO Call DH:0x%08x", hash);
+       return offset;
+}
+static int
 dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
@@ -4220,11 +5091,12 @@ dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        guint32 properties;
        proto_item*     properties_item = NULL;
        proto_tree*     properties_tree = NULL;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
                        rtmax = tvb_get_ntohl(tvb, offset+0);
                        if (tree)
@@ -4304,10 +5176,18 @@ dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
                                }
                        }
                        offset += 4;
+
+                       proto_item_append_text(tree, ", FSINFO Reply");
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", FSINFO Reply  Error:%s", err);
                break;
        }
 
@@ -4317,17 +5197,32 @@ dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
 
 /* RFC 1813, Page 90..92 */
 static int
+dissect_nfs3_pathconf_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree* tree)
+{
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", PATHCONF Call DH:0x%08x", hash);
+       return offset;
+}
+static int
 dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
        guint32 linkmax;
        guint32 name_max;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
                        linkmax = tvb_get_ntohl(tvb, offset + 0);
                        if (tree)
@@ -4347,10 +5242,18 @@ dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
                                hf_nfs_pathconf_case_insensitive, offset);
                        offset = dissect_rpc_bool(tvb, tree,
                                hf_nfs_pathconf_case_preserving, offset);
+
+                       proto_item_append_text(tree, ", PATHCONF Reply");
                break;
                default:
-                       offset = dissect_post_op_attr(tvb, offset, tree,
+                       offset = dissect_nfs_post_op_attr(tvb, offset, tree,
                                "obj_attributes");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", PATHCONF Reply  Error:%s", err);
                break;
        }
 
@@ -4363,9 +5266,17 @@ static int
 dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree* tree)
 {
-       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file");
+       guint32 hash;
+
+       offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
        offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+       }
+       proto_item_append_text(tree, ", COMMIT Call FH:0x%08x", hash);
+
        return offset;
 }
 
@@ -4376,15 +5287,24 @@ dissect_nfs3_commit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
        proto_tree* tree)
 {
        guint32 status;
+       char *err;
 
        offset = dissect_nfsstat3(tvb, offset, tree, &status);
        switch (status) {
                case 0:
                        offset = dissect_wcc_data  (tvb, offset, tree, "file_wcc");
                        offset = dissect_writeverf3(tvb, offset, tree);
+
+                       proto_item_append_text(tree, ", COMMIT Reply");
                break;
                default:
                        offset = dissect_wcc_data(tvb, offset, tree, "file_wcc");
+
+                       err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+                       }
+                       proto_item_append_text(tree, ", COMMIT Reply  Error:%s", err);
                break;
        }
 
@@ -4749,7 +5669,7 @@ static int
 dissect_nfs_fh4(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree, char *name)
 {
-       return dissect_nfs_fh3(tvb, offset, pinfo, tree, name);
+       return dissect_nfs_fh3(tvb, offset, pinfo, tree, name, NULL);
 }
 
 static int
@@ -5985,7 +6905,8 @@ dissect_nfs_open_delegation4(tvbuff_t *tvb, int offset, packet_info *pinfo,
 static int
 dissect_nfs_rpcsec_gss_info(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_sec_oid4);
+       offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
+            hf_nfs_sec_oid4, FALSE, 0, FALSE, NULL, NULL);
        offset = dissect_rpc_uint32(tvb, tree, hf_nfs_qop4, offset);
        offset = dissect_rpc_uint32(tvb, tree,
                hf_nfs_secinfo_rpcsec_gss_info_service, offset);
@@ -6418,7 +7339,7 @@ dissect_nfs_resop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
                /*
                 * With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT, and
                 * NFS4_OP_SETATTR, all other ops do *not* return data with the
-                * failed status code.
+                * failed status code. 
                 */
                if ((status != NFS4_OK) &&
                        ((opcode != NFS4_OP_LOCK) && (opcode != NFS4_OP_LOCKT) &&
@@ -6522,8 +7443,8 @@ dissect_nfs_resop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        break;
 
                case NFS4_OP_SECINFO:
-                       offset = dissect_rpc_list(tvb, pinfo, tree, offset,
-                               dissect_nfs_secinfo4_res);
+                       offset = dissect_rpc_array(tvb, pinfo, newftree, offset,
+                               dissect_nfs_secinfo4_res, hf_nfs_secinfo_arr4);
                        break;
 
                case NFS4_OP_SETATTR:
@@ -6579,7 +7500,7 @@ dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
 /* NULL as function pointer means: type of arguments is "void". */
 static const vsff nfs3_proc[] = {
        { 0,    "NULL",         /* OK */
-       NULL,                           NULL },
+       dissect_nfs3_null_call,         dissect_nfs3_null_reply },
        { 1,    "GETATTR",      /* OK */
        dissect_nfs3_getattr_call,      dissect_nfs3_getattr_reply },
        { 2,    "SETATTR",      /* OK */
@@ -6589,7 +7510,7 @@ static const vsff nfs3_proc[] = {
        { 4,    "ACCESS",       /* OK */
        dissect_nfs3_access_call,       dissect_nfs3_access_reply },
        { 5,    "READLINK",     /* OK */
-       dissect_nfs3_nfs_fh3_call,      dissect_nfs3_readlink_reply },
+       dissect_nfs3_readlink_call,     dissect_nfs3_readlink_reply },
        { 6,    "READ",         /* OK */
        dissect_nfs3_read_call,         dissect_nfs3_read_reply },
        { 7,    "WRITE",        /* OK */
@@ -6597,15 +7518,15 @@ static const vsff nfs3_proc[] = {
        { 8,    "CREATE",       /* OK */
        dissect_nfs3_create_call,       dissect_nfs3_create_reply },
        { 9,    "MKDIR",        /* OK */
-       dissect_nfs3_mkdir_call,        dissect_nfs3_create_reply },
+       dissect_nfs3_mkdir_call,        dissect_nfs3_mkdir_reply },
        { 10,   "SYMLINK",      /* OK */
-       dissect_nfs3_symlink_call,      dissect_nfs3_create_reply },
+       dissect_nfs3_symlink_call,      dissect_nfs3_symlink_reply },
        { 11,   "MKNOD",        /* OK */
-       dissect_nfs3_mknod_call,        dissect_nfs3_create_reply },
+       dissect_nfs3_mknod_call,        dissect_nfs3_mknod_reply },
        { 12,   "REMOVE",       /* OK */
-       dissect_nfs3_diropargs3_call,   dissect_nfs3_remove_reply },
+       dissect_nfs3_remove_call,       dissect_nfs3_remove_reply },
        { 13,   "RMDIR",        /* OK */
-       dissect_nfs3_diropargs3_call,   dissect_nfs3_remove_reply },
+       dissect_nfs3_rmdir_call,        dissect_nfs3_rmdir_reply },
        { 14,   "RENAME",       /* OK */
        dissect_nfs3_rename_call,       dissect_nfs3_rename_reply },
        { 15,   "LINK",         /* OK */
@@ -6615,15 +7536,42 @@ static const vsff nfs3_proc[] = {
        { 17,   "READDIRPLUS",  /* OK */
        dissect_nfs3_readdirplus_call,  dissect_nfs3_readdirplus_reply },
        { 18,   "FSSTAT",       /* OK */
-       dissect_nfs3_nfs_fh3_call,      dissect_nfs3_fsstat_reply },
+       dissect_nfs3_fsstat_call,       dissect_nfs3_fsstat_reply },
        { 19,   "FSINFO",       /* OK */
-       dissect_nfs3_nfs_fh3_call,      dissect_nfs3_fsinfo_reply },
+       dissect_nfs3_fsinfo_call,       dissect_nfs3_fsinfo_reply },
        { 20,   "PATHCONF",     /* OK */
-       dissect_nfs3_nfs_fh3_call,      dissect_nfs3_pathconf_reply },
+       dissect_nfs3_pathconf_call,     dissect_nfs3_pathconf_reply },
        { 21,   "COMMIT",       /* OK */
        dissect_nfs3_commit_call,       dissect_nfs3_commit_reply },
        { 0,NULL,NULL,NULL }
 };
+
+static const value_string nfsv3_proc_vals[] = {
+       { 0,    "NULL" },
+       { 1,    "GETATTR" },
+       { 2,    "SETATTR" },
+       { 3,    "LOOKUP" },
+       { 4,    "ACCESS" },
+       { 5,    "READLINK" },
+       { 6,    "READ" },
+       { 7,    "WRITE" },
+       { 8,    "CREATE" },
+       { 9,    "MKDIR" },
+       { 10,   "SYMLINK" },
+       { 11,   "MKNOD" },
+       { 12,   "REMOVE" },
+       { 13,   "RMDIR" },
+       { 14,   "RENAME" },
+       { 15,   "LINK" },
+       { 16,   "READDIR" },
+       { 17,   "READDIRPLUS" },
+       { 18,   "FSSTAT" },
+       { 19,   "FSINFO" },
+       { 20,   "PATHCONF" },
+       { 21,   "COMMIT" },
+       { 0,    NULL }
+};
+
 /* end of NFS Version 3 */
 
 static const vsff nfs4_proc[] = {
@@ -6634,6 +7582,11 @@ static const vsff nfs4_proc[] = {
        { 0, NULL, NULL, NULL }
 };
 
+static const value_string nfsv4_proc_vals[] = {
+       { 0, "NULL" },
+       { 1, "COMPOUND" },
+       { 0, NULL }
+};
 
 static struct true_false_string yesno = { "Yes", "No" };
 
@@ -6642,6 +7595,15 @@ void
 proto_register_nfs(void)
 {
        static hf_register_info hf[] = {
+               { &hf_nfs_procedure_v2, {
+                       "V2 Procedure", "nfs.procedure_v2", FT_UINT32, BASE_DEC,
+                       VALS(nfsv2_proc_vals), 0, "V2 Procedure", HFILL }},
+               { &hf_nfs_procedure_v3, {
+                       "V3 Procedure", "nfs.procedure_v3", FT_UINT32, BASE_DEC,
+                       VALS(nfsv3_proc_vals), 0, "V3 Procedure", HFILL }},
+               { &hf_nfs_procedure_v4, {
+                       "V4 Procedure", "nfs.procedure_v4", FT_UINT32, BASE_DEC,
+                       VALS(nfsv4_proc_vals), 0, "V4 Procedure", HFILL }},
                { &hf_nfs_fh_length, {
                        "length", "nfs.fh.length", FT_UINT32, BASE_DEC,
                        NULL, 0, "file handle length", HFILL }},
@@ -7526,6 +8488,10 @@ proto_register_nfs(void)
                { &hf_nfs_r_addr, {
                        "r_addr", "nfs.r_addr", FT_BYTES, BASE_DEC, NULL, 0,
                        "r_addr", HFILL }},
+
+               { &hf_nfs_secinfo_arr4, {
+                       "Flavors Info", "nfs.flavors.info", FT_NONE, BASE_NONE,
+                       NULL, 0, "Flavors Info", HFILL }},
        };
 
        static gint *ett[] = {
@@ -7659,7 +8625,7 @@ proto_reg_handoff_nfs(void)
        /* Register the protocol as RPC */
        rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
        /* Register the procedure tables */
-       rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc);
-       rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc);
-       rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc);
+       rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc, hf_nfs_procedure_v2);
+       rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc, hf_nfs_procedure_v3);
+       rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc, hf_nfs_procedure_v4);
 }