Clean up white space.
[obnox/wireshark/wip.git] / packet-mount.c
index 4a8193a6478f1d156d5111198206ccbe50b3d74b..56644c8491edb9cd12a8378c120c157adf0ca3aa 100644 (file)
@@ -1,10 +1,10 @@
 /* packet-mount.c
  * Routines for mount dissection
  *
- * $Id: packet-mount.c,v 1.19 2001/01/18 09:55:09 guy Exp $
+ * $Id: packet-mount.c,v 1.31 2002/04/15 08:55:03 girlich Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Copied from packet-smb.c
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #endif
 
+#include <string.h>
 
 #include "packet-rpc.h"
 #include "packet-mount.h"
@@ -41,7 +42,7 @@
 
 static int proto_mount = -1;
 static int hf_mount_path = -1;
-static int hf_mount_status = -1;
+static int hf_mount3_status = -1;
 static int hf_mount_mountlist_hostname = -1;
 static int hf_mount_mountlist_directory = -1;
 static int hf_mount_mountlist = -1;
@@ -76,23 +77,29 @@ static gint ett_mount_groups = -1;
 static gint ett_mount_exportlist = -1;
 static gint ett_mount_pathconf_mask = -1;
 
+#define MAX_GROUP_NAME_LIST 128
+static char group_name_list[MAX_GROUP_NAME_LIST];
+static int  group_names_len;
 
 /* RFC 1094, Page 24 */
+/* This function dissects fhstatus for v1 and v2 of the mount protocol.
+ * Formally, hf_mount3_status only define the status codes returned by version
+ * 3 of the protocol. 
+ * Though not formally defined in the standard, we use the same 
+ * value-to-string mappings as version 3 since we belive that this mapping 
+ * is consistant with most v1 and v2 implementations.
+ */
 static int
-dissect_fhstatus(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+dissect_fhstatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       guint32 status;
+       gint32 status;
 
-       if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
-       status = EXTRACT_UINT(pd, offset+0);
-       if (tree) {
-               proto_tree_add_uint(tree, hf_mount_status, NullTVB, offset, 4, status);
-       }
-       offset += 4;
+       status=tvb_get_ntohl(tvb,offset);
+       offset = dissect_rpc_uint32(tvb,tree,hf_mount3_status,offset);
 
        switch (status) {
                case 0:
-                       offset = dissect_fhandle(pd,offset,fd,tree,"fhandle");
+                       offset = dissect_fhandle(tvb,offset,pinfo,tree,"fhandle");
                break;
                default:
                        /* void */
@@ -104,55 +111,85 @@ dissect_fhstatus(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
 
 
 static int
-dissect_mount_dirpath_call(const u_char *pd, int offset, frame_data *fd,
-       proto_tree *tree)
+dissect_mount_dirpath_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+               proto_tree *tree)
 {
+       if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
+               rpc_call_info_value *civ=pinfo->private_data;
+
+               if(civ->request && (civ->proc==1)){
+                       unsigned char *host, *name;
+                       unsigned const char *dir;
+                       int len;
+
+                       host=ip_to_str(pinfo->dst.data);
+                       len=tvb_get_ntohl(tvb, offset);
+
+                       dir=tvb_get_ptr(tvb, offset+4, len);
+                       if(dir){
+                               unsigned char *ptr;
+                               name=g_malloc(strlen(host)+1+len+1+200);
+                               ptr=name;
+                               memcpy(ptr, host, strlen(host));
+                               ptr+=strlen(host);
+                               *ptr++=':';
+                               memcpy(ptr, dir, len);
+                               ptr+=len;
+                               *ptr=0;
+
+                               nfs_name_snoop_add_name(civ->xid, tvb, -1, strlen(name), 0, 0, name);
+                       }
+               }
+       }
+
        if ( tree )
        {
-               offset = dissect_rpc_string(pd,offset,fd,tree,hf_mount_path,NULL);
+               offset = dissect_rpc_string(tvb,tree,hf_mount_path,offset,NULL);
        }
-       
+
        return offset;
 }
 
 
 /* RFC 1094, Page 25,26 */
 static int
-dissect_mount_mnt_reply(const u_char *pd, int offset, frame_data *fd,
-       proto_tree *tree)
+dissect_mount1_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       offset = dissect_fhstatus(pd, offset, fd, tree);
+       offset = dissect_fhstatus(tvb,offset,pinfo,tree);
 
        return offset;
 }
 
 
+
 /* RFC 1094, Page 26 */
 /* RFC 1813, Page 110 */
 static int
-dissect_mountlist(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+dissect_mountlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
 {
-       proto_item* mountlist_item = NULL;
-       proto_tree* mountlist_tree = NULL;
+       proto_item* lock_item = NULL;
+       proto_tree* lock_tree = NULL;
        int old_offset = offset;
        char* hostname;
        char* directory;
 
        if (tree) {
-               mountlist_item = proto_tree_add_item(tree, hf_mount_mountlist, NullTVB,
-                                       offset+0, END_OF_FRAME, FALSE);
-               if (mountlist_item)
-                       mountlist_tree = proto_item_add_subtree(mountlist_item, ett_mount_mountlist);
+               lock_item = proto_tree_add_item(tree, hf_mount_mountlist, tvb,
+                                       offset, -1, FALSE);
+               if (lock_item)
+                       lock_tree = proto_item_add_subtree(lock_item, ett_mount_mountlist);
        }
 
-       offset = dissect_rpc_string(pd, offset, fd, mountlist_tree, hf_mount_mountlist_hostname,&hostname);
-       offset = dissect_rpc_string(pd, offset, fd, mountlist_tree, hf_mount_mountlist_directory,&directory);
+       offset = dissect_rpc_string(tvb, lock_tree, 
+                       hf_mount_mountlist_hostname, offset, &hostname);
+       offset = dissect_rpc_string(tvb, lock_tree,
+                       hf_mount_mountlist_directory, offset, &directory);
 
-       if (mountlist_item) {
+       if (lock_item) {
                /* now we have a nicer string */
-               proto_item_set_text(mountlist_item, "Mount List Entry: %s:%s", hostname, directory);
+               proto_item_set_text(lock_item, "Mount List Entry: %s:%s", hostname, directory);
                /* now we know, that mountlist is shorter */
-               proto_item_set_len(mountlist_item, offset - old_offset);
+               proto_item_set_len(lock_item, offset - old_offset);
        }
        g_free(hostname);
        g_free(directory);
@@ -164,21 +201,36 @@ dissect_mountlist(const u_char *pd, int offset, frame_data *fd, proto_tree *tree
 /* RFC 1094, Page 26 */
 /* RFC 1813, Page 110 */
 static int
-dissect_mount_dump_reply(const u_char *pd, int offset, frame_data *fd,
-       proto_tree *tree)
+dissect_mount_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       offset = dissect_rpc_list(pd,offset,fd,tree,dissect_mountlist);
+       offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_mountlist);
 
        return offset;
 }
 
 
+
 /* RFC 1094, Page 26 */
 /* RFC 1813, Page 110 */
 static int
-dissect_group(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+dissect_group(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
 {
-       offset = dissect_rpc_string(pd, offset, fd, tree, hf_mount_groups_group,NULL);
+       int len,str_len;
+       len=tvb_get_ntohl(tvb,offset);
+       str_len=tvb_get_nstringz(tvb,offset+4,
+               MAX_GROUP_NAME_LIST-5-group_names_len,
+               group_name_list+group_names_len);
+       if((group_names_len>=(MAX_GROUP_NAME_LIST-5))||(str_len<0)){
+               strcpy(group_name_list+(MAX_GROUP_NAME_LIST-5),"...");
+               group_names_len=MAX_GROUP_NAME_LIST-1;
+       } else {
+               group_names_len+=str_len;
+               group_name_list[group_names_len++]=' ';
+       }
+       group_name_list[group_names_len]=0;
+
+       offset = dissect_rpc_string(tvb, tree, 
+                       hf_mount_groups_group, offset, NULL);
 
        return offset;
 }
@@ -187,7 +239,7 @@ dissect_group(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
 /* RFC 1094, Page 26 */
 /* RFC 1813, Page 113 */
 static int
-dissect_exportlist(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+dissect_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
        proto_item* exportlist_item = NULL;
        proto_tree* exportlist_tree = NULL;
@@ -197,22 +249,27 @@ dissect_exportlist(const u_char *pd, int offset, frame_data *fd, proto_tree *tre
        proto_item* groups_tree = NULL;
        char* directory;
 
+       group_name_list[0]=0;
+       group_names_len=0;
        if (tree) {
-               exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist, NullTVB,
-                                       offset+0, END_OF_FRAME, FALSE);
+               exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist, tvb,
+                                       offset, -1, FALSE);
                if (exportlist_item)
                        exportlist_tree = proto_item_add_subtree(exportlist_item, ett_mount_exportlist);
        }
 
-       offset = dissect_rpc_string(pd, offset, fd, exportlist_tree, hf_mount_exportlist_directory,&directory);
+       offset = dissect_rpc_string(tvb, exportlist_tree,
+                       hf_mount_exportlist_directory, offset, &directory);
        groups_offset = offset;
+
        if (tree) {
-               groups_item = proto_tree_add_item(exportlist_tree, hf_mount_groups, NullTVB,
-                               offset+0, END_OF_FRAME, FALSE);
+               groups_item = proto_tree_add_item(exportlist_tree, hf_mount_groups, tvb,
+                                       offset, -1, FALSE);
                if (groups_item)
                        groups_tree = proto_item_add_subtree(groups_item, ett_mount_groups);
        }
-       offset = dissect_rpc_list(pd,offset,fd,groups_tree,dissect_group);
+
+       offset = dissect_rpc_list(tvb, pinfo, groups_tree, offset, dissect_group);
        if (groups_item) {
                /* mark empty lists */
                if (offset - groups_offset == 4) {
@@ -225,7 +282,7 @@ dissect_exportlist(const u_char *pd, int offset, frame_data *fd, proto_tree *tre
 
        if (exportlist_item) {
                /* now we have a nicer string */
-               proto_item_set_text(exportlist_item, "Export List Entry: %s", directory);
+               proto_item_set_text(exportlist_item, "Export List Entry: %s -> %s", directory,group_name_list);
                /* now we know, that exportlist is shorter */
                proto_item_set_len(exportlist_item, offset - old_offset);
        }
@@ -238,10 +295,9 @@ dissect_exportlist(const u_char *pd, int offset, frame_data *fd, proto_tree *tre
 /* RFC 1094, Page 26 */
 /* RFC 1813, Page 113 */
 static int
-dissect_mount_export_reply(const u_char *pd, int offset, frame_data *fd,
-       proto_tree *tree)
+dissect_mount_export_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-       offset = dissect_rpc_list(pd,offset,fd,tree,dissect_exportlist);
+       offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_exportlist);
 
        return offset;
 }
@@ -310,178 +366,117 @@ static const true_false_string tos_error_vdisable = {
   "VDISABLE valid"
 };
 
+
 static int
-dissect_mount_pathconf_reply(const u_char *pd, int offset, frame_data *fd,
-       proto_tree *tree)
+dissect_mount_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
 {
+       int saved_offset;
        guint32 pc_mask;
-       proto_item *ti;
-       proto_tree *mask_tree;
+       proto_item *lock_item;
+       proto_tree *lock_tree;
 
+       saved_offset=offset;
        /*
         * Extract the mask first, so we know which other fields the
         * server was able to return to us.
         */
-       if (!BYTES_ARE_IN_FRAME(offset + OFFS_MASK, 4))
-               return offset;
-       pc_mask = EXTRACT_UINT(pd, offset+OFFS_MASK) & 0xFFFF;
-
-       if (!BYTES_ARE_IN_FRAME(offset + 0,4))
-               return offset;
+       pc_mask = tvb_get_ntohl(tvb, offset+OFFS_MASK) & 0xffff;
        if (!(pc_mask & (PC_ERROR_LINK_MAX|PC_ERROR_ALL))) {
                if (tree) {
-                       proto_tree_add_uint(tree,
-                           hf_mount_pathconf_link_max, NullTVB, offset, 4,
-                           EXTRACT_UINT(pd, offset+0));
+                       dissect_rpc_uint32(tvb,tree,hf_mount_pathconf_link_max,offset);
                }
        }
        offset += 4;
 
-       if (!BYTES_ARE_IN_FRAME(offset,4))
-               return offset;
        if (!(pc_mask & (PC_ERROR_MAX_CANON|PC_ERROR_ALL))) {
                if (tree) {
-                       proto_tree_add_uint(tree,
-                           hf_mount_pathconf_max_canon, NullTVB, offset + 2, 2,
-                           (EXTRACT_UINT(pd, offset+0)) & 0xFFFF);
+                       proto_tree_add_item(tree, 
+                               hf_mount_pathconf_max_canon,tvb,offset+2,2,
+                               tvb_get_ntohs(tvb,offset)&0xffff);
                }
        }
-       
        offset += 4;
 
-       if (!BYTES_ARE_IN_FRAME(offset,4))
-               return offset;
        if (!(pc_mask & (PC_ERROR_MAX_INPUT|PC_ERROR_ALL))) {
                if (tree) {
-                       proto_tree_add_uint(tree,
-                           hf_mount_pathconf_max_input, NullTVB, offset + 2, 2,
-                           (EXTRACT_UINT(pd, offset+0)) & 0xFFFF);
+                       proto_tree_add_item(tree, 
+                               hf_mount_pathconf_max_input,tvb,offset+2,2,
+                               tvb_get_ntohs(tvb,offset)&0xffff);
                }
        }
        offset += 4;
 
-       if (!BYTES_ARE_IN_FRAME(offset,4))
-               return offset;
        if (!(pc_mask & (PC_ERROR_NAME_MAX|PC_ERROR_ALL))) {
                if (tree) {
-                       proto_tree_add_uint(tree,
-                           hf_mount_pathconf_name_max, NullTVB, offset + 2, 2,
-                           (EXTRACT_UINT(pd, offset+0)) & 0xFFFF);
+                       proto_tree_add_item(tree, 
+                               hf_mount_pathconf_name_max,tvb,offset+2,2,
+                               tvb_get_ntohs(tvb,offset)&0xffff);
                }
        }
        offset += 4;
 
-       if (!BYTES_ARE_IN_FRAME(offset,4))
-               return offset;
        if (!(pc_mask & (PC_ERROR_PATH_MAX|PC_ERROR_ALL))) {
                if (tree) {
-                       proto_tree_add_uint(tree,
-                           hf_mount_pathconf_path_max, NullTVB, offset + 2, 2,
-                           (EXTRACT_UINT(pd, offset+0)) & 0xFFFF);
+                       proto_tree_add_item(tree, 
+                               hf_mount_pathconf_path_max,tvb,offset+2,2,
+                               tvb_get_ntohs(tvb,offset)&0xffff);
                }
        }
        offset += 4;
 
-       if (!BYTES_ARE_IN_FRAME(offset,4))
-               return offset;
        if (!(pc_mask & (PC_ERROR_PIPE_BUF|PC_ERROR_ALL))) {
                if (tree) {
-                       proto_tree_add_uint(tree,
-                           hf_mount_pathconf_pipe_buf, NullTVB, offset + 2, 2,
-                           (EXTRACT_UINT(pd, offset+0)) & 0xFFFF);
+                       proto_tree_add_item(tree, 
+                               hf_mount_pathconf_pipe_buf,tvb,offset+2,2,
+                               tvb_get_ntohs(tvb,offset)&0xffff);
                }
        }
        offset += 4;
 
        offset += 4;    /* skip "pc_xxx" pad field */
 
-       if (!BYTES_ARE_IN_FRAME(offset,4))
-               return offset;
        if (!(pc_mask & (PC_ERROR_VDISABLE|PC_ERROR_ALL))) {
                if (tree) {
-                       proto_tree_add_uint(tree,
-                           hf_mount_pathconf_vdisable, NullTVB, offset + 3, 1,
-                           (EXTRACT_UINT(pd, offset+0)) & 0xFF);
+                       proto_tree_add_item(tree, 
+                               hf_mount_pathconf_vdisable,tvb,offset+3,1,
+                               tvb_get_ntohs(tvb,offset)&0xffff);
                }
        }
        offset += 4;
 
+
        if (tree) {
-               ti = proto_tree_add_uint(tree, hf_mount_pathconf_mask, NullTVB,
-                   offset + 2, 2, pc_mask);
-               mask_tree = proto_item_add_subtree(ti, ett_mount_pathconf_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_all, NullTVB,
+               lock_item = proto_tree_add_item(tree, hf_mount_pathconf_mask, tvb,
+                                       offset+2, 2, FALSE);
+
+               lock_tree = proto_item_add_subtree(lock_item, ett_mount_pathconf_mask);
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_all, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_link_max, NullTVB,
+
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_link_max, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_max_canon, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_canon, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_max_input, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_input, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_name_max, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_name_max, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_path_max, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_path_max, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_pipe_buf, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_pipe_buf, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_chown_restricted, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_chown_restricted, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_no_trunc, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_no_trunc, tvb,
                    offset + 2, 2, pc_mask);
-               proto_tree_add_boolean(mask_tree, hf_mount_pathconf_error_vdisable, NullTVB,
+               proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_vdisable, tvb,
                    offset + 2, 2, pc_mask);
        }
-       offset += 4;
+
+       offset += 8;
        return offset;
 }
 
-/* proc number, "proc name", dissect_request, dissect_reply */
-/* NULL as function pointer means: type of arguments is "void". */
-
-/* Mount protocol version 1, RFC 1094 */
-static const vsff mount1_proc[] = {
-    { 0, "NULL", NULL, NULL },
-    { MOUNTPROC_MNT,        "MNT",      
-               dissect_mount_dirpath_call, dissect_mount_mnt_reply },
-    { MOUNTPROC_DUMP,       "DUMP",
-               NULL, dissect_mount_dump_reply },
-    { MOUNTPROC_UMNT,      "UMNT",        
-               dissect_mount_dirpath_call, NULL },
-    { MOUNTPROC_UMNTALL,   "UMNTALL",
-               NULL, NULL },
-    { MOUNTPROC_EXPORT,    "EXPORT",
-               NULL, dissect_mount_export_reply },
-    { MOUNTPROC_EXPORTALL, "EXPORTALL",
-               NULL, dissect_mount_export_reply },
-    { 0, NULL, NULL, NULL }
-};
-/* end of mount version 1 */
-
-
-/* Mount protocol version 2, private communication from somebody at Sun;
-   mount V2 is V1 plus MOUNTPROC_PATHCONF to fetch information for the
-   POSIX "pathconf()" call. */
-static const vsff mount2_proc[] = {
-    { 0, "NULL", NULL, NULL },
-    { MOUNTPROC_MNT,        "MNT",      
-               dissect_mount_dirpath_call, dissect_mount_mnt_reply },
-    { MOUNTPROC_DUMP,       "DUMP",
-               NULL, dissect_mount_dump_reply },
-    { MOUNTPROC_UMNT,      "UMNT",        
-               dissect_mount_dirpath_call, NULL },
-    { MOUNTPROC_UMNTALL,   "UMNTALL",
-               NULL, NULL },
-    { MOUNTPROC_EXPORT,    "EXPORT",
-               NULL, dissect_mount_export_reply },
-    { MOUNTPROC_EXPORTALL, "EXPORTALL",
-               NULL, dissect_mount_export_reply },
-    { MOUNTPROC_PATHCONF,  "PATHCONF",
-               dissect_mount_dirpath_call, dissect_mount_pathconf_reply },
-    { 0, NULL, NULL, NULL }
-};
-/* end of mount version 2 */
-
-
 /* RFC 1813, Page 107 */
 static const value_string mount3_mountstat3[] = 
 {
@@ -501,47 +496,39 @@ static const value_string mount3_mountstat3[] =
 
 /* RFC 1813, Page 107 */
 static int
-dissect_mountstat3(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
-       int hfindex, guint32* status)
+dissect_mountstat3(tvbuff_t *tvb, proto_tree *tree, int offset, int hfindex, guint32 *status)
 {
        guint32 mountstat3;
 
-       if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
-       mountstat3 = EXTRACT_UINT(pd, offset+0);
+       mountstat3 = tvb_get_ntohl(tvb, offset);
 
-       if (tree) {
-               proto_tree_add_uint(tree, hfindex, NullTVB, offset, 4, mountstat3);
-       }
-       
-       offset += 4;
+       offset = dissect_rpc_uint32(tvb,tree,hfindex,offset);
        *status = mountstat3;
        return offset;
 }
 
-
 /* RFC 1831, Page 109 */
 static int
-dissect_mount3_mnt_reply(const u_char *pd, int offset, frame_data *fd,
-       proto_tree *tree)
+dissect_mount3_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
        guint32 status;
        guint32 auth_flavors;
        guint32 auth_flavor;
        guint32 auth_flavor_i;
        
-       offset = dissect_mountstat3(pd, offset, fd, tree, hf_mount_status, &status);
+       offset = dissect_mountstat3(tvb,tree,offset,hf_mount3_status,&status);
+
        switch (status) {
                case 0:
-                       offset = dissect_nfs_fh3(pd,offset,fd,tree,"fhandle");
-                       if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
-                       auth_flavors = EXTRACT_UINT(pd,offset+0);
-                       proto_tree_add_uint(tree,hf_mount_flavors, NullTVB,
+                       offset = dissect_nfs_fh3(tvb,offset,pinfo,tree,"fhandle");
+
+                       auth_flavors = tvb_get_ntohl(tvb, offset);
+                       proto_tree_add_uint(tree,hf_mount_flavors, tvb,
                                offset, 4, auth_flavors);
                        offset += 4;
-                       for (auth_flavor_i = 0 ; auth_flavor_i < hf_mount_flavors ; auth_flavor_i++) {
-                               if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
-                               auth_flavor = EXTRACT_UINT(pd,offset+0);
-                               proto_tree_add_uint(tree,hf_mount_flavor, NullTVB,
+                       for (auth_flavor_i = 0 ; auth_flavor_i < auth_flavors ; auth_flavor_i++) {
+                               auth_flavor = tvb_get_ntohl(tvb, offset);
+                               proto_tree_add_uint(tree,hf_mount_flavor, tvb,
                                        offset, 4, auth_flavor);
                                offset += 4;
                        }
@@ -554,6 +541,54 @@ dissect_mount3_mnt_reply(const u_char *pd, int offset, frame_data *fd,
        return offset;
 }
 
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+
+/* Mount protocol version 1, RFC 1094 */
+static const vsff mount1_proc[] = {
+    { 0, "NULL", NULL, NULL },
+    { MOUNTPROC_MNT,        "MNT",      
+               dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
+    { MOUNTPROC_DUMP,       "DUMP",
+               NULL, dissect_mount_dump_reply },
+    { MOUNTPROC_UMNT,      "UMNT",        
+               dissect_mount_dirpath_call, NULL },
+    { MOUNTPROC_UMNTALL,   "UMNTALL",
+               NULL, NULL },
+    { MOUNTPROC_EXPORT,    "EXPORT",
+               NULL, dissect_mount_export_reply },
+    { MOUNTPROC_EXPORTALL, "EXPORTALL",
+               NULL, dissect_mount_export_reply },
+    { 0, NULL, NULL, NULL }
+};
+/* end of mount version 1 */
+
+
+/* Mount protocol version 2, private communication from somebody at Sun;
+   mount V2 is V1 plus MOUNTPROC_PATHCONF to fetch information for the
+   POSIX "pathconf()" call. */
+static const vsff mount2_proc[] = {
+    { 0, "NULL", NULL, NULL },
+    { MOUNTPROC_MNT,        "MNT",      
+               dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
+    { MOUNTPROC_DUMP,       "DUMP",
+               NULL, dissect_mount_dump_reply },
+    { MOUNTPROC_UMNT,      "UMNT",        
+               dissect_mount_dirpath_call, NULL },
+    { MOUNTPROC_UMNTALL,   "UMNTALL",
+               NULL, NULL },
+    { MOUNTPROC_EXPORT,    "EXPORT",
+               NULL, dissect_mount_export_reply },
+    { MOUNTPROC_EXPORTALL, "EXPORTALL",
+               NULL, dissect_mount_export_reply },
+    { MOUNTPROC_PATHCONF,  "PATHCONF",
+               dissect_mount_dirpath_call, dissect_mount_pathconf_reply },
+    { 0, NULL, NULL, NULL }
+};
+/* end of mount version 2 */
+
+
 /* Mount protocol version 3, RFC 1813 */
 static const vsff mount3_proc[] = {
        { 0, "NULL", NULL, NULL },
@@ -578,109 +613,109 @@ proto_register_mount(void)
        static hf_register_info hf[] = {
                { &hf_mount_path, {
                        "Path", "mount.path", FT_STRING, BASE_DEC,
-                       NULL, 0, "Path" }},
-               { &hf_mount_status, {
+                       NULL, 0, "Path", HFILL }},
+               { &hf_mount3_status, {
                        "Status", "mount.status", FT_UINT32, BASE_DEC,
-                       VALS(mount3_mountstat3), 0, "Status" }},
+                       VALS(mount3_mountstat3), 0, "Status", HFILL }},
                { &hf_mount_mountlist_hostname, {
                        "Hostname", "mount.dump.hostname", FT_STRING, BASE_DEC,
-                       NULL, 0, "Hostname" }},
+                       NULL, 0, "Hostname", HFILL }},
                { &hf_mount_mountlist_directory, {
                        "Directory", "mount.dump.directory", FT_STRING, BASE_DEC,
-                       NULL, 0, "Directory" }},
+                       NULL, 0, "Directory", HFILL }},
                { &hf_mount_mountlist, {
                        "Mount List Entry", "mount.dump.entry", FT_NONE, 0,
-                       NULL, 0, "Mount List Entry" }},
+                       NULL, 0, "Mount List Entry", HFILL }},
                { &hf_mount_groups_group, {
                        "Group", "mount.export.group", FT_STRING, BASE_DEC,
-                       NULL, 0, "Group" }},
+                       NULL, 0, "Group", HFILL }},
                { &hf_mount_groups, {
                        "Groups", "mount.export.groups", FT_NONE, 0,
-                       NULL, 0, "Groups" }},
+                       NULL, 0, "Groups", HFILL }},
                { &hf_mount_exportlist_directory, {
                        "Directory", "mount.export.directory", FT_STRING, BASE_DEC,
-                       NULL, 0, "Directory" }},
+                       NULL, 0, "Directory", HFILL }},
                { &hf_mount_exportlist, {
                        "Export List Entry", "mount.export.entry", FT_NONE, 0,
-                       NULL, 0, "Export List Entry" }},
+                       NULL, 0, "Export List Entry", HFILL }},
                { &hf_mount_pathconf_link_max, {
                        "Maximum number of links to a file", "mount.pathconf.link_max",
                        FT_UINT32, BASE_DEC,
-                       NULL, 0, "Maximum number of links allowed to a file" }},
+                       NULL, 0, "Maximum number of links allowed to a file", HFILL }},
                { &hf_mount_pathconf_max_canon, {
                        "Maximum terminal input line length", "mount.pathconf.max_canon",
                        FT_UINT16, BASE_DEC,
-                       NULL, 0, "Max tty input line length" }},
+                       NULL, 0, "Max tty input line length", HFILL }},
                { &hf_mount_pathconf_max_input, {
                        "Terminal input buffer size", "mount.pathconf.max_input",
                        FT_UINT16, BASE_DEC,
-                       NULL, 0, "Terminal input buffer size" }},
+                       NULL, 0, "Terminal input buffer size", HFILL }},
                { &hf_mount_pathconf_name_max, {
                        "Maximum file name length", "mount.pathconf.name_max",
                        FT_UINT16, BASE_DEC,
-                       NULL, 0, "Maximum file name length" }},
+                       NULL, 0, "Maximum file name length", HFILL }},
                { &hf_mount_pathconf_path_max, {
                        "Maximum path name length", "mount.pathconf.path_max",
                        FT_UINT16, BASE_DEC,
-                       NULL, 0, "Maximum path name length" }},
+                       NULL, 0, "Maximum path name length", HFILL }},
                { &hf_mount_pathconf_pipe_buf, {
                        "Pipe buffer size", "mount.pathconf.pipe_buf",
                        FT_UINT16, BASE_DEC,
-                       NULL, 0, "Maximum amount of data that can be written atomically to a pipe" }},
+                       NULL, 0, "Maximum amount of data that can be written atomically to a pipe", HFILL }},
                { &hf_mount_pathconf_vdisable, {
                        "VDISABLE character", "mount.pathconf.vdisable_char",
                        FT_UINT8, BASE_HEX,
-                       NULL, 0, "Character value to disable a terminal special character" }},
+                       NULL, 0, "Character value to disable a terminal special character", HFILL }},
                { &hf_mount_pathconf_mask, {
                        "Reply error/status bits", "mount.pathconf.mask",
                        FT_UINT16, BASE_HEX,
-                       NULL, 0, "Bit mask with error and status bits" }},
+                       NULL, 0, "Bit mask with error and status bits", HFILL }},
                { &hf_mount_pathconf_error_all, {
                        "ERROR_ALL",    "mount.pathconf.mask.error_all",
                        FT_BOOLEAN, 16, TFS(&tos_error_all),
-                       PC_ERROR_ALL, "" }},
+                       PC_ERROR_ALL, "", HFILL }},
                { &hf_mount_pathconf_error_link_max, {
                        "ERROR_LINK_MAX", "mount.pathconf.mask.error_link_max",
                        FT_BOOLEAN, 16, TFS(&tos_error_link_max),
-                       PC_ERROR_LINK_MAX, "" }},
+                       PC_ERROR_LINK_MAX, "", HFILL }},
                { &hf_mount_pathconf_error_max_canon, {
                        "ERROR_MAX_CANON", "mount.pathconf.mask.error_max_canon",
                        FT_BOOLEAN, 16, TFS(&tos_error_max_canon),
-                       PC_ERROR_MAX_CANON, "" }},
+                       PC_ERROR_MAX_CANON, "", HFILL }},
                { &hf_mount_pathconf_error_max_input, {
                        "ERROR_MAX_INPUT", "mount.pathconf.mask.error_max_input",
                        FT_BOOLEAN, 16, TFS(&tos_error_max_input),
-                       PC_ERROR_MAX_INPUT, "" }},
+                       PC_ERROR_MAX_INPUT, "", HFILL }},
                { &hf_mount_pathconf_error_name_max, {
                        "ERROR_NAME_MAX", "mount.pathconf.mask.error_name_max",
                        FT_BOOLEAN, 16, TFS(&tos_error_name_max),
-                       PC_ERROR_NAME_MAX, "" }},
+                       PC_ERROR_NAME_MAX, "", HFILL }},
                { &hf_mount_pathconf_error_path_max, {
                        "ERROR_PATH_MAX", "mount.pathconf.mask.error_path_max",
                        FT_BOOLEAN, 16, TFS(&tos_error_path_max),
-                       PC_ERROR_PATH_MAX, "" }},
+                       PC_ERROR_PATH_MAX, "", HFILL }},
                { &hf_mount_pathconf_error_pipe_buf, {
                        "ERROR_PIPE_BUF", "mount.pathconf.mask.error_pipe_buf",
                        FT_BOOLEAN, 16, TFS(&tos_error_pipe_buf),
-                       PC_ERROR_PIPE_BUF, "" }},
+                       PC_ERROR_PIPE_BUF, "", HFILL }},
                { &hf_mount_pathconf_chown_restricted, {
                        "CHOWN_RESTRICTED", "mount.pathconf.mask.chown_restricted",
                        FT_BOOLEAN, 16, TFS(&tos_chown_restricted),
-                       PC_CHOWN_RESTRICTED, "" }},
+                       PC_CHOWN_RESTRICTED, "", HFILL }},
                { &hf_mount_pathconf_no_trunc, {
                        "NO_TRUNC", "mount.pathconf.mask.no_trunc",
                        FT_BOOLEAN, 16, TFS(&tos_no_trunc),
-                       PC_NO_TRUNC, "" }},
+                       PC_NO_TRUNC, "", HFILL }},
                { &hf_mount_pathconf_error_vdisable, {
                        "ERROR_VDISABLE", "mount.pathconf.mask.error_vdisable",
                        FT_BOOLEAN, 16, TFS(&tos_error_vdisable),
-                       PC_ERROR_VDISABLE, "" }},
+                       PC_ERROR_VDISABLE, "", HFILL }},
                { &hf_mount_flavors, {
                        "Flavors", "mount.flavors", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Flavors" }},
+                       NULL, 0, "Flavors", HFILL }},
                { &hf_mount_flavor, {
                        "Flavor", "mount.flavor", FT_UINT32, BASE_DEC,
-                       VALS(rpc_auth_flavor), 0, "Flavor" }},
+                       VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
        };
        static gint *ett[] = {
                &ett_mount,