[pnfs] Wireshark: Yet another fix for draft 10
Benny Halevy
bhalevy at panasas.com
Tue Jun 5 10:19:55 EDT 2007
Tigran Mkrtchyan wrote:
>
> fixed GETDEVICEINFO for file layout.
Great.
Can you please send to the list one patch against the wireshark release
containing everything you got?
>
> Benny, do you have object layout as well?
Not yet.
> What about merging?
I'm not sure what you mean. If you're asking about merging
the object layout with the rest, then "not yet" again :)
>
>
> Regards,
> TIgran.
>
>
> ________________________________________________________________________
> Tigran Mkrtchyan DESY, IT,
> tigran.mkrtchyan at desy.de Notkestrasse 85,
> Tel: + 49 40 89983946 Hamburg 22607,
> Fax: + 49 40 89984429 Germany.
>
>
> ------------------------------------------------------------------------
>
> /* packet-nfs.c
> * Routines for nfs dissection
> * Copyright 1999, Uwe Girlich <Uwe.Girlich at philosys.de>
> * Copyright 2000-2004, Mike Frisch <frisch at hummingbird.com> (NFSv4 decoding)
> *
> * $Id: packet-nfs.c 19875 2006-11-10 23:36:57Z sahlberg $
> *
> * Wireshark - Network traffic analyzer
> * By Gerald Combs <gerald at wireshark.org>
> * Copyright 1998 Gerald Combs
> *
> * Copied from packet-smb.c
> *
> * This program is free software; you can redistribute it and/or
> * modify it under the terms of the GNU General Public License
> * as published by the Free Software Foundation; either version 2
> * of the License, or (at your option) any later version.
> *
> * This program is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> * GNU General Public License for more details.
> *
> * You should have received a copy of the GNU General Public License
> * along with this program; if not, write to the Free Software
> * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> */
>
> #ifdef HAVE_CONFIG_H
> #include "config.h"
> #endif
>
>
> #include <string.h>
>
>
> #include "packet-rpc.h"
> #include "packet-nfs.h"
> #include <epan/prefs.h>
> #include <epan/packet.h>
> #include <epan/emem.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_fhandle_data = -1;
> static int hf_nfs_fh_mount_fileid = -1;
> static int hf_nfs_fh_mount_generation = -1;
> static int hf_nfs_fh_snapid = -1;
> static int hf_nfs_fh_unused = -1;
> static int hf_nfs_fh_flags = -1;
> static int hf_nfs_fh_fileid = -1;
> static int hf_nfs_fh_generation = -1;
> static int hf_nfs_fh_fsid = -1;
> static int hf_nfs_fh_export_fileid = -1;
> static int hf_nfs_fh_export_generation = -1;
> static int hf_nfs_fh_export_snapid = -1;
> static int hf_nfs_fh_file_flag_mntpoint = -1;
> static int hf_nfs_fh_file_flag_snapdir = -1;
> static int hf_nfs_fh_file_flag_snapdir_ent = -1;
> static int hf_nfs_fh_file_flag_empty = -1;
> static int hf_nfs_fh_file_flag_vbn_access = -1;
> static int hf_nfs_fh_file_flag_multivolume = -1;
> static int hf_nfs_fh_file_flag_metadata = -1;
> static int hf_nfs_fh_file_flag_orphan = -1;
> static int hf_nfs_fh_file_flag_foster = -1;
> static int hf_nfs_fh_file_flag_named_attr = -1;
> static int hf_nfs_fh_file_flag_exp_snapdir = -1;
> static int hf_nfs_fh_file_flag_vfiler = -1;
> static int hf_nfs_fh_file_flag_aggr = -1;
> static int hf_nfs_fh_file_flag_striped = -1;
> static int hf_nfs_fh_file_flag_private = -1;
> static int hf_nfs_fh_file_flag_next_gen = -1;
> static int hf_nfs_fh_handle_type = -1;
> static int hf_nfs_fh_fsid_major = -1;
> static int hf_nfs_fh_fsid_minor = -1;
> static int hf_nfs_fh_fsid_inode = -1;
> static int hf_nfs_fh_xfsid_major = -1;
> static int hf_nfs_fh_xfsid_minor = -1;
> static int hf_nfs_fh_fstype = -1;
> static int hf_nfs_fh_fn = -1;
> static int hf_nfs_fh_fn_len = -1;
> static int hf_nfs_fh_fn_inode = -1;
> static int hf_nfs_fh_fn_generation = -1;
> static int hf_nfs_fh_xfn = -1;
> static int hf_nfs_fh_xfn_len = -1;
> static int hf_nfs_fh_xfn_inode = -1;
> static int hf_nfs_fh_xfn_generation = -1;
> static int hf_nfs_fh_dentry = -1;
> static int hf_nfs_fh_dev = -1;
> static int hf_nfs_fh_xdev = -1;
> static int hf_nfs_fh_dirinode = -1;
> static int hf_nfs_fh_pinode = -1;
> static int hf_nfs_fh_hp_len = -1;
> static int hf_nfs_fh_version = -1;
> static int hf_nfs_fh_auth_type = -1;
> static int hf_nfs_fh_fsid_type = -1;
> static int hf_nfs_fh_fileid_type = -1;
> static int hf_gxfh3_utlfield = -1;
> static int hf_gxfh3_utlfield_tree_r = -1;
> static int hf_gxfh3_utlfield_tree_w = -1;
> static int hf_gxfh3_utlfield_jun = -1;
> static int hf_gxfh3_utlfield_jun_not = -1;
> static int hf_gxfh3_utlfield_ver = -1;
> static int hf_gxfh3_volcnt = -1;
> static int hf_gxfh3_epoch = -1;
> static int hf_gxfh3_ldsid = -1;
> static int hf_gxfh3_cid = -1;
> static int hf_gxfh3_resv = -1;
> static int hf_gxfh3_sfhflags = -1;
> static int hf_gxfh3_sfhflags_resv1 = -1;
> static int hf_gxfh3_sfhflags_resv2 = -1;
> static int hf_gxfh3_sfhflags_ontap7G = -1;
> static int hf_gxfh3_sfhflags_ontapGX = -1;
> static int hf_gxfh3_sfhflags_striped = -1;
> static int hf_gxfh3_sfhflags_empty = -1;
> static int hf_gxfh3_sfhflags_snapdirent = -1;
> static int hf_gxfh3_sfhflags_snapdir = -1;
> static int hf_gxfh3_sfhflags_streamdir = -1;
> static int hf_gxfh3_spinfid = -1;
> static int hf_gxfh3_spinfuid = -1;
> static int hf_gxfh3_exportptid = -1;
> static int hf_gxfh3_exportptuid = -1;
>
> static int hf_nfs_stat = -1;
> static int hf_nfs_full_name = -1;
> static int hf_nfs_name = -1;
> static int hf_nfs_readlink_data = -1;
> static int hf_nfs_read_offset = -1;
> static int hf_nfs_read_count = -1;
> static int hf_nfs_read_totalcount = -1;
> static int hf_nfs_data = -1;
> static int hf_nfs_write_beginoffset = -1;
> static int hf_nfs_write_offset = -1;
> static int hf_nfs_write_totalcount = -1;
> static int hf_nfs_symlink_to = -1;
> static int hf_nfs_readdir_cookie = -1;
> static int hf_nfs_readdir_count = -1;
> static int hf_nfs_readdir_entry = -1;
> static int hf_nfs_readdir_entry_fileid = -1;
> static int hf_nfs_readdir_entry_name = -1;
> static int hf_nfs_readdir_entry_cookie = -1;
> static int hf_nfs_readdir_entry3_fileid = -1;
> static int hf_nfs_readdir_entry3_name = -1;
> static int hf_nfs_readdir_entry3_cookie = -1;
> static int hf_nfs_readdirplus_entry_fileid = -1;
> static int hf_nfs_readdirplus_entry_name = -1;
> static int hf_nfs_readdirplus_entry_cookie = -1;
> static int hf_nfs_readdir_eof = -1;
> static int hf_nfs_statfs_tsize = -1;
> static int hf_nfs_statfs_bsize = -1;
> static int hf_nfs_statfs_blocks = -1;
> static int hf_nfs_statfs_bfree = -1;
> static int hf_nfs_statfs_bavail = -1;
> static int hf_nfs_ftype3 = -1;
> static int hf_nfs_nfsstat3 = -1;
> static int hf_nfs_read_eof = -1;
> static int hf_nfs_write_stable = -1;
> static int hf_nfs_write_committed = -1;
> static int hf_nfs_createmode3 = -1;
> static int hf_nfs_fsstat_invarsec = -1;
> static int hf_nfs_fsinfo_rtmax = -1;
> static int hf_nfs_fsinfo_rtpref = -1;
> static int hf_nfs_fsinfo_rtmult = -1;
> static int hf_nfs_fsinfo_wtmax = -1;
> static int hf_nfs_fsinfo_wtpref = -1;
> static int hf_nfs_fsinfo_wtmult = -1;
> static int hf_nfs_fsinfo_dtpref = -1;
> static int hf_nfs_fsinfo_maxfilesize = -1;
> static int hf_nfs_fsinfo_properties = -1;
> static int hf_nfs_pathconf_linkmax = -1;
> static int hf_nfs_pathconf_name_max = -1;
> static int hf_nfs_pathconf_no_trunc = -1;
> static int hf_nfs_pathconf_chown_restricted = -1;
> static int hf_nfs_pathconf_case_insensitive = -1;
> static int hf_nfs_pathconf_case_preserving = -1;
>
> static int hf_nfs_atime = -1;
> static int hf_nfs_atime_sec = -1;
> static int hf_nfs_atime_nsec = -1;
> static int hf_nfs_atime_usec = -1;
> static int hf_nfs_mtime = -1;
> static int hf_nfs_mtime_sec = -1;
> static int hf_nfs_mtime_nsec = -1;
> static int hf_nfs_mtime_usec = -1;
> static int hf_nfs_ctime = -1;
> static int hf_nfs_ctime_sec = -1;
> static int hf_nfs_ctime_nsec = -1;
> static int hf_nfs_ctime_usec = -1;
> static int hf_nfs_dtime = -1;
> static int hf_nfs_dtime_sec = -1;
> static int hf_nfs_dtime_nsec = -1;
>
> static int hf_nfs_fattr_type = -1;
> static int hf_nfs_fattr_nlink = -1;
> static int hf_nfs_fattr_uid = -1;
> static int hf_nfs_fattr_gid = -1;
> static int hf_nfs_fattr_size = -1;
> static int hf_nfs_fattr_blocksize = -1;
> static int hf_nfs_fattr_rdev = -1;
> static int hf_nfs_fattr_blocks = -1;
> static int hf_nfs_fattr_fsid = -1;
> static int hf_nfs_fattr_fileid = -1;
> static int hf_nfs_fattr3_type = -1;
> static int hf_nfs_fattr3_nlink = -1;
> static int hf_nfs_fattr3_uid = -1;
> static int hf_nfs_fattr3_gid = -1;
> static int hf_nfs_fattr3_size = -1;
> static int hf_nfs_fattr3_used = -1;
> static int hf_nfs_fattr3_rdev = -1;
> static int hf_nfs_fattr3_fsid = -1;
> static int hf_nfs_fattr3_fileid = -1;
> static int hf_nfs_wcc_attr_size = -1;
> static int hf_nfs_set_size3_size = -1;
> static int hf_nfs_cookie3 = -1;
> static int hf_nfs_fsstat3_resok_tbytes = -1;
> static int hf_nfs_fsstat3_resok_fbytes = -1;
> static int hf_nfs_fsstat3_resok_abytes = -1;
> static int hf_nfs_fsstat3_resok_tfiles = -1;
> static int hf_nfs_fsstat3_resok_ffiles = -1;
> static int hf_nfs_fsstat3_resok_afiles = -1;
> static int hf_nfs_uid3 = -1;
> static int hf_nfs_gid3 = -1;
> static int hf_nfs_offset3 = -1;
> static int hf_nfs_count3 = -1;
> static int hf_nfs_count3_maxcount = -1;
> static int hf_nfs_count3_dircount= -1;
>
> /* NFSv4 */
> static int hf_nfs_nfsstat4 = -1;
> static int hf_nfs_argop4 = -1;
> static int hf_nfs_resop4 = -1;
> static int hf_nfs_linktext4 = -1;
> static int hf_nfs_tag4 = -1;
> static int hf_nfs_component4 = -1;
> static int hf_nfs_clientid4 = -1;
> static int hf_nfs_ace4 = -1;
> static int hf_nfs_recall = -1;
> static int hf_nfs_open_claim_type4 = -1;
> static int hf_nfs_opentype4 = -1;
> static int hf_nfs_limit_by4 = -1;
> static int hf_nfs_open_delegation_type4 = -1;
> static int hf_nfs_ftype4 = -1;
> static int hf_nfs_change_info4_atomic = -1;
> static int hf_nfs_open4_share_access = -1;
> static int hf_nfs_open4_share_deny = -1;
> static int hf_nfs_seqid4 = -1;
> static int hf_nfs_lock_seqid4 = -1;
> static int hf_nfs_mand_attr = -1;
> static int hf_nfs_recc_attr = -1;
> static int hf_nfs_time_how4 = -1;
> static int hf_nfs_attrlist4 = -1;
> static int hf_nfs_fattr4_link_support = -1;
> static int hf_nfs_fattr4_symlink_support = -1;
> static int hf_nfs_fattr4_named_attr = -1;
> static int hf_nfs_fattr4_unique_handles = -1;
> static int hf_nfs_fattr4_archive = -1;
> static int hf_nfs_fattr4_cansettime = -1;
> static int hf_nfs_fattr4_case_insensitive = -1;
> static int hf_nfs_fattr4_case_preserving = -1;
> static int hf_nfs_fattr4_chown_restricted = -1;
> static int hf_nfs_fattr4_hidden = -1;
> static int hf_nfs_fattr4_homogeneous = -1;
> static int hf_nfs_fattr4_mimetype = -1;
> static int hf_nfs_fattr4_no_trunc = -1;
> static int hf_nfs_fattr4_system = -1;
> static int hf_nfs_fattr4_owner = -1;
> static int hf_nfs_fattr4_owner_group = -1;
> static int hf_nfs_fattr4_size = -1;
> static int hf_nfs_fattr4_aclsupport = -1;
> static int hf_nfs_fattr4_lease_time = -1;
> static int hf_nfs_fattr4_fileid = -1;
> static int hf_nfs_fattr4_files_avail = -1;
> static int hf_nfs_fattr4_files_free = -1;
> static int hf_nfs_fattr4_files_total = -1;
> static int hf_nfs_fattr4_maxfilesize = -1;
> static int hf_nfs_fattr4_maxlink = -1;
> static int hf_nfs_fattr4_maxname = -1;
> static int hf_nfs_fattr4_numlinks = -1;
> static int hf_nfs_fattr4_maxread = -1;
> static int hf_nfs_fattr4_maxwrite = -1;
> static int hf_nfs_fattr4_quota_hard = -1;
> static int hf_nfs_fattr4_quota_soft = -1;
> static int hf_nfs_fattr4_quota_used = -1;
> static int hf_nfs_fattr4_space_avail = -1;
> static int hf_nfs_fattr4_space_free = -1;
> static int hf_nfs_fattr4_space_total = -1;
> static int hf_nfs_fattr4_space_used = -1;
> static int hf_nfs_who = -1;
> static int hf_nfs_server = -1;
> static int hf_nfs_stable_how4 = -1;
> static int hf_nfs_dirlist4_eof = -1;
> static int hf_nfs_stateid4 = -1;
> static int hf_nfs_offset4 = -1;
> static int hf_nfs_specdata1 = -1;
> static int hf_nfs_specdata2 = -1;
> static int hf_nfs_lock_type4 = -1;
> static int hf_nfs_reclaim4 = -1;
> static int hf_nfs_length4 = -1;
> static int hf_nfs_changeid4 = -1;
> static int hf_nfs_changeid4_before = -1;
> static int hf_nfs_changeid4_after = -1;
> static int hf_nfs_nfstime4_seconds = -1;
> static int hf_nfs_nfstime4_nseconds = -1;
> static int hf_nfs_fsid4_major = -1;
> static int hf_nfs_fsid4_minor = -1;
> static int hf_nfs_acetype4 = -1;
> 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;
> static int hf_nfs_stateid4_delegate_stateid = -1;
> static int hf_nfs_verifier4 = -1;
> static int hf_nfs_cookie4 = -1;
> static int hf_nfs_cookieverf4 = -1;
> static int hf_nfs_cb_program = -1;
> static int hf_nfs_cb_location = -1;
> static int hf_nfs_recall4 = -1;
> static int hf_nfs_filesize = -1;
> static int hf_nfs_count4 = -1;
> static int hf_nfs_count4_dircount = -1;
> static int hf_nfs_count4_maxcount = -1;
> static int hf_nfs_minorversion = -1;
> static int hf_nfs_open_owner4 = -1;
> static int hf_nfs_lock_owner4 = -1;
> static int hf_nfs_new_lock_owner = -1;
> static int hf_nfs_sec_oid4 = -1;
> static int hf_nfs_qop4 = -1;
> static int hf_nfs_secinfo_rpcsec_gss_info_service = -1;
> static int hf_nfs_attrdircreate = -1;
> static int hf_nfs_client_id4_id = -1;
> static int hf_nfs_stateid4_other = -1;
> static int hf_nfs_lock4_reclaim = -1;
> static int hf_nfs_acl4 = -1;
> static int hf_nfs_callback_ident = -1;
> static int hf_nfs_r_netid = -1;
> static int hf_nfs_r_addr = -1;
>
> /* NFSv4.1 */
> static int hf_nfs_length4_minlength = -1;
> static int hf_nfs_layouttype4 = -1;
> static int hf_nfs_layoutlen = -1;
> static int hf_nfs_layoutreturn_type4 = -1;
> static int hf_nfs_iomode4 = -1;
> static int hf_nfs_fldtype4 = -1;
> static int hf_nfs_stripetype4 = -1;
> static int hf_nfs_mdscommit4 = -1;
> static int hf_nfs_stripeunit4 = -1;
> static int hf_nfs_newtime4 = -1;
> static int hf_nfs_newoffset4 = -1;
> static int hf_nfs_layout_avail4 = -1;
> static int hf_nfs_newsize4 = -1;
> static int hf_nfs_layoutupdate4 = -1;
> static int hf_nfs_deviceid4 = -1;
> static int hf_nfs_devicenum4 = -1;
> static int hf_nfs_deviceidx4 = -1;
> static int hf_nfs_layout4 = -1;
> static int hf_nfs_stripedevs4 = -1;
> static int hf_nfs_devaddr4 = -1;
> static int hf_nfs_notifydsop4 = -1;
> static int hf_nfs_return_on_close4 = -1;
> static int hf_nfs_slotid4 = -1;
> static int hf_nfs_sr_status4 = -1;
> static int hf_nfs_serverscope4 = -1;
> static int hf_nfs_minorid4 = -1;
> static int hf_nfs_majorid4 = -1;
> static int hf_nfs_padsize4 = -1;
> static int hf_nfs_cbrenforce4 = -1;
> static int hf_nfs_hashalg4 = -1;
> static int hf_nfs_ssvlen4 = -1;
> static int hf_nfs_maxreqsize4 = -1;
> static int hf_nfs_maxrespsize4 = -1;
> static int hf_nfs_maxrespsizecached4 = -1;
> static int hf_nfs_maxops4 = -1;
> static int hf_nfs_maxreqs4 = -1;
> static int hf_nfs_rdmachanattrs4 = -1;
> static int hf_nfs_machinename4 = -1;
> static int hf_nfs_flavor4 = -1;
> static int hf_nfs_stamp4 = -1;
> static int hf_nfs_uid4 = -1;
> static int hf_nfs_gid4 = -1;
> static int hf_nfs_service4 = -1;
> static int hf_nfs_sessionid4 = -1;
> static int hf_nfs_exch_id_flags4 = -1;
> static int hf_nfs_nii_domain4 = -1;
> static int hf_nfs_nii_name4 = -1;
> static int hf_nfs_create_session_flags4 = -1;
> static int hf_nfs_cachethis4 = -1;
>
> /* Hidden field for v2, v3, and v4 status */
> static int hf_nfs_nfsstat = -1;
>
> static gint ett_nfs = -1;
> static gint ett_nfs_fh_encoding = -1;
> static gint ett_nfs_fh_mount = -1;
> static gint ett_nfs_fh_file = -1;
> static gint ett_nfs_fh_export = -1;
> static gint ett_nfsv4_fh_export = -1;
> static gint ett_nfsv4_fh_file = -1;
> static gint ett_nfsv4_fh_handle_type = -1;
> static gint ett_nfsv4_fh_export_snapgen = -1;
> static gint ett_nfsv4_fh_file_flags = -1;
> static gint ett_nfs_fh_fsid = -1;
> static gint ett_nfs_fh_xfsid = -1;
> static gint ett_nfs_fh_fn = -1;
> static gint ett_nfs_fh_xfn = -1;
> static gint ett_nfs_fh_hp = -1;
> static gint ett_nfs_fh_auth = -1;
> static gint ett_nfs_fhandle = -1;
> static gint ett_nfs_timeval = -1;
> static gint ett_nfs_mode = -1;
> static gint ett_nfs_fattr = -1;
> static gint ett_nfs_sattr = -1;
> static gint ett_nfs_diropargs = -1;
> static gint ett_nfs_readdir_entry = -1;
> static gint ett_nfs_mode3 = -1;
> static gint ett_nfs_specdata3 = -1;
> static gint ett_nfs_fh3 = -1;
> static gint ett_nfs_nfstime3 = -1;
> static gint ett_nfs_fattr3 = -1;
> static gint ett_nfs_post_op_fh3 = -1;
> static gint ett_nfs_sattr3 = -1;
> static gint ett_nfs_diropargs3 = -1;
> static gint ett_nfs_sattrguard3 = -1;
> static gint ett_nfs_set_mode3 = -1;
> static gint ett_nfs_set_uid3 = -1;
> static gint ett_nfs_set_gid3 = -1;
> static gint ett_nfs_set_size3 = -1;
> static gint ett_nfs_set_atime = -1;
> static gint ett_nfs_set_mtime = -1;
> static gint ett_nfs_pre_op_attr = -1;
> static gint ett_nfs_post_op_attr = -1;
> static gint ett_nfs_wcc_attr = -1;
> static gint ett_nfs_wcc_data = -1;
> static gint ett_nfs_access = -1;
> static gint ett_nfs_fsinfo_properties = -1;
> static gint ett_nfs_gxfh3_utlfield = -1;
> static gint ett_nfs_gxfh3_sfhfield = -1;
> static gint ett_nfs_gxfh3_sfhflags = -1;
>
> /* NFSv4 */
> static gint ett_nfs_compound_call4 = -1;
> static gint ett_nfs_utf8string = -1;
> static gint ett_nfs_argop4 = -1;
> static gint ett_nfs_resop4 = -1;
> static gint ett_nfs_access4 = -1;
> static gint ett_nfs_close4 = -1;
> static gint ett_nfs_commit4 = -1;
> static gint ett_nfs_create4 = -1;
> static gint ett_nfs_delegpurge4 = -1;
> static gint ett_nfs_delegreturn4 = -1;
> static gint ett_nfs_getattr4 = -1;
> static gint ett_nfs_getfh4 = -1;
> static gint ett_nfs_link4 = -1;
> static gint ett_nfs_lock4 = -1;
> static gint ett_nfs_lockt4 = -1;
> static gint ett_nfs_locku4 = -1;
> static gint ett_nfs_lookup4 = -1;
> static gint ett_nfs_lookupp4 = -1;
> static gint ett_nfs_nverify4 = -1;
> static gint ett_nfs_open4 = -1;
> static gint ett_nfs_openattr4 = -1;
> static gint ett_nfs_open_confirm4 = -1;
> static gint ett_nfs_open_downgrade4 = -1;
> static gint ett_nfs_putfh4 = -1;
> static gint ett_nfs_putpubfh4 = -1;
> static gint ett_nfs_putrootfh4 = -1;
> static gint ett_nfs_read4 = -1;
> static gint ett_nfs_readdir4 = -1;
> static gint ett_nfs_readlink4 = -1;
> static gint ett_nfs_remove4 = -1;
> static gint ett_nfs_rename4 = -1;
> static gint ett_nfs_renew4 = -1;
> static gint ett_nfs_restorefh4 = -1;
> static gint ett_nfs_savefh4 = -1;
> static gint ett_nfs_secinfo4 = -1;
> static gint ett_nfs_setattr4 = -1;
> static gint ett_nfs_setclientid4 = -1;
> static gint ett_nfs_setclientid_confirm4 = -1;
> static gint ett_nfs_verify4 = -1;
> static gint ett_nfs_write4 = -1;
> static gint ett_nfs_release_lockowner4 = -1;
> static gint ett_nfs_illegal4 = -1;
> static gint ett_nfs_verifier4 = -1;
> static gint ett_nfs_opaque = -1;
> static gint ett_nfs_dirlist4 = -1;
> static gint ett_nfs_pathname4 = -1;
> static gint ett_nfs_change_info4 = -1;
> static gint ett_nfs_open_delegation4 = -1;
> static gint ett_nfs_open_claim4 = -1;
> static gint ett_nfs_opentype4 = -1;
> static gint ett_nfs_lock_owner4 = -1;
> static gint ett_nfs_cb_client4 = -1;
> static gint ett_nfs_client_id4 = -1;
> static gint ett_nfs_bitmap4 = -1;
> static gint ett_nfs_fattr4 = -1;
> static gint ett_nfs_fsid4 = -1;
> static gint ett_nfs_fs_locations4 = -1;
> static gint ett_nfs_fs_location4 = -1;
> static gint ett_nfs_open4_result_flags = -1;
> static gint ett_nfs_secinfo4_flavor_info = -1;
> static gint ett_nfs_stateid4 = -1;
> static gint ett_nfs_fattr4_fh_expire_type = -1;
> static gint ett_nfs_ace4 = -1;
> static gint ett_nfs_clientaddr4 = -1;
> static gint ett_nfs_aceflag4 = -1;
> static gint ett_nfs_acemask4 = -1;
>
> static gint ett_nfs_layoutget4 = -1;
> static gint ett_nfs_layoutcommit4 = -1;
> static gint ett_nfs_layoutreturn4 = -1;
> static gint ett_nfs_getdevinfo4 = -1;
> static gint ett_nfs_getdevlist4 = -1;
> static gint ett_nfs_notifyds4 = -1;
> static gint ett_nfs_exchange_id4 = -1;
> static gint ett_nfs_create_session4 = -1;
> static gint ett_nfs_destroy_session4 = -1;
> static gint ett_nfs_sequence4 = -1;
> static gint ett_nfs_pnfs_create4 = -1;
> static gint ett_nfs_slotid4 = -1;
> static gint ett_nfs_sr_status4 = -1;
> static gint ett_nfs_serverscope4 = -1;
> static gint ett_nfs_minorid4 = -1;
> static gint ett_nfs_majorid4 = -1;
> static gint ett_nfs_persist4 = -1;
> static gint ett_nfs_backchan4 = -1;
> static gint ett_nfs_rdmamode4 = -1;
> static gint ett_nfs_padsize4 = -1;
> static gint ett_nfs_cbrenforce4 = -1;
> static gint ett_nfs_hashalg4 = -1;
> static gint ett_nfs_ssvlen4 = -1;
> static gint ett_nfs_maxreqsize4 = -1;
> static gint ett_nfs_maxrespsize4 = -1;
> static gint ett_nfs_maxrespsizecached4 = -1;
> static gint ett_nfs_maxops4 = -1;
> static gint ett_nfs_maxreqs4 = -1;
> static gint ett_nfs_streamchanattrs4 = -1;
> static gint ett_nfs_rdmachanattrs4 = -1;
> static gint ett_nfs_machinename4 = -1;
> static gint ett_nfs_flavor4 = -1;
> static gint ett_nfs_stamp4 = -1;
> static gint ett_nfs_uid4 = -1;
> static gint ett_nfs_gid4 = -1;
> static gint ett_nfs_service4 = -1;
> static gint ett_nfs_sessionid4 = -1;
>
> /* what type of fhandles shoudl we dissect as */
> static dissector_table_t nfs_fhandle_table;
>
>
> #define FHT_UNKNOWN 0
> #define FHT_SVR4 1
> #define FHT_LINUX_KNFSD_LE 2
> #define FHT_LINUX_NFSD_LE 3
> #define FHT_LINUX_KNFSD_NEW 4
> #define FHT_NETAPP 5
> #define FHT_NETAPP_V4 6
> #define FHT_NETAPP_GX_V3 7
>
>
> static enum_val_t nfs_fhandle_types[] = {
> { "unknown", "Unknown", FHT_UNKNOWN },
> { "svr4", "SVR4", FHT_SVR4 },
> { "knfsd_le", "KNFSD_LE", FHT_LINUX_KNFSD_LE },
> { "nfsd_le", "NFSD_LE", FHT_LINUX_NFSD_LE },
> { "knfsd_new", "KNFSD_NEW", FHT_LINUX_KNFSD_NEW },
> { "ontap_v3", "ONTAP_V3", FHT_NETAPP },
> { "ontap_v4", "ONTAP_V4", FHT_NETAPP_V4},
> { "ontap_gx_v3","ONTAP_GX_V3", FHT_NETAPP_GX_V3},
> { NULL, NULL, 0 }
> };
> /* decode all nfs filehandles as this type */
> gint default_nfs_fhandle_type=FHT_UNKNOWN;
>
> /* For dissector helpers which take a "levels" argument to indicate how
> * many expansions up they should populate the expansion items with
> * text to enhance useability, this flag to "levels" specify that the
> * text should also be appended to COL_INFO
> */
> #define COL_INFO_LEVEL 0x80000000
>
>
> /* fhandle displayfilters to match also corresponding request/response
> packet in addition to the one containing the actual filehandle */
> gboolean nfs_fhandle_reqrep_matching = FALSE;
> static emem_tree_t *nfs_fhandle_frame_table = NULL;
>
>
> /* file name snooping */
> gboolean nfs_file_name_snooping = FALSE;
> gboolean nfs_file_name_full_snooping = FALSE;
> typedef struct nfs_name_snoop {
> int fh_length;
> unsigned char *fh;
> int name_len;
> unsigned char *name;
> int parent_len;
> unsigned char *parent;
> int full_name_len;
> unsigned char *full_name;
> } nfs_name_snoop_t;
>
> typedef struct nfs_name_snoop_key {
> int key;
> int fh_length;
> const unsigned char *fh;
> } nfs_name_snoop_key_t;
>
> static GHashTable *nfs_name_snoop_unmatched = NULL;
>
> static GHashTable *nfs_name_snoop_matched = NULL;
>
> static emem_tree_t *nfs_name_snoop_known = NULL;
> static emem_tree_t *nfs_file_handles = NULL;
>
> /* This function will store one nfs filehandle in our global tree of
> * filehandles.
> * We store all filehandles we see in this tree so that every unique
> * filehandle is only stored once with a unique pointer.
> * We need to store pointers to filehandles in several of our other
> * structures and this is a way to make sure we dont keep any redundant
> * copiesd around for a specific filehandle.
> *
> * If this is the first time this filehandle has been seen an se block
> * is allocated to store the filehandle in.
> * If this filehandle has already been stored in the tree this function returns
> * a pointer to the original copy.
> */
> static nfs_fhandle_data_t *
> store_nfs_file_handle(nfs_fhandle_data_t *nfs_fh)
> {
> guint32 fhlen;
> emem_tree_key_t fhkey[3];
> nfs_fhandle_data_t *new_nfs_fh;
>
> fhlen=nfs_fh->len/4;
> fhkey[0].length=1;
> fhkey[0].key=&fhlen;
> fhkey[1].length=fhlen;
> fhkey[1].key=(guint32 *)nfs_fh->fh;
> fhkey[2].length=0;
>
> new_nfs_fh=se_tree_lookup32_array(nfs_file_handles, &fhkey[0]);
> if(new_nfs_fh){
> return new_nfs_fh;
> }
>
> new_nfs_fh=se_alloc(sizeof(nfs_fhandle_data_t));
> new_nfs_fh->len=nfs_fh->len;
> new_nfs_fh->fh=se_alloc(sizeof(guint32)*(nfs_fh->len/4));
> memcpy(new_nfs_fh->fh, nfs_fh->fh, nfs_fh->len);
> new_nfs_fh->tvb=tvb_new_real_data(new_nfs_fh->fh, new_nfs_fh->len, new_nfs_fh->len);
> fhlen=nfs_fh->len/4;
> fhkey[0].length=1;
> fhkey[0].key=&fhlen;
> fhkey[1].length=fhlen;
> fhkey[1].key=(guint32 *)nfs_fh->fh;
> fhkey[2].length=0;
> se_tree_insert32_array(nfs_file_handles, &fhkey[0], new_nfs_fh);
>
> return new_nfs_fh;
> }
>
> static gint
> nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer 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)
> &&(!memcmp(key1->fh, key2->fh, key1->fh_length));
> }
> static guint
> nfs_name_snoop_matched_hash(gconstpointer k)
> {
> const nfs_name_snoop_key_t *key = (const nfs_name_snoop_key_t *)k;
> int i;
> guint hash;
>
> hash=key->key;
> for(i=0;i<key->fh_length;i++)
> hash ^= key->fh[i];
>
> return hash;
> }
> static gint
> nfs_name_snoop_unmatched_equal(gconstpointer k1, gconstpointer k2)
> {
> guint32 key1 = GPOINTER_TO_UINT(k1);
> guint32 key2 = GPOINTER_TO_UINT(k2);
>
> return key1==key2;
> }
> static guint
> nfs_name_snoop_unmatched_hash(gconstpointer k)
> {
> guint32 key = GPOINTER_TO_UINT(k);
>
> return key;
> }
> static gboolean
> nfs_name_snoop_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
> {
> nfs_name_snoop_t *nns = (nfs_name_snoop_t *)value;
>
> if(nns->name){
> g_free((gpointer)nns->name);
> nns->name=NULL;
> nns->name_len=0;
> }
> if(nns->full_name){
> g_free((gpointer)nns->full_name);
> nns->full_name=NULL;
> nns->full_name_len=0;
> }
> if(nns->parent){
> g_free((gpointer)nns->parent);
> nns->parent=NULL;
> nns->parent_len=0;
> }
> if(nns->fh){
> g_free((gpointer)nns->fh);
> nns->fh=NULL;
> nns->fh_length=0;
> }
> return TRUE;
> }
>
> static void
> nfs_name_snoop_init(void)
> {
> if (nfs_name_snoop_unmatched != NULL) {
> g_hash_table_foreach_remove(nfs_name_snoop_unmatched,
> nfs_name_snoop_unmatched_free_all, NULL);
> } else {
> /* The fragment table does not exist. Create it */
> nfs_name_snoop_unmatched=g_hash_table_new(nfs_name_snoop_unmatched_hash,
> nfs_name_snoop_unmatched_equal);
> }
> if (nfs_name_snoop_matched != NULL) {
> g_hash_table_foreach_remove(nfs_name_snoop_matched,
> nfs_name_snoop_unmatched_free_all, NULL);
> } else {
> /* The fragment table does not exist. Create it */
> nfs_name_snoop_matched=g_hash_table_new(nfs_name_snoop_matched_hash,
> nfs_name_snoop_matched_equal);
> }
> }
>
> 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;
> const unsigned char *ptr=NULL;
>
> /* filter out all '.' and '..' names */
> if(!name){
> ptr=(const unsigned char *)tvb_get_ptr(tvb, name_offset, name_len);
> if(ptr[0]=='.'){
> if(ptr[1]==0){
> return;
> }
> if(ptr[1]=='.'){
> if(ptr[2]==0){
> return;
> }
> }
> }
> }
>
> nns=se_alloc(sizeof(nfs_name_snoop_t));
>
> nns->fh_length=0;
> nns->fh=NULL;
>
> if(parent_len){
> nns->parent_len=parent_len;
> nns->parent=tvb_memdup(tvb, parent_offset, parent_len);
> } else {
> nns->parent_len=0;
> nns->parent=NULL;
> }
>
> if(name){
> nns->name_len=strlen(name);
> nns->name=g_strdup(name);
> } else {
> nns->name_len=name_len;
> nns->name=g_malloc(name_len+1);
> memcpy(nns->name, ptr, name_len);
> }
> nns->name[nns->name_len]=0;
>
> nns->full_name_len=0;
> nns->full_name=NULL;
>
> /* remove any old entry for this */
> old_nns=g_hash_table_lookup(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
> if(old_nns){
> /* if we haven't seen the reply yet, then there are no
> matched entries for it, thus we can dealloc the arrays*/
> if(!old_nns->fh){
> g_free(old_nns->name);
> old_nns->name=NULL;
> old_nns->name_len=0;
>
> g_free(old_nns->parent);
> old_nns->parent=NULL;
> old_nns->parent_len=0;
> }
> g_hash_table_remove(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
> }
>
> g_hash_table_insert(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid), nns);
> }
>
> 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;
>
> /* find which request we correspond to */
> nns=g_hash_table_lookup(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
> if(!nns){
> /* oops couldnt find matching request, bail out */
> return;
> }
>
> /* if we have already seen this response earlier */
> if(nns->fh){
> return;
> }
>
> /* oki, we have a new entry */
> fh=tvb_memdup(tvb, fh_offset, fh_length);
> nns->fh=fh;
> nns->fh_length=fh_length;
>
> key=se_alloc(sizeof(nfs_name_snoop_key_t));
> key->key=0;
> key->fh_length=nns->fh_length;
> key->fh =nns->fh;
>
> /* already have something matched for this fh, remove it from
> the table */
> old_nns=g_hash_table_lookup(nfs_name_snoop_matched, key);
> if(old_nns){
> g_hash_table_remove(nfs_name_snoop_matched, key);
> }
>
> g_hash_table_remove(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
> g_hash_table_insert(nfs_name_snoop_matched, key, nns);
> }
>
> static void
> nfs_full_name_snoop(nfs_name_snoop_t *nns, int *len, unsigned char **name, unsigned char **pos)
> {
> nfs_name_snoop_t *parent_nns = NULL;
> nfs_name_snoop_key_t key;
>
> /* check if the nns component ends with a '/' else we just allocate
> an extra byte to len to accommodate for it later */
> if(nns->name[nns->name_len-1]!='/'){
> (*len)++;
> }
>
> (*len) += nns->name_len;
>
> if(nns->parent==NULL){
> *name = g_malloc((*len)+1);
> *pos = *name;
>
> *pos += g_snprintf(*pos, (*len)+1, "%s", nns->name);
> return;
> }
>
> key.key=0;
> key.fh_length=nns->parent_len;
> key.fh=nns->parent;
>
> parent_nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
>
> if(parent_nns){
> nfs_full_name_snoop(parent_nns, len, name, pos);
> if(*name){
> /* make sure components are '/' separated */
> *pos += g_snprintf(*pos, (*len)+1, "%s%s", ((*pos)[-1]!='/')?"/":"", nns->name);
> }
> return;
> }
>
> return;
> }
>
> static void
> nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_offset, int fh_length, gboolean hidden)
> {
> nfs_name_snoop_key_t key;
> nfs_name_snoop_t *nns = NULL;
>
> /* if this is a new packet, see if we can register the mapping */
> if(!pinfo->fd->flags.visited){
> key.key=0;
> key.fh_length=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){
> guint32 fhlen;
> emem_tree_key_t fhkey[3];
>
> fhlen=nns->fh_length;
> fhkey[0].length=1;
> fhkey[0].key=&fhlen;
> fhkey[1].length=fhlen/4;
> fhkey[1].key=(guint32 *)nns->fh;
> fhkey[2].length=0;
> se_tree_insert32_array(nfs_name_snoop_known, &fhkey[0], nns);
>
> if(nfs_file_name_full_snooping){
> unsigned char *name=NULL, *pos=NULL;
> int len=0;
>
> nfs_full_name_snoop(nns, &len, &name, &pos);
> if(name){
> nns->full_name=name;
> nns->full_name_len=len;
> }
> }
> }
> }
>
> /* see if we know this mapping */
> if(!nns){
> guint32 fhlen;
> emem_tree_key_t fhkey[3];
>
> fhlen=fh_length;
> fhkey[0].length=1;
> fhkey[0].key=&fhlen;
> fhkey[1].length=fhlen/4;
> fhkey[1].key=(guint32 *)tvb_get_ptr(tvb, fh_offset, fh_length);
> fhkey[2].length=0;
>
> nns=se_tree_lookup32_array(nfs_name_snoop_known, &fhkey[0]);
> }
>
> /* if we know the mapping, print the filename */
> if(nns){
> proto_item *fh_item;
>
> if(hidden){
> fh_item=proto_tree_add_string_hidden(tree, hf_nfs_name, tvb,
> fh_offset, 0, nns->name);
> }else {
> fh_item=proto_tree_add_string_format(tree, hf_nfs_name, tvb,
> fh_offset, 0, nns->name, "Name: %s", nns->name);
> }
> PROTO_ITEM_SET_GENERATED(fh_item);
>
> if(nns->full_name){
> if(hidden){
> fh_item=proto_tree_add_string_hidden(tree, hf_nfs_full_name, tvb,
> fh_offset, 0, nns->name);
> } else {
> fh_item=proto_tree_add_string_format(tree, hf_nfs_full_name, tvb,
> fh_offset, 0, nns->name, "Full Name: %s", nns->full_name);
> }
> PROTO_ITEM_SET_GENERATED(fh_item);
> }
> }
> }
>
> /* file handle dissection */
>
> static const value_string names_fhtype[] =
> {
> { FHT_UNKNOWN, "unknown" },
> { FHT_SVR4, "System V R4" },
> { FHT_LINUX_KNFSD_LE, "Linux knfsd (little-endian)" },
> { FHT_LINUX_NFSD_LE, "Linux user-land nfsd (little-endian)" },
> { FHT_LINUX_KNFSD_NEW, "Linux knfsd (new)" },
> { FHT_NETAPP, "ONTAP 7G nfs v3 file handle" },
> { FHT_NETAPP_V4, "ONTAP 7G nfs v4 file handle" },
> { FHT_NETAPP_GX_V3, "ONTAP GX nfs v3 file handle" },
> { 0, NULL }
> };
>
>
> /* SVR4: checked with ReliantUNIX (5.43, 5.44, 5.45) */
>
> static void
> dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> guint32 nof=0;
>
> /* file system id */
> {
> guint32 fsid_O;
> guint32 fsid_L;
> guint32 temp;
> guint32 fsid_major;
> guint32 fsid_minor;
>
> fsid_O = nof;
> fsid_L = 4;
> temp = tvb_get_ntohl(tvb, fsid_O);
> fsid_major = ( temp>>18 ) & 0x3fff; /* 14 bits */
> fsid_minor = ( temp ) & 0x3ffff; /* 18 bits */
> if (tree) {
> proto_item* fsid_item = NULL;
> proto_tree* fsid_tree = NULL;
>
> fsid_item = proto_tree_add_text(tree, tvb,
> fsid_O, fsid_L,
> "file system ID: %d,%d", fsid_major, fsid_minor);
> if (fsid_item) {
> fsid_tree = proto_item_add_subtree(fsid_item,
> ett_nfs_fh_fsid);
> proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
> tvb, fsid_O, 2, fsid_major);
> proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
> tvb, fsid_O+1, 3, fsid_minor);
> }
> }
> nof = fsid_O + fsid_L;
> }
>
> /* file system type */
> {
> guint32 fstype_O;
> guint32 fstype_L;
> guint32 fstype;
>
> fstype_O = nof;
> fstype_L = 4;
> fstype = tvb_get_ntohl(tvb, fstype_O);
> if (tree) {
> proto_tree_add_uint(tree, hf_nfs_fh_fstype, tvb,
> fstype_O, fstype_L, fstype);
> }
> nof = fstype_O + fstype_L;
> }
>
> /* file number */
> {
> guint32 fn_O;
> guint32 fn_len_O;
> guint32 fn_len_L;
> guint32 fn_len;
> guint32 fn_data_O;
> guint32 fn_data_inode_O;
> guint32 fn_data_inode_L;
> guint32 inode;
> guint32 fn_data_gen_O;
> guint32 fn_data_gen_L;
> guint32 gen;
> guint32 fn_L;
>
> fn_O = nof;
> fn_len_O = fn_O;
> fn_len_L = 2;
> fn_len = tvb_get_ntohs(tvb, fn_len_O);
> fn_data_O = fn_O + fn_len_L;
> fn_data_inode_O = fn_data_O + 2;
> fn_data_inode_L = 4;
> inode = tvb_get_ntohl(tvb, fn_data_inode_O);
> fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
> fn_data_gen_L = 4;
> gen = tvb_get_ntohl(tvb, fn_data_gen_O);
> fn_L = fn_len_L + fn_len;
> if (tree) {
> proto_item* fn_item = NULL;
> proto_tree* fn_tree = NULL;
>
> fn_item = proto_tree_add_uint(tree, hf_nfs_fh_fn, tvb,
> fn_O, fn_L, inode);
> if (fn_item) {
> fn_tree = proto_item_add_subtree(fn_item,
> ett_nfs_fh_fn);
> proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_len,
> tvb, fn_len_O, fn_len_L, fn_len);
> proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_inode,
> tvb, fn_data_inode_O, fn_data_inode_L, inode);
> proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_generation,
> tvb, fn_data_gen_O, fn_data_gen_L, gen);
> }
> }
> nof = fn_O + fn_len_L + fn_len;
> }
>
> /* exported file number */
> {
> guint32 xfn_O;
> guint32 xfn_len_O;
> guint32 xfn_len_L;
> guint32 xfn_len;
> guint32 xfn_data_O;
> guint32 xfn_data_inode_O;
> guint32 xfn_data_inode_L;
> guint32 xinode;
> guint32 xfn_data_gen_O;
> guint32 xfn_data_gen_L;
> guint32 xgen;
> guint32 xfn_L;
>
> xfn_O = nof;
> xfn_len_O = xfn_O;
> xfn_len_L = 2;
> xfn_len = tvb_get_ntohs(tvb, xfn_len_O);
> xfn_data_O = xfn_O + xfn_len_L;
> xfn_data_inode_O = xfn_data_O + 2;
> xfn_data_inode_L = 4;
> xinode = tvb_get_ntohl(tvb, xfn_data_inode_O);
> xfn_data_gen_O = xfn_data_inode_O + xfn_data_inode_L;
> xfn_data_gen_L = 4;
> xgen = tvb_get_ntohl(tvb, xfn_data_gen_O);
> xfn_L = xfn_len_L + xfn_len;
> if (tree) {
> proto_item* xfn_item = NULL;
> proto_tree* xfn_tree = NULL;
>
> xfn_item = proto_tree_add_uint(tree, hf_nfs_fh_xfn, tvb,
> xfn_O, xfn_L, xinode);
> if (xfn_item) {
> xfn_tree = proto_item_add_subtree(xfn_item,
> ett_nfs_fh_xfn);
> proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_len,
> tvb, xfn_len_O, xfn_len_L, xfn_len);
> proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_inode,
> tvb, xfn_data_inode_O, xfn_data_inode_L, xinode);
> proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_generation,
> tvb, xfn_data_gen_O, xfn_data_gen_L, xgen);
> }
> }
> }
> }
>
>
> /* Checked with RedHat Linux 6.2 (kernel 2.2.14 knfsd) */
>
> static void
> dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> int offset=0;
> guint32 dentry;
> guint32 inode;
> guint32 dirinode;
> guint32 temp;
> guint32 fsid_major;
> guint32 fsid_minor;
> guint32 xfsid_major;
> guint32 xfsid_minor;
> guint32 xinode;
> guint32 gen;
>
> dentry = tvb_get_letohl(tvb, offset+0);
> inode = tvb_get_letohl(tvb, offset+4);
> dirinode = tvb_get_letohl(tvb, offset+8);
> temp = tvb_get_letohs (tvb,offset+12);
> fsid_major = (temp >> 8) & 0xff;
> fsid_minor = (temp ) & 0xff;
> temp = tvb_get_letohs(tvb,offset+16);
> xfsid_major = (temp >> 8) & 0xff;
> xfsid_minor = (temp ) & 0xff;
> xinode = tvb_get_letohl(tvb,offset+20);
> gen = tvb_get_letohl(tvb,offset+24);
>
> if (tree) {
> proto_tree_add_uint(tree, hf_nfs_fh_dentry,
> tvb, offset+0, 4, dentry);
> proto_tree_add_uint(tree, hf_nfs_fh_fn_inode,
> tvb, offset+4, 4, inode);
> proto_tree_add_uint(tree, hf_nfs_fh_dirinode,
> tvb, offset+8, 4, dirinode);
>
> /* file system id (device) */
> {
> proto_item* fsid_item = NULL;
> proto_tree* fsid_tree = NULL;
>
> fsid_item = proto_tree_add_text(tree, tvb,
> offset+12, 4,
> "file system ID: %d,%d", fsid_major, fsid_minor);
> if (fsid_item) {
> fsid_tree = proto_item_add_subtree(fsid_item,
> ett_nfs_fh_fsid);
> proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
> tvb, offset+13, 1, fsid_major);
> proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
> tvb, offset+12, 1, fsid_minor);
> }
> }
>
> /* exported file system id (device) */
> {
> proto_item* xfsid_item = NULL;
> proto_tree* xfsid_tree = NULL;
>
> xfsid_item = proto_tree_add_text(tree, tvb,
> offset+16, 4,
> "exported file system ID: %d,%d", xfsid_major, xfsid_minor);
> if (xfsid_item) {
> xfsid_tree = proto_item_add_subtree(xfsid_item,
> ett_nfs_fh_xfsid);
> proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_major,
> tvb, offset+17, 1, xfsid_major);
> proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_minor,
> tvb, offset+16, 1, xfsid_minor);
> }
> }
>
> proto_tree_add_uint(tree, hf_nfs_fh_xfn_inode,
> tvb, offset+20, 4, xinode);
> proto_tree_add_uint(tree, hf_nfs_fh_fn_generation,
> tvb, offset+24, 4, gen);
> }
> }
>
>
> /* Checked with RedHat Linux 5.2 (nfs-server 2.2beta47 user-land nfsd) */
>
> static void
> dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> int offset=0;
>
> /* pseudo inode */
> {
> guint32 pinode;
> pinode = tvb_get_letohl(tvb, offset+0);
> if (tree) {
> proto_tree_add_uint(tree, hf_nfs_fh_pinode,
> tvb, offset+0, 4, pinode);
> }
> }
>
> /* hash path */
> {
> guint32 hashlen;
>
> hashlen = tvb_get_guint8(tvb, offset+4);
> if (tree) {
> proto_item* hash_item = NULL;
> proto_tree* hash_tree = NULL;
>
> hash_item = proto_tree_add_text(tree, tvb, offset+4,
> hashlen + 1,
> "hash path: %s",
> tvb_bytes_to_str(tvb,offset+5,hashlen));
> if (hash_item) {
> hash_tree = proto_item_add_subtree(hash_item,
> ett_nfs_fh_hp);
> if (hash_tree) {
> proto_tree_add_uint(hash_tree,
> hf_nfs_fh_hp_len, tvb, offset+4, 1,
> hashlen);
> proto_tree_add_text(hash_tree, tvb, offset+5,
> hashlen,
> "key: %s",
> tvb_bytes_to_str(tvb,offset+5,hashlen));
> }
> }
> }
> }
> }
>
>
> static void
> dissect_fhandle_data_NETAPP(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> int offset=0;
>
> if (tree) {
> guint32 mount = tvb_get_letohl(tvb, offset + 0);
> guint32 mount_gen = tvb_get_letohl(tvb, offset + 4);
> guint16 flags = tvb_get_letohs(tvb, offset + 8);
> guint8 snapid = tvb_get_guint8(tvb, offset + 10);
> guint8 unused = tvb_get_guint8(tvb, offset + 11);
> guint32 inum = tvb_get_ntohl(tvb, offset + 12);
> guint32 generation = tvb_get_letohl(tvb, offset + 16);
> guint32 fsid = tvb_get_letohl(tvb, offset + 20);
> guint32 export = tvb_get_letohl(tvb, offset + 24);
> guint32 export_snapgen = tvb_get_letohl(tvb, offset + 28);
>
> proto_item *item;
> proto_tree *subtree;
> char *flag_string;
> const char *strings[] = { " MNT_PNT", " SNAPDIR", " SNAPDIR_ENT",
> " EMPTY", " VBN_ACCESS", " MULTIVOLUME",
> " METADATA" };
> guint16 bit = sizeof(strings) / sizeof(strings[0]);
>
> flag_string=ep_alloc(512);
> flag_string[0]=0;
> while (bit--)
> if (flags & (1<<bit))
> strcat(flag_string, strings[bit]);
> item = proto_tree_add_text(tree, tvb, offset + 0, 8,
> "mount (inode %u)", mount);
> subtree = proto_item_add_subtree(item, ett_nfs_fh_mount);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_mount_fileid,
> tvb, offset + 0, 4, mount);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_mount_generation,
> tvb, offset + 4, 4, mount_gen);
> item = proto_tree_add_text(tree, tvb, offset + 8, 16,
> "file (inode %u)", inum);
> subtree = proto_item_add_subtree(item, ett_nfs_fh_file);
> item = proto_tree_add_uint_format(subtree, hf_nfs_fh_flags,
> tvb, offset + 8, 2, flags,
> "Flags: %#02x%s", flags,
> flag_string);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
> offset + 10, 1, snapid);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
> offset + 11, 1, unused);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
> offset + 12, 4, inum);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
> offset + 16, 4, generation);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
> offset + 20, 4, fsid);
> item = proto_tree_add_text(tree, tvb, offset + 24, 8,
> "export (inode %u)", export);
> subtree = proto_item_add_subtree(item, ett_nfs_fh_export);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
> tvb, offset + 24, 4, export);
> item = proto_tree_add_uint(subtree,
> hf_nfs_fh_export_generation,
> tvb, offset + 28, 3,
> export_snapgen & 0xffffff);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_export_snapid,
> tvb, offset + 31, 1,
> export_snapgen >> 24);
> }
> }
>
> const value_string netapp_file_flag_vals[] = {
> { 0x0000, "Not set"},
> { 0x0001, "Set"},
> { 0, NULL}
> };
>
> static void
> dissect_fhandle_data_NETAPP_V4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> int offset=0;
> proto_item *item = NULL;
> proto_tree *subtree = NULL;
> guint8 snapid, unused;
> guint16 flags;
> guint32 fileid, snapgen, generation, fsid;
> guint32 handle_type = tvb_get_ntohl(tvb, offset + 24);
> guint32 inum = tvb_get_ntohl(tvb, offset + 12);
>
> char *handle_string=NULL;
> const char *handle_type_strings [] = { "NORMAL",
> "UNEXP",
> "VOLDIR",
> "ROOT",
> "ABSENT",
> "INVALID"
> };
>
> char *flag_string;
> const char *strings[] = { " MNT_PNT",
> " SNAPDIR",
> " SNAPDIR_ENT",
> " EMPTY",
> " VBN_ACCESS",
> " MULTIVOLUME",
> " METADATA",
> " ORPHAN",
> " FOSTER",
> " NAMED_ATTR",
> " EXP_SNAPDIR",
> " VFILER",
> " NS_AGGR",
> " STRIPED",
> " NS_PRIVATE",
> " NEXT_GEN_FH"
> };
> guint16 bit = sizeof(strings) / sizeof(strings[0]);
> proto_tree *flag_tree = NULL;
>
> flag_string=ep_alloc(512);
> flag_string[0]=0;
>
> if(tree){
> if( handle_type !=0 && handle_type <= 255) {
> fileid = tvb_get_ntohl(tvb, offset + 0);
> snapgen = tvb_get_ntohl(tvb, offset + 4);
> flags = tvb_get_ntohs(tvb, offset + 8);
> snapid = tvb_get_guint8(tvb, offset + 10);
> unused = tvb_get_guint8(tvb, offset + 11);
> generation = tvb_get_ntohl(tvb, offset + 16);
> fsid = tvb_get_ntohl(tvb, offset + 20);
> } else {
> fileid = tvb_get_letohl(tvb, offset + 0);
> snapgen = tvb_get_letohl(tvb, offset + 4);
> flags = tvb_get_letohs(tvb, offset + 8);
> snapid = tvb_get_guint8(tvb, offset + 10);
> unused = tvb_get_guint8(tvb, offset + 11);
> generation = tvb_get_letohl(tvb, offset + 16);
> fsid = tvb_get_letohl(tvb, offset + 20);
> handle_type = tvb_get_letohl(tvb, offset + 24);
> }
>
> if(handle_type <= 4) {
> handle_string=handle_type_strings[handle_type];
> } else {
> handle_string=handle_type_strings[5];
> }
>
> while (bit--) {
> if (flags & (1<<bit)) {
> strcat(flag_string, strings[bit]);
> }
> }
>
> item = proto_tree_add_text(tree, tvb, offset + 0, 8, "export (inode %u)", fileid);
> subtree = proto_item_add_subtree(item, ett_nfsv4_fh_export);
>
> item = proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
> tvb, offset + 0, 4, fileid);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_export_generation,
> tvb, offset + 4, 4, snapgen);
> item = proto_tree_add_text(tree, tvb, offset + 8, 16, "file (inode %u)", inum);
> subtree = proto_item_add_subtree(item, ett_nfsv4_fh_file);
> item = proto_tree_add_uint_format(subtree, hf_nfs_fh_flags,
> tvb, offset + 8, 2, flags,
> "Flags: %#02x%s", flags,
> flag_string);
> flag_tree = proto_item_add_subtree(item, ett_nfsv4_fh_file_flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_mntpoint, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_snapdir, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_snapdir_ent, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_empty, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_vbn_access, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_multivolume, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_metadata, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_orphan, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_foster, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_named_attr, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_exp_snapdir, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_vfiler, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_aggr, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_striped, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_private, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_next_gen, tvb, offset+8, 2, flags);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
> offset + 10, 1, snapid);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
> offset + 11, 1, unused);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
> offset + 12, 4, inum);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
> offset + 16, 4, generation);
> item = proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
> offset + 20, 4, fsid);
> item = proto_tree_add_uint_format(tree, hf_nfs_fh_handle_type,
> tvb, offset+24, 4, handle_type,
> "Handle type: %s(%#02x)", handle_string, handle_type);
> }
> }
>
> #define NETAPP_GX_FH3_LENGTH 44
> #define NFS3GX_FH_TREE_MASK 0x80
> #define NFS3GX_FH_JUN_MASK 0x40
> #define NFS3GX_FH_VER_MASK 0x3F
> #define SPINNP_FH_FLAG_RESV1 0x80
> #define SPINNP_FH_FLAG_RESV2 0x40
> #define SPINNP_FH_FLAG_ONTAP_MASK 0x20
> #define SPINNP_FH_FLAG_STRIPED_MASK 0x10
> #define SPINNP_FH_FLAG_EMPTY_MASK 0x08
> #define SPINNP_FH_FLAG_SNAPDIR_ENT_MASK 0x04
> #define SPINNP_FH_FLAG_SNAPDIR_MASK 0x02
> #define SPINNP_FH_FLAG_STREAMDIR_MASK 0x01
>
> static void
> dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> proto_tree *field_tree;
> proto_item *tf;
> guint16 cluster_id;
> guint16 epoch;
> guint32 export_id;
> guint32 export_uid;
> guint8 flags;
> guint8 reserved;
> guint32 local_dsid;
> guint32 spinfile_id;
> guint32 spinfile_uid;
> guint8 utility;
> guint8 volcnt;
> guint32 offset = 0;
>
> if (tree) {
> /* = utility = */
> utility = tvb_get_guint8(tvb, offset);
> tf = proto_tree_add_uint_format(tree, hf_gxfh3_utlfield, tvb,
> offset, 1, utility,
> " utility: 0x%02x",utility);
>
>
> field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_utlfield);
> if (utility & NFS3GX_FH_TREE_MASK) {
> proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_tree_w, tvb,
> offset, 1, utility);
> }
> else {
> proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_tree_r, tvb,
> offset, 1, utility);
> }
> if (utility & NFS3GX_FH_JUN_MASK) {
> proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_jun, tvb,
> offset, 1, utility);
> }
> else {
> proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_jun_not, tvb,
> offset, 1, utility);
> }
> proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_ver, tvb,
> offset, 1, utility);
>
> /* = volume count== */
> volcnt = tvb_get_guint8(tvb, offset+1);
> proto_tree_add_uint_format(tree, hf_gxfh3_volcnt, tvb,
> offset+1, 1, volcnt,
> " volume count: 0x%02x (%d)", volcnt, volcnt);
> /* = epoch = */
> epoch = tvb_get_letohs(tvb, offset+2);
> proto_tree_add_uint_format(tree, hf_gxfh3_epoch, tvb,
> offset+2, 2, epoch,
> " epoch: 0x%04x (%u)", epoch, epoch);
> /* = spin file handle = */
> local_dsid = tvb_get_letohl(tvb, offset+4);
> cluster_id = tvb_get_letohs(tvb, offset+8);
> reserved = tvb_get_guint8(tvb, offset+10);
> flags = tvb_get_guint8(tvb, offset+11);
> spinfile_id = tvb_get_letohl(tvb, offset+12);
> spinfile_uid = tvb_get_letohl(tvb, offset+16);
>
> tf = proto_tree_add_text(tree, tvb, offset+4, 16,
> " spin file handle");
> field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhfield);
>
> proto_tree_add_uint_format(field_tree, hf_gxfh3_ldsid, tvb,
> offset+4, 4, local_dsid,
> " local dsid: 0x%08x (%u)", local_dsid, local_dsid);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_cid, tvb,
> offset+8, 2, cluster_id,
> " cluster id: 0x%04x (%u)", cluster_id, cluster_id);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_resv, tvb,
> offset+10, 1, reserved,
> " reserved: 0x%02x (%u)", reserved, reserved);
>
>
> tf = proto_tree_add_uint_format(field_tree, hf_gxfh3_sfhflags, tvb,
> offset+11, 1, utility,
> " flags: 0x%02x", flags);
> field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhflags);
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv1, tvb,
> offset+11, 1, flags);
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv2, tvb,
> offset+11, 1, flags);
>
> if (flags & SPINNP_FH_FLAG_ONTAP_MASK) {
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontap7G, tvb,
> offset+11, 1, flags);
> }
> else {
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontapGX, tvb,
> offset+11, 1, flags);
> }
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_striped, tvb,
> offset+11, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_empty, tvb,
> offset+11, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdirent, tvb,
> offset+11, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdir, tvb,
> offset+11, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_streamdir, tvb,
> offset+11, 1, flags);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfid, tvb,
> offset+12, 4, spinfile_id,
> "spin file id: 0x%08x (%u)", spinfile_id, spinfile_id);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfuid, tvb,
> offset+16, 4, spinfile_id,
> "spin file unique id: 0x%08x (%u)", spinfile_uid, spinfile_uid);
>
> /* = spin file handle (mount point) = */
> local_dsid = tvb_get_letohl(tvb, offset+20);
> cluster_id = tvb_get_letohs(tvb, offset+24);
> reserved = tvb_get_guint8(tvb, offset+26);
> flags = tvb_get_guint8(tvb, offset+27);
> spinfile_id = tvb_get_letohl(tvb, offset+28);
> spinfile_uid = tvb_get_letohl(tvb, offset+32);
>
> tf = proto_tree_add_text(tree, tvb, offset+20, 16,
> " spin (mount point) file handle");
> field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhfield);
>
> proto_tree_add_uint_format(field_tree, hf_gxfh3_ldsid, tvb,
> offset+20, 4, local_dsid,
> " local dsid: 0x%08x (%u)", local_dsid, local_dsid);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_cid, tvb,
> offset+24, 2, cluster_id,
> " cluster id: 0x%04x (%u)", cluster_id, cluster_id);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_resv, tvb,
> offset+26, 1, reserved,
> " reserved: 0x%02x (%u)", reserved, reserved);
>
>
> tf = proto_tree_add_uint_format(field_tree, hf_gxfh3_sfhflags, tvb,
> offset+27, 1, utility,
> " flags: 0x%02x", flags);
> field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhflags);
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv1, tvb,
> offset+27, 1, flags);
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv2, tvb,
> offset+27, 1, flags);
>
> if (flags & SPINNP_FH_FLAG_ONTAP_MASK) {
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontap7G, tvb,
> offset+27, 1, flags);
> }
> else {
> proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontapGX, tvb,
> offset+27, 1, flags);
> }
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_striped, tvb,
> offset+27, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_empty, tvb,
> offset+27, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdirent, tvb,
> offset+27, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdir, tvb,
> offset+27, 1, flags);
> proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_streamdir, tvb,
> offset+27, 1, flags);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfid, tvb,
> offset+28, 4, spinfile_id,
> "spin file id: 0x%08x (%u)", spinfile_id, spinfile_id);
> proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfuid, tvb,
> offset+32, 4, spinfile_id,
> "spin file unique id: 0x%08x (%u)", spinfile_uid, spinfile_uid);
> /* = export point id = */
> export_id = tvb_get_letohl(tvb, offset+36);
> export_uid = tvb_get_letohl(tvb, offset+40);
> proto_tree_add_uint_format(tree, hf_gxfh3_exportptid, tvb,
> offset+36, 4, spinfile_id,
> " export point id: 0x%08x (%u)", export_id, export_id);
> /* = export point unique id = */
> export_uid = tvb_get_letohl(tvb, offset+40);
> proto_tree_add_uint_format(tree, hf_gxfh3_exportptuid, tvb,
> offset+40, 4, spinfile_id,
> " export point unique id: 0x%08x (%u)", export_uid, export_uid);
>
> } /* end of (tree) */
> }
>
> /* Checked with SuSE 7.1 (kernel 2.4.0 knfsd) */
> /* read linux-2.4.5/include/linux/nfsd/nfsfh.h for more details */
>
> #define AUTH_TYPE_NONE 0
> static const value_string auth_type_names[] = {
> { AUTH_TYPE_NONE, "no authentication" },
> {0,NULL}
> };
>
> #define FSID_TYPE_MAJOR_MINOR_INODE 0
> static const value_string fsid_type_names[] = {
> { FSID_TYPE_MAJOR_MINOR_INODE, "major/minor/inode" },
> {0,NULL}
> };
>
> #define FILEID_TYPE_ROOT 0
> #define FILEID_TYPE_INODE_GENERATION 1
> #define FILEID_TYPE_INODE_GENERATION_PARENT 2
> static const value_string fileid_type_names[] = {
> { FILEID_TYPE_ROOT, "root" },
> { FILEID_TYPE_INODE_GENERATION, "inode/generation" },
> { FILEID_TYPE_INODE_GENERATION_PARENT, "inode/generation/parent" },
> {0,NULL}
> };
>
> static void
> dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> int offset=0;
> guint8 version;
> guint8 auth_type;
> guint8 fsid_type;
> guint8 fileid_type;
>
> version = tvb_get_guint8(tvb, offset + 0);
> if (tree) {
> proto_tree_add_uint(tree, hf_nfs_fh_version,
> tvb, offset+0, 1, version);
> }
>
> switch (version) {
> case 1: {
> auth_type = tvb_get_guint8(tvb, offset + 1);
> fsid_type = tvb_get_guint8(tvb, offset + 2);
> fileid_type = tvb_get_guint8(tvb, offset + 3);
> if (tree) {
> proto_item* encoding_item = proto_tree_add_text(tree, tvb,
> offset + 1, 3,
> "encoding: %u %u %u",
> auth_type, fsid_type, fileid_type);
> if (encoding_item) {
> proto_tree* encoding_tree = proto_item_add_subtree(encoding_item,
> ett_nfs_fh_encoding);
> if (encoding_tree) {
> proto_tree_add_uint(encoding_tree, hf_nfs_fh_auth_type,
> tvb, offset+1, 1, auth_type);
> proto_tree_add_uint(encoding_tree, hf_nfs_fh_fsid_type,
> tvb, offset+2, 1, fsid_type);
> proto_tree_add_uint(encoding_tree, hf_nfs_fh_fileid_type,
> tvb, offset+3, 1, fileid_type);
> }
> }
> }
> offset += 4;
> } break;
> default: {
> /* unknown version */
> goto out;
> }
> }
>
> switch (auth_type) {
> case 0: {
> /* no authentication */
> if (tree) {
> proto_tree_add_text(tree, tvb,
> offset + 0, 0,
> "authentication: none");
> }
> } break;
> default: {
> /* unknown authentication type */
> goto out;
> }
> }
>
> switch (fsid_type) {
> case 0: {
> guint16 fsid_major;
> guint16 fsid_minor;
> guint32 fsid_inode;
>
> fsid_major = tvb_get_ntohs(tvb, offset + 0);
> fsid_minor = tvb_get_ntohs(tvb, offset + 2);
> fsid_inode = tvb_get_letohl(tvb, offset + 4);
> if (tree) {
> proto_item* fsid_item = proto_tree_add_text(tree, tvb,
> offset+0, 8,
> "file system ID: %u,%u (inode %u)",
> fsid_major, fsid_minor, fsid_inode);
> if (fsid_item) {
> proto_tree* fsid_tree = proto_item_add_subtree(fsid_item,
> ett_nfs_fh_fsid);
> if (fsid_tree) {
> proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
> tvb, offset+0, 2, fsid_major);
> proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
> tvb, offset+2, 2, fsid_minor);
> proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_inode,
> tvb, offset+4, 4, fsid_inode);
> }
> }
> }
> offset += 8;
> } break;
> default: {
> /* unknown fsid type */
> goto out;
> }
> }
>
> switch (fileid_type) {
> case 0: {
> if (tree) {
> proto_tree_add_text(tree, tvb,
> offset+0, 0,
> "file ID: root inode");
> }
> } break;
> case 1: {
> guint32 inode;
> guint32 generation;
>
> inode = tvb_get_letohl(tvb, offset + 0);
> generation = tvb_get_letohl(tvb, offset + 4);
>
> if (tree) {
> proto_item* fileid_item = proto_tree_add_text(tree, tvb,
> offset+0, 8,
> "file ID: %u (%u)",
> inode, generation);
> if (fileid_item) {
> proto_tree* fileid_tree = proto_item_add_subtree(
> fileid_item, ett_nfs_fh_fn);
> if (fileid_tree) {
> proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
> tvb, offset+0, 4, inode);
> proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
> tvb, offset+4, 4, generation);
> }
> }
> }
>
> offset += 8;
> } break;
> case 2: {
> guint32 inode;
> guint32 generation;
> guint32 parent_inode;
>
> inode = tvb_get_letohl(tvb, offset + 0);
> generation = tvb_get_letohl(tvb, offset + 4);
> parent_inode = tvb_get_letohl(tvb, offset + 8);
>
> if (tree) {
> proto_item* fileid_item = proto_tree_add_text(tree, tvb,
> offset+0, 8,
> "file ID: %u (%u)",
> inode, generation);
> if (fileid_item) {
> proto_tree* fileid_tree = proto_item_add_subtree(
> fileid_item, ett_nfs_fh_fn);
> if (fileid_tree) {
> proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
> tvb, offset+0, 4, inode);
> proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
> tvb, offset+4, 4, generation);
> proto_tree_add_uint(fileid_tree, hf_nfs_fh_dirinode,
> tvb, offset+8, 4, parent_inode);
> }
> }
> }
>
> offset += 12;
> } break;
> default: {
> /* unknown fileid type */
> goto out;
> }
> }
>
> out:
> ;
> }
>
>
> static void
> dissect_fhandle_data_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
> {
> guint fhlen=tvb_length(tvb);
>
> proto_tree_add_item(tree, hf_nfs_fh_fhandle_data, tvb, 0, fhlen, FALSE);
> }
>
>
> static void
> dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
> proto_tree *tree, unsigned int fhlen, gboolean hidden, guint32 *hash)
> {
> /* this is to set up fhandle display filters to find both packets
> of an RPC call */
> if(nfs_fhandle_reqrep_matching && (!hidden) ){
> nfs_fhandle_data_t *old_fhd=NULL;
>
> if( !pinfo->fd->flags.visited ){
> nfs_fhandle_data_t fhd;
>
> /* first check if we have seen this fhandle before */
> fhd.len=fhlen;
> fhd.fh=(const unsigned char *)tvb_get_ptr(tvb, offset, fhlen);
> old_fhd=store_nfs_file_handle(&fhd);
>
> /* XXX here we should really check that we havent stored
> this fhandle for this frame number already.
> We should also make sure we can handle when we have multiple
> fhandles seen for the same frame, which WILL happen for certain
> nfs calls. For now, we dont handle this and those calls will
> not work properly with this feature
> */
> se_tree_insert32(nfs_fhandle_frame_table, pinfo->fd->num, old_fhd);
> }
> }
>
> /* create a semiunique hash value for the filehandle */
> {
> guint32 fhhash;
> guint32 i;
> proto_item *fh_item;
>
> for(fhhash=0,i=0;i<(fhlen-3);i+=4){
> guint32 val;
> val = tvb_get_ntohl(tvb, offset+i);
> fhhash ^= val;
> fhhash += val;
> }
> if(hidden){
> fh_item=proto_tree_add_uint_hidden(tree, hf_nfs_fh_hash, tvb, offset,
> fhlen, fhhash);
> } else {
> fh_item=proto_tree_add_uint(tree, hf_nfs_fh_hash, tvb, offset,
> fhlen, fhhash);
> }
> PROTO_ITEM_SET_GENERATED(fh_item);
> if(hash){
> *hash=fhhash;
> }
> }
> if(nfs_file_name_snooping){
> nfs_name_snoop_fh(pinfo, tree, tvb, offset, fhlen, hidden);
> }
>
> if(!hidden){
> tvbuff_t *fh_tvb;
> int real_length;
>
> proto_tree_add_text(tree, tvb, offset, 0,
> "decode type as: %s", val_to_str(default_nfs_fhandle_type, names_fhtype, "Unknown"));
>
>
> real_length=fhlen;
> if(real_length<tvb_length_remaining(tvb, offset)){
> real_length=tvb_length_remaining(tvb, offset);
> }
> fh_tvb=tvb_new_subset(tvb, offset, real_length, fhlen);
> if(!dissector_try_port(nfs_fhandle_table, default_nfs_fhandle_type, fh_tvb, pinfo, tree)){
> dissect_fhandle_data_unknown(fh_tvb, pinfo, tree);
> }
> }
> }
>
> void
> dissect_fhandle_hidden(packet_info *pinfo, proto_tree *tree, int frame)
> {
> nfs_fhandle_data_t *nfd;
>
> nfd=se_tree_lookup32(nfs_fhandle_frame_table, frame);
> if(nfd && nfd->len){
> dissect_fhandle_data(nfd->tvb, 0, pinfo, tree, nfd->len, TRUE, NULL);
> }
> }
>
>
> /***************************/
> /* NFS Version 2, RFC 1094 */
> /***************************/
>
>
> /* RFC 1094, Page 12..14 */
> static const value_string names_nfs_stat[] =
> {
> { 0, "NFS_OK" },
> { 1, "NFSERR_PERM" },
> { 2, "NFSERR_NOENT" },
> { 5, "NFSERR_IO" },
> { 6, "NFSERR_NXIO" },
> { 13, "NFSERR_ACCES" },
> { 17, "NFSERR_EXIST" },
> { 18, "NFSERR_XDEV" }, /* not in spec, but can happen */
> { 19, "NFSERR_NODEV" },
> { 20, "NFSERR_NOTDIR" },
> { 21, "NFSERR_ISDIR" },
> { 22, "NFSERR_INVAL" }, /* not in spec, but I think it can happen */
> { 26, "NFSERR_TXTBSY" }, /* not in spec, but I think it can happen */
> { 27, "NFSERR_FBIG" },
> { 28, "NFSERR_NOSPC" },
> { 30, "NFSERR_ROFS" },
> { 31, "NFSERR_MLINK" }, /* not in spec, but can happen */
> { 45, "NFSERR_OPNOTSUPP" }, /* not in spec, but I think it can happen */
> { 63, "NFSERR_NAMETOOLONG" },
> { 66, "NFSERR_NOTEMPTY" },
> { 69, "NFSERR_DQUOT" },
> { 70, "NFSERR_STALE" },
> { 99, "NFSERR_WFLUSH" },
> { 0, NULL }
> };
>
> /* RFC 1094, Page 12..14 */
> static int
> dissect_stat(tvbuff_t *tvb, int offset, proto_tree *tree,
> guint32 *status)
> {
> guint32 stat;
> proto_item *stat_item;
>
> stat = tvb_get_ntohl(tvb, offset+0);
>
> if (tree) {
> proto_tree_add_uint(tree, hf_nfs_stat, tvb, offset+0, 4,
> stat);
> stat_item = proto_tree_add_uint(tree, hf_nfs_nfsstat, tvb,
> offset+0, 4, stat);
> PROTO_ITEM_SET_HIDDEN(stat_item);
> }
>
> offset += 4;
>
> if (status) *status = stat;
>
> return offset;
> }
>
>
> /* RFC 1094, Page 12..14 */
> static int
> dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
> {
> guint32 status;
> const 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;
> const 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;
> const 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;
> const 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;
> const 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;
> }
>
>
> /* RFC 1094, Page 15 */
> static int
> dissect_ftype(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
> {
> guint32 ftype;
> const char* ftype_name = NULL;
>
> const value_string nfs2_ftype[] =
> {
> { 0, "Non-File" },
> { 1, "Regular File" },
> { 2, "Directory" },
> { 3, "Block Special Device" },
> { 4, "Character Special Device" },
> { 5, "Symbolic Link" },
> { 0, NULL }
> };
>
> ftype = tvb_get_ntohl(tvb, offset+0);
> ftype_name = val_to_str(ftype, nfs2_ftype, "%u");
>
> if (tree) {
> proto_tree_add_text(tree, tvb, offset, 4,
> "%s: %s (%u)", name, ftype_name, ftype);
> }
>
> offset += 4;
> return offset;
> }
>
>
> /* RFC 1094, Page 15 */
> int
> dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
> const char *name, guint32 *hash)
> {
> proto_item* fitem;
> proto_tree* ftree = NULL;
>
> if (tree) {
> fitem = proto_tree_add_text(tree, tvb, offset, FHSIZE,
> "%s", name);
> if (fitem)
> ftree = proto_item_add_subtree(fitem, ett_nfs_fhandle);
> }
>
> /* are we snooping fh to filenames ?*/
> if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
> rpc_call_info_value *civ=pinfo->private_data;
>
> /* NFS v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
> if( (civ->prog==100003)
> &&(civ->vers==2)
> &&(!civ->request)
> &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
> ) {
> nfs_name_snoop_add_fh(civ->xid, tvb,
> offset, 32);
> }
>
> /* MOUNT v1,v2 MNT replies might give us a filehandle*/
> if( (civ->prog==100005)
> &&(civ->proc==1)
> &&((civ->vers==1)||(civ->vers==2))
> &&(!civ->request)
> ) {
> nfs_name_snoop_add_fh(civ->xid, tvb,
> offset, 32);
> }
> }
>
> dissect_fhandle_data(tvb, offset, pinfo, ftree, FHSIZE, FALSE, hash);
>
> offset += FHSIZE;
> return offset;
> }
>
> /* RFC 1094, Page 15 */
> static int
> 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)
> {
> 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;
> }
>
>
> /* RFC 1094, Page 15 */
> static int
> dissect_timeval(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_time, int hf_time_sec, int hf_time_usec)
> {
> guint32 seconds;
> guint32 useconds;
> nstime_t ts;
>
> proto_item* time_item;
> proto_tree* time_tree = NULL;
>
> seconds = tvb_get_ntohl(tvb, offset+0);
> useconds = tvb_get_ntohl(tvb, offset+4);
> ts.secs = seconds;
> ts.nsecs = useconds*1000;
>
> if (tree) {
> time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
> &ts);
> if (time_item)
> time_tree = proto_item_add_subtree(time_item, ett_nfs_timeval);
> }
>
> if (time_tree) {
> proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
> seconds);
> proto_tree_add_uint(time_tree, hf_time_usec, tvb, offset+4, 4,
> useconds);
> }
> offset += 8;
> return offset;
> }
>
>
> /* RFC 1094, Page 16 */
> static const value_string nfs2_mode_names[] = {
> { 0040000, "Directory" },
> { 0020000, "Character Special Device" },
> { 0060000, "Block Special Device" },
> { 0100000, "Regular File" },
> { 0120000, "Symbolic Link" },
> { 0140000, "Named Socket" },
> { 0000000, NULL },
> };
>
> static int
> dissect_mode(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
> {
> guint32 mode;
> proto_item* mode_item = NULL;
> proto_tree* mode_tree = NULL;
>
> mode = tvb_get_ntohl(tvb, offset+0);
>
> if (tree) {
> mode_item = proto_tree_add_text(tree, tvb, offset, 4,
> "%s: 0%o", name, mode);
> if (mode_item)
> mode_tree = proto_item_add_subtree(mode_item, ett_nfs_mode);
> }
>
> if (mode_tree) {
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_enumerated_bitfield(mode, 0160000, 16,
> nfs2_mode_names, "%s"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 04000, 16, "Set user id on exec", "not SUID"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 02000, 16, "Set group id on exec", "not SGID"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 01000, 16, "Save swapped text even after use", "not save swapped text"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 0400, 16, "Read permission for owner", "no Read permission for owner"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 0200, 16, "Write permission for owner", "no Write permission for owner"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 0100, 16, "Execute permission for owner", "no Execute permission for owner"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 040, 16, "Read permission for group", "no Read permission for group"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 020, 16, "Write permission for group", "no Write permission for group"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 010, 16, "Execute permission for group", "no Execute permission for group"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 04, 16, "Read permission for others", "no Read permission for others"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 02, 16, "Write permission for others", "no Write permission for others"));
> proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
> decode_boolean_bitfield(mode, 01, 16, "Execute permission for others", "no Execute permission for others"));
> }
>
> offset += 4;
> return offset;
> }
>
>
> /* RFC 1094, Page 15 */
> int
> dissect_fattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
> {
> proto_item* fattr_item = NULL;
> proto_tree* fattr_tree = NULL;
> int old_offset = offset;
>
> if (tree) {
> fattr_item = proto_tree_add_text(tree, tvb, offset, -1,
> "%s", name);
> fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs_fattr);
> }
>
> offset = dissect_ftype(tvb, offset, fattr_tree, "type");
> offset = dissect_mode(tvb, offset, fattr_tree, "mode");
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_nlink, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_uid, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_gid, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_size, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocksize, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_rdev, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocks, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fsid, offset);
> offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fileid, offset);
>
> offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
> offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
> offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_usec);
>
> /* now we know, that fattr is shorter */
> if (fattr_item) {
> proto_item_set_len(fattr_item, offset - old_offset);
> }
>
> return offset;
> }
>
>
> /* RFC 1094, Page 17 */
> static int
> dissect_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
> {
> proto_item* sattr_item = NULL;
> proto_tree* sattr_tree = NULL;
> int old_offset = offset;
>
> if (tree) {
> sattr_item = proto_tree_add_text(tree, tvb, offset, -1,
> "%s", name);
> sattr_tree = proto_item_add_subtree(sattr_item, ett_nfs_sattr);
> }
>
> if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
> offset = dissect_mode(tvb, offset, sattr_tree, "mode");
> else {
> proto_tree_add_text(sattr_tree, tvb, offset, 4, "mode: no value");
> offset += 4;
> }
>
> if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
> offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_uid,
> offset);
> else {
> proto_tree_add_text(sattr_tree, tvb, offset, 4, "uid: no value");
> offset += 4;
> }
>
> if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
> offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_gid,
> offset);
> else {
> proto_tree_add_text(sattr_tree, tvb, offset, 4, "gid: no value");
> offset += 4;
> }
>
> if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
> offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_size,
> offset);
> else {
> proto_tree_add_text(sattr_tree, tvb, offset, 4, "size: no value");
> offset += 4;
> }
>
> if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
> offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
> } else {
> proto_tree_add_text(sattr_tree, tvb, offset, 8, "atime: no value");
> offset += 8;
> }
>
> if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
> offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
> } else {
> proto_tree_add_text(sattr_tree, tvb, offset, 8, "mtime: no value");
> offset += 8;
> }
>
> /* now we know, that sattr is shorter */
> if (sattr_item) {
> proto_item_set_len(sattr_item, offset - old_offset);
> }
>
> return offset;
> }
>
>
> /* RFC 1094, Page 17 */
> static int
> dissect_filename(tvbuff_t *tvb, int offset,
> proto_tree *tree, int hf, char **string_ret)
> {
> offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
> return offset;
> }
>
>
> /* RFC 1094, Page 17 */
> static int
> dissect_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
> {
> 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, packet_info *pinfo, const char *funcname)
> {
> guint32 status;
> const 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:
> 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;
> }
>
> return offset;
> }
>
>
> /* RFC 1094, Page 17,18 */
> static int
> dissect_nfs2_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* 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;
> }
>
>
> /* RFC 1094, Page 18 */
> static int
> dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, const char* label, guint32 *hash, char **name)
> {
> proto_item* diropargs_item = NULL;
> proto_tree* diropargs_tree = NULL;
> int old_offset = offset;
>
> if (tree) {
> diropargs_item = proto_tree_add_text(tree, tvb, offset, -1,
> "%s", label);
> diropargs_tree = proto_item_add_subtree(diropargs_item, ett_nfs_diropargs);
> }
>
> /* are we snooping fh to filenames ?*/
> if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
> /* v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
> rpc_call_info_value *civ=pinfo->private_data;
>
> if( (civ->prog==100003)
> &&(civ->vers==2)
> &&(civ->request)
> &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
> ) {
> nfs_name_snoop_add_name(civ->xid, tvb,
> offset+36, tvb_get_ntohl(tvb, offset+32),
> offset, 32, 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) {
> proto_item_set_len(diropargs_item, offset - old_offset);
> }
>
> return offset;
> }
>
>
> /* RFC 1094, Page 18 */
> static int
> 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);
>
> return offset;
> }
>
> static int
> dissect_nfs2_remove_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, ", REMOVE Call DH:0x%08x/%s", hash, 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);
>
> return offset;
> }
>
>
> /* RFC 1094, Page 18 */
> static int
> dissect_diropres(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, const char *funcname)
> {
> guint32 status;
> guint32 hash;
> const char *err;
>
> offset = dissect_stat(tvb, offset, tree, &status);
> switch (status) {
> case 0:
> 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:
> 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;
> }
>
> return offset;
> }
>
>
> /* nfsdata is simply a chunk of RPC opaque data (length, data, fill bytes) */
> static int
> dissect_nfsdata(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
> {
> offset = dissect_rpc_data(tvb, tree, hf, offset);
> return offset;
> }
>
>
> /* RFC 1094, Page 18 */
> static int
> dissect_nfs2_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
> proto_tree* 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;
> }
>
>
> /* RFC 1094, Page 6 */
> static int
> dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
> proto_tree *tree)
> {
> 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;
> }
>
>
> /* RFC 1094, Page 6 */
> static int
> dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
> proto_tree *tree)
> {
> guint32 status;
> const 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, &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);
> 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, ", READLINK Reply Error:%s", err);
> break;
> }
>
> return offset;
> }
>
>
> /* RFC 1094, Page 7 */
> static int
> dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
> proto_tree *tree)
> {
> guint32 offset_value;
> guint32 count;
> guint32 totalcount;
> guint32 hash;
>
> 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);
> if (tree) {
> proto_tree_add_uint(tree, hf_nfs_read_offset, tvb,
> offset+0, 4, offset_value);
> proto_tree_add_uint(tree, hf_nfs_read_count, tvb,
> offset+4, 4, count);
> proto_tree_add_uint(tree, hf_nfs_read_totalcount, tvb,
> offset+8, 4, totalcount);
> }
> 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;
> }
>
>
> /* RFC 1094, Page 7 */
> static int
> dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
> proto_tree* tree)
> {
> guint32 status;
> const 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:
> 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;
> }
>
> return offset;
> }
>
>
> /* RFC 1094, Page 8 */
> static int
> dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
> proto_tree *tree)
> {
> guint32 beginoffset;
> guint32 offset_value;
> guint32 totalcount;
> guint32 hash;
>
> 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);
> if (tree) {
> proto_tree_add_uint(tree, hf_nfs_write_beginoffset, tvb,
> offset+0, 4, beginoffset);
> proto_tree_add_uint(tree, hf_nfs_write_offset, tvb,
> offset+4, 4, offset_value);
> proto_tree_add_uint(tree, hf_nfs_write_totalcount, tvb,
> offset+8, 4, totalcount);
> }
> 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;
> }
>
>
> /* RFC 1094, Page 8 */
> static int
> 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);
>
> return offset;
> }
>
> static int
> dissect_nfs2_create_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, ", CREATE Call DH:0x%08x/%s", hash, name);
>
> return offset;
> }
>
>
> /* RFC 1094, Page 9 */
> static int
> dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
> proto_tree *tree)
> {
> 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);
>
> return offset;
> }
>
>
> /* RFC 1094, Page 9