Removed some unneeded assignments.
[obnox/wireshark/wip.git] / epan / dissectors / packet-nfs.c
1 /* packet-nfs.c
2  * Routines for nfs dissection
3  * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
4  * Copyright 2000-2004, Mike Frisch <frisch@hummingbird.com> (NFSv4 decoding)
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from packet-smb.c
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "packet-rpc.h"
38 #include "packet-nfs.h"
39 #include <epan/prefs.h>
40 #include <epan/packet.h>
41 #include <epan/emem.h>
42 #include <epan/strutil.h>
43 #include <epan/crc32.h>
44 #include <epan/expert.h>
45
46 #include <epan/crc16.h>
47 #include <glib.h>
48 #include <glib/gprintf.h>
49
50 static int proto_nfs = -1;
51 static int hf_nfs_access_check  = -1;
52 static int hf_nfs_access_supported  = -1;
53 static int hf_nfs_access_rights = -1;
54 static int hf_nfs_access_supp_read = -1;
55 static int hf_nfs_access_supp_lookup = -1;
56 static int hf_nfs_access_supp_modify = -1;
57 static int hf_nfs_access_supp_extend = -1;
58 static int hf_nfs_access_supp_delete = -1;
59 static int hf_nfs_access_supp_execute = -1;
60 static int hf_nfs_access_read = -1;
61 static int hf_nfs_access_lookup = -1;
62 static int hf_nfs_access_modify = -1;
63 static int hf_nfs_access_extend = -1;
64 static int hf_nfs_access_delete = -1;
65 static int hf_nfs_access_execute = -1;
66 static int hf_nfs_access_denied = -1;
67 static int hf_nfs_procedure_v2 = -1;
68 static int hf_nfs_procedure_v3 = -1;
69 static int hf_nfs_procedure_v4 = -1;
70 static int hf_nfs_fh_length = -1;
71 static int hf_nfs_impl_id4_len = -1;
72 static int hf_nfs_fh_hash = -1;
73 static int hf_nfs_fh_fhandle_data = -1;
74 static int hf_nfs_fh_mount_fileid = -1;
75 static int hf_nfs_fh_mount_generation = -1;
76 static int hf_nfs_fh_snapid = -1;
77 static int hf_nfs_fh_unused = -1;
78 static int hf_nfs_fh_flags = -1;
79 static int hf_nfs_fh_fileid = -1;
80 static int hf_nfs_fh_generation = -1;
81 static int hf_nfs_fh_fsid = -1;
82 static int hf_nfs_fh_export_fileid = -1;
83 static int hf_nfs_fh_export_generation = -1;
84 static int hf_nfs_fh_export_snapid = -1;
85 static int hf_nfs_fh_file_flag_mntpoint = -1;
86 static int hf_nfs_fh_file_flag_snapdir = -1;
87 static int hf_nfs_fh_file_flag_snapdir_ent = -1;
88 static int hf_nfs_fh_file_flag_empty = -1;
89 static int hf_nfs_fh_file_flag_vbn_access = -1;
90 static int hf_nfs_fh_file_flag_multivolume = -1;
91 static int hf_nfs_fh_file_flag_metadata = -1;
92 static int hf_nfs_fh_file_flag_orphan = -1;
93 static int hf_nfs_fh_file_flag_foster = -1;
94 static int hf_nfs_fh_file_flag_named_attr = -1;
95 static int hf_nfs_fh_file_flag_exp_snapdir = -1;
96 static int hf_nfs_fh_file_flag_vfiler = -1;
97 static int hf_nfs_fh_file_flag_aggr = -1;
98 static int hf_nfs_fh_file_flag_striped = -1;
99 static int hf_nfs_fh_file_flag_private = -1;
100 static int hf_nfs_fh_file_flag_next_gen = -1;
101 static int hf_nfs_fh_handle_type = -1;
102 static int hf_nfs_fh_fsid_major = -1;
103 static int hf_nfs_fh_fsid_minor = -1;
104 static int hf_nfs_fh_fsid_inode = -1;
105 static int hf_nfs_fh_xfsid_major = -1;
106 static int hf_nfs_fh_xfsid_minor = -1;
107 static int hf_nfs_fh_fstype = -1;
108 static int hf_nfs_fh_fn = -1;
109 static int hf_nfs_fh_fn_len = -1;
110 static int hf_nfs_fh_fn_inode = -1;
111 static int hf_nfs_fh_fn_generation = -1;
112 static int hf_nfs_fh_xfn = -1;
113 static int hf_nfs_fh_xfn_len = -1;
114 static int hf_nfs_fh_xfn_inode = -1;
115 static int hf_nfs_fh_xfn_generation = -1;
116 static int hf_nfs_fh_dentry = -1;
117 static int hf_nfs_fh_dev = -1;
118 static int hf_nfs_fh_xdev = -1;
119 static int hf_nfs_fh_dirinode = -1;
120 static int hf_nfs_fh_pinode = -1;
121 static int hf_nfs_fh_hp_len = -1;
122 static int hf_nfs_fh_version = -1;
123 static int hf_nfs_fh_auth_type = -1;
124 static int hf_nfs_fh_fsid_type = -1;
125 static int hf_nfs_fh_fileid_type = -1;
126 static int hf_nfs_fh_obj_id = -1;
127 static int hf_nfs_fh_ro_node = -1;
128 static int hf_nfs_fh_obj = -1;
129 static int hf_nfs_fh_obj_fsid = -1;
130 static int hf_nfs_fh_obj_treeid = -1;
131 static int hf_nfs_fh_obj_kindid = -1;
132 static int hf_nfs_fh_obj_inode = -1;
133 static int hf_nfs_fh_obj_gen = -1;
134 static int hf_nfs_fh_ex = -1;
135 static int hf_nfs_fh_ex_fsid = -1;
136 static int hf_nfs_fh_ex_treeid = -1;
137 static int hf_nfs_fh_ex_kindid = -1;
138 static int hf_nfs_fh_ex_inode = -1;
139 static int hf_nfs_fh_ex_gen = -1;
140 static int hf_nfs_fh_flag = -1;
141 static int hf_nfs_fh_endianness = -1;
142 static int hf_gxfh3_utlfield = -1;
143 static int hf_gxfh3_utlfield_tree_r = -1;
144 static int hf_gxfh3_utlfield_tree_w = -1;
145 static int hf_gxfh3_utlfield_jun = -1;
146 static int hf_gxfh3_utlfield_jun_not = -1;
147 static int hf_gxfh3_utlfield_ver = -1;
148 static int hf_gxfh3_volcnt = -1;
149 static int hf_gxfh3_epoch = -1;
150 static int hf_gxfh3_ldsid = -1;
151 static int hf_gxfh3_cid = -1;
152 static int hf_gxfh3_resv = -1;
153 static int hf_gxfh3_sfhflags = -1;
154 static int hf_gxfh3_sfhflags_resv1 = -1;
155 static int hf_gxfh3_sfhflags_resv2 = -1;
156 static int hf_gxfh3_sfhflags_ontap7G = -1;
157 static int hf_gxfh3_sfhflags_ontapGX = -1;
158 static int hf_gxfh3_sfhflags_striped = -1;
159 static int hf_gxfh3_sfhflags_empty = -1;
160 static int hf_gxfh3_sfhflags_snapdirent = -1;
161 static int hf_gxfh3_sfhflags_snapdir = -1;
162 static int hf_gxfh3_sfhflags_streamdir = -1;
163 static int hf_gxfh3_spinfid = -1;
164 static int hf_gxfh3_spinfuid = -1;
165 static int hf_gxfh3_exportptid = -1;
166 static int hf_gxfh3_exportptuid = -1;
167
168 static int hf_nfs_stat = -1;
169 static int hf_nfs_full_name = -1;
170 static int hf_nfs_name = -1;
171 static int hf_nfs_readlink_data = -1;
172 static int hf_nfs_read_offset = -1;
173 static int hf_nfs_read_count = -1;
174 static int hf_nfs_read_totalcount = -1;
175 static int hf_nfs_data = -1;
176 static int hf_read_data_length;
177 static int hf_write_data_length;
178 static int hf_nfs_write_beginoffset = -1;
179 static int hf_nfs_write_offset = -1;
180 static int hf_nfs_write_totalcount = -1;
181 static int hf_nfs_symlink_to = -1;
182 static int hf_nfs_readdir_cookie = -1;
183 static int hf_nfs_readdir_count = -1;
184 static int hf_nfs_readdir_entry = -1;
185 static int hf_nfs_readdir_entry_fileid = -1;
186 static int hf_nfs_readdir_entry_name = -1;
187 static int hf_nfs_readdir_entry_cookie = -1;
188 static int hf_nfs_readdir_entry3_fileid = -1;
189 static int hf_nfs_readdir_entry3_name = -1;
190 static int hf_nfs_readdir_entry3_cookie = -1;
191 static int hf_nfs_readdirplus_entry_fileid = -1;
192 static int hf_nfs_readdirplus_entry_name = -1;
193 static int hf_nfs_readdirplus_entry_cookie = -1;
194 static int hf_nfs_readdir_eof = -1;
195 static int hf_nfs_statfs_tsize = -1;
196 static int hf_nfs_statfs_bsize = -1;
197 static int hf_nfs_statfs_blocks = -1;
198 static int hf_nfs_statfs_bfree = -1;
199 static int hf_nfs_statfs_bavail = -1;
200 static int hf_nfs_ftype3 = -1;
201 static int hf_nfs_nfsstat3 = -1;
202 static int hf_nfs_read_eof = -1;
203 static int hf_nfs_write_stable = -1;
204 static int hf_nfs_write_committed = -1;
205 static int hf_nfs_createmode3 = -1;
206 static int hf_nfs_fsstat_invarsec = -1;
207 static int hf_nfs_fsinfo_rtmax = -1;
208 static int hf_nfs_fsinfo_rtpref = -1;
209 static int hf_nfs_fsinfo_rtmult = -1;
210 static int hf_nfs_fsinfo_wtmax = -1;
211 static int hf_nfs_fsinfo_wtpref = -1;
212 static int hf_nfs_fsinfo_wtmult = -1;
213 static int hf_nfs_fsinfo_dtpref = -1;
214 static int hf_nfs_fsinfo_maxfilesize = -1;
215 static int hf_nfs_fsinfo_properties = -1;
216 static int hf_nfs_pathconf_linkmax = -1;
217 static int hf_nfs_pathconf_name_max = -1;
218 static int hf_nfs_pathconf_no_trunc = -1;
219 static int hf_nfs_pathconf_chown_restricted = -1;
220 static int hf_nfs_pathconf_case_insensitive = -1;
221 static int hf_nfs_pathconf_case_preserving = -1;
222
223 static int hf_nfs_atime = -1;
224 static int hf_nfs_atime_sec = -1;
225 static int hf_nfs_atime_nsec = -1;
226 static int hf_nfs_atime_usec = -1;
227 static int hf_nfs_mtime = -1;
228 static int hf_nfs_mtime_sec = -1;
229 static int hf_nfs_mtime_nsec = -1;
230 static int hf_nfs_mtime_usec = -1;
231 static int hf_nfs_ctime = -1;
232 static int hf_nfs_ctime_sec = -1;
233 static int hf_nfs_ctime_nsec = -1;
234 static int hf_nfs_ctime_usec = -1;
235 static int hf_nfs_dtime = -1;
236 static int hf_nfs_dtime_sec = -1;
237 static int hf_nfs_dtime_nsec = -1;
238
239 static int hf_nfs_fattr_type = -1;
240 static int hf_nfs_fattr_nlink = -1;
241 static int hf_nfs_fattr_uid = -1;
242 static int hf_nfs_fattr_gid = -1;
243 static int hf_nfs_fattr_size = -1;
244 static int hf_nfs_fattr_blocksize = -1;
245 static int hf_nfs_fattr_rdev = -1;
246 static int hf_nfs_fattr_blocks = -1;
247 static int hf_nfs_fattr_fsid = -1;
248 static int hf_nfs_fattr_fileid = -1;
249 static int hf_nfs_fattr3_type = -1;
250 static int hf_nfs_fattr3_nlink = -1;
251 static int hf_nfs_fattr3_uid = -1;
252 static int hf_nfs_fattr3_gid = -1;
253 static int hf_nfs_fattr3_size = -1;
254 static int hf_nfs_fattr3_used = -1;
255 static int hf_nfs_fattr3_rdev = -1;
256 static int hf_nfs_fattr3_fsid = -1;
257 static int hf_nfs_fattr3_fileid = -1;
258 static int hf_nfs_wcc_attr_size = -1;
259 static int hf_nfs_set_size3_size = -1;
260 static int hf_nfs_cookie3 = -1;
261 static int hf_nfs_fsstat3_resok_tbytes = -1;
262 static int hf_nfs_fsstat3_resok_fbytes = -1;
263 static int hf_nfs_fsstat3_resok_abytes = -1;
264 static int hf_nfs_fsstat3_resok_tfiles = -1;
265 static int hf_nfs_fsstat3_resok_ffiles = -1;
266 static int hf_nfs_fsstat3_resok_afiles = -1;
267 static int hf_nfs_uid3 = -1;
268 static int hf_nfs_gid3 = -1;
269 static int hf_nfs_offset3 = -1;
270 static int hf_nfs_count3 = -1;
271 static int hf_nfs_count3_maxcount = -1;
272 static int hf_nfs_count3_dircount= -1;
273 static int hf_nfs_mode3 = -1;
274 static int hf_nfs_mode3_suid = -1;
275 static int hf_nfs_mode3_sgid = -1;
276 static int hf_nfs_mode3_sticky = -1;
277 static int hf_nfs_mode3_rusr = -1;
278 static int hf_nfs_mode3_wusr = -1;
279 static int hf_nfs_mode3_xusr = -1;
280 static int hf_nfs_mode3_rgrp = -1;
281 static int hf_nfs_mode3_wgrp = -1;
282 static int hf_nfs_mode3_xgrp = -1;
283 static int hf_nfs_mode3_roth = -1;
284 static int hf_nfs_mode3_woth = -1;
285 static int hf_nfs_mode3_xoth = -1;
286
287 /* NFSv4 */
288 static int hf_nfs_nfsstat4 = -1;
289 static int hf_nfs_op4 = -1;
290 static int hf_nfs_main_opcode = -1;
291 static int hf_nfs_linktext4 = -1;
292 static int hf_nfs_tag4 = -1;
293 static int hf_nfs_ops_count4 = -1;
294 static int hf_nfs_component4 = -1;
295 static int hf_nfs_clientid4 = -1;
296 static int hf_nfs_ace4 = -1;
297 static int hf_nfs_recall = -1;
298 static int hf_nfs_open_claim_type4 = -1;
299 static int hf_nfs_opentype4 = -1;
300 static int hf_nfs_state_protect_how4 = -1;
301 static int hf_nfs_limit_by4 = -1;
302 static int hf_nfs_open_delegation_type4 = -1;
303 static int hf_nfs_ftype4 = -1;
304 static int hf_nfs_change_info4_atomic = -1;
305 static int hf_nfs_open4_share_access = -1;
306 static int hf_nfs_open4_share_deny = -1;
307 static int hf_nfs_seqid4 = -1;
308 static int hf_nfs_lock_seqid4 = -1;
309 static int hf_nfs_mand_attr = -1;
310 static int hf_nfs_recc_attr = -1;
311 static int hf_nfs_time_how4 = -1;
312 static int hf_nfs_attrlist4 = -1;
313 static int hf_nfs_fattr4_link_support = -1;
314 static int hf_nfs_fattr4_symlink_support = -1;
315 static int hf_nfs_fattr4_named_attr = -1;
316 static int hf_nfs_fattr4_unique_handles = -1;
317 static int hf_nfs_fattr4_archive = -1;
318 static int hf_nfs_fattr4_cansettime = -1;
319 static int hf_nfs_fattr4_case_insensitive = -1;
320 static int hf_nfs_fattr4_case_preserving = -1;
321 static int hf_nfs_fattr4_chown_restricted = -1;
322 static int hf_nfs_fattr4_hidden = -1;
323 static int hf_nfs_fattr4_homogeneous = -1;
324 static int hf_nfs_fattr4_mimetype = -1;
325 static int hf_nfs_fattr4_no_trunc = -1;
326 static int hf_nfs_fattr4_system = -1;
327 static int hf_nfs_fattr4_owner = -1;
328 static int hf_nfs_fattr4_owner_group = -1;
329 static int hf_nfs_fattr4_size = -1;
330 static int hf_nfs_fattr4_aclsupport = -1;
331 static int hf_nfs_fattr4_lease_time = -1;
332 static int hf_nfs_fattr4_fileid = -1;
333 static int hf_nfs_fattr4_files_avail = -1;
334 static int hf_nfs_fattr4_files_free = -1;
335 static int hf_nfs_fattr4_files_total = -1;
336 static int hf_nfs_fattr4_maxfilesize = -1;
337 static int hf_nfs_fattr4_maxlink = -1;
338 static int hf_nfs_fattr4_maxname = -1;
339 static int hf_nfs_fattr4_numlinks = -1;
340 static int hf_nfs_fattr4_maxread = -1;
341 static int hf_nfs_fattr4_maxwrite = -1;
342 static int hf_nfs_fattr4_quota_hard = -1;
343 static int hf_nfs_fattr4_quota_soft = -1;
344 static int hf_nfs_fattr4_quota_used = -1;
345 static int hf_nfs_fattr4_space_avail = -1;
346 static int hf_nfs_fattr4_space_free = -1;
347 static int hf_nfs_fattr4_space_total = -1;
348 static int hf_nfs_fattr4_space_used = -1;
349 static int hf_nfs_fattr4_mounted_on_fileid = -1;
350 static int hf_nfs_fattr4_layout_blksize = -1;
351 static int hf_nfs_who = -1;
352 static int hf_nfs_server = -1;
353 static int hf_nfs_fslocation4 = -1;
354 static int hf_nfs_stable_how4 = -1;
355 static int hf_nfs_dirlist4_eof = -1;
356 static int hf_nfs_stateid4 = -1;
357 static int hf_nfs_offset4 = -1;
358 static int hf_nfs_specdata1 = -1;
359 static int hf_nfs_specdata2 = -1;
360 static int hf_nfs_lock_type4 = -1;
361 static int hf_nfs_reclaim4 = -1;
362 static int hf_nfs_length4 = -1;
363 static int hf_nfs_changeid4 = -1;
364 static int hf_nfs_changeid4_before = -1;
365 static int hf_nfs_changeid4_after = -1;
366 static int hf_nfs_nfstime4_seconds = -1;
367 static int hf_nfs_nfstime4_nseconds = -1;
368 static int hf_nfs_fsid4_major = -1;
369 static int hf_nfs_fsid4_minor = -1;
370 static int hf_nfs_acetype4 = -1;
371 static int hf_nfs_aceflag4 = -1;
372 static int hf_nfs_acemask4 = -1;
373 static int hf_nfs_delegate_type = -1;
374 static int hf_nfs_secinfo_flavor = -1;
375 static int hf_nfs_secinfo_arr4 = -1;
376 static int hf_nfs_num_blocks = -1;
377 static int hf_nfs_bytes_per_block = -1;
378 static int hf_nfs_eof = -1;
379 static int hf_nfs_verifier4 = -1;
380 static int hf_nfs_cookie4 = -1;
381 static int hf_nfs_cookieverf4 = -1;
382 static int hf_nfs_cb_program = -1;
383 static int hf_nfs_cb_location = -1;
384 static int hf_nfs_recall4 = -1;
385 static int hf_nfs_filesize = -1;
386 static int hf_nfs_count4 = -1;
387 static int hf_nfs_count4_dircount = -1;
388 static int hf_nfs_count4_maxcount = -1;
389 static int hf_nfs_minorversion = -1;
390 static int hf_nfs_open_owner4 = -1;
391 static int hf_nfs_lock_owner4 = -1;
392 static int hf_nfs_new_lock_owner = -1;
393 static int hf_nfs_sec_oid4 = -1;
394 static int hf_nfs_qop4 = -1;
395 static int hf_nfs_secinfo_rpcsec_gss_info_service = -1;
396 static int hf_nfs_attrdircreate = -1;
397 static int hf_nfs_client_id4_id = -1;
398 static int hf_nfs_stateid4_other = -1;
399 static int hf_nfs_stateid4_hash = -1;
400 static int hf_nfs_lock4_reclaim = -1;
401 static int hf_nfs_acl4 = -1;
402 static int hf_nfs_callback_ident = -1;
403 static int hf_nfs_r_netid = -1;
404 static int hf_nfs_gsshandle4 = -1;
405 static int hf_nfs_r_addr = -1;
406 static int hf_nfs_createmode4 = -1;
407
408 /* NFSv4.1 */
409 static int hf_nfs_length4_minlength = -1;
410 static int hf_nfs_layouttype4 = -1;
411 static int hf_nfs_layoutreturn_type4 = -1;
412 static int hf_nfs_iomode4 = -1;
413 static int hf_nfs_stripetype4 = -1;
414 static int hf_nfs_mdscommit4 = -1;
415 static int hf_nfs_stripeunit4 = -1;
416 static int hf_nfs_newtime4 = -1;
417 static int hf_nfs_newoffset4 = -1;
418 static int hf_nfs_layout_avail4 = -1;
419 static int hf_nfs_newsize4 = -1;
420 static int hf_nfs_layoutupdate4 = -1;
421 static int hf_nfs_deviceid4 = -1;
422 static int hf_nfs_devicenum4 = -1;
423 static int hf_nfs_deviceidx4 = -1;
424 static int hf_nfs_layout4 = -1;
425 static int hf_nfs_stripedevs4 = -1;
426 static int hf_nfs_devaddr4 = -1;
427 static int hf_nfs_return_on_close4 = -1;
428 static int hf_nfs_slotid4 = -1;
429 static int hf_nfs_high_slotid4 = -1;
430 static int hf_nfs_target_high_slotid4 = -1;
431 static int hf_nfs_sr_status4 = -1;
432 static int hf_nfs_serverscope4 = -1;
433 static int hf_nfs_minorid4 = -1;
434 static int hf_nfs_majorid4 = -1;
435 static int hf_nfs_padsize4 = -1;
436 static int hf_nfs_cbrenforce4 = -1;
437 static int hf_nfs_hashalg4 = -1;
438 static int hf_nfs_ssvlen4 = -1;
439 static int hf_nfs_maxreqsize4 = -1;
440 static int hf_nfs_maxrespsize4 = -1;
441 static int hf_nfs_maxrespsizecached4 = -1;
442 static int hf_nfs_maxops4 = -1;
443 static int hf_nfs_maxreqs4 = -1;
444 static int hf_nfs_rdmachanattrs4 = -1;
445 static int hf_nfs_machinename4 = -1;
446 static int hf_nfs_flavor4 = -1;
447 static int hf_nfs_stamp4 = -1;
448 static int hf_nfs_uid4 = -1;
449 static int hf_nfs_gid4 = -1;
450 static int hf_nfs_service4 = -1;
451 static int hf_nfs_sessionid4 = -1;
452 static int hf_nfs_exch_id_flags4 = -1;
453 static int hf_nfs_exchid_flags_moved_refer = -1;
454 static int hf_nfs_exchid_flags_moved_migr = -1;
455 static int hf_nfs_exchid_flags_bind_princ = -1;
456 static int hf_nfs_exchid_flags_non_pnfs = -1;
457 static int hf_nfs_exchid_flags_pnfs_mds = -1;
458 static int hf_nfs_exchid_flags_pnfs_ds = -1;
459 static int hf_nfs_exchid_flags_upd_conf_rec_a = -1;
460 static int hf_nfs_exchid_flags_confirmed_r = -1;
461 static int hf_nfs_state_protect_window = -1;
462 static int hf_nfs_state_protect_num_gss_handles = -1;
463 static int hf_nfs_prot_info4_spi_window = -1;
464 static int hf_nfs_prot_info4_svv_length = -1;
465 static int hf_nfs_prot_info4_encr_alg = -1;
466 static int hf_nfs_prot_info4_hash_alg = -1;
467 static int hf_nfs_nii_domain4 = -1;
468 static int hf_nfs_nii_name4 = -1;
469 static int hf_nfs_create_session_flags4 = -1;
470 static int hf_nfs_cachethis4 = -1;
471 static int hf_nfs_util4 = -1;
472 static int hf_nfs_first_stripe_idx4 = -1;
473 static int hf_nfs_layout_count = -1;
474 static int hf_nfs_pattern_offset = -1;
475 static int hf_nfs_notification_bitmap4 = -1;
476 static int hf_nfs_lrs_present = -1;
477 static int hf_nfs_nfl_util = -1;
478 static int hf_nfs_nfl_first_stripe_index = -1;
479 static int hf_nfs_lrf_body_content = -1;
480 static int hf_nfs_reclaim_one_fs4 = -1;
481
482 /* Hidden field for v2, v3, and v4 status */
483 int hf_nfs_nfsstat = -1;
484
485 static gint ett_nfs = -1;
486 static gint ett_nfs_fh_encoding = -1;
487 static gint ett_nfs_fh_mount = -1;
488 static gint ett_nfs_fh_file = -1;
489 static gint ett_nfs_fh_export = -1;
490 static gint ett_nfsv4_fh_export = -1;
491 static gint ett_nfsv4_fh_file   = -1;
492 static gint ett_nfsv4_fh_handle_type = -1;
493 static gint ett_nfsv4_fh_export_snapgen = -1;
494 static gint ett_nfsv4_fh_file_flags = -1;
495 static gint ett_nfs_fh_fsid = -1;
496 static gint ett_nfs_fh_xfsid = -1;
497 static gint ett_nfs_fh_fn = -1;
498 static gint ett_nfs_fh_xfn = -1;
499 static gint ett_nfs_fh_hp = -1;
500 static gint ett_nfs_fh_auth = -1;
501 static gint ett_nfs_fhandle = -1;
502 static gint ett_nfs_timeval = -1;
503 static gint ett_nfs_mode = -1;
504 static gint ett_nfs_fattr = -1;
505 static gint ett_nfs_sattr = -1;
506 static gint ett_nfs_diropargs = -1;
507 static gint ett_nfs_readdir_entry = -1;
508 static gint ett_nfs_mode3 = -1;
509 static gint ett_nfs_specdata3 = -1;
510 static gint ett_nfs_fh3 = -1;
511 static gint ett_nfs_nfstime3 = -1;
512 static gint ett_nfs_fattr3 = -1;
513 static gint ett_nfs_post_op_fh3 = -1;
514 static gint ett_nfs_sattr3 = -1;
515 static gint ett_nfs_diropargs3 = -1;
516 static gint ett_nfs_sattrguard3 = -1;
517 static gint ett_nfs_set_mode3 = -1;
518 static gint ett_nfs_set_uid3 = -1;
519 static gint ett_nfs_set_gid3 = -1;
520 static gint ett_nfs_set_size3 = -1;
521 static gint ett_nfs_set_atime = -1;
522 static gint ett_nfs_set_mtime = -1;
523 static gint ett_nfs_pre_op_attr = -1;
524 static gint ett_nfs_post_op_attr = -1;
525 static gint ett_nfs_wcc_attr = -1;
526 static gint ett_nfs_wcc_data = -1;
527 static gint ett_nfs_access3 = -1;
528 static gint ett_nfs_fsinfo_properties = -1;
529 static gint ett_nfs_gxfh3_utlfield = -1;
530 static gint ett_nfs_gxfh3_sfhfield = -1;
531 static gint ett_nfs_gxfh3_sfhflags = -1;
532
533 /* NFSv4 */
534 static gint ett_nfs_compound_call4 = -1;
535 static gint ett_nfs_utf8string = -1;
536 static gint ett_nfs_argop4 = -1;
537 static gint ett_nfs_resop4 = -1;
538 static gint ett_nfs_access4 = -1;
539 static gint ett_nfs_access_supp4 = -1;
540 static gint ett_nfs_close4 = -1;
541 static gint ett_nfs_commit4 = -1;
542 static gint ett_nfs_create4 = -1;
543 static gint ett_nfs_delegpurge4 = -1;
544 static gint ett_nfs_delegreturn4 = -1;
545 static gint ett_nfs_getattr4 = -1;
546 static gint ett_nfs_getattr4_args = -1;
547 static gint ett_nfs_getattr4_resp = -1;
548 static gint ett_nfs4_resok4 = -1;
549 static gint ett_nfs4_obj_attrs = -1;
550 static gint ett_nfs4_fattr4_new_attr_vals = -1;
551 static gint ett_nfs4_fattr4_attrmask = -1;
552 static gint ett_nfs4_attribute = -1;
553 static gint ett_nfs_getfh4 = -1;
554 static gint ett_nfs_link4 = -1;
555 static gint ett_nfs_lock4 = -1;
556 static gint ett_nfs_lockt4 = -1;
557 static gint ett_nfs_locku4 = -1;
558 static gint ett_nfs_lookup4 = -1;
559 static gint ett_nfs_lookupp4 = -1;
560 static gint ett_nfs_nverify4 = -1;
561 static gint ett_nfs_open4 = -1;
562 static gint ett_nfs_openattr4 = -1;
563 static gint ett_nfs_open_confirm4 = -1;
564 static gint ett_nfs_open_downgrade4 = -1;
565 static gint ett_nfs_putfh4 = -1;
566 static gint ett_nfs_putpubfh4 = -1;
567 static gint ett_nfs_putrootfh4 = -1;
568 static gint ett_nfs_read4 = -1;
569 static gint ett_nfs_readdir4 = -1;
570 static gint ett_nfs_readlink4 = -1;
571 static gint ett_nfs_remove4 = -1;
572 static gint ett_nfs_rename4 = -1;
573 static gint ett_nfs_renew4 = -1;
574 static gint ett_nfs_restorefh4 = -1;
575 static gint ett_nfs_savefh4 = -1;
576 static gint ett_nfs_secinfo4 = -1;
577 static gint ett_nfs_setattr4 = -1;
578 static gint ett_nfs_setclientid4 = -1;
579 static gint ett_nfs_setclientid_confirm4 = -1;
580 static gint ett_nfs_verify4 = -1;
581 static gint ett_nfs_write4 = -1;
582 static gint ett_nfs_release_lockowner4 = -1;
583 static gint ett_nfs_illegal4 = -1;
584 static gint ett_nfs_verifier4 = -1;
585 static gint ett_nfs_opaque = -1;
586 static gint ett_nfs_dirlist4 = -1;
587 static gint ett_nfs_pathname4 = -1;
588 static gint ett_nfs_change_info4 = -1;
589 static gint ett_nfs_open_delegation4 = -1;
590 static gint ett_nfs_open_claim4 = -1;
591 static gint ett_nfs_opentype4 = -1;
592 static gint ett_nfs_lock_owner4 = -1;
593 static gint ett_nfs_cb_client4 = -1;
594 static gint ett_nfs_client_id4 = -1;
595 static gint ett_nfs_clientowner4 = -1;
596 static gint ett_exchangeid_flags = -1;
597 static gint ett_server_owner4 = -1;
598 static gint ett_nfs_bitmap4 = -1;
599 static gint ett_nfs_attr_request = -1;
600 static gint ett_nfs_fattr4 = -1;
601 static gint ett_nfs_fsid4 = -1;
602 static gint ett_nfs_fs_locations4 = -1;
603 static gint ett_nfs_fs_location4 = -1;
604 static gint ett_nfs_open4_result_flags = -1;
605 static gint ett_nfs_secinfo4_flavor_info = -1;
606 static gint ett_nfs_stateid4 = -1;
607 static gint ett_nfs_fattr4_fh_expire_type = -1;
608 static gint ett_nfs_ace4 = -1;
609 static gint ett_nfs_clientaddr4 = -1;
610 static gint ett_nfs_aceflag4 = -1;
611 static gint ett_nfs_acemask4 = -1;
612
613 static gint ett_nfs_layoutget4 = -1;
614 static gint ett_nfs_layoutcommit4 = -1;
615 static gint ett_nfs_layoutreturn4 = -1;
616 static gint ett_nfs_getdevinfo4 = -1;
617 static gint ett_nfs_getdevlist4 = -1;
618 static gint ett_nfs_exchange_id4 = -1;
619 static gint ett_nfs_create_session4 = -1;
620 static gint ett_nfs_destroy_session4 = -1;
621 static gint ett_nfs_sequence4 = -1;
622 static gint ett_nfs_slotid4 = -1;
623 static gint ett_nfs_sr_status4 = -1;
624 static gint ett_nfs_serverscope4 = -1;
625 static gint ett_nfs_minorid4 = -1;
626 static gint ett_nfs_majorid4 = -1;
627 static gint ett_nfs_persist4 = -1;
628 static gint ett_nfs_backchan4 = -1;
629 static gint ett_nfs_rdmamode4 = -1;
630 static gint ett_nfs_padsize4 = -1;
631 static gint ett_nfs_cbrenforce4 = -1;
632 static gint ett_nfs_hashalg4 = -1;
633 static gint ett_nfs_ssvlen4 = -1;
634 static gint ett_nfs_maxreqsize4 = -1;
635 static gint ett_nfs_maxrespsize4 = -1;
636 static gint ett_nfs_maxrespsizecached4 = -1;
637 static gint ett_nfs_maxops4 = -1;
638 static gint ett_nfs_maxreqs4 = -1;
639 static gint ett_nfs_streamchanattrs4 = -1;
640 static gint ett_nfs_rdmachanattrs4 = -1;
641 static gint ett_nfs_machinename4 = -1;
642 static gint ett_nfs_flavor4 = -1;
643 static gint ett_nfs_stamp4 = -1;
644 static gint ett_nfs_uid4 = -1;
645 static gint ett_nfs_gid4 = -1;
646 static gint ett_nfs_service4 = -1;
647 static gint ett_nfs_sessionid4 = -1;
648 static gint ett_nfs_layoutseg = -1;
649 static gint ett_nfs_fh_obj = -1;
650 static gint ett_nfs_fh_ex = -1;
651 static gint ett_nfs_layoutseg_fh = -1;
652 static gint ett_nfs_reclaim_complete4 = -1;
653
654 /* what type of fhandles shoudl we dissect as */
655 static dissector_table_t nfs_fhandle_table;
656
657
658 #define FHT_UNKNOWN             0
659 #define FHT_SVR4                1
660 #define FHT_LINUX_KNFSD_LE      2
661 #define FHT_LINUX_NFSD_LE       3
662 #define FHT_LINUX_KNFSD_NEW     4
663 #define FHT_NETAPP              5
664 #define FHT_NETAPP_V4           6
665 #define FHT_NETAPP_GX_V3        7
666 #define FHT_CELERRA             8
667
668
669 static enum_val_t nfs_fhandle_types[] = {
670         { "unknown",    "Unknown",      FHT_UNKNOWN },
671         { "svr4",       "SVR4",         FHT_SVR4 },
672         { "knfsd_le",   "KNFSD_LE",     FHT_LINUX_KNFSD_LE },
673         { "nfsd_le",    "NFSD_LE",      FHT_LINUX_NFSD_LE },
674         { "knfsd_new",  "KNFSD_NEW",    FHT_LINUX_KNFSD_NEW },
675         { "ontap_v3",   "ONTAP_V3",     FHT_NETAPP },
676         { "ontap_v4",   "ONTAP_V4",     FHT_NETAPP_V4},
677         { "ontap_gx_v3","ONTAP_GX_V3",  FHT_NETAPP_GX_V3},
678         { "celerra",    "CELERRA",      FHT_CELERRA },
679         { NULL, NULL, 0 }
680 };
681 /* decode all nfs filehandles as this type */
682 static gint default_nfs_fhandle_type=FHT_UNKNOWN;
683
684 /* For dissector helpers which take a "levels" argument to indicate how
685  * many expansions up they should populate the expansion items with
686  * text to enhance useability, this flag to "levels" specify that the
687  * text should also be appended to COL_INFO
688  */
689 #define COL_INFO_LEVEL 0x80000000
690
691
692 /* fhandle displayfilters to match also corresponding request/response
693    packet in addition to the one containing the actual filehandle */
694 gboolean nfs_fhandle_reqrep_matching = FALSE;
695 static emem_tree_t *nfs_fhandle_frame_table = NULL;
696
697 typedef struct _nfsv4_operation_summary {
698                 guint32 opcode;
699                 gboolean iserror;
700                 GString *optext;
701 } nfsv4_operation_summary;
702
703
704 /* To try to determine which NFSv4 operations are most important in a request, we categorize
705  the operations into different "tiers".
706  All operations falling into the highest tier (where 1 is highest, 5 is lowest) are considered
707  to be the "most significant" operations.  This information is useful for display purposes,
708  filtering, and for response time calculations.
709  For example, virtually all NFSv4 requests include a GETATTR.  But in a request with
710  PUTFH; CLOSE; GETATTR operations, CLOSE is the significant operation.  In a request with
711  PUTFH; GETATTR operations, GETATTR is the significant operation.  CLOSE has higher tier than
712  GETATTR, which is in a higher tier than PUTFH.
713  In practice this seems to be a very reliable method of determining the most significant
714  operation(s). */
715
716 static int nfsv4_operation_tiers[] = {
717                  1 /* 0 */ ,
718                  1 /* 1 */ ,
719                  1 /* 2 */ ,
720                  2 /* 3, NFS4_OP_ACCESS */ ,
721                  1 /* 4, NFS4_OP_CLOSE */,
722                  1 /* 5, NFS4_OP_COMMIT */,
723                  1 /* 6, NFS4_OP_CREATE */,
724                  1 /* 7, NFS4_OP_DELEGPURGE     */,
725                  1 /* 8, NFS4_OP_DELEGRETURN */,
726                  3 /* 9, NFS4_OP_GETATTR */,
727                  4 /* 10, NFS4_OP_GETFH */,
728                  1 /* 11, NFS4_OP_LINK  */,
729                  1 /* 12, NFS4_OP_LOCK */,
730                  1 /* 13, NFS4_OP_LOCKT */,
731                  1 /* 14, NFS4_OP_LOCKU */,
732                  1 /* 15, NFS4_OP_LOOKUP */,
733                  1 /* 16, NFS4_OP_LOOKUPP */,
734                  2 /* 17, NFS4_OP_NVERIFY */,
735                  1 /* 18, NFS4_OP_OPEN */,
736                  1 /* 19, NFS4_OP_OPENATTR */,
737                  1 /* 20, NFS4_OP_OPEN_CONFIRM */,
738                  1 /* 21, NFS4_OP_OPEN_DOWNGRADE */,
739                  4 /* 22, NFS4_OP_PUTFH */,
740                  3 /* 23, NFS4_OP_PUTPUBFH      */,
741                  3 /* 24, NFS4_OP_PUTROOTFH     */,
742                  1 /* 25, NFS4_OP_READ  */,
743                  1 /* 26, NFS4_OP_READDIR */,
744                  1 /* 27, NFS4_OP_READLINK      */,
745                  1 /* 28, NFS4_OP_REMOVE */,
746                  1 /* 29, NFS4_OP_RENAME */,
747                  1 /* 30, NFS4_OP_RENEW */,
748                  4 /* 31, NFS4_OP_RESTOREFH     */,
749                  4 /* 32, NFS4_OP_SAVEFH */,
750                  1 /* 33, NFS4_OP_SECINFO */,
751                  1 /* 34, NFS4_OP_SETATTR */,
752                  1 /* 35, NFS4_OP_SETCLIENTID */,
753                  1 /* 36, NFS4_OP_SETCLIENTID_CONFIRM */,
754                  1 /* 37, NFS4_OP_VERIFY */,
755                  1 /* 38, NFS4_OP_WRITE */,
756                  1 /* 39, NFS4_OP_RELEASE_LOCKOWNER     */,
757                         /* Minor version 1 */
758                  1 /* 40, NFS4_OP_BACKCHANNEL_CTL */,
759                  1 /* 41, NFS4_OP_BIND_CONN_TO_SESSION */,
760                  1 /* 42, NFS4_OP_EXCHANGE_ID */,
761                  1 /* 43, NFS4_OP_CREATE_SESSION */,
762                  1 /* 44, NFS4_OP_DESTROY_SESSION */,
763                  1 /* 45, NFS4_OP_FREE_STATEID */,
764                  1 /* 46, NFS4_OP_GET_DIR_DELEGATION */,
765                  1 /* 47, NFS4_OP_GETDEVINFO */,
766                  1 /* 48, NFS4_OP_GETDEVLIST */,
767                  1 /* 49, NFS4_OP_LAYOUTCOMMIT */,
768                  1 /* 50, NFS4_OP_LAYOUTGET */,
769                  1 /* 51, NFS4_OP_LAYOUTRETURN */,
770                  1 /* 52, NFS4_OP_SECINFO_NO_NAME */,
771                  1 /* 53, NFS4_OP_SEQUENCE */,
772                  1 /* 54, NFS4_OP_SET_SSV */,
773                  1 /* 55, NFS4_OP_TEST_STATEID */,
774                  1 /* 56, NFS4_OP_WANT_DELEGATION  */,
775                  1 /* 57, NFS4_OP_DESTROY_CLIENTID  */,
776                  1 /* 58, NFS4_OP_RECLAIM_COMPLETE */
777 };
778
779
780 /* file name snooping */
781 gboolean nfs_file_name_snooping = FALSE;
782 static gboolean nfs_file_name_full_snooping = FALSE;
783 typedef struct nfs_name_snoop {
784         int fh_length;
785         unsigned char *fh;
786         int name_len;
787         char *name;
788         int parent_len;
789         unsigned char *parent;
790         int full_name_len;
791         char *full_name;
792 } nfs_name_snoop_t;
793
794 typedef struct nfs_name_snoop_key {
795         int key;
796         int fh_length;
797         const unsigned char *fh;
798 } nfs_name_snoop_key_t;
799
800 static GHashTable *nfs_name_snoop_unmatched = NULL;
801
802 static GHashTable *nfs_name_snoop_matched = NULL;
803
804 static emem_tree_t *nfs_name_snoop_known = NULL;
805 static emem_tree_t *nfs_file_handles = NULL;
806
807 static gboolean nfs_display_v4_tag = TRUE;
808 static gboolean display_major_nfsv4_ops = TRUE;
809
810 static int dissect_nfs_stateid4(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *hash);
811
812 static void reg_callback(int cbprog);
813
814 /* This function will store one nfs filehandle in our global tree of
815  * filehandles.
816  * We store all filehandles we see in this tree so that every unique
817  * filehandle is only stored once with a unique pointer.
818  * We need to store pointers to filehandles in several of our other
819  * structures and this is a way to make sure we dont keep any redundant
820  * copiesd around for a specific filehandle.
821  *
822  * If this is the first time this filehandle has been seen an se block
823  * is allocated to store the filehandle in.
824  * If this filehandle has already been stored in the tree this function returns
825  * a pointer to the original copy.
826  */
827 static nfs_fhandle_data_t *
828 store_nfs_file_handle(nfs_fhandle_data_t *nfs_fh)
829 {
830         guint32 fhlen;
831         guint32 *fhdata;
832         emem_tree_key_t fhkey[3];
833         nfs_fhandle_data_t *new_nfs_fh;
834
835         fhlen=nfs_fh->len/4;
836         /* align the file handle data */
837         fhdata=g_memdup(nfs_fh->fh, fhlen*4);
838         fhkey[0].length=1;
839         fhkey[0].key=&fhlen;
840         fhkey[1].length=fhlen;
841         fhkey[1].key=fhdata;
842         fhkey[2].length=0;
843
844         new_nfs_fh=se_tree_lookup32_array(nfs_file_handles, &fhkey[0]);
845         if(new_nfs_fh){
846                 g_free(fhdata);
847                 return new_nfs_fh;
848         }
849
850         new_nfs_fh=se_alloc(sizeof(nfs_fhandle_data_t));
851         new_nfs_fh->len=nfs_fh->len;
852         new_nfs_fh->fh=se_alloc(sizeof(guint32)*(nfs_fh->len/4));
853         memcpy((void *)new_nfs_fh->fh, nfs_fh->fh, nfs_fh->len);
854         new_nfs_fh->tvb=tvb_new_real_data(new_nfs_fh->fh, new_nfs_fh->len, new_nfs_fh->len);
855         fhlen=nfs_fh->len/4;
856         fhkey[0].length=1;
857         fhkey[0].key=&fhlen;
858         fhkey[1].length=fhlen;
859         fhkey[1].key=fhdata;
860         fhkey[2].length=0;
861         se_tree_insert32_array(nfs_file_handles, &fhkey[0], new_nfs_fh);
862
863         g_free(fhdata);
864         return new_nfs_fh;
865 }
866
867 static gint
868 nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer k2)
869 {
870         const nfs_name_snoop_key_t *key1 = (const nfs_name_snoop_key_t *)k1;
871         const nfs_name_snoop_key_t *key2 = (const nfs_name_snoop_key_t *)k2;
872
873         return (key1->key==key2->key)
874              &&(key1->fh_length==key2->fh_length)
875              &&(!memcmp(key1->fh, key2->fh, key1->fh_length));
876 }
877 static guint
878 nfs_name_snoop_matched_hash(gconstpointer k)
879 {
880         const nfs_name_snoop_key_t *key = (const nfs_name_snoop_key_t *)k;
881         int i;
882         guint hash;
883
884         hash=key->key;
885         for(i=0;i<key->fh_length;i++)
886                 hash ^= key->fh[i];
887
888         return hash;
889 }
890 static gint
891 nfs_name_snoop_unmatched_equal(gconstpointer k1, gconstpointer k2)
892 {
893         guint32 key1 = GPOINTER_TO_UINT(k1);
894         guint32 key2 = GPOINTER_TO_UINT(k2);
895
896         return key1==key2;
897 }
898 static guint
899 nfs_name_snoop_unmatched_hash(gconstpointer k)
900 {
901         guint32 key = GPOINTER_TO_UINT(k);
902
903         return key;
904 }
905 static gboolean
906 nfs_name_snoop_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
907 {
908         nfs_name_snoop_t *nns = (nfs_name_snoop_t *)value;
909
910         if(nns->name){
911                 g_free((gpointer)nns->name);
912                 nns->name=NULL;
913                 nns->name_len=0;
914         }
915         if(nns->full_name){
916                 g_free((gpointer)nns->full_name);
917                 nns->full_name=NULL;
918                 nns->full_name_len=0;
919         }
920         if(nns->parent){
921                 g_free((gpointer)nns->parent);
922                 nns->parent=NULL;
923                 nns->parent_len=0;
924         }
925         if(nns->fh){
926                 g_free((gpointer)nns->fh);
927                 nns->fh=NULL;
928                 nns->fh_length=0;
929         }
930         return TRUE;
931 }
932
933 static void
934 nfs_name_snoop_init(void)
935 {
936         if (nfs_name_snoop_unmatched != NULL) {
937                 g_hash_table_foreach_remove(nfs_name_snoop_unmatched,
938                                 nfs_name_snoop_unmatched_free_all, NULL);
939         } else {
940                 /* The fragment table does not exist. Create it */
941                 nfs_name_snoop_unmatched=g_hash_table_new(nfs_name_snoop_unmatched_hash,
942                         nfs_name_snoop_unmatched_equal);
943         }
944         if (nfs_name_snoop_matched != NULL) {
945                 g_hash_table_foreach_remove(nfs_name_snoop_matched,
946                                 nfs_name_snoop_unmatched_free_all, NULL);
947         } else {
948                 /* The fragment table does not exist. Create it */
949                 nfs_name_snoop_matched=g_hash_table_new(nfs_name_snoop_matched_hash,
950                         nfs_name_snoop_matched_equal);
951         }
952 }
953
954 void
955 nfs_name_snoop_add_name(int xid, tvbuff_t *tvb, int name_offset, int name_len, int parent_offset, int parent_len, char *name)
956 {
957         nfs_name_snoop_t *nns, *old_nns;
958         const char *ptr=NULL;
959
960         /* filter out all '.' and '..' names */
961         if(!name){
962                 ptr=(const char *)tvb_get_ptr(tvb, name_offset, name_len);
963         } else {
964                 ptr=name;
965         }
966         if(ptr[0]=='.'){
967                 if(ptr[1]==0){
968                         return;
969                 }
970                 if(ptr[1]=='.'){
971                         if(ptr[2]==0){
972                                 return;
973                         }
974                 }
975         }
976
977         nns=se_alloc(sizeof(nfs_name_snoop_t));
978
979         nns->fh_length=0;
980         nns->fh=NULL;
981
982         if(parent_len){
983                 nns->parent_len=parent_len;
984                 nns->parent=tvb_memdup(tvb, parent_offset, parent_len);
985         } else {
986                 nns->parent_len=0;
987                 nns->parent=NULL;
988         }
989
990         if(name){
991                 nns->name_len=(int)strlen(name);
992                 nns->name=g_strdup(name);
993         } else {
994                 nns->name_len=name_len;
995                 nns->name=g_malloc(name_len+1);
996                 memcpy(nns->name, ptr, name_len);
997         }
998         nns->name[nns->name_len]=0;
999
1000         nns->full_name_len=0;
1001         nns->full_name=NULL;
1002
1003         /* remove any old entry for this */
1004         old_nns=g_hash_table_lookup(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
1005         if(old_nns){
1006                 /* if we haven't seen the reply yet, then there are no
1007                    matched entries for it, thus we can dealloc the arrays*/
1008                 if(!old_nns->fh){
1009                         g_free(old_nns->name);
1010                         old_nns->name=NULL;
1011                         old_nns->name_len=0;
1012
1013                         g_free(old_nns->parent);
1014                         old_nns->parent=NULL;
1015                         old_nns->parent_len=0;
1016                 }
1017                 g_hash_table_remove(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
1018         }
1019
1020         g_hash_table_insert(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid), nns);
1021 }
1022
1023 static void
1024 nfs_name_snoop_add_fh(int xid, tvbuff_t *tvb, int fh_offset, int fh_length)
1025 {
1026         unsigned char *fh;
1027         nfs_name_snoop_t *nns, *old_nns;
1028         nfs_name_snoop_key_t *key;
1029
1030         /* find which request we correspond to */
1031         nns=g_hash_table_lookup(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
1032         if(!nns){
1033                 /* oops couldnt find matching request, bail out */
1034                 return;
1035         }
1036
1037         /* if we have already seen this response earlier */
1038         if(nns->fh){
1039                 return;
1040         }
1041
1042         /* oki, we have a new entry */
1043         fh=tvb_memdup(tvb, fh_offset, fh_length);
1044         nns->fh=fh;
1045         nns->fh_length=fh_length;
1046
1047         key=se_alloc(sizeof(nfs_name_snoop_key_t));
1048         key->key=0;
1049         key->fh_length=nns->fh_length;
1050         key->fh    =nns->fh;
1051
1052         /* already have something matched for this fh, remove it from
1053            the table */
1054         old_nns=g_hash_table_lookup(nfs_name_snoop_matched, key);
1055         if(old_nns){
1056                 g_hash_table_remove(nfs_name_snoop_matched, key);
1057         }
1058
1059         g_hash_table_remove(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
1060         g_hash_table_insert(nfs_name_snoop_matched, key, nns);
1061 }
1062
1063 static void
1064 nfs_full_name_snoop(nfs_name_snoop_t *nns, int *len, char **name, char **pos)
1065 {
1066         nfs_name_snoop_t *parent_nns = NULL;
1067         nfs_name_snoop_key_t key;
1068
1069         /* check if the nns component ends with a '/' else we just allocate
1070            an extra byte to len to accommodate for it later */
1071         if(nns->name[nns->name_len-1]!='/'){
1072                 (*len)++;
1073         }
1074
1075         (*len) += nns->name_len;
1076
1077         if(nns->parent==NULL){
1078                 *name = g_malloc((*len)+1);
1079                 *pos = *name;
1080
1081                 *pos += g_snprintf(*pos, (*len)+1, "%s", nns->name);
1082                 return;
1083         }
1084
1085         key.key=0;
1086         key.fh_length=nns->parent_len;
1087         key.fh=nns->parent;
1088
1089         parent_nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
1090
1091         if(parent_nns){
1092                 nfs_full_name_snoop(parent_nns, len, name, pos);
1093                 if(*name){
1094                         /* make sure components are '/' separated */
1095                         *pos += g_snprintf(*pos, (*len)+1, "%s%s", ((*pos)[-1]!='/')?"/":"", nns->name);
1096                 }
1097                 return;
1098         }
1099
1100         return;
1101 }
1102
1103 static void
1104 nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_offset, int fh_length, gboolean hidden)
1105 {
1106         nfs_name_snoop_key_t key;
1107         nfs_name_snoop_t *nns = NULL;
1108
1109         /* if this is a new packet, see if we can register the mapping */
1110         if(!pinfo->fd->flags.visited){
1111                 key.key=0;
1112                 key.fh_length=fh_length;
1113                 key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
1114
1115                 nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
1116                 if(nns){
1117                         guint32 fhlen;
1118                         guint32 *fhdata;
1119                         emem_tree_key_t fhkey[3];
1120
1121                         fhlen=nns->fh_length;
1122                         /* align it */
1123                         fhdata=g_memdup(nns->fh, fhlen);
1124                         fhkey[0].length=1;
1125                         fhkey[0].key=&fhlen;
1126                         fhkey[1].length=fhlen/4;
1127                         fhkey[1].key=fhdata;
1128                         fhkey[2].length=0;
1129                         se_tree_insert32_array(nfs_name_snoop_known, &fhkey[0], nns);
1130                         g_free(fhdata);
1131
1132                         if(nfs_file_name_full_snooping){
1133                                 char *name=NULL, *pos=NULL;
1134                                 int len=0;
1135
1136                                 nfs_full_name_snoop(nns, &len, &name, &pos);
1137                                 if(name){
1138                                         nns->full_name=name;
1139                                         nns->full_name_len=len;
1140                                 }
1141                         }
1142                 }
1143         }
1144
1145         /* see if we know this mapping */
1146         if(!nns){
1147                 guint32 fhlen;
1148                 guint32 *fhdata;
1149                 emem_tree_key_t fhkey[3];
1150
1151                 fhlen=fh_length;
1152                 /* align it */
1153                 fhdata=tvb_memdup(tvb, fh_offset, fh_length);
1154                 fhkey[0].length=1;
1155                 fhkey[0].key=&fhlen;
1156                 fhkey[1].length=fhlen/4;
1157                 fhkey[1].key=fhdata;
1158                 fhkey[2].length=0;
1159
1160                 nns=se_tree_lookup32_array(nfs_name_snoop_known, &fhkey[0]);
1161                 g_free(fhdata);
1162         }
1163
1164         /* if we know the mapping, print the filename */
1165         if(nns){
1166                 proto_item *fh_item;
1167
1168                 if(hidden){
1169                         fh_item=proto_tree_add_string(tree, hf_nfs_name, tvb,
1170                                 fh_offset, 0, nns->name);
1171                         PROTO_ITEM_SET_HIDDEN(fh_item);
1172                 } else {
1173                         fh_item=proto_tree_add_string_format(tree, hf_nfs_name, tvb,
1174                                 fh_offset, 0, nns->name, "Name: %s", nns->name);
1175                 }
1176                 PROTO_ITEM_SET_GENERATED(fh_item);
1177
1178                 if(nns->full_name){
1179                         if(hidden){
1180                                 fh_item=proto_tree_add_string(tree, hf_nfs_full_name, tvb,
1181                                         fh_offset, 0, nns->full_name);
1182                                 PROTO_ITEM_SET_HIDDEN(fh_item);
1183                         } else {
1184                                 fh_item=proto_tree_add_string_format(tree, hf_nfs_full_name, tvb,
1185                                         fh_offset, 0, nns->full_name, "Full Name: %s", nns->full_name);
1186                         }
1187                         PROTO_ITEM_SET_GENERATED(fh_item);
1188                 }
1189         }
1190 }
1191
1192 /* file handle dissection */
1193
1194 static const value_string names_fhtype[] =
1195 {
1196         {       FHT_UNKNOWN,            "unknown"                               },
1197         {       FHT_SVR4,               "System V R4"                           },
1198         {       FHT_LINUX_KNFSD_LE,     "Linux knfsd (little-endian)"           },
1199         {       FHT_LINUX_NFSD_LE,      "Linux user-land nfsd (little-endian)"  },
1200         {       FHT_LINUX_KNFSD_NEW,    "Linux knfsd (new)"                     },
1201         {       FHT_NETAPP,             "ONTAP 7G nfs v3 file handle"           },
1202         {       FHT_NETAPP_V4,          "ONTAP 7G nfs v4 file handle"           },
1203         {       FHT_NETAPP_GX_V3,       "ONTAP GX nfs v3 file handle"           },
1204         {       FHT_CELERRA,            "Celerra nfs file handle"               },
1205         {       0,                      NULL                                    }
1206 };
1207 static value_string_ext names_fhtype_ext = VALUE_STRING_EXT_INIT(names_fhtype);
1208
1209
1210 static const true_false_string tfs_endianness = { "Little Endian", "Big Endian" };
1211
1212 /* SVR4: checked with ReliantUNIX (5.43, 5.44, 5.45), OpenSolaris (build 101a) */
1213
1214 static void
1215 dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
1216 {
1217         gboolean        little_endian;  /* We support little endian and big endian. */
1218         gboolean        have_flag;      /* The flag field at the end is optional. */
1219         gboolean        found;          /* Did we really detect the file handle format? */
1220         guint32         nof=0;
1221         guint32         len1;
1222         guint32         len2;
1223         guint32         fhlen;          /* File handle length. */
1224
1225         /* By default we assume big endianness. */
1226         little_endian = FALSE;
1227
1228         /* By default, we aassume, that the flag is no there. */
1229         have_flag = FALSE;
1230
1231         /* Not detected yet. */
1232         found = FALSE;
1233
1234         /* Somehow this is no calling argument, so we have to re-calculate it. */
1235         fhlen = tvb_reported_length(tvb);
1236
1237         /* Check for little endianness. */
1238         len1 = tvb_get_letohs(tvb, 8);
1239         if (tvb_bytes_exist(tvb, 10+len1, 2)) {
1240                 len2 = tvb_get_letohs(tvb, 10+len1);
1241
1242                 if (12+len1+len2 == fhlen) {
1243                         little_endian = TRUE;
1244                         have_flag = FALSE;
1245                         found = TRUE;
1246                 }
1247                 if (16+len1+len2 == fhlen) {
1248                         little_endian = TRUE;
1249                         have_flag = TRUE;
1250                         found = TRUE;
1251                 }
1252         }
1253
1254         if (!found) {
1255                 /* Check for big endianness. */
1256                 len1 = tvb_get_ntohs(tvb, 8);
1257                 if (tvb_bytes_exist(tvb, 10+len1, 2)) {
1258                         len2 = tvb_get_ntohs(tvb, 10+len1);
1259
1260                         if (12+len1+len2 == fhlen) {
1261                                 little_endian = FALSE;
1262                                 have_flag = FALSE;
1263                                 found = TRUE;
1264                         }
1265                         if (16+len1+len2 == fhlen) {
1266                                 little_endian = FALSE;
1267                                 have_flag = TRUE;
1268                                 found = TRUE;
1269                         }
1270                 }
1271         }
1272
1273         if (tree) {
1274                 proto_tree_add_boolean(tree, hf_nfs_fh_endianness, tvb,
1275                         0, fhlen, little_endian);
1276         }
1277
1278         /* We are fairly sure, that when found==FALSE, the following code will
1279         throw an exception. */
1280
1281         /* file system id */
1282         {
1283         guint32 fsid_O;
1284         guint32 fsid_L;
1285         guint32 temp;
1286         guint32 fsid_major;
1287         guint32 fsid_minor;
1288
1289         fsid_O = nof;
1290         fsid_L = 4;
1291         if (little_endian)
1292                 temp = tvb_get_letohl(tvb, fsid_O);
1293         else
1294                 temp = tvb_get_ntohl(tvb, fsid_O);
1295         fsid_major = ( temp>>18 ) &  0x3fff; /* 14 bits */
1296         fsid_minor = ( temp     ) & 0x3ffff; /* 18 bits */
1297         if (tree) {
1298                 proto_item* fsid_item;
1299                 proto_tree* fsid_tree;
1300
1301                 fsid_item = proto_tree_add_text(tree, tvb,
1302                         fsid_O, fsid_L,
1303                         "file system ID: %d,%d", fsid_major, fsid_minor);
1304                 fsid_tree = proto_item_add_subtree(fsid_item,
1305                                         ett_nfs_fh_fsid);
1306                 if (little_endian) {
1307                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
1308                                         tvb, fsid_O+2, 2, fsid_major);
1309                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
1310                                         tvb, fsid_O,   3, fsid_minor);
1311                 }
1312                 else {
1313                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
1314                                         tvb, fsid_O,   2, fsid_major);
1315                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
1316                                         tvb, fsid_O+1, 3, fsid_minor);
1317                 }
1318         }
1319         nof = fsid_O + fsid_L;
1320         }
1321
1322         /* file system type */
1323         {
1324         guint32 fstype_O;
1325         guint32 fstype_L;
1326         guint32 fstype;
1327
1328         fstype_O = nof;
1329         fstype_L = 4;
1330         if (little_endian)
1331                 fstype = tvb_get_letohl(tvb, fstype_O);
1332         else
1333                 fstype = tvb_get_ntohl(tvb, fstype_O);
1334         if (tree) {
1335                 proto_tree_add_uint(tree, hf_nfs_fh_fstype, tvb,
1336                         fstype_O, fstype_L, fstype);
1337         }
1338         nof = fstype_O + fstype_L;
1339         }
1340
1341         /* file number */
1342         {
1343         guint32 fn_O;
1344         guint32 fn_len_O;
1345         guint32 fn_len_L;
1346         guint32 fn_len;
1347         guint32 fn_data_O;
1348         guint32 fn_data_inode_O;
1349         guint32 fn_data_inode_L;
1350         guint32 inode;
1351         guint32 fn_data_gen_O;
1352         guint32 fn_data_gen_L;
1353         guint32 gen;
1354         guint32 fn_L;
1355
1356         fn_O = nof;
1357         fn_len_O = fn_O;
1358         fn_len_L = 2;
1359         if (little_endian)
1360                 fn_len = tvb_get_letohs(tvb, fn_len_O);
1361         else
1362                 fn_len = tvb_get_ntohs(tvb, fn_len_O);
1363         fn_data_O = fn_O + fn_len_L;
1364         fn_data_inode_O = fn_data_O + 2;
1365         fn_data_inode_L = 4;
1366         if (little_endian)
1367                 inode = tvb_get_letohl(tvb, fn_data_inode_O);
1368         else
1369                 inode = tvb_get_ntohl(tvb, fn_data_inode_O);
1370         if (little_endian)
1371                 fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
1372         else
1373                 fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
1374         fn_data_gen_L = 4;
1375         if (little_endian)
1376                 gen = tvb_get_letohl(tvb, fn_data_gen_O);
1377         else
1378                 gen = tvb_get_ntohl(tvb, fn_data_gen_O);
1379         fn_L = fn_len_L + fn_len;
1380         if (tree) {
1381                 proto_item* fn_item;
1382                 proto_tree* fn_tree;
1383
1384                 fn_item = proto_tree_add_uint(tree, hf_nfs_fh_fn, tvb,
1385                         fn_O, fn_L, inode);
1386                 fn_tree = proto_item_add_subtree(fn_item,
1387                                         ett_nfs_fh_fn);
1388                 proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_len,
1389                                 tvb, fn_len_O, fn_len_L, fn_len);
1390                 proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_inode,
1391                                 tvb, fn_data_inode_O, fn_data_inode_L, inode);
1392                 proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_generation,
1393                                 tvb, fn_data_gen_O, fn_data_gen_L, gen);
1394         }
1395         nof = fn_O + fn_len_L + fn_len;
1396         }
1397
1398         /* exported file number */
1399         {
1400         guint32 xfn_O;
1401         guint32 xfn_len_O;
1402         guint32 xfn_len_L;
1403         guint32 xfn_len;
1404         guint32 xfn_data_O;
1405         guint32 xfn_data_inode_O;
1406         guint32 xfn_data_inode_L;
1407         guint32 xinode;
1408         guint32 xfn_data_gen_O;
1409         guint32 xfn_data_gen_L;
1410         guint32 xgen;
1411         guint32 xfn_L;
1412
1413         xfn_O = nof;
1414         xfn_len_O = xfn_O;
1415         xfn_len_L = 2;
1416         if (little_endian)
1417                 xfn_len = tvb_get_letohs(tvb, xfn_len_O);
1418         else
1419                 xfn_len = tvb_get_ntohs(tvb, xfn_len_O);
1420         xfn_data_O = xfn_O + xfn_len_L;
1421         xfn_data_inode_O = xfn_data_O + 2;
1422         xfn_data_inode_L = 4;
1423         if (little_endian)
1424                 xinode = tvb_get_letohl(tvb, xfn_data_inode_O);
1425         else
1426                 xinode = tvb_get_ntohl(tvb, xfn_data_inode_O);
1427         xfn_data_gen_O = xfn_data_inode_O + xfn_data_inode_L;
1428         xfn_data_gen_L = 4;
1429         if (little_endian)
1430                 xgen = tvb_get_letohl(tvb, xfn_data_gen_O);
1431         else
1432                 xgen = tvb_get_ntohl(tvb, xfn_data_gen_O);
1433         xfn_L = xfn_len_L + xfn_len;
1434         if (tree) {
1435                 proto_item* xfn_item;
1436                 proto_tree* xfn_tree;
1437
1438                 xfn_item = proto_tree_add_uint(tree, hf_nfs_fh_xfn, tvb,
1439                         xfn_O, xfn_L, xinode);
1440                 xfn_tree = proto_item_add_subtree(xfn_item,
1441                                         ett_nfs_fh_xfn);
1442                 proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_len,
1443                                 tvb, xfn_len_O, xfn_len_L, xfn_len);
1444                 proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_inode,
1445                                 tvb, xfn_data_inode_O, xfn_data_inode_L, xinode);
1446                 proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_generation,
1447                                 tvb, xfn_data_gen_O, xfn_data_gen_L, xgen);
1448         }
1449         nof = xfn_O + xfn_len_L + xfn_len;
1450         }
1451
1452         /* flag */
1453         if (have_flag) {
1454                 guint32 flag_O;
1455                 guint32 flag_L;
1456                 guint32 flag_value;
1457
1458                 flag_O = nof;
1459                 flag_L = 4;
1460                 if (little_endian)
1461                         flag_value = tvb_get_letohl(tvb, flag_O);
1462                 else
1463                         flag_value = tvb_get_ntohl(tvb, flag_O);
1464                 if (tree) {
1465                         proto_tree_add_uint(tree, hf_nfs_fh_flag, tvb,
1466                                             flag_O, flag_L, flag_value);
1467                 }
1468         }
1469 }
1470
1471
1472 /* Checked with RedHat Linux 6.2 (kernel 2.2.14 knfsd) */
1473
1474 static void
1475 dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
1476 {
1477         int offset=0;
1478         guint32 dentry;
1479         guint32 inode;
1480         guint32 dirinode;
1481         guint32 temp;
1482         guint32 fsid_major;
1483         guint32 fsid_minor;
1484         guint32 xfsid_major;
1485         guint32 xfsid_minor;
1486         guint32 xinode;
1487         guint32 gen;
1488
1489         dentry   = tvb_get_letohl(tvb, offset+0);
1490         inode    = tvb_get_letohl(tvb, offset+4);
1491         dirinode = tvb_get_letohl(tvb, offset+8);
1492         temp     = tvb_get_letohs (tvb,offset+12);
1493         fsid_major = (temp >> 8) & 0xff;
1494         fsid_minor = (temp     ) & 0xff;
1495         temp     = tvb_get_letohs(tvb,offset+16);
1496         xfsid_major = (temp >> 8) & 0xff;
1497         xfsid_minor = (temp     ) & 0xff;
1498         xinode   = tvb_get_letohl(tvb,offset+20);
1499         gen      = tvb_get_letohl(tvb,offset+24);
1500
1501         if (tree) {
1502                 proto_tree_add_uint(tree, hf_nfs_fh_dentry,
1503                                 tvb, offset+0, 4, dentry);
1504                 proto_tree_add_uint(tree, hf_nfs_fh_fn_inode,
1505                                 tvb, offset+4, 4, inode);
1506                 proto_tree_add_uint(tree, hf_nfs_fh_dirinode,
1507                                 tvb, offset+8, 4, dirinode);
1508
1509                 /* file system id (device) */
1510                 {
1511                 proto_item* fsid_item = NULL;
1512                 proto_tree* fsid_tree = NULL;
1513
1514                 fsid_item = proto_tree_add_text(tree, tvb,
1515                                         offset+12, 4,
1516                                         "file system ID: %d,%d",
1517                                         fsid_major, fsid_minor);
1518                 fsid_tree = proto_item_add_subtree(fsid_item,
1519                                         ett_nfs_fh_fsid);
1520                 proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
1521                                 tvb, offset+13, 1, fsid_major);
1522                 proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
1523                                 tvb, offset+12, 1, fsid_minor);
1524                 }
1525
1526                 /* exported file system id (device) */
1527                 {
1528                 proto_item* xfsid_item;
1529                 proto_tree* xfsid_tree;
1530
1531                 xfsid_item = proto_tree_add_text(tree, tvb,
1532                         offset+16, 4,
1533                         "exported file system ID: %d,%d", xfsid_major, xfsid_minor);
1534                 xfsid_tree = proto_item_add_subtree(xfsid_item,
1535                                         ett_nfs_fh_xfsid);
1536                 proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_major,
1537                                 tvb, offset+17, 1, xfsid_major);
1538                 proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_minor,
1539                                 tvb, offset+16, 1, xfsid_minor);
1540                 }
1541
1542                 proto_tree_add_uint(tree, hf_nfs_fh_xfn_inode,
1543                                 tvb, offset+20, 4, xinode);
1544                 proto_tree_add_uint(tree, hf_nfs_fh_fn_generation,
1545                                 tvb, offset+24, 4, gen);
1546         }
1547 }
1548
1549
1550 /* Checked with RedHat Linux 5.2 (nfs-server 2.2beta47 user-land nfsd) */
1551
1552 static void
1553 dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
1554 {
1555         int offset=0;
1556
1557         /* pseudo inode */
1558         {
1559                 guint32 pinode;
1560                 pinode   = tvb_get_letohl(tvb, offset+0);
1561                 if (tree) {
1562                         proto_tree_add_uint(tree, hf_nfs_fh_pinode,
1563                                             tvb, offset+0, 4, pinode);
1564                 }
1565         }
1566
1567         /* hash path */
1568         {
1569                 guint32 hashlen;
1570
1571                 hashlen  = tvb_get_guint8(tvb, offset+4);
1572                 if (tree) {
1573                         proto_item* hash_item;
1574                         proto_tree* hash_tree;
1575
1576                         hash_item = proto_tree_add_text(tree, tvb, offset+4,
1577                                                         hashlen + 1,
1578                                                         "hash path: %s",
1579                                                         tvb_bytes_to_str(tvb,offset+5,hashlen));
1580                         hash_tree = proto_item_add_subtree(hash_item,
1581                                                            ett_nfs_fh_hp);
1582                         proto_tree_add_uint(hash_tree,
1583                                             hf_nfs_fh_hp_len, tvb, offset+4, 1,
1584                                             hashlen);
1585                         proto_tree_add_text(hash_tree, tvb, offset+5,
1586                                             hashlen,
1587                                             "key: %s",
1588                                             tvb_bytes_to_str(tvb,offset+5,hashlen));
1589                 }
1590         }
1591 }
1592
1593
1594 static void
1595 dissect_fhandle_data_NETAPP(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
1596 {
1597         int offset=0;
1598
1599         if (tree) {
1600                 guint32 mount = tvb_get_letohl(tvb, offset + 0);
1601                 guint32 mount_gen = tvb_get_letohl(tvb, offset + 4);
1602                 guint16 flags = tvb_get_letohs(tvb, offset + 8);
1603                 guint8 snapid = tvb_get_guint8(tvb, offset + 10);
1604                 guint8 unused = tvb_get_guint8(tvb, offset + 11);
1605                 guint32 inum = tvb_get_ntohl(tvb, offset + 12);
1606                 guint32 generation = tvb_get_letohl(tvb, offset + 16);
1607                 guint32 fsid = tvb_get_letohl(tvb, offset + 20);
1608                 guint32 export = tvb_get_letohl(tvb, offset + 24);
1609                 guint32 export_snapgen = tvb_get_letohl(tvb, offset + 28);
1610
1611                 proto_item *item;
1612                 proto_tree *subtree;
1613                 char *flag_string;
1614                 const char *strings[] = { " MNT_PNT", " SNAPDIR", " SNAPDIR_ENT",
1615                                     " EMPTY", " VBN_ACCESS", " MULTIVOLUME",
1616                                     " METADATA" };
1617                 guint16 bit = sizeof(strings) / sizeof(strings[0]);
1618
1619                 flag_string=ep_alloc(512);
1620                 flag_string[0]=0;
1621                 while (bit--) {
1622                         if (flags & (1<<bit)) {
1623                                 g_strlcat(flag_string, strings[bit], 512);
1624                         }
1625                 }
1626                 item = proto_tree_add_text(tree, tvb, offset + 0, 8,
1627                                            "mount (inode %u)", mount);
1628                 subtree = proto_item_add_subtree(item, ett_nfs_fh_mount);
1629                 proto_tree_add_uint(subtree, hf_nfs_fh_mount_fileid,
1630                                            tvb, offset + 0, 4, mount);
1631                 proto_tree_add_uint(subtree, hf_nfs_fh_mount_generation,
1632                                            tvb, offset + 4, 4, mount_gen);
1633                 item = proto_tree_add_text(tree, tvb, offset + 8, 16,
1634                                            "file (inode %u)", inum);
1635                 subtree = proto_item_add_subtree(item, ett_nfs_fh_file);
1636                 proto_tree_add_uint_format(subtree, hf_nfs_fh_flags,
1637                                                   tvb, offset + 8, 2, flags,
1638                                                   "Flags: %#02x%s", flags,
1639                                                   flag_string);
1640                 proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
1641                                            offset + 10, 1, snapid);
1642                 proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
1643                                            offset + 11, 1, unused);
1644                 proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
1645                                            offset + 12, 4, inum);
1646                 proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
1647                                            offset + 16, 4, generation);
1648                 proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
1649                                            offset + 20, 4, fsid);
1650                 item = proto_tree_add_text(tree, tvb, offset + 24, 8,
1651                                            "export (inode %u)", export);
1652                 subtree = proto_item_add_subtree(item, ett_nfs_fh_export);
1653                 proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
1654                                            tvb, offset + 24, 4, export);
1655                 proto_tree_add_uint(subtree,
1656                                            hf_nfs_fh_export_generation,
1657                                            tvb, offset + 28, 3,
1658                                            export_snapgen & 0xffffff);
1659                 proto_tree_add_uint(subtree, hf_nfs_fh_export_snapid,
1660                                            tvb, offset + 31, 1,
1661                                            export_snapgen >> 24);
1662         }
1663 }
1664
1665 static const value_string netapp_file_flag_vals[] =  {
1666         { 0x0000,       "Not set"},
1667         { 0x0001,       "Set"},
1668         { 0,            NULL}
1669 };
1670
1671 static void
1672 dissect_fhandle_data_NETAPP_V4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
1673 {
1674         int offset=0;
1675         proto_item *item = NULL;
1676         proto_tree *subtree = NULL;
1677         guint8  snapid, unused;
1678         guint16 flags;
1679         guint32 fileid, snapgen, generation, fsid;
1680         guint32 handle_type = tvb_get_ntohl(tvb, offset + 24);
1681         guint32 inum = tvb_get_ntohl(tvb, offset + 12);
1682
1683         const char *handle_string=NULL;
1684         const char *handle_type_strings [] = { "NORMAL",
1685                                                "UNEXP",
1686                                                "VOLDIR",
1687                                                "ROOT",
1688                                                "ABSENT",
1689                                                "INVALID"
1690                                              };
1691
1692         char *flag_string;
1693         const char *strings[] = { " MNT_PNT",
1694                                   " SNAPDIR",
1695                                   " SNAPDIR_ENT",
1696                                   " EMPTY",
1697                                   " VBN_ACCESS",
1698                                   " MULTIVOLUME",
1699                                   " METADATA",
1700                                   " ORPHAN",
1701                                   " FOSTER",
1702                                   " NAMED_ATTR",
1703                                   " EXP_SNAPDIR",
1704                                   " VFILER",
1705                                   " NS_AGGR",
1706                                   " STRIPED",
1707                                   " NS_PRIVATE",
1708                                   " NEXT_GEN_FH"
1709                                 };
1710         guint16 bit = sizeof(strings) / sizeof(strings[0]);
1711         proto_tree *flag_tree = NULL;
1712
1713         flag_string=ep_alloc(512);
1714         flag_string[0]=0;
1715
1716         if(tree){
1717                 if( handle_type !=0 && handle_type <= 255) {
1718                         fileid = tvb_get_ntohl(tvb, offset + 0);
1719                         snapgen = tvb_get_ntohl(tvb, offset + 4);
1720                         flags = tvb_get_ntohs(tvb, offset + 8);
1721                         snapid = tvb_get_guint8(tvb, offset + 10);
1722                         unused = tvb_get_guint8(tvb, offset + 11);
1723                         generation = tvb_get_ntohl(tvb, offset + 16);
1724                         fsid = tvb_get_ntohl(tvb, offset + 20);
1725                 } else {
1726                         fileid = tvb_get_letohl(tvb, offset + 0);
1727                         snapgen = tvb_get_letohl(tvb, offset + 4);
1728                         flags = tvb_get_letohs(tvb, offset + 8);
1729                         snapid = tvb_get_guint8(tvb, offset + 10);
1730                         unused = tvb_get_guint8(tvb, offset + 11);
1731                         generation = tvb_get_letohl(tvb, offset + 16);
1732                         fsid = tvb_get_letohl(tvb, offset + 20);
1733                         handle_type = tvb_get_letohl(tvb, offset + 24);
1734                 }
1735
1736                 if(handle_type <= 4) {
1737                         handle_string=handle_type_strings[handle_type];
1738                 } else {
1739                         handle_string=handle_type_strings[5];
1740                 }
1741
1742                 while (bit--) {
1743                         if (flags & (1<<bit)) {
1744                                 g_strlcat(flag_string, strings[bit], 512);
1745                         }
1746                 }
1747                 item = proto_tree_add_text(tree, tvb, offset + 0, 8, "export (inode %u)", fileid);
1748                 subtree = proto_item_add_subtree(item, ett_nfsv4_fh_export);
1749
1750                 proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
1751                                            tvb, offset + 0, 4, fileid);
1752                 proto_tree_add_uint(subtree, hf_nfs_fh_export_generation,
1753                                            tvb, offset + 4, 4, snapgen);
1754                 item = proto_tree_add_text(tree, tvb, offset + 8, 16, "file (inode %u)", inum);
1755                 subtree = proto_item_add_subtree(item, ett_nfsv4_fh_file);
1756                 item = proto_tree_add_uint_format(subtree, hf_nfs_fh_flags,
1757                                                   tvb, offset + 8, 2, flags,
1758                                                   "Flags: %#02x%s", flags,
1759                                                   flag_string);
1760                 flag_tree = proto_item_add_subtree(item, ett_nfsv4_fh_file_flags);
1761                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_mntpoint, tvb, offset+8, 2, flags);
1762                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_snapdir, tvb, offset+8, 2, flags);
1763                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_snapdir_ent, tvb, offset+8, 2, flags);
1764                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_empty, tvb, offset+8, 2, flags);
1765                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_vbn_access, tvb, offset+8, 2, flags);
1766                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_multivolume, tvb, offset+8, 2, flags);
1767                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_metadata, tvb, offset+8, 2, flags);
1768                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_orphan, tvb, offset+8, 2, flags);
1769                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_foster, tvb, offset+8, 2, flags);
1770                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_named_attr, tvb, offset+8, 2, flags);
1771                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_exp_snapdir, tvb, offset+8, 2, flags);
1772                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_vfiler, tvb, offset+8, 2, flags);
1773                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_aggr, tvb, offset+8, 2, flags);
1774                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_striped, tvb, offset+8, 2, flags);
1775                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_private, tvb, offset+8, 2, flags);
1776                 proto_tree_add_uint(flag_tree, hf_nfs_fh_file_flag_next_gen, tvb, offset+8, 2, flags);
1777                 proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
1778                                            offset + 10, 1, snapid);
1779                 proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
1780                                            offset + 11, 1, unused);
1781                 proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
1782                                            offset + 12, 4, inum);
1783                 proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
1784                                            offset + 16, 4, generation);
1785                 proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
1786                                            offset + 20, 4, fsid);
1787                 proto_tree_add_uint_format(tree, hf_nfs_fh_handle_type,
1788                                                   tvb, offset+24, 4, handle_type,
1789                                                   "Handle type: %s(%#02x)", handle_string, handle_type);
1790         }
1791 }
1792
1793 #define NETAPP_GX_FH3_LENGTH            44
1794 #define NFS3GX_FH_TREE_MASK             0x80
1795 #define NFS3GX_FH_JUN_MASK              0x40
1796 #define NFS3GX_FH_VER_MASK              0x3F
1797 #define SPINNP_FH_FLAG_RESV1            0x80
1798 #define SPINNP_FH_FLAG_RESV2            0x40
1799 #define SPINNP_FH_FLAG_ONTAP_MASK       0x20
1800 #define SPINNP_FH_FLAG_STRIPED_MASK     0x10
1801 #define SPINNP_FH_FLAG_EMPTY_MASK       0x08
1802 #define SPINNP_FH_FLAG_SNAPDIR_ENT_MASK 0x04
1803 #define SPINNP_FH_FLAG_SNAPDIR_MASK     0x02
1804 #define SPINNP_FH_FLAG_STREAMDIR_MASK   0x01
1805
1806 static void
1807 dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
1808 {
1809         proto_tree *field_tree;
1810         proto_item *tf;
1811         guint16     cluster_id;
1812         guint16     epoch;
1813         guint32     export_id;
1814         guint32     export_uid;
1815         guint8      flags;
1816         guint8      reserved;
1817         guint32     local_dsid;
1818         guint32     spinfile_id;
1819         guint32     spinfile_uid;
1820         guint8      utility;
1821         guint8      volcnt;
1822         guint32 offset = 0;
1823
1824         if (tree) {
1825                 /* = utility = */
1826                 utility = tvb_get_guint8(tvb, offset);
1827                 tf = proto_tree_add_uint_format(tree, hf_gxfh3_utlfield, tvb,
1828                                                 offset, 1, utility,
1829                                                 "  utility: 0x%02x",utility);
1830
1831
1832                 field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_utlfield);
1833                 if (utility & NFS3GX_FH_TREE_MASK) {
1834                         proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_tree_w, tvb,
1835                                             offset, 1, utility);
1836                 }
1837                 else {
1838                         proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_tree_r, tvb,
1839                                             offset, 1, utility);
1840                 }
1841                 if (utility & NFS3GX_FH_JUN_MASK) {
1842                         proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_jun, tvb,
1843                                             offset, 1, utility);
1844                 }
1845                 else {
1846                         proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_jun_not, tvb,
1847                                             offset, 1, utility);
1848                 }
1849                 proto_tree_add_uint(field_tree, hf_gxfh3_utlfield_ver, tvb,
1850                                     offset, 1, utility);
1851
1852                 /* = volume count== */
1853                 volcnt = tvb_get_guint8(tvb, offset+1);
1854                 proto_tree_add_uint_format(tree, hf_gxfh3_volcnt, tvb,
1855                                            offset+1, 1, volcnt,
1856                                            "  volume count: 0x%02x (%d)", volcnt, volcnt);
1857                 /* = epoch = */
1858                 epoch = tvb_get_letohs(tvb, offset+2);
1859                 proto_tree_add_uint_format(tree, hf_gxfh3_epoch, tvb,
1860                                            offset+2, 2, epoch,
1861                                            "  epoch: 0x%04x (%u)", epoch, epoch);
1862                 /* = spin file handle = */
1863                 local_dsid   = tvb_get_letohl(tvb, offset+4);
1864                 cluster_id   = tvb_get_letohs(tvb, offset+8);
1865                 reserved     = tvb_get_guint8(tvb, offset+10);
1866                 flags        = tvb_get_guint8(tvb, offset+11);
1867                 spinfile_id  = tvb_get_letohl(tvb, offset+12);
1868                 spinfile_uid = tvb_get_letohl(tvb, offset+16);
1869
1870                 tf = proto_tree_add_text(tree, tvb, offset+4, 16,
1871                                          "  spin file handle");
1872                 field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhfield);
1873
1874                 proto_tree_add_uint_format(field_tree, hf_gxfh3_ldsid, tvb,
1875                                            offset+4, 4, local_dsid,
1876                                            " local dsid: 0x%08x (%u)", local_dsid, local_dsid);
1877                 proto_tree_add_uint_format(field_tree, hf_gxfh3_cid, tvb,
1878                                            offset+8, 2, cluster_id,
1879                                            " cluster id: 0x%04x (%u)", cluster_id, cluster_id);
1880                 proto_tree_add_uint_format(field_tree, hf_gxfh3_resv, tvb,
1881                                            offset+10, 1, reserved,
1882                                            " reserved: 0x%02x (%u)", reserved, reserved);
1883
1884
1885                 tf = proto_tree_add_uint_format(field_tree, hf_gxfh3_sfhflags, tvb,
1886                                                 offset+11, 1, utility,
1887                                                 " flags: 0x%02x", flags);
1888                 field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhflags);
1889                 proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv1, tvb,
1890                                     offset+11, 1, flags);
1891                 proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv2, tvb,
1892                                     offset+11, 1, flags);
1893
1894                 if (flags & SPINNP_FH_FLAG_ONTAP_MASK) {
1895                         proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontap7G, tvb,
1896                                             offset+11, 1, flags);
1897                 }
1898                 else {
1899                         proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontapGX, tvb,
1900                                             offset+11, 1, flags);
1901                 }
1902                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_striped, tvb,
1903                                        offset+11, 1, flags);
1904                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_empty, tvb,
1905                                        offset+11, 1, flags);
1906                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdirent, tvb,
1907                                        offset+11, 1, flags);
1908                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdir, tvb,
1909                                        offset+11, 1, flags);
1910                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_streamdir, tvb,
1911                                        offset+11, 1, flags);
1912                 proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfid, tvb,
1913                                            offset+12, 4, spinfile_id,
1914                                            "spin file id: 0x%08x (%u)", spinfile_id, spinfile_id);
1915                 proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfuid, tvb,
1916                                            offset+16, 4, spinfile_id,
1917                                            "spin file unique id: 0x%08x (%u)", spinfile_uid, spinfile_uid);
1918
1919                 /* = spin file handle (mount point) = */
1920                 local_dsid   = tvb_get_letohl(tvb, offset+20);
1921                 cluster_id   = tvb_get_letohs(tvb, offset+24);
1922                 reserved     = tvb_get_guint8(tvb, offset+26);
1923                 flags        = tvb_get_guint8(tvb, offset+27);
1924                 spinfile_id  = tvb_get_letohl(tvb, offset+28);
1925                 spinfile_uid = tvb_get_letohl(tvb, offset+32);
1926
1927                 tf = proto_tree_add_text(tree, tvb, offset+20, 16,
1928                                          "  spin (mount point) file handle");
1929                 field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhfield);
1930
1931                 proto_tree_add_uint_format(field_tree, hf_gxfh3_ldsid, tvb,
1932                                            offset+20, 4, local_dsid,
1933                                            " local dsid: 0x%08x (%u)", local_dsid, local_dsid);
1934                 proto_tree_add_uint_format(field_tree, hf_gxfh3_cid, tvb,
1935                                            offset+24, 2, cluster_id,
1936                                            " cluster id: 0x%04x (%u)", cluster_id, cluster_id);
1937                 proto_tree_add_uint_format(field_tree, hf_gxfh3_resv, tvb,
1938                                            offset+26, 1, reserved,
1939                                            " reserved: 0x%02x (%u)", reserved, reserved);
1940
1941
1942                 tf = proto_tree_add_uint_format(field_tree, hf_gxfh3_sfhflags, tvb,
1943                                                 offset+27, 1, utility,
1944                                                 " flags: 0x%02x", flags);
1945                 field_tree = proto_item_add_subtree(tf, ett_nfs_gxfh3_sfhflags);
1946                 proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv1, tvb,
1947                                     offset+27, 1, flags);
1948                 proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_resv2, tvb,
1949                                     offset+27, 1, flags);
1950
1951                 if (flags & SPINNP_FH_FLAG_ONTAP_MASK) {
1952                         proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontap7G, tvb,
1953                                             offset+27, 1, flags);
1954                 }
1955                 else {
1956                         proto_tree_add_uint(field_tree, hf_gxfh3_sfhflags_ontapGX, tvb,
1957                                             offset+27, 1, flags);
1958                 }
1959                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_striped, tvb,
1960                                        offset+27, 1, flags);
1961                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_empty, tvb,
1962                                        offset+27, 1, flags);
1963                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdirent, tvb,
1964                                        offset+27, 1, flags);
1965                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_snapdir, tvb,
1966                                        offset+27, 1, flags);
1967                 proto_tree_add_boolean(field_tree, hf_gxfh3_sfhflags_streamdir, tvb,
1968                                        offset+27, 1, flags);
1969                 proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfid, tvb,
1970                                            offset+28, 4, spinfile_id,
1971                                            "spin file id: 0x%08x (%u)", spinfile_id, spinfile_id);
1972                 proto_tree_add_uint_format(field_tree, hf_gxfh3_spinfuid, tvb,
1973                                            offset+32, 4, spinfile_id,
1974                                            "spin file unique id: 0x%08x (%u)", spinfile_uid, spinfile_uid);
1975                 /* = export point id  = */
1976                 export_id  = tvb_get_letohl(tvb, offset+36);
1977                 export_uid = tvb_get_letohl(tvb, offset+40);
1978                 proto_tree_add_uint_format(tree, hf_gxfh3_exportptid, tvb,
1979                                            offset+36, 4, spinfile_id,
1980                                            "  export point id: 0x%08x (%u)", export_id, export_id);
1981                 /* = export point unique id  = */
1982                 export_uid = tvb_get_letohl(tvb, offset+40);
1983                 proto_tree_add_uint_format(tree, hf_gxfh3_exportptuid, tvb,
1984                                            offset+40, 4, spinfile_id,
1985                                            "  export point unique id: 0x%08x (%u)", export_uid, export_uid);
1986
1987         }  /* end of (tree) */
1988 }
1989
1990 /* Checked with SuSE 7.1 (kernel 2.4.0 knfsd) */
1991 /* read linux-2.4.5/include/linux/nfsd/nfsfh.h for more details */
1992
1993 #define AUTH_TYPE_NONE 0
1994 static const value_string auth_type_names[] = {
1995         {       AUTH_TYPE_NONE,                         "no authentication"             },
1996         {       0,      NULL}
1997 };
1998
1999 #define FSID_TYPE_MAJOR_MINOR_INODE 0
2000 static const value_string fsid_type_names[] = {
2001         {       FSID_TYPE_MAJOR_MINOR_INODE,            "major/minor/inode"             },
2002         {       0,      NULL}
2003 };
2004
2005 #define FILEID_TYPE_ROOT                        0
2006 #define FILEID_TYPE_INODE_GENERATION            1
2007 #define FILEID_TYPE_INODE_GENERATION_PARENT     2
2008 static const value_string fileid_type_names[] = {
2009         {       FILEID_TYPE_ROOT,                       "root"                          },
2010         {       FILEID_TYPE_INODE_GENERATION,           "inode/generation"              },
2011         {       FILEID_TYPE_INODE_GENERATION_PARENT,    "inode/generation/parent"       },
2012         {       0,      NULL}
2013 };
2014
2015 static void
2016 dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
2017 {
2018         int offset=0;
2019         guint8 version;
2020         guint8 auth_type;
2021         guint8 fsid_type;
2022         guint8 fileid_type;
2023
2024         version     = tvb_get_guint8(tvb, offset + 0);
2025         if (tree) {
2026                 proto_tree_add_uint(tree, hf_nfs_fh_version,
2027                         tvb, offset+0, 1, version);
2028         }
2029
2030         switch (version) {
2031                 case 1: {
2032                         auth_type   = tvb_get_guint8(tvb, offset + 1);
2033                         fsid_type   = tvb_get_guint8(tvb, offset + 2);
2034                         fileid_type = tvb_get_guint8(tvb, offset + 3);
2035                         if (tree) {
2036                                 proto_item* encoding_item = proto_tree_add_text(tree, tvb,
2037                                         offset + 1, 3,
2038                                         "encoding: %u %u %u",
2039                                         auth_type, fsid_type, fileid_type);
2040                                 {
2041                                         proto_tree* encoding_tree = proto_item_add_subtree(encoding_item,
2042                                                 ett_nfs_fh_encoding);
2043
2044                                         proto_tree_add_uint(encoding_tree, hf_nfs_fh_auth_type,
2045                                                         tvb, offset+1, 1, auth_type);
2046                                         proto_tree_add_uint(encoding_tree, hf_nfs_fh_fsid_type,
2047                                                         tvb, offset+2, 1, fsid_type);
2048                                         proto_tree_add_uint(encoding_tree, hf_nfs_fh_fileid_type,
2049                                                         tvb, offset+3, 1, fileid_type);
2050                                 }
2051                         }
2052                         offset += 4;
2053                 } break;
2054                 default: {
2055                         /* unknown version */
2056                         goto out;
2057                 }
2058         }
2059
2060         switch (auth_type) {
2061                 case 0: {
2062                         /* no authentication */
2063                         if (tree) {
2064                                 proto_tree_add_text(tree, tvb,
2065                                         offset + 0, 0,
2066                                         "authentication: none");
2067                         }
2068                 } break;
2069                 default: {
2070                         /* unknown authentication type */
2071                         goto out;
2072                 }
2073         }
2074
2075         switch (fsid_type) {
2076                 case 0: {
2077                         guint16 fsid_major;
2078                         guint16 fsid_minor;
2079                         guint32 fsid_inode;
2080
2081                         fsid_major = tvb_get_ntohs(tvb, offset + 0);
2082                         fsid_minor = tvb_get_ntohs(tvb, offset + 2);
2083                         fsid_inode = tvb_get_letohl(tvb, offset + 4);
2084                         if (tree) {
2085                                 proto_item* fsid_item = proto_tree_add_text(tree, tvb,
2086                                         offset+0, 8,
2087                                         "file system ID: %u,%u (inode %u)",
2088                                         fsid_major, fsid_minor, fsid_inode);
2089                                 {
2090                                         proto_tree* fsid_tree = proto_item_add_subtree(fsid_item,
2091                                                 ett_nfs_fh_fsid);
2092
2093                                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
2094                                                         tvb, offset+0, 2, fsid_major);
2095                                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
2096                                                         tvb, offset+2, 2, fsid_minor);
2097                                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_inode,
2098                                                         tvb, offset+4, 4, fsid_inode);
2099                                 }
2100                         }
2101                         offset += 8;
2102                 } break;
2103                 default: {
2104                         /* unknown fsid type */
2105                         goto out;
2106                 }
2107         }
2108
2109         switch (fileid_type) {
2110                 case 0: {
2111                         if (tree) {
2112                                 proto_tree_add_text(tree, tvb,
2113                                         offset+0, 0,
2114                                         "file ID: root inode");
2115                         }
2116                 } break;
2117                 case 1: {
2118                         guint32 inode;
2119                         guint32 generation;
2120
2121                         inode = tvb_get_letohl(tvb, offset + 0);
2122                         generation = tvb_get_letohl(tvb, offset + 4);
2123
2124                         if (tree) {
2125                                 proto_item* fileid_item = proto_tree_add_text(tree, tvb,
2126                                         offset+0, 8,
2127                                         "file ID: %u (%u)",
2128                                         inode, generation);
2129                                 {
2130                                         proto_tree* fileid_tree = proto_item_add_subtree(
2131                                                 fileid_item, ett_nfs_fh_fn);
2132
2133                                         proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
2134                                                 tvb, offset+0, 4, inode);
2135                                         proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
2136                                                 tvb, offset+4, 4, generation);
2137                                 }
2138                         }
2139
2140                         offset += 8;
2141                 } break;
2142                 case 2: {
2143                         guint32 inode;
2144                         guint32 generation;
2145                         guint32 parent_inode;
2146
2147                         inode = tvb_get_letohl(tvb, offset + 0);
2148                         generation = tvb_get_letohl(tvb, offset + 4);
2149                         parent_inode = tvb_get_letohl(tvb, offset + 8);
2150
2151                         if (tree) {
2152                                  proto_item* fileid_item = proto_tree_add_text(tree, tvb,
2153                                         offset+0, 8,
2154                                         "file ID: %u (%u)",
2155                                         inode, generation);
2156                                  {
2157                                         proto_tree* fileid_tree = proto_item_add_subtree(
2158                                                 fileid_item, ett_nfs_fh_fn);
2159
2160                                         proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
2161                                                 tvb, offset+0, 4, inode);
2162                                         proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
2163                                                 tvb, offset+4, 4, generation);
2164                                         proto_tree_add_uint(fileid_tree, hf_nfs_fh_dirinode,
2165                                                 tvb, offset+8, 4, parent_inode);
2166                                 }
2167                         }
2168
2169                         offset += 12;
2170                 } break;
2171                 default: {
2172                         /* unknown fileid type */
2173                         goto out;
2174                 }
2175         }
2176
2177 out:
2178         ;
2179 }
2180
2181
2182 /* Dissect EMC Celerra NFSv3/v4 File Handles */
2183 static void
2184 dissect_fhandle_data_CELERRA(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree)
2185 {
2186         guint16 offset=0;
2187         guint16 fhlen;
2188         guint32 obj_fsid;
2189         guint16 obj_kindid;
2190         guint16 obj_treeid;
2191         guint32 obj_inode;
2192         guint32 obj_gen;
2193         guint32 ex_fsid;
2194         guint16 ex_kindid;
2195         guint16 ex_treeid;
2196         guint32 ex_inode;
2197         guint32 ex_gen;
2198         guint32 obj_id;
2199         guint32 ro_node;
2200
2201         if (!tree) return;
2202
2203         fhlen = tvb_reported_length(tvb);
2204
2205         /* Display the entire filehandle */
2206         proto_tree_add_item(tree, hf_nfs_fh_fhandle_data, tvb, 0, fhlen, FALSE);
2207
2208         /*      On Celerra if fhlen = 32, it's an NFSv3 filehandle */
2209         if (fhlen == 32) {
2210                 /* Create a "File/Dir" subtree: bytes 0 thru 15 of the 32-byte file handle       */
2211                 {
2212                 proto_item* obj_item = NULL;
2213                 proto_tree* obj_tree = NULL;
2214                 obj_item = proto_tree_add_item(tree, hf_nfs_fh_obj, tvb, offset+0, 16, TRUE );
2215                 obj_tree = proto_item_add_subtree(obj_item, ett_nfs_fh_obj);
2216
2217                 obj_fsid   = tvb_get_letohl(tvb, offset+0);
2218                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_fsid,   tvb,  offset+0, 4, obj_fsid);
2219                 obj_kindid = tvb_get_letohs(tvb, offset+4);
2220                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_kindid, tvb,  offset+4, 2, obj_kindid);
2221                 obj_treeid = tvb_get_letohs(tvb, offset+6);
2222                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_treeid, tvb,  offset+6, 2, obj_treeid);
2223                 obj_inode  = tvb_get_letohl(tvb, offset+8);
2224                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_inode,  tvb,  offset+8, 4, obj_inode);
2225                 obj_gen   = tvb_get_letohl(tvb, offset+12);
2226                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+12, 4, obj_gen);
2227                 }
2228                 {
2229                 /* Create "Export" subtree (NFSv3: Bytes 16 thru 31 of the 32-byte file handle  */
2230                 proto_item* ex_item = NULL;
2231                 proto_tree* ex_tree = NULL;
2232                 ex_item = proto_tree_add_item(tree, hf_nfs_fh_ex, tvb,  offset+16, 16, TRUE );
2233                 ex_tree = proto_item_add_subtree(ex_item, ett_nfs_fh_ex);
2234
2235                 ex_fsid   = tvb_get_letohl(tvb, offset+16);
2236                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_fsid,     tvb, offset+16, 4, ex_fsid);
2237                 ex_kindid = tvb_get_letohs(tvb, offset+20);
2238                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_kindid,   tvb, offset+20, 2, ex_kindid);
2239                 ex_treeid = tvb_get_letohs(tvb, offset+22);
2240                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_treeid,   tvb, offset+22, 2, ex_treeid);
2241                 ex_inode  = tvb_get_letohl(tvb, offset+24);
2242                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_inode,    tvb, offset+24, 4, ex_inode);
2243                 ex_gen    = tvb_get_letohl(tvb, offset+28);
2244                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_gen,      tvb, offset+28, 4, ex_gen);
2245                 }
2246         } else {
2247                 /* On Celerra if fhlen = 40, it's an NFSv4 filehandle).  In Celerra NFSv4
2248                 filehandles, the first 4 bytes are the Named Attribute ID, and the next 4 bytes
2249                 is the RO_Node boolean which is true is the file/dir is Read Only.  Unlike the
2250                 NFSv3 filehandles, the next 16 bytes contain the *export* info followed by 16 bytes
2251                 containing the *file/dir* info. */
2252
2253                 /* "Named Attribute ID" or "Object ID" (bytes 0 thru 3) */
2254                 obj_id = tvb_get_letohl(tvb, offset+0);
2255                 if (obj_id <= 0 || obj_id > 9) obj_id = 1;
2256                 proto_tree_add_uint(tree, hf_nfs_fh_obj_id,         tvb,  offset+0, 4, obj_id);
2257
2258                 /* "RO_Node" boolean (bytes 4 thru 7) */
2259                 ro_node = tvb_get_letohl(tvb, offset+4);
2260                 proto_tree_add_boolean(tree, hf_nfs_fh_ro_node,     tvb,  offset+4, 4, ro_node);
2261
2262                 /* Create "Export" subtree (bytes 8 thru 23 of the 40-byte filehandle  */
2263                 {
2264                 proto_item* ex_item = NULL;
2265                 proto_tree* ex_tree = NULL;
2266                 ex_item = proto_tree_add_item(tree, hf_nfs_fh_ex,  tvb,  offset+8, 16, TRUE );
2267                 ex_tree = proto_item_add_subtree(ex_item, ett_nfs_fh_ex);
2268
2269                 ex_fsid   = tvb_get_letohl(tvb, offset+8);
2270                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_fsid,    tvb,  offset+8,  4, ex_fsid);
2271                 ex_kindid = tvb_get_letohs(tvb, offset+12);
2272                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_kindid,  tvb, offset+12,  2, ex_kindid);
2273                 ex_treeid = tvb_get_letohs(tvb, offset+14);
2274                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_treeid,  tvb, offset+14,  2, ex_treeid);
2275                 ex_inode  = tvb_get_letohl(tvb, offset+16);
2276                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_inode,   tvb, offset+16,  4, ex_inode);
2277                 ex_gen    = tvb_get_letohl(tvb, offset+20);
2278                 proto_tree_add_uint(ex_tree, hf_nfs_fh_ex_gen,     tvb, offset+20,  4, ex_gen);
2279                 }
2280                 /* Create a "File/Dir/Object" subtree (bytes 24 thru 39 of the 40-byte filehandle)       */
2281                 {
2282                 proto_item* obj_item = NULL;
2283                 proto_tree* obj_tree = NULL;
2284                 obj_item = proto_tree_add_item(tree, hf_nfs_fh_obj, tvb, offset+24, 16, TRUE);
2285                 obj_tree = proto_item_add_subtree(obj_item, ett_nfs_fh_obj);
2286
2287                 obj_fsid   = tvb_get_letohl(tvb, offset+24);
2288                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_fsid,   tvb, offset+24,  4, obj_fsid);
2289                 obj_kindid = tvb_get_letohs(tvb, offset+28);
2290                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_kindid, tvb, offset+28,  2, obj_kindid);
2291                 obj_treeid = tvb_get_letohs(tvb, offset+30);
2292                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_treeid, tvb, offset+30,  2, obj_treeid);
2293                 obj_inode  = tvb_get_letohl(tvb, offset+32);
2294                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_inode,  tvb, offset+32,  4, obj_inode);
2295                 obj_gen   = tvb_get_letohl(tvb, offset+36);
2296                 proto_tree_add_uint(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+36,  4, obj_gen);
2297                 }
2298         }
2299 };
2300
2301 static void
2302 dissect_fhandle_data_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
2303 {
2304         guint fhlen=tvb_length(tvb);
2305
2306         proto_tree_add_item(tree, hf_nfs_fh_fhandle_data, tvb, 0, fhlen, FALSE);
2307 }
2308
2309
2310 static void
2311 dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
2312                      proto_tree *tree, unsigned int fhlen, gboolean hidden,
2313                      guint32 *hash)
2314 {
2315         /* this is to set up fhandle display filters to find both packets
2316            of an RPC call */
2317         if(nfs_fhandle_reqrep_matching && (!hidden) ){
2318                 nfs_fhandle_data_t *old_fhd=NULL;
2319
2320                 if( !pinfo->fd->flags.visited ){
2321                         nfs_fhandle_data_t fhd;
2322
2323                         /* first check if we have seen this fhandle before */
2324                         fhd.len=fhlen;
2325                         fhd.fh=(const unsigned char *)tvb_get_ptr(tvb, offset, fhlen);
2326                         old_fhd=store_nfs_file_handle(&fhd);
2327
2328                         /* XXX here we should really check that we havent stored
2329                            this fhandle for this frame number already.
2330                            We should also make sure we can handle when we have multiple
2331                            fhandles seen for the same frame, which WILL happen for certain
2332                            nfs calls. For now, we dont handle this and those calls will
2333                            not work properly with this feature
2334                         */
2335                         se_tree_insert32(nfs_fhandle_frame_table, pinfo->fd->num, old_fhd);
2336                 }
2337         }
2338
2339         /* Create a unique hash value for the filehandle using CRC32 */
2340         {
2341                 guint32 fhhash;
2342                 guint8 *fh_array;
2343                 proto_item *fh_item;
2344
2345                 fh_array = tvb_get_string(tvb, offset, fhlen);
2346                 fhhash = crc32_ccitt(fh_array, fhlen);
2347
2348                 if(hidden){
2349                         fh_item=proto_tree_add_uint(tree, hf_nfs_fh_hash, tvb, offset,
2350                                 fhlen, fhhash);
2351                         PROTO_ITEM_SET_HIDDEN(fh_item);
2352                 } else {
2353                         fh_item=proto_tree_add_uint(tree, hf_nfs_fh_hash, tvb, offset,
2354                                 fhlen, fhhash);
2355                 }
2356                 PROTO_ITEM_SET_GENERATED(fh_item);
2357                 if(hash){
2358                         *hash=fhhash;
2359                 }
2360         }
2361         if(nfs_file_name_snooping){
2362                 nfs_name_snoop_fh(pinfo, tree, tvb, offset, fhlen, hidden);
2363         }
2364
2365         if(!hidden){
2366                 tvbuff_t *fh_tvb;
2367                 int real_length;
2368
2369                 proto_tree_add_text(tree, tvb, offset, 0,
2370                         "decode type as: %s", val_to_str_ext_const(default_nfs_fhandle_type, &names_fhtype_ext, "Unknown"));
2371
2372
2373                 real_length=fhlen;
2374                 if(default_nfs_fhandle_type != FHT_UNKNOWN && real_length<tvb_length_remaining(tvb, offset)){
2375                         real_length=tvb_length_remaining(tvb, offset);
2376                 }
2377                 fh_tvb=tvb_new_subset(tvb, offset, real_length, fhlen);
2378                 if(!dissector_try_uint(nfs_fhandle_table, default_nfs_fhandle_type, fh_tvb, pinfo, tree)){
2379                         dissect_fhandle_data_unknown(fh_tvb, pinfo, tree);
2380                 }
2381         }
2382 }
2383
2384 void
2385 dissect_fhandle_hidden(packet_info *pinfo, proto_tree *tree, int frame)
2386 {
2387         nfs_fhandle_data_t *nfd;
2388
2389         nfd=se_tree_lookup32(nfs_fhandle_frame_table, frame);
2390         if(nfd && nfd->len){
2391                 dissect_fhandle_data(nfd->tvb, 0, pinfo, tree, nfd->len, TRUE, NULL);
2392         }
2393 }
2394
2395
2396 /***************************/
2397 /* NFS Version 2, RFC 1094 */
2398 /***************************/
2399
2400
2401 /* RFC 1094, Page 12..14 */
2402 static const value_string names_nfs_stat[] =
2403 {
2404         {       0,      "NFS_OK" },
2405         {       1,      "NFSERR_PERM" },
2406         {       2,      "NFSERR_NOENT" },
2407         {       5,      "NFSERR_IO" },
2408         {       6,      "NFSERR_NXIO" },
2409         {       11,     "NFSERR_EAGAIN" },
2410         {       13,     "NFSERR_ACCES" },
2411         {       17,     "NFSERR_EXIST" },
2412         {       18,     "NFSERR_XDEV" },        /* not in spec, but can happen */
2413         {       19,     "NFSERR_NODEV" },
2414         {       20,     "NFSERR_NOTDIR" },
2415         {       21,     "NFSERR_ISDIR" },
2416         {       22,     "NFSERR_INVAL" },       /* not in spec, but I think it can happen */
2417         {       26,     "NFSERR_TXTBSY" },      /* not in spec, but I think it can happen */
2418         {       27,     "NFSERR_FBIG" },
2419         {       28,     "NFSERR_NOSPC" },
2420         {       30,     "NFSERR_ROFS" },
2421         {       31,     "NFSERR_MLINK" },       /* not in spec, but can happen */
2422         {       45,     "NFSERR_OPNOTSUPP" },   /* not in spec, but I think it can happen */
2423         {       63,     "NFSERR_NAMETOOLONG" },
2424         {       66,     "NFSERR_NOTEMPTY" },
2425         {       69,     "NFSERR_DQUOT" },
2426         {       70,     "NFSERR_STALE" },
2427         {       71,     "NFSERR_REMOTE" },
2428         {       99,     "NFSERR_WFLUSH" },
2429         {       10001,  "NFSERR_BADHANDLE" },
2430         {       10002,  "NFSERR_NOT_SYNC" },
2431         {       10003,  "NFSERR_BAD_COOKIE" },
2432         {       10004,  "NFSERR_NOTSUPP" },
2433         {       10005,  "NFSERR_TOOSMALL" },
2434         {       10006,  "NFSERR_SERVERFAULT" },
2435         {       10007,  "NFSERR_BADTYPE" },
2436         {       10008,  "NFSERR_JUKEBOX" },
2437         {       10009,  "NFSERR_SAME" },
2438         {       10010,  "NFSERR_DENIED" },
2439         {       10011,  "NFSERR_EXPIRED" },
2440         {       10012,  "NFSERR_LOCKED" },
2441         {       10013,  "NFSERR_GRACE" },
2442         {       10014,  "NFSERR_FHEXPIRED" },
2443         {       10015,  "NFSERR_SHARE_DENIED" },
2444         {       10016,  "NFSERR_WRONGSEC" },
2445         {       10017,  "NFSERR_CLID_INUSE" },
2446         {       10018,  "NFSERR_RESOURCE" },
2447         {       10019,  "NFSERR_MOVED" },
2448         {       10020,  "NFSERR_NOFILEHANDLE" },
2449         {       10021,  "NFSERR_MINOR_VERS_MISMATCH" },
2450         {       10022,  "NFSERR_STALE_CLIENTID" },
2451         {       10023,  "NFSERR_STALE_STATEID" },
2452         {       10024,  "NFSERR_OLD_STATEID" },
2453         {       10025,  "NFSERR_BAD_STATEID" },
2454         {       10026,  "NFSERR_BAD_SEQID" },
2455         {       10027,  "NFSERR_NOT_SAME" },
2456         {       10028,  "NFSERR_LOCK_RANGE" },
2457         {       10029,  "NFSERR_SYMLINK" },
2458         {       10030,  "NFSERR_RESTOREFH" },
2459         {       10031,  "NFSERR_LEASE_MOVED" },
2460         {       10032,  "NFSERR_ATTRNOTSUPP" },
2461         {       10033,  "NFSERR_NO_GRACE" },
2462         {       10034,  "NFSERR_RECLAIM_BAD" },
2463         {       10035,  "NFSERR_RECLAIM_CONFLICT" },
2464         {       10036,  "NFSERR_BAD_XDR" },
2465         {       10037,  "NFSERR_LOCKS_HELD" },
2466         {       10038,  "NFSERR_OPENMODE" },
2467         {       10039,  "NFSERR_BADOWNER" },
2468         {       10040,  "NFSERR_BADCHAR" },
2469         {       10041,  "NFSERR_BADNAME" },
2470         {       10042,  "NFSERR_BAD_RANGE" },
2471         {       10043,  "NFSERR_LOCK_NOTSUPP" },
2472         {       10044,  "NFSERR_OP_ILLEGAL" },
2473         {       10045,  "NFSERR_DEADLOCK" },
2474         {       10046,  "NFSERR_FILE_OPEN" },
2475         {       10047,  "NFSERR_ADMIN_REVOKED" },
2476         {       10048,  "NFSERR_CB_PATH_DOWN" },
2477         {       10049,  "NFSERR_REPLAY_ME" },
2478         {       0,      NULL }
2479 };
2480 static value_string_ext names_nfs_stat_ext = VALUE_STRING_EXT_INIT(names_nfs_stat);
2481
2482 /* RFC 1094, Page 12..14 */
2483 static int
2484 dissect_stat(tvbuff_t *tvb, int offset, proto_tree *tree,
2485         guint32 *status)
2486 {
2487         guint32 stat;
2488         proto_item *stat_item;
2489
2490         stat = tvb_get_ntohl(tvb, offset+0);
2491
2492         if (tree) {
2493                 proto_tree_add_uint(tree, hf_nfs_stat, tvb, offset+0, 4,
2494                         stat);
2495                 stat_item = proto_tree_add_uint(tree, hf_nfs_nfsstat, tvb,
2496                         offset+0, 4, stat);
2497                 PROTO_ITEM_SET_HIDDEN(stat_item);
2498         }
2499
2500         offset += 4;
2501
2502         if (status) *status = stat;
2503
2504         return offset;
2505 }
2506
2507
2508 /* RFC 1094, Page 12..14 */
2509 static int
2510 dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2511 {
2512         guint32 status;
2513         const char *err;
2514
2515         offset = dissect_stat(tvb, offset, tree, &status);
2516         switch (status) {
2517                 case 0:
2518                         proto_item_append_text(tree, ", RMDIR Reply");
2519                         break;
2520                 default:
2521                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
2522                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2523                         proto_item_append_text(tree, ", RMDIR Reply  Error:%s", err);
2524         }
2525
2526         return offset;
2527 }
2528
2529 static int
2530 dissect_nfs2_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2531 {
2532         guint32 status;
2533         const char *err;
2534
2535         offset = dissect_stat(tvb, offset, tree, &status);
2536         switch (status) {
2537                 case 0:
2538                         proto_item_append_text(tree, ", SYMLINK Reply");
2539                         break;
2540                 default:
2541                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
2542                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2543                         proto_item_append_text(tree, ", SYMLINK Reply  Error:%s", err);
2544         }
2545
2546         return offset;
2547 }
2548
2549 static int
2550 dissect_nfs2_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2551 {
2552         guint32 status;
2553         const char *err;
2554
2555         offset = dissect_stat(tvb, offset, tree, &status);
2556         switch (status) {
2557                 case 0:
2558                         proto_item_append_text(tree, ", LINK Reply");
2559                         break;
2560                 default:
2561                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
2562                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2563                         proto_item_append_text(tree, ", LINK Reply  Error:%s", err);
2564         }
2565
2566         return offset;
2567 }
2568
2569 static int
2570 dissect_nfs2_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2571 {
2572         guint32 status;
2573         const char *err;
2574
2575         offset = dissect_stat(tvb, offset, tree, &status);
2576         switch (status) {
2577                 case 0:
2578                         proto_item_append_text(tree, ", RENAME Reply");
2579                         break;
2580                 default:
2581                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
2582                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2583                         proto_item_append_text(tree, ", RENAME Reply  Error:%s", err);
2584         }
2585
2586         return offset;
2587 }
2588
2589 static int
2590 dissect_nfs2_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2591 {
2592         guint32 status;
2593         const char *err;
2594
2595         offset = dissect_stat(tvb, offset, tree, &status);
2596         switch (status) {
2597                 case 0:
2598                         proto_item_append_text(tree, ", REMOVE Reply");
2599                         break;
2600                 default:
2601                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
2602                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2603                         proto_item_append_text(tree, ", REMOVE Reply  Error:%s", err);
2604         }
2605
2606         return offset;
2607 }
2608
2609
2610 /* RFC 1094, Page 15 */
2611 static const value_string nfs2_ftype[] =
2612 {
2613         {       0,      "Non-File" },
2614         {       1,      "Regular File" },
2615         {       2,      "Directory" },
2616         {       3,      "Block Special Device" },
2617         {       4,      "Character Special Device" },
2618         {       5,      "Symbolic Link" },
2619         {       0,      NULL }
2620 };
2621 static value_string_ext nfs2_ftype_ext = VALUE_STRING_EXT_INIT(nfs2_ftype);
2622
2623 static int
2624 dissect_ftype(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
2625 {
2626         guint32 ftype;
2627         const char* ftype_name_p = NULL;
2628
2629         ftype = tvb_get_ntohl(tvb, offset+0);
2630
2631         if (tree) {
2632                 ftype_name_p = val_to_str_ext(ftype, &nfs2_ftype_ext, "%u");
2633
2634                 proto_tree_add_text(tree, tvb, offset, 4,
2635                         "%s: %s (%u)", name, ftype_name_p, ftype);
2636         }
2637
2638         offset += 4;
2639         return offset;
2640 }
2641
2642
2643 /* RFC 1094, Page 15 */
2644 int
2645 dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
2646                 const char *name, guint32 *hash)
2647 {
2648         proto_item* fitem;
2649         proto_tree* ftree = NULL;
2650
2651         if (tree) {
2652                 fitem = proto_tree_add_text(tree, tvb, offset, FHSIZE,
2653                         "%s", name);
2654
2655                 ftree = proto_item_add_subtree(fitem, ett_nfs_fhandle);
2656         }
2657
2658         /* are we snooping fh to filenames ?*/
2659         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
2660                 rpc_call_info_value *civ=pinfo->private_data;
2661
2662                 /* NFS v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
2663                 if( (civ->prog==100003)
2664                   &&(civ->vers==2)
2665                   &&(!civ->request)
2666                   &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
2667                 ) {
2668                         nfs_name_snoop_add_fh(civ->xid, tvb,
2669                                 offset, 32);
2670                 }
2671
2672                 /* MOUNT v1,v2 MNT replies might give us a filehandle*/
2673                 if( (civ->prog==100005)
2674                   &&(civ->proc==1)
2675                   &&((civ->vers==1)||(civ->vers==2))
2676                   &&(!civ->request)
2677                 ) {
2678                         nfs_name_snoop_add_fh(civ->xid, tvb,
2679                                 offset, 32);
2680                 }
2681         }
2682
2683         dissect_fhandle_data(tvb, offset, pinfo, ftree, FHSIZE, FALSE, hash);
2684
2685         offset += FHSIZE;
2686         return offset;
2687 }
2688
2689 /* RFC 1094, Page 15 */
2690 static int
2691 dissect_nfs2_statfs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2692 {
2693         guint32 hash;
2694
2695         offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
2696
2697         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2698         proto_item_append_text(tree, ", STATFS Call FH:0x%08x", hash);
2699
2700         return offset;
2701 }
2702
2703 static int
2704 dissect_nfs2_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2705 {
2706         guint32 hash;
2707
2708         offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
2709
2710         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2711         proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
2712
2713         return offset;
2714 }
2715
2716 static int
2717 dissect_nfs2_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2718 {
2719         guint32 hash;
2720
2721         offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
2722
2723         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2724         proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
2725
2726         return offset;
2727 }
2728
2729
2730 /* RFC 1094, Page 15 */
2731 static int
2732 dissect_timeval(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_time, int hf_time_sec, int hf_time_usec)
2733 {
2734         guint32 seconds;
2735         guint32 useconds;
2736         nstime_t ts;
2737
2738         proto_item* time_item;
2739         proto_tree* time_tree;
2740
2741         seconds = tvb_get_ntohl(tvb, offset+0);
2742         useconds = tvb_get_ntohl(tvb, offset+4);
2743         ts.secs = seconds;
2744         ts.nsecs = useconds*1000;
2745
2746         if (tree) {
2747                 time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
2748                                 &ts);
2749
2750                 time_tree = proto_item_add_subtree(time_item, ett_nfs_timeval);
2751
2752                 proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
2753                                     seconds);
2754                 proto_tree_add_uint(time_tree, hf_time_usec, tvb, offset+4, 4,
2755                                     useconds);
2756         }
2757         offset += 8;
2758         return offset;
2759 }
2760
2761
2762 /* RFC 1094, Page 16 */
2763 static const value_string nfs2_mode_names[] = {
2764         {       0040000,        "Directory"     },
2765         {       0020000,        "Character Special Device"      },
2766         {       0060000,        "Block Special Device"  },
2767         {       0100000,        "Regular File"  },
2768         {       0120000,        "Symbolic Link" },
2769         {       0140000,        "Named Socket"  },
2770         {       0000000,        NULL            }
2771 };
2772
2773 static int
2774 dissect_mode(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
2775 {
2776         guint32 mode;
2777         proto_item* mode_item;
2778         proto_tree* mode_tree;
2779
2780         mode = tvb_get_ntohl(tvb, offset+0);
2781
2782         if (tree) {
2783                 mode_item = proto_tree_add_text(tree, tvb, offset, 4,
2784                         "%s: 0%o", name, mode);
2785
2786                 mode_tree = proto_item_add_subtree(mode_item, ett_nfs_mode);
2787
2788                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2789                         decode_enumerated_bitfield(mode,  0160000, 16,
2790                         nfs2_mode_names, "%s"));
2791                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2792                 decode_boolean_bitfield(mode,   04000, 16, "Set user id on exec", "not SUID"));
2793                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2794                 decode_boolean_bitfield(mode,   02000, 16, "Set group id on exec", "not SGID"));
2795                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2796                 decode_boolean_bitfield(mode,   01000, 16, "Save swapped text even after use", "not save swapped text"));
2797                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2798                 decode_boolean_bitfield(mode,    0400, 16, "Read permission for owner", "no Read permission for owner"));
2799                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2800                 decode_boolean_bitfield(mode,    0200, 16, "Write permission for owner", "no Write permission for owner"));
2801                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2802                 decode_boolean_bitfield(mode,    0100, 16, "Execute permission for owner", "no Execute permission for owner"));
2803                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2804                 decode_boolean_bitfield(mode,     040, 16, "Read permission for group", "no Read permission for group"));
2805                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2806                 decode_boolean_bitfield(mode,     020, 16, "Write permission for group", "no Write permission for group"));
2807                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2808                 decode_boolean_bitfield(mode,     010, 16, "Execute permission for group", "no Execute permission for group"));
2809                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2810                 decode_boolean_bitfield(mode,      04, 16, "Read permission for others", "no Read permission for others"));
2811                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2812                 decode_boolean_bitfield(mode,      02, 16, "Write permission for others", "no Write permission for others"));
2813                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2814                 decode_boolean_bitfield(mode,      01, 16, "Execute permission for others", "no Execute permission for others"));
2815         }
2816
2817         offset += 4;
2818         return offset;
2819 }
2820
2821
2822 /* RFC 1094, Page 15 */
2823 int
2824 dissect_fattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
2825 {
2826         proto_item* fattr_item = NULL;
2827         proto_tree* fattr_tree = NULL;
2828         int old_offset = offset;
2829
2830         if (tree) {
2831                 fattr_item = proto_tree_add_text(tree, tvb, offset, -1,
2832                         "%s", name);
2833                 fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs_fattr);
2834         }
2835
2836         offset = dissect_ftype(tvb, offset, fattr_tree, "type");
2837         offset = dissect_mode(tvb, offset, fattr_tree, "mode");
2838         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_nlink, offset);
2839         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_uid, offset);
2840         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_gid, offset);
2841         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_size, offset);
2842         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocksize, offset);
2843         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_rdev, offset);
2844         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocks, offset);
2845         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fsid, offset);
2846         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fileid, offset);
2847
2848         offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
2849         offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
2850         offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_usec);
2851
2852         /* now we know, that fattr is shorter */
2853         if (fattr_item) {
2854                 proto_item_set_len(fattr_item, offset - old_offset);
2855         }
2856
2857         return offset;
2858 }
2859
2860
2861 /* RFC 1094, Page 17 */
2862 static int
2863 dissect_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
2864 {
2865         proto_item* sattr_item = NULL;
2866         proto_tree* sattr_tree = NULL;
2867         int old_offset = offset;
2868
2869         if (tree) {
2870                 sattr_item = proto_tree_add_text(tree, tvb, offset, -1,
2871                         "%s", name);
2872                 sattr_tree = proto_item_add_subtree(sattr_item, ett_nfs_sattr);
2873         }
2874
2875         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2876                 offset = dissect_mode(tvb, offset, sattr_tree, "mode");
2877         else {
2878                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "mode: no value");
2879                 offset += 4;
2880         }
2881
2882         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2883                 offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_uid,
2884                         offset);
2885         else {
2886                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "uid: no value");
2887                 offset += 4;
2888         }
2889
2890         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2891                 offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_gid,
2892                         offset);
2893         else {
2894                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "gid: no value");
2895                 offset += 4;
2896         }
2897
2898         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2899                 offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_size,
2900                         offset);
2901         else {
2902                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "size: no value");
2903                 offset += 4;
2904         }
2905
2906         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
2907                 offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
2908         } else {
2909                 proto_tree_add_text(sattr_tree, tvb, offset, 8, "atime: no value");
2910                 offset += 8;
2911         }
2912
2913         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
2914                 offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
2915         } else {
2916                 proto_tree_add_text(sattr_tree, tvb, offset, 8, "mtime: no value");
2917                 offset += 8;
2918         }
2919
2920         /* now we know, that sattr is shorter */
2921         if (sattr_item) {
2922                 proto_item_set_len(sattr_item, offset - old_offset);
2923         }
2924
2925         return offset;
2926 }
2927
2928
2929 /* RFC 1094, Page 17 */
2930 static int
2931 dissect_filename(tvbuff_t *tvb, int offset,
2932     proto_tree *tree, int hf, char **string_ret)
2933 {
2934         offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
2935         return offset;
2936 }
2937
2938
2939 /* RFC 1094, Page 17 */
2940 static int
2941 dissect_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
2942 {
2943         offset = dissect_rpc_string(tvb, tree, hf, offset, name);
2944         return offset;
2945 }
2946
2947
2948 /* RFC 1094, Page 17,18 */
2949 static int
2950 dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, const char *funcname)
2951 {
2952         guint32 status;
2953         const char *err;
2954
2955         offset = dissect_stat(tvb, offset, tree, &status);
2956         switch (status) {
2957                 case 0:
2958                         offset = dissect_fattr(tvb, offset, tree, "attributes");
2959                         proto_item_append_text(tree, ", %s Reply", funcname);
2960                 break;
2961                 default:
2962                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
2963                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2964                         proto_item_append_text(tree, ", %s Reply  Error:%s", funcname, err);
2965                 break;
2966         }
2967
2968         return offset;
2969 }
2970
2971
2972 /* RFC 1094, Page 17,18 */
2973 static int
2974 dissect_nfs2_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2975 {
2976         offset = dissect_attrstat(tvb, offset, tree, pinfo, "WRITE");
2977
2978         return offset;
2979 }
2980
2981 static int
2982 dissect_nfs2_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2983 {
2984         offset = dissect_attrstat(tvb, offset, tree, pinfo, "SETATTR");
2985
2986         return offset;
2987 }
2988
2989 static int
2990 dissect_nfs2_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2991 {
2992         offset = dissect_attrstat(tvb, offset, tree, pinfo, "GETATTR");
2993
2994         return offset;
2995 }
2996
2997
2998 /* RFC 1094, Page 18 */
2999 static int
3000 dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, const char* label, guint32 *hash, char **name)
3001 {
3002         proto_item* diropargs_item = NULL;
3003         proto_tree* diropargs_tree = NULL;
3004         int old_offset = offset;
3005
3006         if (tree) {
3007                 diropargs_item = proto_tree_add_text(tree, tvb, offset, -1,
3008                         "%s", label);
3009                 diropargs_tree = proto_item_add_subtree(diropargs_item, ett_nfs_diropargs);
3010         }
3011
3012         /* are we snooping fh to filenames ?*/
3013         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
3014                 /* v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
3015                 rpc_call_info_value *civ=pinfo->private_data;
3016
3017                 if( (civ->prog==100003)
3018                   &&(civ->vers==2)
3019                   &&(civ->request)
3020                   &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
3021                 ) {
3022                         nfs_name_snoop_add_name(civ->xid, tvb,
3023                                 offset+36, tvb_get_ntohl(tvb, offset+32),
3024                                 offset, 32, NULL);
3025                 }
3026         }
3027
3028         offset = dissect_fhandle(tvb, offset, pinfo, diropargs_tree, "dir", hash);
3029         offset = dissect_filename(tvb, offset, diropargs_tree, hf_nfs_name, name);
3030
3031         /* now we know, that diropargs is shorter */
3032         if (diropargs_item) {
3033                 proto_item_set_len(diropargs_item, offset - old_offset);
3034         }
3035
3036         return offset;
3037 }
3038
3039
3040 /* RFC 1094, Page 18 */
3041 static int
3042 dissect_nfs2_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
3043 {
3044         guint32 hash;
3045         char *name=NULL;
3046
3047         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
3048
3049         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
3050         proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
3051
3052         return offset;
3053 }
3054
3055 static int
3056 dissect_nfs2_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
3057 {
3058         guint32 hash;
3059         char *name=NULL;
3060
3061         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
3062
3063         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
3064         proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
3065
3066         return offset;
3067 }
3068
3069 static int
3070 dissect_nfs2_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
3071 {
3072         guint32 hash;
3073         char *name=NULL;
3074
3075         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
3076
3077         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
3078         proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
3079
3080         return offset;
3081 }
3082
3083
3084 /* RFC 1094, Page 18 */
3085 static int
3086 dissect_diropres(tvbuff_t *tvb, int offset, packet_info *pinfo,
3087                  proto_tree *tree, const char *funcname)
3088 {
3089         guint32 status;
3090         guint32 hash;
3091         const char *err;
3092
3093         offset = dissect_stat(tvb, offset, tree, &status);
3094         switch (status) {
3095                 case 0:
3096                         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
3097                         offset = dissect_fattr  (tvb, offset, tree, "attributes");
3098                         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
3099                         proto_item_append_text(tree, ", %s Reply FH:0x%08x", funcname, hash);
3100                 break;
3101                 default:
3102                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
3103                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
3104                         proto_item_append_text(tree, ", %s Reply  Error:%s", funcname, err);
3105                 break;
3106         }
3107
3108         return offset;
3109 }
3110
3111
3112 /* nfsdata is simply a chunk of RPC opaque data (length, data, fill bytes) */
3113 static int
3114 dissect_nfsdata(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
3115 {
3116         offset = dissect_rpc_data(tvb, tree, hf, offset);
3117         return offset;
3118 }
3119
3120
3121 /* RFC 1094, Page 18 */
3122 static int
3123 dissect_nfs2_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
3124                          proto_tree* tree)
3125 {
3126         offset = dissect_diropres(tvb, offset, pinfo, tree, "MKDIR");
3127         return offset;
3128 }
3129
3130 static int
3131 dissect_nfs2_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
3132                           proto_tree* tree)
3133 {
3134         offset = dissect_diropres(tvb, offset, pinfo, tree, "CREATE");
3135         return offset;
3136 }
3137
3138 static int
3139 dissect_nfs2_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
3140                           proto_tree* tree)
3141 {
3142         offset = dissect_diropres(tvb, offset, pinfo, tree, "LOOKUP");
3143         return offset;
3144 }
3145
3146
3147 /* RFC 1094, Page 6 */
3148 static int
3149 dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3150                           proto_tree *tree)
3151 {
3152         guint32 hash;
3153
3154         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
3155         offset = dissect_sattr  (tvb, offset,        tree, "attributes");
3156
3157         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
3158         proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
3159         return offset;
3160 }
3161
3162
3163 /* RFC 1094, Page 6 */
3164 static int
3165 dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
3166                             proto_tree *tree)
3167 {
3168         guint32 status;
3169         const char *err;
3170         char *name=NULL;
3171
3172         offset = dissect_stat(tvb, offset, tree, &status);
3173         switch (status) {
3174                 case 0:
3175                         offset = dissect_path(tvb, offset, tree, hf_nfs_readlink_data, &name);
3176                         col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
3177                         proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
3178                 break;
3179                 default:
3180                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
3181                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
3182                         proto_item_append_text(tree, ", READLINK Reply  Error:%s", err);
3183                 break;
3184         }
3185
3186         return offset;
3187 }
3188
3189
3190 /* RFC 1094, Page 7 */
3191 static int
3192 dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3193                        proto_tree *tree)
3194 {
3195         guint32 offset_value;
3196         guint32 count;
3197         guint32 totalcount;
3198         guint32 hash;
3199
3200         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
3201         offset_value = tvb_get_ntohl(tvb, offset+0);
3202         count        = tvb_get_ntohl(tvb, offset+4);
3203         totalcount   = tvb_get_ntohl(tvb, offset+8);
3204         if (tree) {
3205                 proto_tree_add_uint(tree, hf_nfs_read_offset, tvb,
3206                 offset+0, 4, offset_value);
3207                 proto_tree_add_uint(tree, hf_nfs_read_count, tvb,
3208                 offset+4, 4, count);
3209                 proto_tree_add_uint(tree, hf_nfs_read_totalcount, tvb,
3210                 offset+8, 4, totalcount);
3211         }
3212         offset += 12;
3213
3214         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
3215         proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
3216
3217         return offset;
3218 }
3219
3220
3221 /* RFC 1094, Page 7 */
3222 static int
3223 dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
3224                         proto_tree* tree)
3225 {
3226         guint32 status;
3227         const char *err;
3228
3229         offset = dissect_stat(tvb, offset, tree, &status);
3230         switch (status) {
3231                 case 0:
3232                         offset = dissect_fattr(tvb, offset, tree, "attributes");
3233                         proto_item_append_text(tree, ", READ Reply");
3234                         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
3235                 break;
3236                 default:
3237                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
3238                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
3239                         proto_item_append_text(tree, ", READ Reply  Error:%s", err);
3240                 break;
3241         }
3242
3243         return offset;
3244 }
3245
3246
3247 /* RFC 1094, Page 8 */
3248 static int
3249 dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3250                         proto_tree *tree)
3251 {
3252         guint32 beginoffset;
3253         guint32 offset_value;
3254         guint32 totalcount;
3255         guint32 hash;
3256
3257         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
3258         beginoffset  = tvb_get_ntohl(tvb, offset+0);
3259         offset_value = tvb_get_ntohl(tvb, offset+4);
3260         totalcount   = tvb_get_ntohl(tvb, offset+8);
3261         if (tree) {
3262                 proto_tree_add_uint(tree, hf_nfs_write_beginoffset, tvb,
3263                 offset+0, 4, beginoffset);
3264                 proto_tree_add_uint(tree, hf_nfs_write_offset, tvb,
3265                 offset+4, 4, offset_value);
3266                 proto_tree_add_uint(tree, hf_nfs_write_totalcount, tvb,
3267                 offset+8, 4, totalcount);
3268         }
3269         offset += 12;
3270
3271         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
3272         proto_item_append_text(tree, ", WRITE Call FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
3273
3274         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
3275
3276         return offset;
3277 }
3278
3279
3280 /* RFC 1094, Page 8 */
3281 static int
3282 dissect_nfs2_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3283                         proto_tree *tree)
3284 {
3285         guint32 hash;
3286         char *name=NULL;
3287
3288         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
3289         offset = dissect_sattr    (tvb, offset,        tree, "attributes");
3290
3291         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
3292         proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
3293
3294         return offset;
3295 }
3296
3297 static int
3298 dissect_nfs2_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3299                          proto_tree *tree)
3300 {
3301         guint32 hash;
3302         char *name=NULL;
3303
3304         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
3305         offset = dissect_sattr    (tvb, offset,        tree, "attributes");
3306
3307         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
3308         proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s", hash, name);
3309
3310         return offset;
3311 }
3312
3313
3314 /* RFC 1094, Page 9 */
3315 static int
3316 dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3317                          proto_tree *tree)
3318 {
3319         guint32 from_hash;
3320         char *from_name=NULL;
3321         guint32 to_hash;
3322         char *to_name=NULL;
3323
3324         offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
3325         offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
3326
3327         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);
3328         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);
3329
3330         return offset;
3331 }
3332
3333
3334 /* RFC 1094, Page 9 */
3335 static int
3336 dissect_nfs2_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3337                        proto_tree *tree)
3338 {
3339         guint32 from_hash;
3340         guint32 to_hash;
3341         char *to_name=NULL;
3342
3343         offset = dissect_fhandle(tvb, offset, pinfo, tree, "from", &from_hash);
3344         offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
3345
3346         col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
3347         proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
3348
3349         return offset;
3350 }
3351
3352
3353 /* RFC 1094, Page 10 */
3354 static int
3355 dissect_nfs2_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3356                           proto_tree *tree)
3357 {
3358         guint32 from_hash;
3359         char *from_name=NULL;
3360         char *to_name=NULL;
3361
3362         offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
3363         offset = dissect_path(tvb, offset, tree, hf_nfs_symlink_to, &to_name);
3364         offset = dissect_sattr(tvb, offset, tree, "attributes");
3365
3366         col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
3367         proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
3368
3369         return offset;
3370 }
3371
3372
3373 /* RFC 1094, Page 11 */
3374 static int
3375 dissect_nfs2_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3376                           proto_tree *tree)
3377 {
3378         guint32 cookie;
3379         guint32 count;
3380         guint32 hash;
3381
3382         offset = dissect_fhandle(tvb, offset, pinfo, tree, "dir", &hash);
3383         cookie  = tvb_get_ntohl(tvb, offset+ 0);
3384         count = tvb_get_ntohl(tvb, offset+ 4);
3385         if (tree) {
3386                 proto_tree_add_uint(tree, hf_nfs_readdir_cookie, tvb,
3387                         offset+ 0, 4, cookie);
3388                 proto_tree_add_uint(tree, hf_nfs_readdir_count, tvb,
3389                         offset+ 4, 4, count);
3390         }
3391         offset += 8;
3392
3393         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
3394         proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
3395
3396         return offset;
3397 }
3398
3399
3400 /* RFC 1094, Page 11 */
3401 static int
3402 dissect_readdir_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
3403                       proto_tree* tree)
3404 {
3405         proto_item* entry_item = NULL;
3406         proto_tree* entry_tree = NULL;
3407         int old_offset = offset;
3408         guint32 fileid;
3409         guint32 cookie;
3410         char *name;
3411
3412         if (tree) {
3413                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
3414                         offset+0, -1, FALSE);
3415                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
3416         }
3417
3418         fileid = tvb_get_ntohl(tvb, offset + 0);
3419         if (entry_tree)
3420                 proto_tree_add_uint(entry_tree, hf_nfs_readdir_entry_fileid, tvb,
3421                         offset+0, 4, fileid);
3422         offset += 4;
3423
3424         offset = dissect_filename(tvb, offset, entry_tree,
3425                 hf_nfs_readdir_entry_name, &name);
3426         if (entry_item)
3427                 proto_item_set_text(entry_item, "Entry: file ID %u, name %s",
3428                 fileid, name);
3429
3430         cookie = tvb_get_ntohl(tvb, offset + 0);
3431         if (entry_tree)
3432                 proto_tree_add_uint(entry_tree, hf_nfs_readdir_entry_cookie, tvb,
3433                         offset+0, 4, cookie);
3434         offset += 4;
3435
3436         /* now we know, that a readdir entry is shorter */
3437         if (entry_item) {
3438                 proto_item_set_len(entry_item, offset - old_offset);
3439         }
3440
3441         return offset;
3442 }
3443
3444 /* RFC 1094, Page 11 */
3445 static int
3446 dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
3447                            proto_tree* tree)
3448 {
3449         guint32 status;
3450         guint32 eof_value;
3451         const char *err;
3452
3453         offset = dissect_stat(tvb, offset, tree, &status);
3454         switch (status) {
3455                 case 0:
3456                         proto_item_append_text(tree, ", READDIR Reply");
3457
3458                         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
3459                                 dissect_readdir_entry);
3460                         eof_value = tvb_get_ntohl(tvb, offset+0);
3461                         if (tree)
3462                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
3463                                         offset+ 0, 4, eof_value);
3464                         offset += 4;
3465                 break;
3466                 default:
3467                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
3468                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
3469                         proto_item_append_text(tree, ", READDIR Reply  Error:%s", err);
3470                 break;
3471         }
3472
3473         return offset;
3474 }
3475
3476
3477 /* RFC 1094, Page 12 */
3478 static int
3479 dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
3480                           proto_tree* tree)
3481 {
3482         guint32 status;
3483         guint32 tsize;
3484         guint32 bsize;
3485         guint32 blocks;
3486         guint32 bfree;
3487         guint32 bavail;
3488         const char *err;
3489
3490         offset = dissect_stat(tvb, offset, tree, &status);
3491         switch (status) {
3492                 case 0:
3493                         tsize  = tvb_get_ntohl(tvb, offset+ 0);
3494                         bsize  = tvb_get_ntohl(tvb, offset+ 4);
3495                         blocks = tvb_get_ntohl(tvb, offset+ 8);
3496                         bfree  = tvb_get_ntohl(tvb, offset+12);
3497                         bavail = tvb_get_ntohl(tvb, offset+16);
3498                         if (tree) {
3499                                 proto_tree_add_uint(tree, hf_nfs_statfs_tsize, tvb,
3500                                         offset+ 0, 4, tsize);
3501                                 proto_tree_add_uint(tree, hf_nfs_statfs_bsize, tvb,
3502                                         offset+ 4, 4, bsize);
3503                                 proto_tree_add_uint(tree, hf_nfs_statfs_blocks, tvb,
3504                                         offset+ 8, 4, blocks);
3505                                 proto_tree_add_uint(tree, hf_nfs_statfs_bfree, tvb,
3506                                         offset+12, 4, bfree);
3507                                 proto_tree_add_uint(tree, hf_nfs_statfs_bavail, tvb,
3508                                         offset+16, 4, bavail);
3509                         }
3510                         offset += 20;
3511                         proto_item_append_text(tree, ", STATFS Reply");
3512                 break;
3513                 default:
3514                         err=val_to_str_ext(status, &names_nfs_stat_ext, "Unknown error:%u");
3515                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
3516                         proto_item_append_text(tree, ", STATFS Reply  Error:%s", err);
3517                 break;
3518         }
3519
3520         return offset;
3521 }
3522
3523
3524 /* proc number, "proc name", dissect_request, dissect_reply */
3525 /* NULL as function pointer means: type of arguments is "void". */
3526 static const vsff nfs2_proc[] = {
3527         { 0,    "NULL",         /* OK */
3528         NULL,                           NULL },
3529         { 1,    "GETATTR",      /* OK */
3530         dissect_nfs2_getattr_call,      dissect_nfs2_getattr_reply },
3531         { 2,    "SETATTR",      /* OK */
3532         dissect_nfs2_setattr_call,      dissect_nfs2_setattr_reply },
3533         { 3,    "ROOT",         /* OK */
3534         NULL,                           NULL },
3535         { 4,    "LOOKUP",       /* OK */
3536         dissect_nfs2_lookup_call,       dissect_nfs2_lookup_reply },
3537         { 5,    "READLINK",     /* OK */
3538         dissect_nfs2_readlink_call,     dissect_nfs2_readlink_reply },
3539         { 6,    "READ",         /* OK */
3540         dissect_nfs2_read_call,         dissect_nfs2_read_reply },
3541         { 7,    "WRITECACHE",   /* OK */
3542         NULL,                           NULL },
3543         { 8,    "WRITE",        /* OK */
3544         dissect_nfs2_write_call,        dissect_nfs2_write_reply },
3545         { 9,    "CREATE",       /* OK */
3546         dissect_nfs2_create_call,       dissect_nfs2_create_reply },
3547         { 10,   "REMOVE",       /* OK */
3548         dissect_nfs2_remove_call,       dissect_nfs2_remove_reply },
3549         { 11,   "RENAME",       /* OK */
3550         dissect_nfs2_rename_call,       dissect_nfs2_rename_reply },
3551         { 12,   "LINK",         /* OK */
3552         dissect_nfs2_link_call,         dissect_nfs2_link_reply },
3553         { 13,   "SYMLINK",      /* OK */
3554         dissect_nfs2_symlink_call,      dissect_nfs2_symlink_reply },
3555         { 14,   "MKDIR",        /* OK */
3556         dissect_nfs2_mkdir_call,        dissect_nfs2_mkdir_reply },
3557         { 15,   "RMDIR",        /* OK */
3558         dissect_nfs2_rmdir_call,        dissect_nfs2_rmdir_reply },
3559         { 16,   "READDIR",      /* OK */
3560         dissect_nfs2_readdir_call,      dissect_nfs2_readdir_reply },
3561         { 17,   "STATFS",       /* OK */
3562         dissect_nfs2_statfs_call,       dissect_nfs2_statfs_reply },
3563         { 0,    NULL,   NULL,   NULL }
3564 };
3565
3566 static const value_string nfsv2_proc_vals[] = {
3567         { 0,    "NULL" },
3568         { 1,    "GETATTR" },
3569         { 2,    "SETATTR" },
3570         { 3,    "ROOT" },
3571         { 4,    "LOOKUP" },
3572         { 5,    "READLINK" },
3573         { 6,    "READ" },
3574         { 7,    "WRITECACHE" },
3575         { 8,    "WRITE" },
3576         { 9,    "CREATE" },
3577         { 10,   "REMOVE" },
3578         { 11,   "RENAME" },
3579         { 12,   "LINK" },
3580         { 13,   "SYMLINK" },
3581         { 14,   "MKDIR" },
3582         { 15,   "RMDIR" },
3583         { 16,   "READDIR" },
3584         { 17,   "STATFS" },
3585         { 0,    NULL }
3586 };
3587
3588 /* end of NFS Version 2 */
3589
3590
3591 /***************************/
3592 /* NFS Version 3, RFC 1813 */
3593 /***************************/
3594
3595
3596 /* RFC 1813, Page 15 */
3597 static int
3598 dissect_filename3(tvbuff_t *tvb, int offset,
3599     proto_tree *tree, int hf, char **string_ret)
3600 {
3601         offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
3602         return offset;
3603 }
3604
3605
3606 /* RFC 1813, Page 15 */
3607 static int
3608 dissect_nfspath3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
3609 {
3610         offset = dissect_rpc_string(tvb, tree, hf, offset, name);
3611         return offset;
3612 }
3613
3614 /* RFC 1813, Page 15 */
3615 static int
3616 dissect_cookieverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
3617 {
3618         proto_tree_add_text(tree, tvb, offset, NFS3_COOKIEVERFSIZE,
3619                 "Verifier: Opaque Data");
3620         offset += NFS3_COOKIEVERFSIZE;
3621         return offset;
3622 }
3623
3624
3625 /* RFC 1813, Page 16 */
3626 static int
3627 dissect_createverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
3628 {
3629         proto_tree_add_text(tree, tvb, offset, NFS3_CREATEVERFSIZE,
3630                 "Verifier: Opaque Data");
3631         offset += NFS3_CREATEVERFSIZE;
3632         return offset;
3633 }
3634
3635
3636 /* RFC 1813, Page 16 */
3637 static int
3638 dissect_writeverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
3639 {
3640         proto_tree_add_text(tree, tvb, offset, NFS3_WRITEVERFSIZE,
3641                 "Verifier: Opaque Data");
3642         offset += NFS3_WRITEVERFSIZE;
3643         return offset;
3644 }
3645
3646 /* RFC 1813, Page 16 */
3647 static int
3648 dissect_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *mode)
3649 {
3650         static const int *mode_bits[] = {
3651                 &hf_nfs_mode3_suid,
3652                 &hf_nfs_mode3_sgid,
3653                 &hf_nfs_mode3_sticky,
3654                 &hf_nfs_mode3_rusr,
3655                 &hf_nfs_mode3_wusr,
3656                 &hf_nfs_mode3_xusr,
3657                 &hf_nfs_mode3_rgrp,
3658                 &hf_nfs_mode3_wgrp,
3659                 &hf_nfs_mode3_xgrp,
3660                 &hf_nfs_mode3_roth,
3661                 &hf_nfs_mode3_woth,
3662                 &hf_nfs_mode3_xoth,
3663                 NULL
3664         };
3665
3666
3667         if(mode){
3668                 *mode=tvb_get_ntohl(tvb, offset+0);
3669         }
3670
3671         proto_tree_add_bitmask(tree, tvb, offset, hf_nfs_mode3, ett_nfs_mode3, mode_bits, FALSE);
3672
3673         offset += 4;
3674         return offset;
3675 }
3676
3677 /* RFC 1813, Page 16,17 */
3678 static const value_string names_nfs_nfsstat3[] =
3679 {
3680         {       0,      "NFS3_OK" },
3681         {       1,      "NFS3ERR_PERM" },
3682         {       2,      "NFS3ERR_NOENT" },
3683         {       5,      "NFS3ERR_IO" },
3684         {       6,      "NFS3ERR_NXIO" },
3685         {       13,     "NFS3ERR_ACCES" },
3686         {       17,     "NFS3ERR_EXIST" },
3687         {       18,     "NFS3ERR_XDEV" },
3688         {       19,     "NFS3ERR_NODEV" },
3689         {       20,     "NFS3ERR_NOTDIR" },
3690         {       21,     "NFS3ERR_ISDIR" },
3691         {       22,     "NFS3ERR_INVAL" },
3692         {       27,     "NFS3ERR_FBIG" },
3693         {       28,     "NFS3ERR_NOSPC" },
3694         {       30,     "NFS3ERR_ROFS" },
3695         {       31,     "NFS3ERR_MLINK" },
3696         {       63,     "NFS3ERR_NAMETOOLONG" },
3697         {       66,     "NFS3ERR_NOTEMPTY" },
3698         {       69,     "NFS3ERR_DQUOT" },
3699         {       70,     "NFS3ERR_STALE" },
3700         {       71,     "NFS3ERR_REMOTE" },
3701         {       10001,  "NFS3ERR_BADHANDLE" },
3702         {       10002,  "NFS3ERR_NOT_SYNC" },
3703         {       10003,  "NFS3ERR_BAD_COOKIE" },
3704         {       10004,  "NFS3ERR_NOTSUPP" },
3705         {       10005,  "NFS3ERR_TOOSMALL" },
3706         {       10006,  "NFS3ERR_SERVERFAULT" },
3707         {       10007,  "NFS3ERR_BADTYPE" },
3708         {       10008,  "NFS3ERR_JUKEBOX" },
3709         {       0,      NULL }
3710 };
3711 static value_string_ext names_nfs_nfsstat3_ext = VALUE_STRING_EXT_INIT(names_nfs_nfsstat3);
3712
3713
3714 /* RFC 1813, Page 16 */
3715 static int
3716 dissect_nfsstat3(tvbuff_t *tvb, int offset, proto_tree *tree,guint32 *status)
3717 {
3718         guint32 nfsstat3;
3719         proto_item *stat_item;
3720
3721         nfsstat3 = tvb_get_ntohl(tvb, offset+0);
3722
3723         if (tree) {
3724                 proto_tree_add_uint(tree, hf_nfs_nfsstat3, tvb,
3725                         offset+0, 4, nfsstat3);
3726                 stat_item = proto_tree_add_uint(tree, hf_nfs_nfsstat, tvb,
3727                         offset+0, 4, nfsstat3);
3728                 PROTO_ITEM_SET_HIDDEN(stat_item);
3729         }
3730
3731         offset += 4;
3732         *status = nfsstat3;
3733         return offset;
3734 }
3735
3736
3737 static const value_string names_nfs_ftype3[] =
3738 {
3739         {       NF3REG, "Regular File" },
3740         {       NF3DIR, "Directory" },
3741         {       NF3BLK, "Block Special Device" },
3742         {       NF3CHR, "Character Special Device" },
3743         {       NF3LNK, "Symbolic Link" },
3744         {       NF3SOCK,"Socket" },
3745         {       NF3FIFO,"Named Pipe" },
3746         {       0,      NULL }
3747 };
3748 static value_string_ext names_nfs_ftype3_ext = VALUE_STRING_EXT_INIT(names_nfs_ftype3);
3749
3750
3751 /* RFC 1813, Page 20 */
3752 static int
3753 dissect_ftype3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf,
3754                guint32* ftype3)
3755 {
3756         guint32 type;
3757
3758         type = tvb_get_ntohl(tvb, offset+0);
3759
3760         if (tree) {
3761                 proto_tree_add_uint(tree, hf, tvb, offset, 4, type);
3762         }
3763
3764         offset += 4;
3765         *ftype3 = type;
3766         return offset;
3767 }
3768
3769
3770 /* RFC 1813, Page 20 */
3771 static int
3772 dissect_specdata3(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
3773 {
3774         guint32 specdata1;
3775         guint32 specdata2;
3776
3777         proto_item* specdata3_item;
3778         proto_tree* specdata3_tree;
3779
3780         specdata1 = tvb_get_ntohl(tvb, offset+0);
3781         specdata2 = tvb_get_ntohl(tvb, offset+4);
3782
3783         if (tree) {
3784                 specdata3_item = proto_tree_add_text(tree, tvb, offset, 8,
3785                         "%s: %u,%u", name, specdata1, specdata2);
3786
3787                 specdata3_tree = proto_item_add_subtree(specdata3_item,
3788                                         ett_nfs_specdata3);
3789
3790                 proto_tree_add_text(specdata3_tree, tvb,offset+0,4,
3791                                     "specdata1: %u", specdata1);
3792                 proto_tree_add_text(specdata3_tree, tvb,offset+4,4,
3793                                     "specdata2: %u", specdata2);
3794         }
3795
3796         offset += 8;
3797         return offset;
3798 }
3799
3800
3801 /* RFC 1813, Page 21 */
3802 int
3803 dissect_nfs_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
3804                 const char *name, guint32 *hash)
3805 {
3806         guint fh3_len;
3807         guint fh3_len_full;
3808         guint fh3_fill;
3809         proto_item* fitem = NULL;
3810         proto_tree* ftree = NULL;
3811         int fh_offset,fh_length;
3812
3813         fh3_len = tvb_get_ntohl(tvb, offset+0);
3814         fh3_len_full = rpc_roundup(fh3_len);
3815         fh3_fill = fh3_len_full - fh3_len;
3816
3817         if (tree) {
3818                 fitem = proto_tree_add_text(tree, tvb, offset, 4+fh3_len_full,
3819                         "%s", name);
3820
3821                 ftree = proto_item_add_subtree(fitem, ett_nfs_fh3);
3822         }
3823
3824         /* are we snooping fh to filenames ?*/
3825         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
3826                 rpc_call_info_value *civ=pinfo->private_data;
3827
3828                 /* NFS v3 LOOKUP, CREATE, MKDIR, READDIRPLUS
3829                         calls might give us a mapping*/
3830                 if( ((civ->prog==100003)
3831                   &&((civ->vers==3)
3832                   &&(!civ->request)
3833                   &&((civ->proc==3)||(civ->proc==8)||(civ->proc==9)||(civ->proc==17))))
3834                 || civ->vers==4
3835                 ) {
3836                         fh_length=tvb_get_ntohl(tvb, offset);
3837                         fh_offset=offset+4;
3838                         nfs_name_snoop_add_fh(civ->xid, tvb, fh_offset,
3839                                               fh_length);
3840                 }
3841
3842                 /* MOUNT v3 MNT replies might give us a filehandle */
3843                 if( (civ->prog==100005)
3844                   &&(civ->vers==3)
3845                   &&(!civ->request)
3846                   &&(civ->proc==1)
3847                 ) {
3848                         fh_length=tvb_get_ntohl(tvb, offset);
3849                         fh_offset=offset+4;
3850                         nfs_name_snoop_add_fh(civ->xid, tvb, fh_offset,
3851                                               fh_length);
3852                 }
3853         }
3854
3855         proto_tree_add_uint(ftree, hf_nfs_fh_length, tvb, offset+0, 4,
3856                         fh3_len);
3857
3858         /* Handle WebNFS requests where filehandle may be 0 length */
3859         if (fh3_len > 0)
3860         {
3861                 dissect_fhandle_data(tvb, offset+4, pinfo, ftree, fh3_len, FALSE, hash);
3862
3863                 offset += fh3_len_full;
3864         }
3865
3866         offset += 4;
3867
3868         return offset;
3869 }
3870
3871
3872 /* RFC 1813, Page 21 */
3873 static int
3874 dissect_nfstime3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_time,
3875                  int hf_time_sec, int hf_time_nsec)
3876 {
3877         guint32 seconds;
3878         guint32 nseconds;
3879         nstime_t ts;
3880
3881         proto_item* time_item;
3882         proto_tree* time_tree;
3883
3884         seconds = tvb_get_ntohl(tvb, offset+0);
3885         nseconds = tvb_get_ntohl(tvb, offset+4);
3886         ts.secs = seconds;
3887         ts.nsecs = nseconds;
3888
3889         if (tree) {
3890                 time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
3891                                 &ts);
3892
3893                 time_tree = proto_item_add_subtree(time_item, ett_nfs_nfstime3);
3894
3895                 proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
3896                                         seconds);
3897                 proto_tree_add_uint(time_tree, hf_time_nsec, tvb, offset+4, 4,
3898                                         nseconds);
3899         }
3900         offset += 8;
3901         return offset;
3902 }
3903
3904
3905 /* RFC 1813, Page 22
3906  * The levels parameter tells this helper how many levels up in the tree it
3907  * should display useful info such as type,mode,uid,gid
3908  * If level has the COL_INFO_LEVEL flag set it will also display
3909  * this info in the info column.
3910  */
3911 static int
3912 dissect_nfs_fattr3(packet_info *pinfo, tvbuff_t *tvb, int offset,
3913                    proto_tree *tree, const char* name, guint32 levels)
3914 {
3915         proto_item* fattr3_item = NULL;
3916         proto_tree* fattr3_tree = NULL;
3917         int old_offset = offset;
3918         guint32 type, mode, uid, gid;
3919
3920         if (tree) {
3921                 fattr3_item = proto_tree_add_text(tree, tvb, offset, -1,
3922                         "%s", name);
3923                 fattr3_tree = proto_item_add_subtree(fattr3_item, ett_nfs_fattr3);
3924         }
3925
3926         /* ftype */
3927         offset = dissect_ftype3(tvb,offset,fattr3_tree,hf_nfs_fattr3_type,&type);
3928
3929         /* mode */
3930         offset = dissect_mode3(tvb,offset,fattr3_tree,&mode);
3931
3932         /* nlink */
3933         offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_nlink,
3934                 offset);
3935
3936         /* uid */
3937         uid=tvb_get_ntohl(tvb, offset);
3938         offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_uid,
3939                 offset);
3940
3941         /* gid */
3942         gid=tvb_get_ntohl(tvb, offset);
3943         offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_gid,
3944                 offset);
3945
3946         /* size*/
3947         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_size,
3948                 offset);
3949
3950         /* used */
3951         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_used,
3952                 offset);
3953
3954         /* rdev */
3955         offset = dissect_specdata3(tvb,offset,fattr3_tree,"rdev");
3956
3957         /* fsid */
3958         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_fsid,
3959                 offset);
3960
3961         /* fileid */
3962         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_fileid,
3963                 offset);
3964
3965         /* atime */
3966         offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_atime,hf_nfs_atime_sec,hf_nfs_atime_nsec);
3967
3968         /* mtime */
3969         offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_mtime,hf_nfs_mtime_sec,hf_nfs_mtime_nsec);
3970
3971         /* ctime */
3972         offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_ctime,hf_nfs_ctime_sec,hf_nfs_ctime_nsec);
3973
3974         /* now we know, that fattr3 is shorter */
3975         if (fattr3_item) {
3976                 proto_item_set_len(fattr3_item, offset - old_offset);
3977         }
3978
3979
3980         /* put some nice info in COL_INFO for GETATTR replies */
3981         if(levels&COL_INFO_LEVEL) {
3982                 levels&=(~COL_INFO_LEVEL);
3983                 col_append_fstr(pinfo->cinfo, COL_INFO,
3984                                 "  %s mode:%04o uid:%d gid:%d",
3985                                 val_to_str_ext(type, &names_nfs_ftype3_ext,"Unknown Type:0x%x"),
3986                                 mode&0x0fff, uid, gid);
3987         }
3988         /* populate the expansion lines with some nice useable info */
3989         while( fattr3_tree && levels-- ){
3990                 proto_item_append_text(fattr3_tree, "  %s mode:%04o uid:%d gid:%d",
3991                                 val_to_str_ext(type, &names_nfs_ftype3_ext,"Unknown Type:0x%x"),
3992                                 mode&0x0fff, uid, gid);
3993                 fattr3_tree=fattr3_tree->parent;
3994         }
3995
3996         return offset;
3997 }
3998
3999
4000 static const value_string value_follows[] =
4001 {
4002         { 0, "no value" },
4003         { 1, "value follows" },
4004         { 0, NULL }
4005 };
4006
4007
4008 /* RFC 1813, Page 23 */
4009 int
4010 dissect_nfs_post_op_attr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
4011                          const char* name)
4012 {
4013         proto_item* post_op_attr_item = NULL;
4014         proto_tree* post_op_attr_tree = NULL;
4015         int old_offset = offset;
4016         guint32 attributes_follow;
4017
4018         if (tree) {
4019                 post_op_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
4020                         "%s", name);
4021                 post_op_attr_tree = proto_item_add_subtree(post_op_attr_item,
4022                         ett_nfs_post_op_attr);
4023         }
4024
4025         attributes_follow = tvb_get_ntohl(tvb, offset+0);
4026         proto_tree_add_text(post_op_attr_tree, tvb, offset, 4,
4027                 "attributes_follow: %s (%u)",
4028                 val_to_str_const(attributes_follow,value_follows,"Unknown"), attributes_follow);
4029         offset += 4;
4030         switch (attributes_follow) {
4031                 case TRUE:
4032                         offset = dissect_nfs_fattr3(pinfo, tvb, offset,
4033                                                     post_op_attr_tree,
4034                                                     "attributes", 2);
4035                 break;
4036                 case FALSE:
4037                         /* void */
4038                 break;
4039         }
4040
4041         /* now we know, that post_op_attr_tree is shorter */
4042         if (post_op_attr_item) {
4043                 proto_item_set_len(post_op_attr_item, offset - old_offset);
4044         }
4045
4046         return offset;
4047 }
4048
4049
4050 /* RFC 1813, Page 24 */
4051 static int
4052 dissect_wcc_attr(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4053 {
4054         proto_item* wcc_attr_item = NULL;
4055         proto_tree* wcc_attr_tree = NULL;
4056         int old_offset = offset;
4057
4058         if (tree) {
4059                 wcc_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
4060                         "%s", name);
4061                 wcc_attr_tree = proto_item_add_subtree(wcc_attr_item,
4062                         ett_nfs_wcc_attr);
4063         }
4064
4065         offset = dissect_rpc_uint64(tvb, wcc_attr_tree, hf_nfs_wcc_attr_size,
4066                 offset);
4067         offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_nsec);
4068         offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
4069         /* now we know, that wcc_attr_tree is shorter */
4070         if (wcc_attr_item) {
4071                 proto_item_set_len(wcc_attr_item, offset - old_offset);
4072         }
4073
4074         return offset;
4075 }
4076
4077
4078 /* RFC 1813, Page 24 */
4079 static int
4080 dissect_pre_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4081 {
4082         proto_item* pre_op_attr_item = NULL;
4083         proto_tree* pre_op_attr_tree = NULL;
4084         int old_offset = offset;
4085         guint32 attributes_follow;
4086
4087         if (tree) {
4088                 pre_op_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
4089                         "%s", name);
4090                 pre_op_attr_tree = proto_item_add_subtree(pre_op_attr_item,
4091                         ett_nfs_pre_op_attr);
4092         }
4093
4094         attributes_follow = tvb_get_ntohl(tvb, offset+0);
4095         proto_tree_add_text(pre_op_attr_tree, tvb, offset, 4,
4096                 "attributes_follow: %s (%u)",
4097                 val_to_str_const(attributes_follow,value_follows,"Unknown"), attributes_follow);
4098         offset += 4;
4099         switch (attributes_follow) {
4100                 case TRUE:
4101                         offset = dissect_wcc_attr(tvb, offset, pre_op_attr_tree,
4102                                         "attributes");
4103                 break;
4104                 case FALSE:
4105                         /* void */
4106                 break;
4107         }
4108
4109         /* now we know, that pre_op_attr_tree is shorter */
4110         if (pre_op_attr_item) {
4111                 proto_item_set_len(pre_op_attr_item, offset - old_offset);
4112         }
4113
4114         return offset;
4115 }
4116
4117
4118 /* RFC 1813, Page 24 */
4119 static int
4120 dissect_wcc_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, const char* name)
4121 {
4122         proto_item* wcc_data_item = NULL;
4123         proto_tree* wcc_data_tree = NULL;
4124         int old_offset = offset;
4125
4126         if (tree) {
4127                 wcc_data_item = proto_tree_add_text(tree, tvb, offset, -1,
4128                         "%s", name);
4129                 wcc_data_tree = proto_item_add_subtree(wcc_data_item,
4130                         ett_nfs_wcc_data);
4131         }
4132
4133         offset = dissect_pre_op_attr (tvb, offset, wcc_data_tree, "before");
4134         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, wcc_data_tree, "after" );
4135
4136         /* now we know, that wcc_data is shorter */
4137         if (wcc_data_item) {
4138                 proto_item_set_len(wcc_data_item, offset - old_offset);
4139         }
4140
4141         return offset;
4142 }
4143
4144
4145 /* RFC 1813, Page 25 */
4146 static int
4147 dissect_post_op_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
4148                     proto_tree *tree, const char* name)
4149 {
4150         proto_item* post_op_fh3_item = NULL;
4151         proto_tree* post_op_fh3_tree = NULL;
4152         int old_offset = offset;
4153         guint32 handle_follows;
4154
4155         if (tree) {
4156                 post_op_fh3_item = proto_tree_add_text(tree, tvb, offset, -1,
4157                         "%s", name);
4158                 post_op_fh3_tree = proto_item_add_subtree(post_op_fh3_item,
4159                         ett_nfs_post_op_fh3);
4160         }
4161
4162         handle_follows = tvb_get_ntohl(tvb, offset+0);
4163         proto_tree_add_text(post_op_fh3_tree, tvb, offset, 4,
4164                 "handle_follows: %s (%u)",
4165                 val_to_str_const(handle_follows,value_follows,"Unknown"), handle_follows);
4166         offset += 4;
4167         switch (handle_follows) {
4168                 case TRUE:
4169                         offset = dissect_nfs_fh3(tvb, offset, pinfo, post_op_fh3_tree,
4170                                         "handle", NULL);
4171                 break;
4172                 case FALSE:
4173                         /* void */
4174                 break;
4175         }
4176
4177         /* now we know, that post_op_fh3_tree is shorter */
4178         if (post_op_fh3_item) {
4179                 proto_item_set_len(post_op_fh3_item, offset - old_offset);
4180         }
4181
4182         return offset;
4183 }
4184
4185
4186 /* RFC 1813, Page 25 */
4187 static int
4188 dissect_set_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4189 {
4190         proto_item* set_mode3_item = NULL;
4191         proto_tree* set_mode3_tree = NULL;
4192         int old_offset = offset;
4193         guint32 set_it;
4194         const char* set_it_name;
4195
4196         set_it = tvb_get_ntohl(tvb, offset+0);
4197
4198         if (tree) {
4199                 set_it_name = val_to_str_const(set_it,value_follows,"Unknown");
4200
4201                 set_mode3_item = proto_tree_add_text(tree, tvb, offset, -1,
4202                         "%s: %s", name, set_it_name);
4203                 set_mode3_tree = proto_item_add_subtree(set_mode3_item,
4204                         ett_nfs_set_mode3);
4205
4206                 proto_tree_add_text(set_mode3_tree, tvb, offset, 4,
4207                         "set_it: %s (%u)", set_it_name, set_it);
4208         }
4209
4210         offset += 4;
4211
4212         switch (set_it) {
4213                 case 1:
4214                         offset = dissect_mode3(tvb, offset, set_mode3_tree,
4215                                         NULL);
4216                 break;
4217                 default:
4218                         /* void */
4219                 break;
4220         }
4221
4222         /* now we know, that set_mode3 is shorter */
4223         if (set_mode3_item) {
4224                 proto_item_set_len(set_mode3_item, offset - old_offset);
4225         }
4226
4227         return offset;
4228 }
4229
4230
4231 /* RFC 1813, Page 26 */
4232 static int
4233 dissect_set_uid3(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4234 {
4235         proto_item* set_uid3_item = NULL;
4236         proto_tree* set_uid3_tree = NULL;
4237         int old_offset = offset;
4238         guint32 set_it;
4239         const char* set_it_name;
4240
4241         set_it = tvb_get_ntohl(tvb, offset+0);
4242
4243         if (tree) {
4244                 set_it_name = val_to_str_const(set_it,value_follows,"Unknown");
4245
4246                 set_uid3_item = proto_tree_add_text(tree, tvb, offset, -1,
4247                         "%s: %s", name, set_it_name);
4248                 set_uid3_tree = proto_item_add_subtree(set_uid3_item,
4249                         ett_nfs_set_uid3);
4250
4251                 proto_tree_add_text(set_uid3_tree, tvb, offset, 4,
4252                         "set_it: %s (%u)", set_it_name, set_it);
4253         }
4254         offset += 4;
4255
4256         switch (set_it) {
4257                 case 1:
4258                         offset = dissect_rpc_uint32(tvb, set_uid3_tree,
4259                                                     hf_nfs_uid3, offset);
4260                 break;
4261                 default:
4262                         /* void */
4263                 break;
4264         }
4265
4266         /* now we know, that set_uid3 is shorter */
4267         if (set_uid3_item) {
4268                 proto_item_set_len(set_uid3_item, offset - old_offset);
4269         }
4270
4271         return offset;
4272 }
4273
4274
4275 /* RFC 1813, Page 26 */
4276 static int
4277 dissect_set_gid3(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4278 {
4279         proto_item* set_gid3_item = NULL;
4280         proto_tree* set_gid3_tree = NULL;
4281         int old_offset = offset;
4282         guint32 set_it;
4283         const char* set_it_name;
4284
4285         set_it = tvb_get_ntohl(tvb, offset+0);
4286
4287         if (tree) {
4288                 set_it_name = val_to_str_const(set_it,value_follows,"Unknown");
4289                 set_gid3_item = proto_tree_add_text(tree, tvb, offset, -1,
4290                         "%s: %s", name, set_it_name);
4291                 set_gid3_tree = proto_item_add_subtree(set_gid3_item,
4292                         ett_nfs_set_gid3);
4293                 proto_tree_add_text(set_gid3_tree, tvb, offset, 4,
4294                         "set_it: %s (%u)", set_it_name, set_it);
4295         }
4296
4297         offset += 4;
4298
4299         switch (set_it) {
4300                 case 1:
4301                         offset = dissect_rpc_uint32(tvb, set_gid3_tree,
4302                                 hf_nfs_gid3, offset);
4303                 break;
4304                 default:
4305                         /* void */
4306                 break;
4307         }
4308
4309         /* now we know, that set_gid3 is shorter */
4310         if (set_gid3_item) {
4311                 proto_item_set_len(set_gid3_item, offset - old_offset);
4312         }
4313
4314         return offset;
4315 }
4316
4317
4318 /* RFC 1813, Page 26 */
4319 static int
4320 dissect_set_size3(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4321 {
4322         proto_item* set_size3_item = NULL;
4323         proto_tree* set_size3_tree = NULL;
4324         int old_offset = offset;
4325         guint32 set_it;
4326         const char* set_it_name;
4327
4328         set_it = tvb_get_ntohl(tvb, offset+0);
4329
4330         if (tree) {
4331                 set_it_name = val_to_str_const(set_it,value_follows,"Unknown");
4332
4333                 set_size3_item = proto_tree_add_text(tree, tvb, offset, -1,
4334                         "%s: %s", name, set_it_name);
4335                 set_size3_tree = proto_item_add_subtree(set_size3_item,
4336                         ett_nfs_set_size3);
4337                 proto_tree_add_text(set_size3_tree, tvb, offset, 4,
4338                         "set_it: %s (%u)", set_it_name, set_it);
4339         }
4340
4341         offset += 4;
4342
4343         switch (set_it) {
4344                 case 1:
4345                         offset = dissect_rpc_uint64(tvb, set_size3_tree,
4346                                 hf_nfs_set_size3_size, offset);
4347                 break;
4348                 default:
4349                         /* void */
4350                 break;
4351         }
4352
4353         /* now we know, that set_size3 is shorter */
4354         if (set_size3_item) {
4355                 proto_item_set_len(set_size3_item, offset - old_offset);
4356         }
4357
4358         return offset;
4359 }
4360
4361
4362 /* RFC 1813, Page 25 */
4363 #define DONT_CHANGE 0
4364 #define SET_TO_SERVER_TIME 1
4365 #define SET_TO_CLIENT_TIME 2
4366
4367 static const value_string time_how[] =
4368 {
4369         { DONT_CHANGE,          "don't change" },
4370         { SET_TO_SERVER_TIME,   "set to server time" },
4371         { SET_TO_CLIENT_TIME,   "set to client time" },
4372         { 0, NULL }
4373 };
4374
4375
4376 /* RFC 1813, Page 26 */
4377 static int
4378 dissect_set_atime(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4379 {
4380         proto_item* set_atime_item = NULL;
4381         proto_tree* set_atime_tree = NULL;
4382         int old_offset = offset;
4383         guint32 set_it;
4384         const char* set_it_name;
4385
4386         set_it = tvb_get_ntohl(tvb, offset+0);
4387
4388         if (tree) {
4389                 set_it_name = val_to_str_const(set_it,time_how,"Unknown");
4390
4391                 set_atime_item = proto_tree_add_text(tree, tvb, offset, -1,
4392                         "%s: %s", name, set_it_name);
4393                 set_atime_tree = proto_item_add_subtree(set_atime_item,
4394                         ett_nfs_set_atime);
4395
4396                 proto_tree_add_text(set_atime_tree, tvb, offset, 4,
4397                         "set_it: %s (%u)", set_it_name, set_it);
4398         }
4399         offset += 4;
4400
4401         switch (set_it) {
4402                 case SET_TO_CLIENT_TIME:
4403                         if (set_atime_item) {
4404                                 offset = dissect_nfstime3(tvb, offset, set_atime_tree,
4405                                         hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
4406                         }
4407                 break;
4408                 default:
4409                         /* void */
4410                 break;
4411         }
4412
4413         /* now we know, that set_atime is shorter */
4414         if (set_atime_item) {
4415                 proto_item_set_len(set_atime_item, offset - old_offset);
4416         }
4417
4418         return offset;
4419 }
4420
4421
4422 /* RFC 1813, Page 26 */
4423 static int
4424 dissect_set_mtime(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4425 {
4426         proto_item* set_mtime_item = NULL;
4427         proto_tree* set_mtime_tree = NULL;
4428         int old_offset = offset;
4429         guint32 set_it;
4430         const char* set_it_name;
4431
4432         set_it = tvb_get_ntohl(tvb, offset+0);
4433
4434         if (tree) {
4435                 set_it_name = val_to_str_const(set_it,time_how,"Unknown");
4436
4437                 set_mtime_item = proto_tree_add_text(tree, tvb, offset, -1,
4438                         "%s: %s", name, set_it_name);
4439                 set_mtime_tree = proto_item_add_subtree(set_mtime_item,
4440                         ett_nfs_set_mtime);
4441                 proto_tree_add_text(set_mtime_tree, tvb, offset, 4,
4442                                 "set_it: %s (%u)", set_it_name, set_it);
4443         }
4444
4445         offset += 4;
4446
4447         switch (set_it) {
4448                 case SET_TO_CLIENT_TIME:
4449                         if (set_mtime_item) {
4450                                 offset = dissect_nfstime3(tvb, offset, set_mtime_tree,
4451                                         hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
4452                         }
4453                 break;
4454                 default:
4455                         /* void */
4456                 break;
4457         }
4458
4459         /* now we know, that set_mtime is shorter */
4460         if (set_mtime_item) {
4461                 proto_item_set_len(set_mtime_item, offset - old_offset);
4462         }
4463
4464         return offset;
4465 }
4466
4467
4468 /* RFC 1813, Page 25..27 */
4469 static int
4470 dissect_sattr3(tvbuff_t *tvb, int offset, proto_tree *tree, const char* name)
4471 {
4472         proto_item* sattr3_item = NULL;
4473         proto_tree* sattr3_tree = NULL;
4474         int old_offset = offset;
4475
4476         if (tree) {
4477                 sattr3_item = proto_tree_add_text(tree, tvb, offset, -1,
4478                         "%s", name);
4479                 sattr3_tree = proto_item_add_subtree(sattr3_item, ett_nfs_sattr3);
4480         }
4481
4482         offset = dissect_set_mode3(tvb, offset, sattr3_tree, "mode");
4483         offset = dissect_set_uid3 (tvb, offset, sattr3_tree, "uid");
4484         offset = dissect_set_gid3 (tvb, offset, sattr3_tree, "gid");
4485         offset = dissect_set_size3(tvb, offset, sattr3_tree, "size");
4486         offset = dissect_set_atime(tvb, offset, sattr3_tree, "atime");
4487         offset = dissect_set_mtime(tvb, offset, sattr3_tree, "mtime");
4488
4489         /* now we know, that sattr3 is shorter */
4490         if (sattr3_item) {
4491                 proto_item_set_len(sattr3_item, offset - old_offset);
4492         }
4493
4494         return offset;
4495 }
4496
4497
4498 /* RFC 1813, Page 27 */
4499 static int
4500 dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo,
4501                    proto_tree *tree, const char* label, guint32 *hash,
4502                    char **name)
4503 {
4504         proto_item* diropargs3_item = NULL;
4505         proto_tree* diropargs3_tree = NULL;
4506         int old_offset = offset;
4507         int parent_offset, parent_len;
4508         int name_offset, name_len;
4509
4510         if (tree) {
4511                 diropargs3_item = proto_tree_add_text(tree, tvb, offset, -1,
4512                         "%s", label);
4513                 diropargs3_tree = proto_item_add_subtree(diropargs3_item,
4514                         ett_nfs_diropargs3);
4515         }
4516
4517         parent_offset=offset+4;
4518         parent_len=tvb_get_ntohl(tvb, offset);
4519         offset = dissect_nfs_fh3(tvb, offset, pinfo, diropargs3_tree, "dir", hash);
4520         name_offset=offset+4;
4521         name_len=tvb_get_ntohl(tvb, offset);
4522         offset = dissect_filename3(tvb, offset, diropargs3_tree,
4523                 hf_nfs_name, name);
4524
4525         /* are we snooping fh to filenames ?*/
4526         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
4527                 /* v3 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
4528                 rpc_call_info_value *civ=pinfo->private_data;
4529
4530                 if( (civ->prog==100003)
4531                   &&(civ->vers==3)
4532                   &&(civ->request)
4533                   &&((civ->proc==3)||(civ->proc==8)||(civ->proc==9))
4534                 ) {
4535                         nfs_name_snoop_add_name(civ->xid, tvb,
4536                                 name_offset, name_len,
4537                                 parent_offset, parent_len, NULL);
4538                 }
4539         }
4540
4541
4542         /* now we know, that diropargs3 is shorter */
4543         if (diropargs3_item) {
4544                 proto_item_set_len(diropargs3_item, offset - old_offset);
4545         }
4546
4547         return offset;
4548 }
4549
4550 static int
4551 dissect_nfs3_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4552                          proto_tree *tree)
4553 {
4554         guint32 hash;
4555         char *name=NULL;
4556
4557         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
4558
4559         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
4560         proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
4561
4562         return offset;
4563 }
4564
4565 static int
4566 dissect_nfs3_null_call(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
4567                        proto_tree *tree)
4568 {
4569         proto_item_append_text(tree, ", NULL Call");
4570
4571         return offset;
4572 }
4573
4574 static int
4575 dissect_nfs3_null_reply(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
4576                         proto_tree *tree)
4577 {
4578         proto_item_append_text(tree, ", NULL Reply");
4579
4580         return offset;
4581 }
4582
4583 static int
4584 dissect_nfs3_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4585         proto_tree *tree)
4586 {
4587         guint32 hash;
4588         char *name=NULL;
4589
4590         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
4591
4592         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
4593         proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
4594
4595         return offset;
4596 }
4597
4598
4599
4600 /* RFC 1813, Page 32,33 */
4601 static int
4602 dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4603                           proto_tree* tree)
4604 {
4605         guint32 hash;
4606
4607         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
4608
4609         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4610         proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
4611
4612         return offset;
4613 }
4614
4615
4616 /* RFC 1813, Page 32,33 */
4617 static int
4618 dissect_nfs3_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4619                            proto_tree* tree)
4620 {
4621         guint32 status;
4622         const char *err;
4623
4624         proto_item_append_text(tree, ", GETATTR Reply");
4625
4626         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4627         switch (status) {
4628                 case 0:
4629                         offset = dissect_nfs_fattr3(pinfo, tvb, offset, tree, "obj_attributes",2|COL_INFO_LEVEL);
4630                 break;
4631                 default:
4632                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
4633                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4634                         proto_item_append_text(tree, "  Error:%s", err);
4635                 break;
4636         }
4637
4638         return offset;
4639 }
4640
4641
4642 /* RFC 1813, Page 33 */
4643 static int
4644 dissect_sattrguard3(tvbuff_t *tvb, int offset, proto_tree* tree, const char *name)
4645 {
4646         proto_item* sattrguard3_item = NULL;
4647         proto_tree* sattrguard3_tree = NULL;
4648         int old_offset = offset;
4649         guint32 check;
4650         const char* check_name;
4651
4652         check = tvb_get_ntohl(tvb, offset+0);
4653
4654         if (tree) {
4655                 check_name = val_to_str_const(check,value_follows,"Unknown");
4656
4657                 sattrguard3_item = proto_tree_add_text(tree, tvb, offset, -1,
4658                         "%s: %s", name, check_name);
4659                 sattrguard3_tree = proto_item_add_subtree(sattrguard3_item,
4660                         ett_nfs_sattrguard3);
4661
4662                 proto_tree_add_text(sattrguard3_tree, tvb, offset, 4,
4663                         "check: %s (%u)", check_name, check);
4664         }
4665
4666
4667         offset += 4;
4668
4669         switch (check) {
4670                 case TRUE:
4671                         offset = dissect_nfstime3(tvb, offset, sattrguard3_tree,
4672                                         hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
4673                 break;
4674                 case FALSE:
4675                         /* void */
4676                 break;
4677         }
4678
4679         /* now we know, that sattrguard3 is shorter */
4680         if (sattrguard3_item) {
4681                 proto_item_set_len(sattrguard3_item, offset - old_offset);
4682         }
4683
4684         return offset;
4685 }
4686
4687
4688 /* RFC 1813, Page 33..36 */
4689 static int
4690 dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4691                           proto_tree* tree)
4692 {
4693         guint32 hash;
4694
4695         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "object", &hash);
4696         offset = dissect_sattr3     (tvb, offset,        tree, "new_attributes");
4697         offset = dissect_sattrguard3(tvb, offset,        tree, "guard");
4698
4699         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4700         proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
4701
4702         return offset;
4703 }
4704
4705
4706 /* RFC 1813, Page 33..36 */
4707 static int
4708 dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4709                            proto_tree* tree)
4710 {
4711         guint32 status;
4712         const char *err;
4713
4714         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4715         switch (status) {
4716                 case 0:
4717                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "obj_wcc");
4718                         proto_item_append_text(tree, ", SETATTR Reply");
4719                 break;
4720                 default:
4721                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "obj_wcc");
4722
4723                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
4724                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4725                         proto_item_append_text(tree, ", SETATTR Reply  Error:%s", err);
4726                 break;
4727         }
4728
4729         return offset;
4730 }
4731
4732
4733 /* RFC 1813, Page 37..39 */
4734 static int
4735 dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4736                          proto_tree* tree)
4737 {
4738         guint32 hash;
4739         char *name=NULL;
4740
4741         offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what", &hash, &name);
4742
4743         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
4744         proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
4745
4746         return offset;
4747 }
4748
4749
4750 /* RFC 1813, Page 37..39 */
4751 static int
4752 dissect_nfs3_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4753                           proto_tree* tree)
4754 {
4755         guint32 status;
4756         const char *err;
4757         guint32 hash;
4758
4759         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4760         switch (status) {
4761                 case 0:
4762                         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
4763                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
4764                                 "obj_attributes");
4765                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
4766                                 "dir_attributes");
4767
4768                         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4769                         proto_item_append_text(tree, ", LOOKUP Reply FH:0x%08x", hash);
4770                 break;
4771                 default:
4772                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
4773                                 "dir_attributes");
4774
4775                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
4776                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4777                         proto_item_append_text(tree, ", LOOKUP Reply  Error:%s", err);
4778                 break;
4779         }
4780
4781         return offset;
4782 }
4783
4784
4785 static const value_string accvs[] = {
4786         { 0x01, "RD" },
4787         { 0x02, "LU" },
4788         { 0x04, "MD" },
4789         { 0x08, "XT" },
4790         { 0x10, "DL" },
4791         { 0x20, "XE" },
4792         { 0,    NULL }
4793 };
4794
4795 static const true_false_string tfs_access_supp = { "supported", "!NOT Supported!"};
4796 static const true_false_string tfs_access_rights = {"allowed", "*Access Denied*"};
4797
4798 proto_tree*
4799 display_access_items(tvbuff_t* tvb, int offset, packet_info* pinfo, proto_tree* tree,
4800                      guint32 amask, char mtype, int version, GString* optext, char* label)
4801 {
4802         gboolean nfsv3 = (version==3 ? TRUE : FALSE);
4803         proto_item* access_item = NULL;
4804         proto_tree* access_subtree = NULL;
4805         proto_item* access_subitem = NULL;
4806         guint32 itype;
4807
4808         /* XXX Legend (delete if desired)
4809
4810            'C' CHECK access:      append label to both headers and create subtree and list
4811            'N' NOT SUPPORTED:     append label to both headers
4812            'S' SUPPORTED or not:  create subtree and list
4813            'D' DENIED:            append label to both headers
4814            'A' ALLOWED:           append label to both headers
4815            'R' RIGHTS:            create subtree and list */
4816
4817         switch (mtype) {
4818                 case 'C':
4819                         access_item = proto_tree_add_item(tree, hf_nfs_access_check, tvb,
4820                                 offset, 4, FALSE);
4821                         access_subtree = proto_item_add_subtree(access_item,
4822                                 (nfsv3 ? ett_nfs_access3 : ett_nfs_access4));
4823                         break;
4824                 case 'S':
4825                         access_item = proto_tree_add_item(tree, hf_nfs_access_supported, tvb,
4826                                 offset, 4, FALSE);
4827                         access_subtree = proto_item_add_subtree(access_item, ett_nfs_access_supp4);
4828                         break;
4829                 case 'R':
4830                         access_item = proto_tree_add_item(tree, hf_nfs_access_rights, tvb,
4831                                 offset, 4, FALSE);
4832                         access_subtree = proto_item_add_subtree(access_item,
4833                                 (nfsv3 ? ett_nfs_access3 : ett_nfs_access4));
4834                         break;
4835         }
4836         /* Append label to the Info column and tree */
4837         if (mtype!='S' && mtype!='R') {
4838                 if (nfsv3) {
4839                         col_append_fstr(pinfo->cinfo, COL_INFO,", [%s:", label);
4840                 } else {
4841                         g_string_append_printf (optext, ", [%s:", label);
4842                 }
4843                 proto_item_append_text(tree, ", [%s:", label);
4844         }
4845
4846         for (itype=0; itype < 6; itype++) {
4847                 if (amask & accvs[itype].value) {
4848                         if (mtype!='S' && mtype!='R')   {
4849                                 /* List access type in Info column and tree */
4850                                 if (nfsv3) {
4851                                         col_append_fstr(pinfo->cinfo, COL_INFO," %s", accvs[itype].strptr);
4852                                 } else {
4853                                         g_string_append_printf (optext, " %s", accvs[itype].strptr);
4854                                 }
4855                                 proto_item_append_text(tree, " %s", accvs[itype].strptr);
4856                         }
4857                         if (mtype=='C' || mtype=='S' || mtype=='R') {
4858
4859                                 switch (itype) {
4860                                         case 0:
4861                                                 access_subitem = proto_tree_add_item (access_subtree,
4862                                                         (mtype=='S' ? hf_nfs_access_supp_read : hf_nfs_access_read),
4863                                                         tvb, offset, 4, FALSE);
4864                                                 break;
4865                                         case 1:
4866                                                 access_subitem = proto_tree_add_item (access_subtree,
4867                                                         (mtype=='S' ? hf_nfs_access_supp_lookup : hf_nfs_access_lookup),
4868                                                         tvb, offset, 4, FALSE);
4869                                                 break;
4870                                         case 2:
4871                                                 access_subitem = proto_tree_add_item (access_subtree,
4872                                                         (mtype=='S' ? hf_nfs_access_supp_modify : hf_nfs_access_modify),
4873                                                         tvb, offset, 4, FALSE);
4874                                                 break;
4875                                         case 3:
4876                                                 access_subitem = proto_tree_add_item (access_subtree,
4877                                                         (mtype=='S' ? hf_nfs_access_supp_extend : hf_nfs_access_extend),
4878                                                         tvb, offset, 4, FALSE);
4879                                                 break;
4880                                         case 4:
4881                                                 access_subitem = proto_tree_add_item (access_subtree,
4882                                                         (mtype=='S' ? hf_nfs_access_supp_delete : hf_nfs_access_delete),
4883                                                         tvb, offset, 4, FALSE);
4884                                                 break;
4885                                         case 5:
4886                                                 access_subitem = proto_tree_add_item (access_subtree,
4887                                                         (mtype=='S' ? hf_nfs_access_supp_execute : hf_nfs_access_execute),
4888                                                         tvb, offset, 4, FALSE);
4889                                                 break;
4890                                 }
4891                                 if (mtype=='C') proto_item_append_text(access_subitem, "?" );
4892                         }
4893                 }
4894         }
4895         if (mtype!='S' && mtype!='R') {
4896                 if (nfsv3) {
4897                         col_append_fstr(pinfo->cinfo, COL_INFO,"]");
4898                 } else {
4899                         g_string_append_printf (optext, "]");
4900                 }
4901                 proto_item_append_text(tree, "]");
4902         }
4903         return access_subtree;
4904 }
4905
4906 /* RFC 1813, Page 40..43 */
4907 /* RFC 3530, Page 140..142 */
4908 int
4909 dissect_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree* tree,
4910                      int version, GString *optext)
4911 {
4912         rpc_call_info_value *civ;
4913         guint32* acc_req=NULL, acc_supp=0, acc_rights=0;
4914         guint32 mask_not_supp=0, mask_denied=0, mask_allowed=0;
4915         guint32 e_check, e_rights;
4916         gboolean nfsv3 = (version==3 ? TRUE : FALSE);
4917         gboolean nfsv4 = (version==4 ? TRUE : FALSE);
4918         proto_tree* access_tree = NULL;
4919         proto_item* ditem = NULL;
4920
4921         /* Retrieve the access mask from the call */
4922         civ = pinfo->private_data;
4923         acc_req = civ->private_data;
4924         /* Should never happen because ONC-RPC requires the call in order to dissect the reply. */
4925         if (acc_req==NULL) {
4926                 return offset+4;
4927         }
4928         if(nfsv4) {
4929                 acc_supp = tvb_get_ntohl(tvb, offset+0);
4930         } else {
4931                 acc_supp = *acc_req;
4932         }
4933         /*  V3/V4 - Get access rights mask and create a subtree for it */
4934         acc_rights = tvb_get_ntohl(tvb, (nfsv3 ? offset+0: offset+4));
4935
4936         /* Create access masks: not_supported, denied, and allowed */
4937         mask_not_supp = *acc_req ^ acc_supp;
4938         e_check = acc_supp;
4939         e_rights = acc_supp & acc_rights;  /* guard against broken implementations */
4940         mask_denied =  e_check ^ e_rights;
4941         mask_allowed = e_check & e_rights;
4942
4943         if (nfsv4) {
4944                 if (mask_not_supp > 0) {
4945                         display_access_items(tvb, offset, pinfo, tree, mask_not_supp, 'N', 4,
4946                                 optext, "NOT Supported") ;
4947                 }
4948                 display_access_items(tvb, offset, pinfo, tree, acc_supp, 'S', 4,
4949                         optext, "Supported");
4950                 offset+=4;
4951         }
4952         if (mask_denied > 0) {
4953                 display_access_items(tvb, offset, pinfo, tree, mask_denied, 'D', version,
4954                         optext, "Access Denied") ;
4955         }
4956         if (mask_allowed > 0) {
4957                 display_access_items(tvb, offset, pinfo, tree, mask_allowed, 'A', version,
4958                         optext, "Allowed") ;
4959         }
4960         /* Pass the OR'd masks rather than acc_rights so that display_access_items will
4961            process types that have been denied access. Since proto_tree_add_item uses the
4962            mask in the tvb (not the passed mask), the correct (denied) access is displayed. */
4963         access_tree = display_access_items(tvb, offset, pinfo, tree,
4964                 (mask_allowed | mask_denied), 'R', version, optext, NULL) ;
4965
4966         ditem = proto_tree_add_boolean(access_tree, hf_nfs_access_denied, tvb,
4967                                 offset, 4, (mask_denied > 0 ? TRUE : FALSE ));
4968         PROTO_ITEM_SET_GENERATED(ditem);
4969
4970         return offset+4;
4971 }
4972
4973 /* RFC 1813, Page 40..43 */
4974 static int
4975 dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree* tree)
4976 {
4977         guint32 fhhash, *acc_request, amask;
4978         rpc_call_info_value *civ;
4979
4980         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &fhhash);
4981
4982         /* Get access mask to check and save it for comparison to the access reply. */
4983         amask = tvb_get_ntohl(tvb, offset);
4984         acc_request = se_memdup( &amask, sizeof(guint32));
4985         civ = pinfo->private_data;
4986         civ->private_data = acc_request;
4987
4988         /* Append filehandle to Info column and main tree header */
4989         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", fhhash);
4990         proto_item_append_text(tree, ", ACCESS Call, FH:0x%08x", fhhash);
4991
4992         display_access_items(tvb, offset, pinfo, tree, amask, 'C', 3, NULL, "Check") ;
4993
4994         offset+=4;
4995         return offset;
4996 }
4997
4998 /* RFC 1813, Page 40..43 */
4999 static int
5000 dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5001                           proto_tree* tree)
5002 {
5003         guint32 status;
5004         const char *err;
5005
5006         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5007         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5008                                         "obj_attributes");
5009
5010         if (status==0) {
5011                 proto_item_append_text(tree, ", ACCESS Reply");
5012                 offset = dissect_access_reply(tvb, offset, pinfo, tree, 3, NULL);
5013         } else {
5014                 err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5015                 col_append_fstr(pinfo->cinfo, COL_INFO," Error: %s", err);
5016                 proto_item_append_text(tree, ", ACCESS Reply  Error: %s", err);
5017         }
5018         return offset;
5019 }
5020
5021
5022 /* RFC 1813, Page 44,45 */
5023 static int
5024 dissect_nfs3_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5025                            proto_tree* tree)
5026 {
5027         guint32 hash;
5028
5029         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
5030
5031         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5032         proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
5033
5034         return offset;
5035 }
5036 static int
5037 dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5038                             proto_tree* tree)
5039 {
5040         guint32 status;
5041         const char *err;
5042         char *name=NULL;
5043
5044         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5045         switch (status) {
5046                 case 0:
5047                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5048                                 "symlink_attributes");
5049                         offset = dissect_nfspath3(tvb, offset, tree,
5050                                 hf_nfs_readlink_data, &name);
5051
5052                         col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
5053                         proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
5054                 break;
5055                 default:
5056                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5057                                 "symlink_attributes");
5058
5059                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5060                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5061                         proto_item_append_text(tree, ", READLINK Reply  Error:%s", err);
5062                 break;
5063         }
5064
5065         return offset;
5066 }
5067
5068
5069 /* RFC 1813, Page 46..48 */
5070 static int
5071 dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5072                        proto_tree* tree)
5073 {
5074         guint64 off;
5075         guint32 len;
5076         guint32 hash;
5077
5078         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
5079
5080         off=tvb_get_ntoh64(tvb, offset);
5081         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
5082
5083         len=tvb_get_ntohl(tvb, offset);
5084         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
5085
5086
5087         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%" G_GINT64_MODIFIER "u Len:%u", hash, off, len);
5088         proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%" G_GINT64_MODIFIER "u Len:%u", hash, off, len);
5089
5090         return offset;
5091 }
5092
5093
5094 /* RFC 1813, Page 46..48 */
5095 static int
5096 dissect_nfs3_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5097                         proto_tree* tree)
5098 {
5099         guint32 status;
5100         guint32 len;
5101         const char *err;
5102
5103         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5104         switch (status) {
5105                 case 0:
5106                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5107                                 "file_attributes");
5108                         len=tvb_get_ntohl(tvb, offset);
5109                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
5110                                 offset);
5111                         offset = dissect_rpc_bool(tvb, tree, hf_nfs_read_eof,
5112                                 offset);
5113                         col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d", len);
5114                         proto_item_append_text(tree, ", READ Reply Len:%d", len);
5115                         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
5116                 break;
5117                 default:
5118                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5119                                 "file_attributes");
5120
5121                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5122                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5123                         proto_item_append_text(tree, ", READ Reply  Error:%s", err);
5124                 break;
5125         }
5126
5127         return offset;
5128 }
5129
5130
5131 /* RFC 1813, Page 49 */
5132 static const value_string names_stable_how[] = {
5133         {       UNSTABLE,  "UNSTABLE"  },
5134         {       DATA_SYNC, "DATA_SYNC" },
5135         {       FILE_SYNC, "FILE_SYNC" },
5136         {       0, NULL }
5137 };
5138
5139
5140 /* RFC 1813, Page 49 */
5141 static int
5142 dissect_stable_how(tvbuff_t *tvb, int offset, proto_tree* tree, int hfindex)
5143 {
5144         guint32 stable_how;
5145
5146         stable_how = tvb_get_ntohl(tvb,offset+0);
5147         if (tree) {
5148                 proto_tree_add_uint(tree, hfindex, tvb,
5149                                 offset, 4, stable_how);
5150         }
5151         offset += 4;
5152
5153         return offset;
5154 }
5155
5156
5157 /* RFC 1813, Page 49..54 */
5158 static int
5159 dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5160                         proto_tree* tree)
5161 {
5162         guint64 off;
5163         guint32 len;
5164         guint32 stable;
5165         guint32 hash;
5166
5167         offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file", &hash);
5168
5169         off=tvb_get_ntoh64(tvb, offset);
5170         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
5171
5172         len=tvb_get_ntohl(tvb, offset);
5173         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
5174
5175         stable=tvb_get_ntohl(tvb, offset);
5176         offset = dissect_stable_how(tvb, offset, tree, hf_nfs_write_stable);
5177
5178         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%" G_GINT64_MODIFIER "u Len:%u %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
5179         proto_item_append_text(tree, ", WRITE Call FH:0x%08x Offset:%" G_GINT64_MODIFIER "u Len:%u %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
5180
5181         offset = dissect_nfsdata   (tvb, offset, tree, hf_nfs_data);
5182
5183         return offset;
5184 }
5185
5186
5187 /* RFC 1813, Page 49..54 */
5188 static int
5189 dissect_nfs3_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5190                          proto_tree* tree)
5191 {
5192         guint32 status;
5193         guint32 len;
5194         guint32 stable;
5195         const char *err;
5196
5197         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5198         switch (status) {
5199                 case 0:
5200                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
5201                         len=tvb_get_ntohl(tvb, offset);
5202                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
5203                                 offset);
5204                         stable=tvb_get_ntohl(tvb, offset);
5205                         offset = dissect_stable_how(tvb, offset, tree,
5206                                 hf_nfs_write_committed);
5207                         offset = dissect_writeverf3(tvb, offset, tree);
5208
5209                         col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
5210                         proto_item_append_text(tree, ", WRITE Reply Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
5211                 break;
5212                 default:
5213                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
5214
5215                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5216                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5217                         proto_item_append_text(tree, ", WRITE Reply  Error:%s", err);
5218                 break;
5219         }
5220
5221         return offset;
5222 }
5223
5224
5225 /* RFC 1813, Page 54 */
5226 static const value_string names_createmode3[] = {
5227         {       UNCHECKED, "UNCHECKED" },
5228         {       GUARDED,   "GUARDED" },
5229         {       EXCLUSIVE, "EXCLUSIVE" },
5230         {       0, NULL }
5231 };
5232
5233
5234 /* RFC 1813, Page 54 */
5235 static int
5236 dissect_createmode3(tvbuff_t *tvb, int offset, proto_tree* tree, guint32* mode)
5237 {
5238         guint32 mode_value;
5239
5240         mode_value = tvb_get_ntohl(tvb, offset + 0);
5241         if (tree) {
5242                 proto_tree_add_uint(tree, hf_nfs_createmode3, tvb,
5243                 offset+0, 4, mode_value);
5244         }
5245         offset += 4;
5246
5247         *mode = mode_value;
5248         return offset;
5249 }
5250
5251
5252 /* RFC 1813, Page 54..58 */
5253 static int
5254 dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5255                          proto_tree* tree)
5256 {
5257         guint32 mode;
5258         guint32 hash;
5259         char *name=NULL;
5260
5261         offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where", &hash, &name);
5262         offset = dissect_createmode3(tvb, offset, tree, &mode);
5263         switch (mode) {
5264                 case UNCHECKED:
5265                 case GUARDED:
5266                         offset = dissect_sattr3(tvb, offset, tree, "obj_attributes");
5267                 break;
5268                 case EXCLUSIVE:
5269                         offset = dissect_createverf3(tvb, offset, tree);
5270                 break;
5271         }
5272
5273         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
5274         proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
5275
5276         return offset;
5277 }
5278
5279
5280 /* RFC 1813, Page 54..58 */
5281 static int
5282 dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
5283                           proto_tree* tree)
5284 {
5285         guint32 status;
5286         const char *err;
5287
5288         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5289         switch (status) {
5290                 case 0:
5291                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
5292                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5293                                 "obj_attributes");
5294                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5295                         proto_item_append_text(tree, ", CREATE Reply");
5296                 break;
5297                 default:
5298                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5299
5300                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5301                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5302                         proto_item_append_text(tree, ", CREATE Reply  Error:%s", err);
5303                 break;
5304         }
5305
5306         return offset;
5307 }
5308
5309
5310 /* RFC 1813, Page 58..60 */
5311 static int
5312 dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5313                         proto_tree* tree)
5314 {
5315         guint32 hash;
5316         char *name=NULL;
5317
5318         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
5319         offset = dissect_sattr3    (tvb, offset, tree, "attributes");
5320
5321         col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
5322         proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
5323
5324         return offset;
5325 }
5326
5327 static int
5328 dissect_nfs3_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
5329                          proto_tree* tree)
5330 {
5331         guint32 status;
5332         const char *err;
5333
5334         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5335         switch (status) {
5336                 case 0:
5337                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
5338                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5339                                 "obj_attributes");
5340                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5341                         proto_item_append_text(tree, ", MKDIR Reply");
5342                 break;
5343                 default:
5344                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5345
5346                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5347                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5348                         proto_item_append_text(tree, ", MKDIR Reply  Error:%s", err);
5349                 break;
5350         }
5351
5352         return offset;
5353 }
5354
5355
5356 /* RFC 1813, Page 61..63 */
5357 static int
5358 dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5359                           proto_tree* tree)
5360 {
5361         guint32 from_hash;
5362         char *from_name=NULL;
5363         char *to_name=NULL;
5364
5365         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &from_hash, &from_name);
5366         offset = dissect_sattr3    (tvb, offset,        tree, "symlink_attributes");
5367         offset = dissect_nfspath3  (tvb, offset,        tree, hf_nfs_symlink_to, &to_name);
5368
5369         col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
5370         proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
5371
5372         return offset;
5373 }
5374 static int
5375 dissect_nfs3_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
5376                            proto_tree* tree)
5377 {
5378         guint32 status;
5379         const char *err;
5380
5381         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5382         switch (status) {
5383                 case 0:
5384                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
5385                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5386                                 "obj_attributes");
5387                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5388                         proto_item_append_text(tree, ", SYMLINK Reply");
5389                 break;
5390                 default:
5391                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5392
5393                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5394                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5395                         proto_item_append_text(tree, ", SYMLINK Reply  Error:%s", err);
5396                 break;
5397         }
5398
5399         return offset;
5400 }
5401
5402
5403 /* RFC 1813, Page 63..66 */
5404 static int
5405 dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5406                         proto_tree* tree)
5407 {
5408         guint32 type;
5409         guint32 hash;
5410         char *name=NULL;
5411         const char *type_str;
5412
5413         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
5414         offset = dissect_ftype3(tvb, offset, tree, hf_nfs_ftype3, &type);
5415         switch (type) {
5416                 case NF3CHR:
5417                 case NF3BLK:
5418                         offset = dissect_sattr3(tvb, offset, tree, "dev_attributes");
5419                         offset = dissect_specdata3(tvb, offset, tree, "spec");
5420                 break;
5421                 case NF3SOCK:
5422                 case NF3FIFO:
5423                         offset = dissect_sattr3(tvb, offset, tree, "pipe_attributes");
5424                 break;
5425                 default:
5426                         /* nothing to do */
5427                 break;
5428         }
5429
5430         type_str=val_to_str_ext(type, &names_nfs_ftype3_ext, "Unknown type:%u");
5431         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x/%s %s", hash, name, type_str);
5432         proto_item_append_text(tree, ", MKNOD Call FH:0x%08x/%s %s", hash, name, type_str);
5433
5434         return offset;
5435 }
5436 static int
5437 dissect_nfs3_mknod_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
5438                          proto_tree* tree)
5439 {
5440         guint32 status;
5441         const char *err;
5442
5443         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5444         switch (status) {
5445                 case 0:
5446                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
5447                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5448                                 "obj_attributes");
5449                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5450                         proto_item_append_text(tree, ", MKNOD Reply");
5451                 break;
5452                 default:
5453                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5454
5455                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5456                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5457                         proto_item_append_text(tree, ", MKNOD Reply  Error:%s", err);
5458                 break;
5459         }
5460
5461         return offset;
5462 }
5463
5464
5465 /* RFC 1813, Page 67..69 */
5466 static int
5467 dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5468                           proto_tree* tree)
5469 {
5470         guint32 status;
5471         const char *err;
5472
5473         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5474         switch (status) {
5475                 case 0:
5476                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5477                         proto_item_append_text(tree, ", REMOVE Reply");
5478                 break;
5479                 default:
5480                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5481                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5482                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5483                         proto_item_append_text(tree, ", REMOVE Reply  Error:%s", err);
5484                 break;
5485         }
5486
5487         return offset;
5488 }
5489 static int
5490 dissect_nfs3_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5491                          proto_tree* tree)
5492 {
5493         guint32 status;
5494         const char *err;
5495
5496         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5497         switch (status) {
5498                 case 0:
5499                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5500                         proto_item_append_text(tree, ", RMDIR Reply");
5501                 break;
5502                 default:
5503                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5504                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5505                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5506                         proto_item_append_text(tree, ", RMDIR Reply  Error:%s", err);
5507                 break;
5508         }
5509
5510         return offset;
5511 }
5512
5513
5514 /* RFC 1813, Page 71..74 */
5515 static int
5516 dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5517                          proto_tree* tree)
5518 {
5519         guint32 from_hash;
5520         char *from_name=NULL;
5521         guint32 to_hash;
5522         char *to_name=NULL;
5523
5524         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
5525         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
5526
5527         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);
5528         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);
5529
5530         return offset;
5531 }
5532
5533
5534 /* RFC 1813, Page 71..74 */
5535 static int
5536 dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5537                           proto_tree* tree)
5538 {
5539         guint32 status;
5540         const char *err;
5541
5542         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5543         switch (status) {
5544                 case 0:
5545                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "fromdir_wcc");
5546                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "todir_wcc");
5547                         proto_item_append_text(tree, ", RENAME Reply");
5548                 break;
5549                 default:
5550                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "fromdir_wcc");
5551                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "todir_wcc");
5552
5553                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5554                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5555                         proto_item_append_text(tree, ", RENAME Reply  Error:%s", err);
5556                 break;
5557         }
5558
5559         return offset;
5560 }
5561
5562
5563 /* RFC 1813, Page 74..76 */
5564 static int
5565 dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5566                        proto_tree* tree)
5567 {
5568         guint32 from_hash;
5569         guint32 to_hash;
5570         char *to_name=NULL;
5571
5572         offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file", &from_hash);
5573         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link", &to_hash, &to_name);
5574
5575         col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
5576         proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
5577
5578         return offset;
5579 }
5580
5581
5582 /* RFC 1813, Page 74..76 */
5583 static int
5584 dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5585                         proto_tree* tree)
5586 {
5587         guint32 status;
5588         const char *err;
5589
5590         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5591         switch (status) {
5592                 case 0:
5593                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5594                                 "file_attributes");
5595                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "linkdir_wcc");
5596                         proto_item_append_text(tree, ", LINK Reply");
5597                 break;
5598                 default:
5599                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5600                                 "file_attributes");
5601                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "linkdir_wcc");
5602
5603                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5604                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5605                         proto_item_append_text(tree, ", LINK Reply  Error:%s", err);
5606                 break;
5607         }
5608
5609         return offset;
5610 }
5611
5612
5613 /* RFC 1813, Page 76..80 */
5614 static int
5615 dissect_nfs3_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5616                           proto_tree* tree)
5617 {
5618         guint32 hash;
5619
5620         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir", &hash);
5621         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
5622         offset = dissect_cookieverf3(tvb, offset, tree);
5623         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
5624
5625         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5626         proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
5627
5628         return offset;
5629 }
5630
5631
5632 /* RFC 1813, Page 76..80 */
5633 static int
5634 dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5635                proto_tree* tree)
5636 {
5637         proto_item* entry_item = NULL;
5638         proto_tree* entry_tree = NULL;
5639         int old_offset = offset;
5640         char *name=NULL;
5641
5642         if (tree) {
5643                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
5644                         offset+0, -1, FALSE);
5645                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
5646         }
5647
5648         offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdir_entry3_fileid,
5649                 offset);
5650
5651         offset = dissect_filename3(tvb, offset, entry_tree,
5652                 hf_nfs_readdir_entry3_name, &name);
5653         if (entry_item)
5654                 proto_item_set_text(entry_item, "Entry: name %s", name);
5655
5656         col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
5657
5658         offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdir_entry3_cookie,
5659                 offset);
5660
5661         /* now we know, that a readdir entry is shorter */
5662         if (entry_item) {
5663                 proto_item_set_len(entry_item, offset - old_offset);
5664         }
5665
5666         return offset;
5667 }
5668
5669
5670 /* RFC 1813, Page 76..80 */
5671 static int
5672 dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
5673                            proto_tree* tree)
5674 {
5675         guint32 status;
5676         guint32 eof_value;
5677         const char *err;
5678
5679         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5680         switch (status) {
5681                 case 0:
5682                         proto_item_append_text(tree, ", READDIR Reply");
5683
5684                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5685                                 "dir_attributes");
5686                         offset = dissect_cookieverf3(tvb, offset, tree);
5687                         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
5688                                 dissect_entry3);
5689                         eof_value = tvb_get_ntohl(tvb, offset+0);
5690                         if (tree)
5691                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
5692                                         offset+ 0, 4, eof_value);
5693                         offset += 4;
5694                 break;
5695                 default:
5696                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5697                                 "dir_attributes");
5698
5699                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5700                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5701                         proto_item_append_text(tree, ", READDIR Reply  Error:%s", err);
5702                 break;
5703         }
5704
5705         return offset;
5706 }
5707
5708
5709 /* RFC 1813, Page 80..83 */
5710 static int
5711 dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5712                               proto_tree* tree)
5713 {
5714         guint32 hash = 0;
5715
5716         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir", &hash);
5717         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
5718         offset = dissect_cookieverf3(tvb, offset, tree);
5719         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_dircount,
5720                 offset);
5721         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_maxcount,
5722                 offset);
5723
5724         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5725         proto_item_append_text(tree, ", READDIRPLUS Call FH:0x%08x", hash);
5726
5727         return offset;
5728 }
5729
5730
5731 /* RFC 1813, Page 80..83 */
5732 static int
5733 dissect_entryplus3(tvbuff_t *tvb, int offset, packet_info *pinfo,
5734                    proto_tree* tree)
5735 {
5736         proto_item* entry_item = NULL;
5737         proto_tree* entry_tree = NULL;
5738         int old_offset = offset;
5739         char *name=NULL;
5740
5741         if (tree) {
5742                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
5743                         offset+0, -1, FALSE);
5744                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
5745         }
5746
5747         offset = dissect_rpc_uint64(tvb, entry_tree,
5748                 hf_nfs_readdirplus_entry_fileid, offset);
5749
5750         offset = dissect_filename3(tvb, offset, entry_tree,
5751                 hf_nfs_readdirplus_entry_name, &name);
5752
5753         /* are we snooping fh to filenames ?*/
5754         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
5755                 rpc_call_info_value *civ=pinfo->private_data;
5756                 /* v3 READDIRPLUS replies will give us a mapping */
5757                 if( (civ->prog==100003)
5758                   &&(civ->vers==3)
5759                   &&(!civ->request)
5760                   &&((civ->proc==17))
5761                 ) {
5762                         nfs_name_snoop_add_name(civ->xid, tvb, 0, 0,
5763                                 0/*parent offset*/, 0/*parent len*/,
5764                                 name);
5765                 }
5766         }
5767
5768         if (entry_item)
5769                 proto_item_set_text(entry_item, "Entry: name %s", name);
5770
5771         col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
5772
5773         offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdirplus_entry_cookie,
5774                 offset);
5775
5776         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, entry_tree,
5777                 "name_attributes");
5778
5779         offset = dissect_post_op_fh3(tvb, offset, pinfo, entry_tree, "name_handle");
5780
5781         /* now we know, that a readdirplus entry is shorter */
5782         if (entry_item) {
5783                 proto_item_set_len(entry_item, offset - old_offset);
5784         }
5785
5786         return offset;
5787 }
5788
5789
5790 /* RFC 1813, Page 80..83 */
5791 static int
5792 dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
5793                                proto_tree* tree)
5794 {
5795         guint32 status;
5796         guint32 eof_value;
5797         const char *err;
5798
5799         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5800         switch (status) {
5801                 case 0:
5802                         proto_item_append_text(tree, ", READDIRPLUS Reply");
5803
5804                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5805                                 "dir_attributes");
5806                         offset = dissect_cookieverf3(tvb, offset, tree);
5807                         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
5808                                 dissect_entryplus3);
5809                         eof_value = tvb_get_ntohl(tvb, offset+0);
5810                         if (tree)
5811                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
5812                                         offset+ 0, 4, eof_value);
5813                         offset += 4;
5814                 break;
5815                 default:
5816                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5817                                 "dir_attributes");
5818
5819                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5820                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5821                         proto_item_append_text(tree, ", READDIRPLUS Reply  Error:%s", err);
5822                 break;
5823         }
5824
5825         return offset;
5826 }
5827
5828
5829 /* RFC 1813, Page 84..86 */
5830 static int
5831 dissect_nfs3_fsstat_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5832                          proto_tree* tree)
5833 {
5834         guint32 hash;
5835
5836         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
5837
5838         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5839         proto_item_append_text(tree, ", FSSTAT Call DH:0x%08x", hash);
5840         return offset;
5841 }
5842
5843
5844 static int
5845 dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5846                           proto_tree* tree)
5847 {
5848         guint32 status;
5849         guint32 invarsec;
5850         const char *err;
5851
5852         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5853         switch (status) {
5854                 case 0:
5855                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5856                                 "obj_attributes");
5857                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_tbytes,
5858                                 offset);
5859                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_fbytes,
5860                                 offset);
5861                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_abytes,
5862                                 offset);
5863                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_tfiles,
5864                                 offset);
5865                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_ffiles,
5866                                 offset);
5867                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_afiles,
5868                                 offset);
5869                         invarsec = tvb_get_ntohl(tvb, offset + 0);
5870                         if (tree)
5871                                 proto_tree_add_uint(tree, hf_nfs_fsstat_invarsec, tvb,
5872                                 offset+0, 4, invarsec);
5873                         offset += 4;
5874
5875                         proto_item_append_text(tree, ", FSSTAT Reply");
5876                 break;
5877                 default:
5878                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5879                                 "obj_attributes");
5880
5881                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
5882                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5883                         proto_item_append_text(tree, ", FSSTAT Reply  Error:%s", err);
5884                 break;
5885         }
5886
5887         return offset;
5888 }
5889
5890
5891 #define FSF3_LINK        0x0001
5892 #define FSF3_SYMLINK     0x0002
5893 #define FSF3_HOMOGENEOUS 0x0008
5894 #define FSF3_CANSETTIME  0x0010
5895
5896
5897 /* RFC 1813, Page 86..90 */
5898 static int
5899 dissect_nfs3_fsinfo_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5900                          proto_tree* tree)
5901 {
5902         guint32 hash;
5903
5904         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
5905
5906         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5907         proto_item_append_text(tree, ", FSINFO Call DH:0x%08x", hash);
5908         return offset;
5909 }
5910 static int
5911 dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5912                           proto_tree* tree)
5913 {
5914         guint32 status;
5915         guint32 rtmax;
5916         guint32 rtpref;
5917         guint32 rtmult;
5918         guint32 wtmax;
5919         guint32 wtpref;
5920         guint32 wtmult;
5921         guint32 dtpref;
5922         guint32 properties;
5923         proto_item*     properties_item = NULL;
5924         proto_tree*     properties_tree = NULL;
5925         const char *err;
5926
5927         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5928         switch (status) {
5929                 case 0:
5930                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
5931                                 "obj_attributes");
5932                         rtmax = tvb_get_ntohl(tvb, offset+0);
5933                         if (tree)
5934                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmax, tvb,
5935                                 offset+0, 4, rtmax);
5936                         offset += 4;
5937                         rtpref = tvb_get_ntohl(tvb, offset+0);
5938                         if (tree)
5939                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtpref, tvb,
5940                                 offset+0, 4, rtpref);
5941                         offset += 4;
5942                         rtmult = tvb_get_ntohl(tvb, offset+0);
5943                         if (tree)
5944                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmult, tvb,
5945                                 offset+0, 4, rtmult);
5946                         offset += 4;
5947                         wtmax = tvb_get_ntohl(tvb, offset+0);
5948                         if (tree)
5949                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmax, tvb,
5950                                 offset+0, 4, wtmax);
5951                         offset += 4;
5952                         wtpref = tvb_get_ntohl(tvb, offset+0);
5953                         if (tree)
5954                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtpref, tvb,
5955                                 offset+0, 4, wtpref);
5956                         offset += 4;
5957                         wtmult = tvb_get_ntohl(tvb, offset+0);
5958                         if (tree)
5959                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmult, tvb,
5960                                 offset+0, 4, wtmult);
5961                         offset += 4;
5962                         dtpref = tvb_get_ntohl(tvb, offset+0);
5963                         if (tree)
5964                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_dtpref, tvb,
5965                                 offset+0, 4, dtpref);
5966                         offset += 4;
5967
5968                         offset = dissect_rpc_uint64(tvb, tree,
5969                                 hf_nfs_fsinfo_maxfilesize, offset);
5970                         offset = dissect_nfstime3(tvb, offset, tree, hf_nfs_dtime, hf_nfs_dtime_sec, hf_nfs_dtime_nsec);
5971                         properties = tvb_get_ntohl(tvb, offset+0);
5972                         if (tree) {
5973                                 properties_item = proto_tree_add_uint(tree,
5974                                 hf_nfs_fsinfo_properties,
5975                                 tvb, offset+0, 4, properties);
5976
5977                                 properties_tree = proto_item_add_subtree(properties_item,
5978                                                 ett_nfs_fsinfo_properties);
5979
5980                                 proto_tree_add_text(properties_tree, tvb,
5981                                         offset, 4, "%s",
5982                                         decode_boolean_bitfield(properties,
5983                                         FSF3_CANSETTIME,5,
5984                                         "SETATTR can set time on server",
5985                                         "SETATTR can't set time on server"));
5986
5987                                 proto_tree_add_text(properties_tree, tvb,
5988                                         offset, 4, "%s",
5989                                         decode_boolean_bitfield(properties,
5990                                         FSF3_HOMOGENEOUS,5,
5991                                         "PATHCONF is valid for all files",
5992                                         "PATHCONF should be get for every single file"));
5993
5994                                 proto_tree_add_text(properties_tree, tvb,
5995                                         offset, 4, "%s",
5996                                         decode_boolean_bitfield(properties,
5997                                         FSF3_SYMLINK,5,
5998                                         "File System supports symbolic links",
5999                                         "File System does not symbolic hard links"));
6000
6001                                 proto_tree_add_text(properties_tree, tvb,
6002                                         offset, 4, "%s",
6003                                         decode_boolean_bitfield(properties,
6004                                         FSF3_LINK,5,
6005                                         "File System supports hard links",
6006                                         "File System does not support hard links"));
6007                         }
6008                         offset += 4;
6009
6010                         proto_item_append_text(tree, ", FSINFO Reply");
6011                 break;
6012                 default:
6013                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
6014                                 "obj_attributes");
6015
6016                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
6017                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
6018                         proto_item_append_text(tree, ", FSINFO Reply  Error:%s", err);
6019                 break;
6020         }
6021
6022         return offset;
6023 }
6024
6025
6026 /* RFC 1813, Page 90..92 */
6027 static int
6028 dissect_nfs3_pathconf_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
6029                            proto_tree* tree)
6030 {
6031         guint32 hash;
6032
6033         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
6034
6035         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
6036         proto_item_append_text(tree, ", PATHCONF Call DH:0x%08x", hash);
6037         return offset;
6038 }
6039 static int
6040 dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
6041                             proto_tree* tree)
6042 {
6043         guint32 status;
6044         guint32 linkmax;
6045         guint32 name_max;
6046         const char *err;
6047
6048         offset = dissect_nfsstat3(tvb, offset, tree, &status);
6049         switch (status) {
6050                 case 0:
6051                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
6052                                 "obj_attributes");
6053                         linkmax = tvb_get_ntohl(tvb, offset + 0);
6054                         if (tree)
6055                                 proto_tree_add_uint(tree, hf_nfs_pathconf_linkmax, tvb,
6056                                 offset+0, 4, linkmax);
6057                         offset += 4;
6058                         name_max = tvb_get_ntohl(tvb, offset + 0);
6059                         if (tree)
6060                                 proto_tree_add_uint(tree, hf_nfs_pathconf_name_max, tvb,
6061                                 offset+0, 4, name_max);
6062                         offset += 4;
6063                         offset = dissect_rpc_bool(tvb, tree,
6064                                 hf_nfs_pathconf_no_trunc, offset);
6065                         offset = dissect_rpc_bool(tvb, tree,
6066                                 hf_nfs_pathconf_chown_restricted, offset);
6067                         offset = dissect_rpc_bool(tvb, tree,
6068                                 hf_nfs_pathconf_case_insensitive, offset);
6069                         offset = dissect_rpc_bool(tvb, tree,
6070                                 hf_nfs_pathconf_case_preserving, offset);
6071
6072                         proto_item_append_text(tree, ", PATHCONF Reply");
6073                 break;
6074                 default:
6075                         offset = dissect_nfs_post_op_attr(tvb, offset, pinfo, tree,
6076                                 "obj_attributes");
6077
6078                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
6079                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
6080                         proto_item_append_text(tree, ", PATHCONF Reply  Error:%s", err);
6081                 break;
6082         }
6083
6084         return offset;
6085 }
6086
6087
6088 /* RFC 1813, Page 92..95 */
6089 static int
6090 dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
6091                          proto_tree* tree)
6092 {
6093         guint32 hash;
6094
6095         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
6096         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
6097         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
6098
6099         col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
6100         proto_item_append_text(tree, ", COMMIT Call FH:0x%08x", hash);
6101
6102         return offset;
6103 }
6104
6105
6106 /* RFC 1813, Page 92..95 */
6107 static int
6108 dissect_nfs3_commit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
6109                           proto_tree* tree)
6110 {
6111         guint32 status;
6112         const char *err;
6113
6114         offset = dissect_nfsstat3(tvb, offset, tree, &status);
6115         switch (status) {
6116                 case 0:
6117                         offset = dissect_wcc_data  (tvb, offset, pinfo, tree, "file_wcc");
6118                         offset = dissect_writeverf3(tvb, offset, tree);
6119
6120                         proto_item_append_text(tree, ", COMMIT Reply");
6121                 break;
6122                 default:
6123                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
6124
6125                         err=val_to_str_ext(status, &names_nfs_nfsstat3_ext, "Unknown error:%u");
6126                         col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
6127                         proto_item_append_text(tree, ", COMMIT Reply  Error:%s", err);
6128                 break;
6129         }
6130
6131         return offset;
6132 }
6133
6134 /**********************************************************/
6135 /* NFS Version 4, RFC 3010 with nfs4_prot.x 1.103 changes */
6136 /**********************************************************/
6137
6138 /* NFSv4 Draft Specification, Page 198-199 */
6139 static const value_string names_nfs_nfsstat4[] = {
6140         {       0,      "NFS4_OK"                                       },
6141         {       1,      "NFS4ERR_PERM"                                  },
6142         {       2,      "NFS4ERR_NOENT"                                 },
6143         {       5,      "NFS4ERR_IO"                                    },
6144         {       6,      "NFS4ERR_NXIO"                                  },
6145         {       13,     "NFS4ERR_ACCES"                                 },
6146         {       17,     "NFS4ERR_EXIST"                                 },
6147         {       18,     "NFS4ERR_XDEV"                                  },
6148         {       19,     "NFS4ERR_NODEV"                                 },
6149         {       20,     "NFS4ERR_NOTDIR"                                },
6150         {       21,     "NFS4ERR_ISDIR"                                 },
6151         {       22,     "NFS4ERR_INVAL"                                 },
6152         {       27,     "NFS4ERR_FBIG"                                  },
6153         {       28,     "NFS4ERR_NOSPC"                                 },
6154         {       30,     "NFS4ERR_ROFS"                                  },
6155         {       31,     "NFS4ERR_MLINK"                                 },
6156         {       63,     "NFS4ERR_NAMETOOLONG"                           },
6157         {       66,     "NFS4ERR_NOTEMPTY"                              },
6158         {       69,     "NFS4ERR_DQUOT"                                 },
6159         {       70,     "NFS4ERR_STALE"                                 },
6160         {       10001,  "NFS4ERR_BADHANDLE"                             },
6161         {       10003,  "NFS4ERR_BAD_COOKIE"                            },
6162         {       10004,  "NFS4ERR_NOTSUPP"                               },
6163         {       10005,  "NFS4ERR_TOOSMALL"                              },
6164         {       10006,  "NFS4ERR_SERVERFAULT"                           },
6165         {       10007,  "NFS4ERR_BADTYPE"                               },
6166         {       10008,  "NFS4ERR_DELAY"                                 },
6167         {       10009,  "NFS4ERR_SAME"                                  },
6168         {       10010,  "NFS4ERR_DENIED"                                },
6169         {       10011,  "NFS4ERR_EXPIRED"                               },
6170         {       10012,  "NFS4ERR_LOCKED"                                },
6171         {       10013,  "NFS4ERR_GRACE"                                 },
6172         {       10014,  "NFS4ERR_FHEXPIRED"                             },
6173         {       10015,  "NFS4ERR_SHARE_DENIED"                          },
6174         {       10016,  "NFS4ERR_WRONGSEC"                              },
6175         {       10017,  "NFS4ERR_CLID_INUSE"                            },
6176         {       10018,  "NFS4ERR_RESOURCE"                              },
6177         {       10019,  "NFS4ERR_MOVED"                                 },
6178         {       10020,  "NFS4ERR_NOFILEHANDLE"                          },
6179         {       10021,  "NFS4ERR_MINOR_VERS_MISMATCH"                   },
6180         {       10022,  "NFS4ERR_STALE_CLIENTID"                        },
6181         {       10023,  "NFS4ERR_STALE_STATEID"                         },
6182         {       10024,  "NFS4ERR_OLD_STATEID"                           },
6183         {       10025,  "NFS4ERR_BAD_STATEID"                           },
6184         {       10026,  "NFS4ERR_BAD_SEQID"                             },
6185         {       10027,  "NFS4ERR_NOT_SAME"                              },
6186         {       10028,  "NFS4ERR_LOCK_RANGE"                            },
6187         {       10029,  "NFS4ERR_SYMLINK"                               },
6188         {       10030,  "NFS4ERR_READDIR_NOSPC"                         },
6189         {       10031,  "NFS4ERR_LEASE_MOVED"                           },
6190         {       10032,  "NFS4ERR_ATTRNOTSUPP"                           },
6191         {       10033,  "NFS4ERR_NO_GRACE"                              },
6192         {       10034,  "NFS4ERR_RECLAIM_BAD"                           },
6193         {       10035,  "NFS4ERR_RECLAIM_CONFLICT"                      },
6194         {       10036,  "NFS4ERR_BADXDR"                                },
6195         {       10037,  "NFS4ERR_LOCKS_HELD"                            },
6196         {       10038,  "NFS4ERR_OPENMODE"                              },
6197         {       10039,  "NFS4ERR_BADOWNER"                              },
6198         {       10040,  "NFS4ERR_BADCHAR"                               },
6199         {       10041,  "NFS4ERR_BADNAME"                               },
6200         {       10042,  "NFS4ERR_BAD_RANGE"                             },
6201         {       10043,  "NFS4ERR_LOCK_NOTSUPP"                          },
6202         {       10044,  "NFS4ERR_OP_ILLEGAL"                            },
6203         {       10045,  "NFS4ERR_DEADLOCK"                              },
6204         {       10046,  "NFS4ERR_FILE_OPEN"                             },
6205         {       10047,  "NFS4ERR_ADMIN_REVOKED"                         },
6206         {       10048,  "NFS4ERR_CB_PATH_DOWN"                          },
6207         {       10049,  "NFS4ERR_BADIOMODE"                             },
6208         {       10050,  "NFS4ERR_BADLAYOUT"                             },
6209         {       10051,  "NFS4ERR_BAD_SESSION_DIGEST"                    },
6210         {       10052,  "NFS4ERR_BADSESSION"                            },
6211         {       10053,  "NFS4ERR_BADSLOT"                               },
6212         {       10054,  "NFS4ERR_COMPLETE_ALREADY"                      },
6213         {       10055,  "NFS4ERR_CONN_NOT_BOUND_TO_SESSION"             },
6214         {       10056,  "NFS4ERR_DELEG_ALREADY_WANTED"                  },
6215         {       10057,  "NFS4ERR_DIRDELEG_UNAVAIL"                      },
6216         {       10058,  "NFS4ERR_LAYOUTTRYLATER"                        },
6217         {       10059,  "NFS4ERR_LAYOUTUNAVAILABLE"                     },
6218         {       10060,  "NFS4ERR_NOMATCHING_LAYOUT"                     },
6219         {       10061,  "NFS4ERR_RECALLCONFLICT"                        },
6220         {       10062,  "NFS4ERR_UNKNOWN_LAYOUTTYPE"                    },
6221         {       10063,  "NFS4ERR_SEQ_MISORDERED"                        },
6222         {       10064,  "NFS4ERR_SEQUENCE_POS"                          },
6223         {       10065,  "NFS4ERR_REQ_TOO_BIG"                           },
6224         {       10066,  "NFS4ERR_REP_TOO_BIG"                           },
6225         {       10067,  "NFS4ERR_REP_TOO_BIG_TO_CACHE"                  },
6226         {       10068,  "NFS4ERR_RETRY_UNCACHED_REP"                    },
6227         {       10069,  "NFS4ERR_UNSAFE_COMPOUND"                       },
6228         {       10070,  "NFS4ERR_TOO_MANY_OPS"                          },
6229         {       10071,  "NFS4ERR_OP_NOT_IN_SESSION"                     },
6230         {       10072,  "NFS4ERR_HASH_ALG_UNSUPP"                       },
6231         {       10073,  "NFS4ERR_CONN_BINDING_NOT_ENFORCED"             },
6232         {       10074,  "NFS4ERR_CLIENTID_BUSY"                         },
6233         {       10075,  "NFS4ERR_PNFS_IO_HOLE"                          },
6234         {       10076,  "NFS4ERR_SEQ_FALSE_RETRY"                       },
6235         {       10077,  "NFS4ERR_BAD_HIGH_SLOT"                         },
6236         {       10078,  "NFS4ERR_DEADSESSION"                           },
6237         {       10079,  "NFS4ERR_ENCR_ALG_UNSUPP"                       },
6238         {       10080,  "NFS4ERR_PNFS_NO_LAYOUT"                        },
6239         {       10081,  "NFS4ERR_NOT_ONLY_OP"                           },
6240         {       10082,  "NFS4ERR_WRONG_CRED"                            },
6241         {       10083,  "NFS4ERR_WRONG_TYPE"                            },
6242         {       10084,  "NFS4ERR_DIRDELEG_UNAVAIL"                      },
6243         {       10085,  "NFS4ERR_REJECT_DELEG"                          },
6244         {       10086,  "NFS4ERR_RETURNCONFLICT"                        },
6245         {       0,      NULL }
6246 };
6247 static value_string_ext names_nfs_nfsstat4_ext = VALUE_STRING_EXT_INIT(names_nfs_nfsstat4);
6248
6249
6250 static int
6251 dissect_nfs_nfsstat4(tvbuff_t *tvb, int offset,
6252                      proto_tree *tree, guint32 *status)
6253 {
6254         guint32 stat;
6255         proto_item *stat_item;
6256
6257         stat = tvb_get_ntohl(tvb, offset+0);
6258
6259         if (tree) {
6260                 proto_tree_add_uint(tree, hf_nfs_nfsstat4, tvb, offset+0, 4,
6261                         stat);
6262                 stat_item = proto_tree_add_uint(tree, hf_nfs_nfsstat, tvb,
6263                         offset+0, 4, stat);
6264                 PROTO_ITEM_SET_HIDDEN(stat_item);
6265         }
6266
6267         offset += 4;
6268
6269         if (status) *status = stat;
6270
6271         return offset;
6272 }
6273
6274
6275 static int
6276 dissect_nfs_utf8string(tvbuff_t *tvb, int offset,
6277                        proto_tree *tree, int hf, char **string_ret)
6278 {
6279         /* TODO: this dissector is subject to change; do not remove */
6280         return dissect_rpc_string(tvb, tree, hf, offset, string_ret);
6281 }
6282
6283 static int
6284 dissect_nfs_specdata4(tvbuff_t *tvb, int offset, proto_tree *tree)
6285 {
6286         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_specdata1, offset);
6287         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_specdata2, offset);
6288
6289         return offset;
6290 }
6291
6292 static const value_string names_ftype4[] = {
6293         {       NF4REG,         "NF4REG"        },
6294         {       NF4DIR,         "NF4DIR"        },
6295         {       NF4BLK,         "NF4BLK"        },
6296         {       NF4CHR,         "NF4CHR"        },
6297         {       NF4LNK,         "NF4LNK"        },
6298         {       NF4SOCK,        "NF4SOCK"       },
6299         {       NF4FIFO,        "NF4FIFO"       },
6300         {       NF4ATTRDIR,     "NF4ATTRDIR"    },
6301         {       NF4NAMEDATTR,   "NF4NAMEDATTR"  },
6302         {       0,      NULL }
6303 };
6304
6305 static int
6306 dissect_nfs_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
6307 {
6308         proto_tree *newftree = NULL;
6309         proto_item *fitem = NULL;
6310
6311         fitem = proto_tree_add_text(tree, tvb, offset, 4, "Owner");
6312
6313         if (fitem)
6314         {
6315                 newftree = proto_item_add_subtree(fitem, ett_nfs_lock_owner4);
6316
6317                 offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
6318                 offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
6319         }
6320
6321         return offset;
6322 }
6323
6324 static int
6325 dissect_nfs_pathname4(tvbuff_t *tvb, int offset, proto_tree *tree)
6326 {
6327         guint32 comp_count, i;
6328         proto_item *fitem = NULL;
6329         proto_tree *newftree = NULL;
6330
6331         comp_count=tvb_get_ntohl(tvb, offset);
6332         fitem = proto_tree_add_text(tree, tvb, offset, 4,
6333                 "pathname components (%u)", comp_count);
6334         offset += 4;
6335
6336         if (fitem)
6337         {
6338                 newftree = proto_item_add_subtree(fitem, ett_nfs_pathname4);
6339
6340                 for (i = 0; i < comp_count; i++)
6341                                 offset = dissect_nfs_utf8string(tvb, offset, newftree,
6342                                         hf_nfs_component4, NULL);
6343         }
6344
6345         return offset;
6346 }
6347
6348 static int
6349 dissect_nfs_nfstime4(tvbuff_t *tvb, int offset, proto_tree *tree)
6350 {
6351         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_nfstime4_seconds, offset);
6352         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_nfstime4_nseconds, offset);
6353
6354         return offset;
6355 }
6356
6357 static const value_string names_time_how4[] = {
6358 #define SET_TO_SERVER_TIME4 0
6359         {       SET_TO_SERVER_TIME4,    "SET_TO_SERVER_TIME4"   },
6360 #define SET_TO_CLIENT_TIME4 1
6361         {       SET_TO_CLIENT_TIME4,    "SET_TO_CLIENT_TIME4"   },
6362         {       0,      NULL    }
6363 };
6364
6365 static int
6366 dissect_nfs_settime4(tvbuff_t *tvb, int offset,
6367                      proto_tree *tree, const char *name _U_)
6368 {
6369         guint32 set_it;
6370
6371         set_it = tvb_get_ntohl(tvb, offset);
6372         proto_tree_add_uint(tree, hf_nfs_time_how4, tvb, offset+0,
6373                 4, set_it);
6374         offset += 4;
6375
6376         if (set_it == SET_TO_CLIENT_TIME4)
6377                 offset = dissect_nfs_nfstime4(tvb, offset, tree);
6378
6379         return offset;
6380 }
6381
6382 static int
6383 dissect_nfs_fsid4(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
6384 {
6385         proto_tree *newftree = NULL;
6386         proto_item *fitem = NULL;
6387
6388         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
6389
6390         if (fitem == NULL) return offset;
6391
6392         newftree = proto_item_add_subtree(fitem, ett_nfs_fsid4);
6393
6394         if (newftree == NULL) return offset;
6395
6396         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_fsid4_major,
6397                 offset);
6398         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_fsid4_minor,
6399                 offset);
6400
6401         return offset;
6402 }
6403
6404 static const value_string names_acetype4[] = {
6405 #define ACE4_ACCESS_ALLOWED_ACE_TYPE    0x00000000
6406         {       ACE4_ACCESS_ALLOWED_ACE_TYPE, "ACE4_ACCESS_ALLOWED_ACE_TYPE"  },
6407 #define ACE4_ACCESS_DENIED_ACE_TYPE             0x00000001
6408         {       ACE4_ACCESS_DENIED_ACE_TYPE, "ACE4_ACCESS_DENIED_ACE_TYPE" },
6409 #define ACE4_SYSTEM_AUDIT_ACE_TYPE              0x00000002
6410         {       ACE4_SYSTEM_AUDIT_ACE_TYPE, "ACE4_SYSTEM_AUDIT_ACE_TYPE" },
6411 #define ACE4_SYSTEM_ALARM_ACE_TYPE              0x00000003
6412         {       ACE4_SYSTEM_ALARM_ACE_TYPE, "ACE4_SYSTEM_ALARM_ACE_TYPE" },
6413         {       0,      NULL }
6414 };
6415
6416 /* ACE mask values */
6417 #define ACE4_READ_DATA                  0x00000001
6418 #define ACE4_LIST_DIRECTORY             0x00000001
6419 #define ACE4_WRITE_DATA                 0x00000002
6420 #define ACE4_ADD_FILE                   0x00000002
6421 #define ACE4_APPEND_DATA                0x00000004
6422 #define ACE4_ADD_SUBDIRECTORY           0x00000004
6423 #define ACE4_READ_NAMED_ATTRS           0x00000008
6424 #define ACE4_WRITE_NAMED_ATTRS          0x00000010
6425 #define ACE4_EXECUTE                    0x00000020
6426 #define ACE4_DELETE_CHILD               0x00000040
6427 #define ACE4_READ_ATTRIBUTES            0x00000080
6428 #define ACE4_WRITE_ATTRIBUTES           0x00000100
6429 #define ACE4_DELETE                     0x00010000
6430 #define ACE4_READ_ACL                   0x00020000
6431 #define ACE4_WRITE_ACL                  0x00040000
6432 #define ACE4_WRITE_OWNER                0x00080000
6433 #define ACE4_SYNCHRONIZE                0x00100000
6434
6435 static int
6436 dissect_nfs_acemask4(tvbuff_t *tvb, int offset, proto_tree *tree)
6437 {
6438         guint32 acemask;
6439         proto_item *acemask_item = NULL;
6440         proto_tree *acemask_tree = NULL;
6441
6442         acemask = tvb_get_ntohl(tvb, offset);
6443
6444         acemask_item = proto_tree_add_text(tree, tvb, offset, 4,
6445                 "acemask: 0x%08x", acemask);
6446
6447         if (acemask_item)
6448                 acemask_tree = proto_item_add_subtree(acemask_item, ett_nfs_acemask4);
6449
6450         if (acemask_tree)
6451         {
6452                 if (acemask & ACE4_READ_DATA)
6453                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6454                                 "ACE4_READ_DATA/ACE4_LIST_DIRECTORY (0x%08x)",
6455                                 ACE4_READ_DATA);
6456
6457                 if (acemask & ACE4_WRITE_DATA)
6458                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6459                                 "ACE4_WRITE_DATA/ACE4_ADD_FILE (0x%08x)",
6460                                 ACE4_WRITE_DATA);
6461
6462                 if (acemask & ACE4_APPEND_DATA)
6463                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6464                                 "ACE4_ADD_FILE/ACE4_ADD_SUBDIRECTORY (0x%08x)",
6465                                 ACE4_APPEND_DATA);
6466
6467                 if (acemask & ACE4_READ_NAMED_ATTRS)
6468                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6469                                 "ACE4_READ_NAMED_ATTRS (0x%08x)",
6470                                 ACE4_READ_NAMED_ATTRS);
6471
6472                 if (acemask & ACE4_WRITE_NAMED_ATTRS)
6473                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6474                                 "ACE4_WRITE_NAMED_ATTRS (0x%08x)",
6475                                 ACE4_WRITE_NAMED_ATTRS);
6476
6477                 if (acemask & ACE4_EXECUTE)
6478                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6479                                 "ACE4_EXECUTE (0x%08x)",
6480                                 ACE4_EXECUTE);
6481
6482                 if (acemask & ACE4_DELETE_CHILD)
6483                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6484                                 "ACE4_DELETE_CHILD (0x%08x)",
6485                                 ACE4_DELETE_CHILD);
6486
6487                 if (acemask & ACE4_READ_ATTRIBUTES)
6488                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6489                                 "ACE4_READ_ATTRIBUTES (0x%08x)",
6490                                 ACE4_READ_ATTRIBUTES);
6491
6492                 if (acemask & ACE4_WRITE_ATTRIBUTES)
6493                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6494                                 "ACE4_WRITE_ATTRIBUTES (0x%08x)",
6495                                 ACE4_WRITE_ATTRIBUTES);
6496
6497                 if (acemask & ACE4_DELETE)
6498                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6499                                 "ACE4_DELETE (0x%08x)",
6500                                 ACE4_DELETE);
6501
6502                 if (acemask & ACE4_READ_ACL)
6503                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6504                                 "ACE4_READ_ACL (0x%08x)",
6505                                 ACE4_READ_ACL);
6506
6507                 if (acemask & ACE4_WRITE_ACL)
6508                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6509                                 "ACE4_WRITE_ACL (0x%08x)",
6510                                 ACE4_WRITE_ACL);
6511
6512                 if (acemask & ACE4_WRITE_OWNER)
6513                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6514                                 "ACE4_WRITE_OWNER (0x%08x)",
6515                                 ACE4_WRITE_OWNER);
6516
6517                 if (acemask & ACE4_SYNCHRONIZE)
6518                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
6519                                 "ACE4_SYNCHRONIZE (0x%08x)",
6520                                 ACE4_SYNCHRONIZE);
6521         }
6522
6523         offset += 4;
6524
6525         return offset;
6526 }
6527
6528 /* ACE flag values */
6529 #define ACE4_FILE_INHERIT_ACE                   0x00000001
6530 #define ACE4_DIRECTORY_INHERIT_ACE              0x00000002
6531 #define ACE4_NO_PROPAGATE_INHERIT_ACE           0x00000004
6532 #define ACE4_INHERIT_ONLY_ACE                   0x00000008
6533 #define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG         0x00000010
6534 #define ACE4_FAILED_ACCESS_ACE_FLAG             0x00000020
6535 #define ACE4_IDENTIFIER_GROUP                   0x00000040
6536
6537
6538 static int
6539 dissect_nfs_ace4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
6540                 proto_tree *tree)
6541 {
6542         proto_item* ace_item = NULL;
6543         proto_tree* ace_tree = NULL;
6544         proto_item *aceflag_item = NULL;
6545         proto_tree *aceflag_tree = NULL;
6546         guint32 aceflag4;
6547
6548         if (tree) {
6549                 ace_item = proto_tree_add_text(tree, tvb, offset, 4,
6550                         "ACE");
6551
6552                 ace_tree = proto_item_add_subtree(ace_item, ett_nfs_ace4);
6553         }
6554
6555         offset = dissect_rpc_uint32(tvb, ace_tree, hf_nfs_acetype4, offset);
6556
6557         if (ace_tree) {
6558                 aceflag4 = tvb_get_ntohl(tvb, offset);
6559
6560                 aceflag_item = proto_tree_add_text(ace_tree, tvb, offset, 4,
6561                         "aceflag: 0x%08x", aceflag4);
6562
6563                 if (aceflag_item)
6564                 {
6565                         aceflag_tree = proto_item_add_subtree(aceflag_item, ett_nfs_aceflag4);
6566
6567                         if (aceflag_tree)
6568                         {
6569                                 if (aceflag4 & ACE4_FILE_INHERIT_ACE)
6570                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
6571                                                 "ACE4_FILE_INHERIT_ACE (0x%08x)", ACE4_FILE_INHERIT_ACE);
6572
6573                                 if (aceflag4 & ACE4_DIRECTORY_INHERIT_ACE)
6574                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
6575                                                 "ACE4_DIRECTORY_INHERIT_ACE (0x%08x)",
6576                                                  ACE4_DIRECTORY_INHERIT_ACE);
6577
6578                                 if (aceflag4 & ACE4_INHERIT_ONLY_ACE)
6579                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
6580                                                 "ACE4_INHERIT_ONLY_ACE (0x%08x)",
6581                                                 ACE4_INHERIT_ONLY_ACE);
6582
6583                                 if (aceflag4 & ACE4_SUCCESSFUL_ACCESS_ACE_FLAG)
6584                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
6585                                                 "ACE4_SUCCESSFUL_ACCESS_ACE_FLAG (0x%08x)",
6586                                                 ACE4_SUCCESSFUL_ACCESS_ACE_FLAG);
6587
6588                                 if (aceflag4 & ACE4_FAILED_ACCESS_ACE_FLAG)
6589                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
6590                                                 "ACE4_FAILED_ACCESS_ACE_FLAG (0x%08x)",
6591                                                 ACE4_FAILED_ACCESS_ACE_FLAG);
6592
6593                                 if (aceflag4 & ACE4_IDENTIFIER_GROUP)
6594                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
6595                                                 "ACE4_IDENTIFIER_GROUP (0x%08x)",
6596                                                 ACE4_IDENTIFIER_GROUP);
6597                         }
6598                 }
6599         }
6600
6601         offset += 4;
6602
6603         offset = dissect_nfs_acemask4(tvb, offset, ace_tree);
6604
6605         offset = dissect_nfs_utf8string(tvb, offset, ace_tree, hf_nfs_who, NULL);
6606
6607         return offset;
6608 }
6609
6610 static int
6611 dissect_nfs_fattr4_acl(tvbuff_t *tvb, int offset, packet_info *pinfo,
6612                        proto_tree *tree)
6613 {
6614         return dissect_rpc_array(tvb, pinfo, tree, offset, dissect_nfs_ace4,
6615                 hf_nfs_acl4);
6616 }
6617
6618 static int
6619 dissect_nfs_fh4(tvbuff_t *tvb, int offset, packet_info *pinfo,
6620                 proto_tree *tree, const char *name, guint32 *hash)
6621 {
6622         return dissect_nfs_fh3(tvb, offset, pinfo, tree, name, hash);
6623 }
6624
6625 static int
6626 dissect_nfs_server4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
6627 {
6628         return dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_server, NULL);
6629 }
6630
6631 static int
6632 dissect_nfs_fs_location4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
6633                          proto_tree *tree)
6634 {
6635         proto_tree *newftree = NULL;
6636         proto_item *fitem = NULL;
6637
6638         fitem = proto_tree_add_text(tree, tvb, offset, 0, "fs_location4");
6639
6640         if (fitem == NULL) return offset;
6641
6642         newftree = proto_item_add_subtree(fitem, ett_nfs_fs_location4);
6643
6644         offset = dissect_rpc_array(tvb, pinfo, newftree, offset, dissect_nfs_server4, hf_nfs_server);
6645         offset = dissect_nfs_pathname4(tvb, offset, newftree);
6646
6647         return offset;
6648 }
6649
6650 static int
6651 dissect_nfs_fs_locations4(tvbuff_t *tvb, packet_info *pinfo, int offset,
6652                           proto_tree *tree, const char *name)
6653 {
6654         proto_tree *newftree = NULL;
6655         proto_item *fitem = NULL;
6656
6657         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
6658
6659         if (fitem == NULL) return offset;
6660
6661         newftree = proto_item_add_subtree(fitem, ett_nfs_fs_locations4);
6662
6663         offset = dissect_nfs_pathname4(tvb, offset, newftree);
6664
6665         offset = dissect_rpc_array(tvb, pinfo, newftree, offset,
6666                 dissect_nfs_fs_location4, hf_nfs_fslocation4);
6667
6668         return offset;
6669 }
6670
6671 static int
6672 dissect_nfs_mode4(tvbuff_t *tvb, int offset,
6673                   proto_tree *tree, const char *name)
6674 {
6675         return dissect_mode(tvb, offset, tree, name);
6676 }
6677
6678 static const value_string nfs4_fattr4_fh_expire_type_names[] = {
6679 #define FH4_PERSISTENT 0x00000000
6680         {       FH4_PERSISTENT, "FH4_PERSISTENT"        },
6681 #define FH4_NOEXPIRE_WITH_OPEN 0x00000001
6682         {       FH4_NOEXPIRE_WITH_OPEN, "FH4_NOEXPIRE_WITH_OPEN"        },
6683 #define FH4_VOLATILE_ANY 0x00000002
6684         {       FH4_VOLATILE_ANY,       "FH4_VOLATILE_ANY"      },
6685 #define FH4_VOL_MIGRATION 0x00000004
6686         {       FH4_VOL_MIGRATION,      "FH4_VOL_MIGRATION"     },
6687 #define FH4_VOL_RENAME 0x00000008
6688         {       FH4_VOL_RENAME, "FH4_VOL_RENAME"        },
6689         {       0,      NULL    }
6690 };
6691
6692
6693 static int
6694 dissect_nfs_fattr4_fh_expire_type(tvbuff_t *tvb, int offset, proto_tree *tree)
6695 {
6696         guint32 expire_type;
6697         proto_item *expire_type_item = NULL;
6698         proto_tree *expire_type_tree = NULL;
6699
6700         expire_type = tvb_get_ntohl(tvb, offset + 0);
6701
6702         if (tree)
6703         {
6704                 expire_type_item = proto_tree_add_text(tree, tvb, offset, 4,
6705                         "fattr4_fh_expire_type: 0x%08x", expire_type);
6706
6707                 expire_type_tree = proto_item_add_subtree(expire_type_item,
6708                                 ett_nfs_fattr4_fh_expire_type);
6709         }
6710
6711         if (expire_type_tree)
6712         {
6713                 if (expire_type == FH4_PERSISTENT)
6714                 {
6715                         proto_tree_add_text(expire_type_tree, tvb, offset, 4, "%s",
6716                                 decode_enumerated_bitfield(expire_type, 0xFFFFFFFF, 32,
6717                                 nfs4_fattr4_fh_expire_type_names, "%s"));
6718                 }
6719                 else
6720                 {
6721                         if (expire_type & FH4_NOEXPIRE_WITH_OPEN)
6722                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
6723                                                 "FH4_NOEXPIRE_WITH_OPEN (0x%08x)", FH4_NOEXPIRE_WITH_OPEN);
6724
6725                         if (expire_type & FH4_VOLATILE_ANY)
6726                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
6727                                                 "FH4_VOLATILE_ANY (0x%08x)", FH4_VOLATILE_ANY);
6728
6729                         if (expire_type & FH4_VOL_MIGRATION)
6730                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
6731                                                 "FH4_VOL_MIGRATION (0x%08x)", FH4_VOL_MIGRATION);
6732
6733                         if (expire_type & FH4_VOL_RENAME)
6734                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
6735                                                 "FH4_VOL_RENAME (0x%08x)", FH4_VOL_RENAME);
6736                 }
6737         }
6738
6739         offset += 4;
6740
6741         return offset;
6742 }
6743
6744 static int
6745 dissect_nfs_fs_layout_type(tvbuff_t *tvb, proto_tree *tree, int offset)
6746 {
6747         guint count, i;
6748
6749         count = tvb_get_ntohl(tvb, offset);
6750         offset +=4;
6751
6752         for (i = 0; i < count; i++) {
6753                 offset += dissect_rpc_uint32(tvb, tree, hf_nfs_layouttype4, offset);
6754         }
6755
6756         return offset;
6757 }
6758
6759 static const value_string names_fattr4[] = {
6760 #define FATTR4_SUPPORTED_ATTRS     0
6761         {       FATTR4_SUPPORTED_ATTRS, "FATTR4_SUPPORTED_ATTRS"        },
6762 #define FATTR4_TYPE                1
6763         {       FATTR4_TYPE,    "FATTR4_TYPE"   },
6764 #define FATTR4_FH_EXPIRE_TYPE      2
6765         {       FATTR4_FH_EXPIRE_TYPE,  "FATTR4_FH_EXPIRE_TYPE" },
6766 #define FATTR4_CHANGE              3
6767         {       FATTR4_CHANGE,  "FATTR4_CHANGE" },
6768 #define FATTR4_SIZE                4
6769         {       FATTR4_SIZE,    "FATTR4_SIZE"   },
6770 #define FATTR4_LINK_SUPPORT        5
6771         {       FATTR4_LINK_SUPPORT,    "FATTR4_LINK_SUPPORT"   },
6772 #define FATTR4_SYMLINK_SUPPORT     6
6773         {       FATTR4_SYMLINK_SUPPORT, "FATTR4_SYMLINK_SUPPORT"        },
6774 #define FATTR4_NAMED_ATTR          7
6775         {       FATTR4_NAMED_ATTR,      "FATTR4_NAMED_ATTR"     },
6776 #define FATTR4_FSID                8
6777         {       FATTR4_FSID,    "FATTR4_FSID"   },
6778 #define FATTR4_UNIQUE_HANDLES      9
6779         {       FATTR4_UNIQUE_HANDLES,  "FATTR4_UNIQUE_HANDLES" },
6780 #define FATTR4_LEASE_TIME          10
6781         {       FATTR4_LEASE_TIME,      "FATTR4_LEASE_TIME"     },
6782 #define FATTR4_RDATTR_ERROR        11
6783         {       FATTR4_RDATTR_ERROR,    "FATTR4_RDATTR_ERROR"   },
6784 #define FATTR4_ACL                 12
6785         {       FATTR4_ACL,     "FATTR4_ACL"    },
6786 #define FATTR4_ACLSUPPORT          13
6787         {       FATTR4_ACLSUPPORT,      "FATTR4_ACLSUPPORT"     },
6788 #define FATTR4_ARCHIVE             14
6789         {       FATTR4_ARCHIVE, "FATTR4_ARCHIVE"        },
6790 #define FATTR4_CANSETTIME          15
6791         {       FATTR4_CANSETTIME, "FATTR4_CANSETTIME"  },
6792 #define FATTR4_CASE_INSENSITIVE    16
6793         {       FATTR4_CASE_INSENSITIVE, "FATTR4_CASE_INSENSITIVE"      },
6794 #define FATTR4_CASE_PRESERVING     17
6795         {       FATTR4_CASE_PRESERVING, "FATTR4_CASE_PRESERVING"        },
6796 #define FATTR4_CHOWN_RESTRICTED    18
6797         {       FATTR4_CHOWN_RESTRICTED, "FATTR4_CHOWN_RESTRICTED"      },
6798 #define FATTR4_FILEHANDLE          19
6799         {       FATTR4_FILEHANDLE, "FATTR4_FILEHANDLE"  },
6800 #define FATTR4_FILEID              20
6801         {       FATTR4_FILEID, "FATTR4_FILEID"  },
6802 #define FATTR4_FILES_AVAIL         21
6803         {       FATTR4_FILES_AVAIL, "FATTR4_FILES_AVAIL"        },
6804 #define FATTR4_FILES_FREE          22
6805         {       FATTR4_FILES_FREE, "FATTR4_FILES_FREE"  },
6806 #define FATTR4_FILES_TOTAL         23
6807         {       FATTR4_FILES_TOTAL, "FATTR4_FILES_TOTAL"        },
6808 #define FATTR4_FS_LOCATIONS        24
6809         {       FATTR4_FS_LOCATIONS, "FATTR4_FS_LOCATIONS"      },
6810 #define FATTR4_HIDDEN              25
6811         {       FATTR4_HIDDEN, "FATTR4_HIDDEN"  },
6812 #define FATTR4_HOMOGENEOUS         26
6813         {       FATTR4_HOMOGENEOUS, "FATTR4_HOMOGENEOUS"        },
6814 #define FATTR4_MAXFILESIZE         27
6815         {       FATTR4_MAXFILESIZE, "FATTR4_MAXFILESIZE"        },
6816 #define FATTR4_MAXLINK             28
6817         {       FATTR4_MAXLINK, "FATTR4_MAXLINK"        },
6818 #define FATTR4_MAXNAME             29
6819         {       FATTR4_MAXNAME, "FATTR4_MAXNAME"        },
6820 #define FATTR4_MAXREAD             30
6821         {       FATTR4_MAXREAD, "FATTR4_MAXREAD"        },
6822 #define FATTR4_MAXWRITE            31
6823         {       FATTR4_MAXWRITE, "FATTR4_MAXWRITE"      },
6824 #define FATTR4_MIMETYPE            32
6825         {       FATTR4_MIMETYPE, "FATTR4_MIMETYPE"      },
6826 #define FATTR4_MODE                33
6827         {       FATTR4_MODE, "FATTR4_MODE"      },
6828 #define FATTR4_NO_TRUNC            34
6829         {       FATTR4_NO_TRUNC, "FATTR4_NO_TRUNC"      },
6830 #define FATTR4_NUMLINKS            35
6831         {       FATTR4_NUMLINKS, "FATTR4_NUMLINKS"      },
6832 #define FATTR4_OWNER               36
6833         {       FATTR4_OWNER, "FATTR4_OWNER"    },
6834 #define FATTR4_OWNER_GROUP         37
6835         {       FATTR4_OWNER_GROUP, "FATTR4_OWNER_GROUP"        },
6836 #define FATTR4_QUOTA_AVAIL_HARD    38
6837         {       FATTR4_QUOTA_AVAIL_HARD, "FATTR4_QUOTA_AVAIL_HARD"      },
6838 #define FATTR4_QUOTA_AVAIL_SOFT    39
6839         {       FATTR4_QUOTA_AVAIL_SOFT, "FATTR4_QUOTA_AVAIL_SOFT"      },
6840 #define FATTR4_QUOTA_USED          40
6841         {       FATTR4_QUOTA_USED, "FATTR4_QUOTA_USED"  },
6842 #define FATTR4_RAWDEV              41
6843         {       FATTR4_RAWDEV, "FATTR4_RAWDEV"  },
6844 #define FATTR4_SPACE_AVAIL         42
6845         {       FATTR4_SPACE_AVAIL, "FATTR4_SPACE_AVAIL"        },
6846 #define FATTR4_SPACE_FREE          43
6847         {       FATTR4_SPACE_FREE, "FATTR4_SPACE_FREE"  },
6848 #define FATTR4_SPACE_TOTAL         44
6849         {       FATTR4_SPACE_TOTAL, "FATTR4_SPACE_TOTAL"        },
6850 #define FATTR4_SPACE_USED          45
6851         {       FATTR4_SPACE_USED, "FATTR4_SPACE_USED"  },
6852 #define FATTR4_SYSTEM              46
6853         {       FATTR4_SYSTEM, "FATTR4_SYSTEM"  },
6854 #define FATTR4_TIME_ACCESS         47
6855         {       FATTR4_TIME_ACCESS, "FATTR4_TIME_ACCESS"        },
6856 #define FATTR4_TIME_ACCESS_SET     48
6857         {       FATTR4_TIME_ACCESS_SET, "FATTR4_TIME_ACCESS_SET"        },
6858 #define FATTR4_TIME_BACKUP         49
6859         {       FATTR4_TIME_BACKUP, "FATTR4_TIME_BACKUP"        },
6860 #define FATTR4_TIME_CREATE         50
6861         {       FATTR4_TIME_CREATE, "FATTR4_TIME_CREATE"        },
6862 #define FATTR4_TIME_DELTA          51
6863         {       FATTR4_TIME_DELTA, "FATTR4_TIME_DELTA"  },
6864 #define FATTR4_TIME_METADATA       52
6865         {       FATTR4_TIME_METADATA, "FATTR4_TIME_METADATA"    },
6866 #define FATTR4_TIME_MODIFY         53
6867         {       FATTR4_TIME_MODIFY, "FATTR4_TIME_MODIFY"        },
6868 #define FATTR4_TIME_MODIFY_SET     54
6869         {       FATTR4_TIME_MODIFY_SET, "FATTR4_TIME_MODIFY_SET"        },
6870 #define FATTR4_MOUNTED_ON_FILEID   55
6871         {       FATTR4_MOUNTED_ON_FILEID, "FATTR4_MOUNTED_ON_FILEID"    },
6872 #define FATTR4_DIR_NOTIF_DELAY 56
6873         {       FATTR4_DIR_NOTIF_DELAY, "FATTR4_DIR_NOTIF_DELAY"        },
6874 #define FATTR4_DIRENT_NOTIF_DELAY  57
6875         {       FATTR4_DIRENT_NOTIF_DELAY, "FATTR4_DIRENT_NOTIF_DELAY"  },
6876 #define FATTR4_DACL                58
6877         {       FATTR4_DACL, "FATTR4_DACL"                              },
6878 #define FATTR4_SACL                59
6879         {       FATTR4_SACL, "FATTR4_SACL"                              },
6880 #define FATTR4_CHANGE_POLICY       60
6881         {       FATTR4_CHANGE_POLICY, "FATTR4_CHANGE_POLICY"            },
6882 #define FATTR4_FS_STATUS           61
6883         {       FATTR4_FS_STATUS, "FATTR4_FS_STATUS"                    },
6884 #define FATTR4_FS_LAYOUT_TYPE      62
6885         {       FATTR4_FS_LAYOUT_TYPE, "FATTR4_FS_LAYOUT_TYPE"          },
6886 #define FATTR4_LAYOUT_HINT         63
6887         {       FATTR4_LAYOUT_HINT, "FATTR4_LAYOUT_HINT"                },
6888 #define FATTR4_LAYOUT_TYPE         64
6889         {       FATTR4_LAYOUT_TYPE, "FATTR4_LAYOUT_TYPE"                },
6890 #define FATTR4_LAYOUT_BLKSIZE      65
6891         {       FATTR4_LAYOUT_BLKSIZE, "FATTR4_LAYOUT_BLKSIZE"          },
6892 #define FATTR4_LAYOUT_ALIGNMENT    66
6893         {       FATTR4_LAYOUT_ALIGNMENT, "FATTR4_LAYOUT_ALIGNMENT"      },
6894 #define FATTR4_FS_LOCATIONS_INFO   67
6895         {       FATTR4_FS_LOCATIONS_INFO, "FATTR4_FS_LOCATIONS_INFO"    },
6896 #define FATTR4_MDSTHRESHOLD        68
6897         {       FATTR4_MDSTHRESHOLD, "FATTR4_MDSTHRESHOLD"              },
6898 #define FATTR4_RETENTION_GET       69
6899         {       FATTR4_RETENTION_GET, "FATTR4_RETENTION_GET"            },
6900 #define FATTR4_RETENTION_SET       70
6901         {       FATTR4_RETENTION_SET, "FATTR4_RETENTION_SET"            },
6902 #define FATTR4_RETENTEVT_GET       71
6903         {       FATTR4_RETENTEVT_GET, "FATTR4_RETENTEVT_GET"            },
6904 #define FATTR4_RETENTEVT_SET       72
6905         {       FATTR4_RETENTEVT_SET, "FATTR4_RETENTEVT_SET"            },
6906 #define FATTR4_RETENTION_HOLD      73
6907         {       FATTR4_RETENTION_HOLD, "FATTR4_RETENTION_HOLD"          },
6908 #define FATTR4_MODE_SET_MASKED     74
6909         {       FATTR4_MODE_SET_MASKED, "FATTR4_MODE_SET_MASKED"        },
6910 #define FATTR4_SUPPATTR_EXCLCREAT  75
6911         {       FATTR4_SUPPATTR_EXCLCREAT, "FATTR4_SUPPATTR_EXCLCREAT"  },
6912 #define FATTR4_FS_CHARSET_CAP      76
6913         {       FATTR4_FS_CHARSET_CAP, "FATTR4_FS_CHARSET_CAP"          },
6914         {       0,      NULL    }
6915 };
6916
6917 #define FATTR4_BITMAP_ONLY 0
6918 #define FATTR4_FULL_DISSECT 1
6919 /* XXX - What's a good maximum?  Linux appears to use 10.
6920  * FreeBSD appears to use 2.  OpenSolaris appears to use 2.  */
6921 #define MAX_BITMAP_LEN 10
6922
6923 static int
6924 dissect_nfs4_bitmap4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree,
6925                      guint32 bitmap_size, guint32 **bitmap, guint32 *attr_count)
6926 {
6927         guint32 i,j,count,attribute_number,current_bitmap;
6928         guint32 bitmask = 0x00000000;
6929
6930         proto_item *bitmap_item = NULL;
6931         proto_tree *bitmap_tree = NULL;
6932
6933         *attr_count = 0;
6934         if(bitmap_size > 0) {
6935                 *bitmap = se_alloc_array(guint32, bitmap_size);
6936         }
6937
6938         for(i = 0; i < bitmap_size; i++) {
6939                 current_bitmap = tvb_get_ntohl(tvb, offset);
6940                 (*bitmap)[i] = current_bitmap;
6941                 bitmap_item = proto_tree_add_text(tree, tvb, offset, 4, "bitmap[%u] = 0x%08x", i, current_bitmap);
6942                 bitmap_tree = proto_item_add_subtree(bitmap_item, ett_nfs_bitmap4);
6943                 for(count = 0; current_bitmap; current_bitmap >>= 1) {
6944                         count += current_bitmap & 1;
6945                 }
6946                 current_bitmap = (*bitmap)[i];
6947                 proto_tree_add_text(bitmap_tree, tvb, offset, 4, "[%u attribute%s requested]", count, plurality(count, "", "s"));
6948                 *attr_count += count;
6949                 bitmask = 0x00000001;
6950                 for(j = 0; j < 32; j++) {
6951                         attribute_number = 32*i + j;
6952                         if((current_bitmap & bitmask) == bitmask) {
6953                                 proto_tree_add_uint(bitmap_tree,
6954                                 (attribute_number < FATTR4_ACL) ? hf_nfs_mand_attr : hf_nfs_recc_attr,
6955                                 tvb, offset, 4, attribute_number);
6956                         }
6957                         bitmask <<= 1;
6958                 }
6959                 offset += 4;
6960         }
6961
6962         return offset;
6963 }
6964
6965 static int
6966 dissect_nfs4_attr_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint8 flag)
6967 {
6968         guint32 bitmap_size = 0;
6969         guint32 *bitmap = NULL;
6970         guint32 attr_count = 0;
6971
6972         proto_item *ar_item = NULL;
6973         proto_tree *ar_tree = NULL;
6974
6975         bitmap_size = tvb_get_ntohl(tvb, offset);
6976         if(bitmap_size > MAX_BITMAP_LEN) {
6977                 proto_tree_add_text(tree, tvb, offset, 4, "attr_request length is too big: %u", bitmap_size);
6978                 THROW(ReportedBoundsError);
6979         }
6980         tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_size * 4);
6981         offset += 4;
6982
6983         ar_item = proto_tree_add_text(tree, tvb, offset, bitmap_size * 4, "%s", flag?"attr_request":"attrmask");
6984         ar_tree = proto_item_add_subtree(ar_item, ett_nfs_attr_request);
6985         offset = dissect_nfs4_bitmap4(tvb, offset, pinfo, ar_tree, bitmap_size, &bitmap, &attr_count);
6986
6987         return offset;
6988 }
6989
6990 static int
6991 dissect_nfs_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo,
6992                        proto_tree *tree, int type)
6993 {
6994         guint32 bitmap_len;
6995         proto_item *fitem = NULL;
6996         proto_tree *newftree = NULL;
6997         proto_item *attr_fitem = NULL;
6998         proto_tree *attr_newftree = NULL;
6999         guint32 i;
7000         gint j;
7001         guint32 fattr;
7002         guint32 *bitmap=NULL;
7003         guint32 sl;
7004         int attr_vals_offset;
7005
7006         bitmap_len = tvb_get_ntohl(tvb, offset);
7007         if (bitmap_len > MAX_BITMAP_LEN) {
7008                 proto_tree_add_text(tree, tvb, offset, 4,
7009                         "Huge bitmap length: %u", bitmap_len);
7010                 THROW(ReportedBoundsError);
7011         }
7012         tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_len * 4);
7013         fitem = proto_tree_add_text(tree, tvb, offset, 4 + bitmap_len * 4,
7014                 "%s", "attrmask");
7015         offset += 4;
7016
7017         newftree = proto_item_add_subtree(fitem, ett_nfs_bitmap4);
7018
7019         attr_vals_offset = offset + 4 + bitmap_len * 4;
7020
7021         if(bitmap_len)
7022                 bitmap = ep_alloc(bitmap_len * sizeof(guint32));
7023
7024         for (i = 0; i < bitmap_len; i++)
7025         {
7026                 bitmap[i] = tvb_get_ntohl(tvb, offset);
7027
7028                 sl = 0x00000001;
7029
7030                 for (j = 0; j < 32; j++)
7031                 {
7032                         fattr = 32 * i + j;
7033
7034                         if (bitmap[i] & sl)
7035                         {
7036                                 /* switch label if attribute is recommended vs. mandatory */
7037                                 attr_fitem = proto_tree_add_uint(newftree,
7038                                         (fattr < FATTR4_ACL)? hf_nfs_mand_attr: hf_nfs_recc_attr,
7039                                         tvb, offset, 4, fattr);
7040
7041                                 attr_newftree = proto_item_add_subtree(attr_fitem, ett_nfs_bitmap4);
7042
7043                                 if (type == FATTR4_FULL_DISSECT)
7044                                 {
7045                                         /* do a full decode of the arguments for the set flag */
7046                                         switch(fattr)
7047                                         {
7048                                         case FATTR4_SUPPORTED_ATTRS:
7049                                                 attr_vals_offset = dissect_nfs_attributes(tvb,
7050                                                         attr_vals_offset, pinfo, attr_newftree,
7051                                                         FATTR4_BITMAP_ONLY);
7052                                                 break;
7053
7054                                         case FATTR4_TYPE:
7055                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
7056                                                         attr_newftree, hf_nfs_ftype4, attr_vals_offset);
7057                                                 break;
7058
7059                                         case FATTR4_FH_EXPIRE_TYPE:
7060                                                 attr_vals_offset = dissect_nfs_fattr4_fh_expire_type(tvb,
7061                                                         attr_vals_offset, attr_newftree);
7062                                                 break;
7063
7064                                         case FATTR4_CHANGE:
7065                                                 attr_vals_offset = dissect_rpc_uint64(tvb, attr_newftree,
7066                                                         hf_nfs_changeid4, attr_vals_offset);
7067                                                 break;
7068
7069                                         case FATTR4_SIZE:
7070                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7071                                                         attr_newftree, hf_nfs_fattr4_size, attr_vals_offset);
7072                                                 break;
7073
7074                                         case FATTR4_LINK_SUPPORT:
7075                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7076                                                         attr_newftree, hf_nfs_fattr4_link_support,
7077                                                         attr_vals_offset);
7078                                                 break;
7079
7080                                         case FATTR4_SYMLINK_SUPPORT:
7081                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7082                                                         attr_newftree, hf_nfs_fattr4_symlink_support,
7083                                                         attr_vals_offset);
7084                                                 break;
7085
7086                                         case FATTR4_NAMED_ATTR:
7087                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7088                                                         attr_newftree, hf_nfs_fattr4_named_attr, attr_vals_offset);
7089                                                 break;
7090
7091                                         case FATTR4_FSID:
7092                                                 attr_vals_offset = dissect_nfs_fsid4(tvb, attr_vals_offset,
7093                                                         attr_newftree, "fattr4_fsid");
7094                                                 break;
7095
7096                                         case FATTR4_UNIQUE_HANDLES:
7097                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7098                                                         attr_newftree, hf_nfs_fattr4_unique_handles,
7099                                                         attr_vals_offset);
7100                                                 break;
7101
7102                                         case FATTR4_LEASE_TIME:
7103                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
7104                                                         attr_newftree, hf_nfs_fattr4_lease_time,
7105                                                         attr_vals_offset);
7106                                                 break;
7107
7108                                         case FATTR4_RDATTR_ERROR:
7109                                                 attr_vals_offset = dissect_nfs_nfsstat4(tvb,
7110                                                         attr_vals_offset, attr_newftree, NULL);
7111                                                 break;
7112
7113                                         case FATTR4_ACL:
7114                                                 attr_vals_offset = dissect_nfs_fattr4_acl(tvb,
7115                                                         attr_vals_offset, pinfo, attr_newftree);
7116                                                 break;
7117
7118                                         case FATTR4_ACLSUPPORT:
7119                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
7120                                                         attr_newftree, hf_nfs_fattr4_aclsupport,
7121                                                         attr_vals_offset);
7122                                                 break;
7123
7124                                         case FATTR4_ARCHIVE:
7125                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7126                                                         attr_newftree, hf_nfs_fattr4_archive,
7127                                                         attr_vals_offset);
7128                                                 break;
7129
7130                                         case FATTR4_CANSETTIME:
7131                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7132                                                         attr_newftree, hf_nfs_fattr4_cansettime, attr_vals_offset);
7133                                                 break;
7134
7135                                         case FATTR4_CASE_INSENSITIVE:
7136                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7137                                                         attr_newftree, hf_nfs_fattr4_case_insensitive,
7138                                                         attr_vals_offset);
7139                                                 break;
7140
7141                                         case FATTR4_CASE_PRESERVING:
7142                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7143                                                         attr_newftree, hf_nfs_fattr4_case_preserving,
7144                                                         attr_vals_offset);
7145                                                 break;
7146
7147                                         case FATTR4_CHOWN_RESTRICTED:
7148                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7149                                                         attr_newftree, hf_nfs_fattr4_chown_restricted,
7150                                                         attr_vals_offset);
7151                                                 break;
7152
7153                                         case FATTR4_FILEID:
7154                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7155                                                         attr_newftree, hf_nfs_fattr4_fileid, attr_vals_offset);
7156                                                 break;
7157
7158                                         case FATTR4_FILES_AVAIL:
7159                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7160                                                         attr_newftree, hf_nfs_fattr4_files_avail,
7161                                                         attr_vals_offset);
7162                                                 break;
7163
7164                                         case FATTR4_FILEHANDLE:
7165                                                 attr_vals_offset = dissect_nfs_fh4(tvb, attr_vals_offset,
7166                                                         pinfo, attr_newftree, "fattr4_filehandle", NULL);
7167                                                 break;
7168
7169                                         case FATTR4_FILES_FREE:
7170                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7171                                                         attr_newftree, hf_nfs_fattr4_files_free, attr_vals_offset);
7172                                                 break;
7173
7174                                         case FATTR4_FILES_TOTAL:
7175                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7176                                                         attr_newftree, hf_nfs_fattr4_files_total,
7177                                                         attr_vals_offset);
7178                                                 break;
7179
7180                                         case FATTR4_FS_LOCATIONS:
7181                                                 attr_vals_offset = dissect_nfs_fs_locations4(tvb, pinfo,
7182                                                         attr_vals_offset, attr_newftree,
7183                                                         "fattr4_fs_locations");
7184                                                 break;
7185
7186                                         case FATTR4_HIDDEN:
7187                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7188                                                         attr_newftree, hf_nfs_fattr4_hidden, attr_vals_offset);
7189                                                 break;
7190
7191                                         case FATTR4_HOMOGENEOUS:
7192                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7193                                                         attr_newftree, hf_nfs_fattr4_homogeneous,
7194                                                         attr_vals_offset);
7195                                                 break;
7196
7197                                         case FATTR4_MAXFILESIZE:
7198                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7199                                                         attr_newftree, hf_nfs_fattr4_maxfilesize,
7200                                                         attr_vals_offset);
7201                                                 break;
7202
7203                                         case FATTR4_MAXLINK:
7204                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
7205                                                         attr_newftree, hf_nfs_fattr4_maxlink, attr_vals_offset);
7206                                                 break;
7207
7208                                         case FATTR4_MAXNAME:
7209                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
7210                                                         attr_newftree, hf_nfs_fattr4_maxname, attr_vals_offset);
7211                                                 break;
7212
7213                                         case FATTR4_MAXREAD:
7214                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7215                                                         attr_newftree, hf_nfs_fattr4_maxread, attr_vals_offset);
7216                                                 break;
7217
7218                                         case FATTR4_MAXWRITE:
7219                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7220                                                         attr_newftree, hf_nfs_fattr4_maxwrite, attr_vals_offset);
7221                                                 break;
7222
7223                                         case FATTR4_MIMETYPE:
7224                                                 attr_vals_offset = dissect_nfs_utf8string(tvb,
7225                                                         attr_vals_offset, attr_newftree,
7226                                                         hf_nfs_fattr4_mimetype, NULL);
7227                                                 break;
7228
7229                                         case FATTR4_MODE:
7230                                                 attr_vals_offset = dissect_nfs_mode4(tvb,
7231                                                         attr_vals_offset, attr_newftree, "fattr4_mode");
7232                                                 break;
7233
7234                                         case FATTR4_NO_TRUNC:
7235                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7236                                                         attr_newftree, hf_nfs_fattr4_no_trunc, attr_vals_offset);
7237                                                 break;
7238
7239                                         case FATTR4_NUMLINKS:
7240                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
7241                                                         attr_newftree, hf_nfs_fattr4_numlinks, attr_vals_offset);
7242                                                 break;
7243
7244                                         case FATTR4_OWNER:
7245                                                 attr_vals_offset = dissect_nfs_utf8string(tvb,
7246                                                         attr_vals_offset, attr_newftree,
7247                                                         hf_nfs_fattr4_owner,
7248                                                         NULL);
7249                                                 break;
7250
7251                                         case FATTR4_OWNER_GROUP:
7252                                                 attr_vals_offset = dissect_nfs_utf8string(tvb,
7253                                                         attr_vals_offset, attr_newftree,
7254                                                         hf_nfs_fattr4_owner_group, NULL);
7255                                                 break;
7256
7257                                         case FATTR4_QUOTA_AVAIL_HARD:
7258                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7259                                                         attr_newftree, hf_nfs_fattr4_quota_hard, attr_vals_offset);
7260                                                 break;
7261
7262                                         case FATTR4_QUOTA_AVAIL_SOFT:
7263                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7264                                                         attr_newftree, hf_nfs_fattr4_quota_soft, attr_vals_offset);
7265                                                 break;
7266
7267                                         case FATTR4_QUOTA_USED:
7268                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7269                                                         attr_newftree, hf_nfs_fattr4_quota_used, attr_vals_offset);
7270                                                 break;
7271
7272                                         case FATTR4_RAWDEV:
7273                                                 attr_vals_offset = dissect_nfs_specdata4(tvb,
7274                                                         attr_vals_offset, attr_newftree);
7275                                                 break;
7276
7277                                         case FATTR4_SPACE_AVAIL:
7278                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7279                                                         attr_newftree, hf_nfs_fattr4_space_avail,
7280                                                         attr_vals_offset);
7281                                                 break;
7282
7283                                         case FATTR4_SPACE_FREE:
7284                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7285                                                         attr_newftree, hf_nfs_fattr4_space_free, attr_vals_offset);
7286                                                 break;
7287
7288                                         case FATTR4_SPACE_TOTAL:
7289                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7290                                                         attr_newftree, hf_nfs_fattr4_space_total,
7291                                                         attr_vals_offset);
7292                                                 break;
7293
7294                                         case FATTR4_SPACE_USED:
7295                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
7296                                                         attr_newftree, hf_nfs_fattr4_space_used, attr_vals_offset);
7297                                                 break;
7298
7299                                         case FATTR4_SYSTEM:
7300                                                 attr_vals_offset = dissect_rpc_bool(tvb,
7301                                                         attr_newftree, hf_nfs_fattr4_system, attr_vals_offset);
7302                                                 break;
7303
7304                                         case FATTR4_TIME_ACCESS:
7305                                         case FATTR4_TIME_BACKUP:
7306                                         case FATTR4_TIME_CREATE:
7307                                         case FATTR4_TIME_DELTA:
7308                                         case FATTR4_TIME_METADATA:
7309                                         case FATTR4_TIME_MODIFY:
7310                                                 attr_vals_offset = dissect_nfs_nfstime4(tvb, attr_vals_offset,
7311                                                         attr_newftree);
7312                                                 break;
7313
7314                                         case FATTR4_TIME_ACCESS_SET:
7315                                         case FATTR4_TIME_MODIFY_SET:
7316                                                 attr_vals_offset = dissect_nfs_settime4(tvb,
7317                                                         attr_vals_offset, attr_newftree, "settime4");
7318                                                 break;
7319                                         case FATTR4_MOUNTED_ON_FILEID:
7320                                                 attr_vals_offset = dissect_rpc_uint64(tvb, attr_newftree,
7321                                                         hf_nfs_fattr4_mounted_on_fileid, attr_vals_offset);
7322                                                 break;
7323                                         case FATTR4_FS_LAYOUT_TYPE:
7324                                                 attr_vals_offset = dissect_nfs_fs_layout_type(tvb, attr_newftree,
7325                                                                                                         attr_vals_offset);
7326                                                 break;
7327                                         case FATTR4_LAYOUT_BLKSIZE:
7328                                                 attr_vals_offset = dissect_rpc_uint32(tvb, attr_newftree,
7329                                                         hf_nfs_fattr4_layout_blksize, attr_vals_offset);
7330                                                 break;
7331
7332                                         default:
7333                                                 break;
7334                                         }
7335                                 }
7336                         }
7337
7338                         sl <<= 1;
7339                 }
7340
7341                 offset += 4;
7342         }
7343
7344         return offset;
7345 }
7346
7347 static int
7348 dissect_nfs4_attribute(tvbuff_t *tvb, int offset, packet_info *pinfo , proto_tree *tree, guint32 attribute_number)
7349 {
7350         proto_item *attribute_item;
7351         proto_tree *attribute_tree;
7352
7353         attribute_item = proto_tree_add_uint(tree,
7354                         (attribute_number < FATTR4_ACL) ? hf_nfs_mand_attr : hf_nfs_recc_attr,
7355                                          tvb, offset, 0, attribute_number);
7356         attribute_tree = proto_item_add_subtree(attribute_item, ett_nfs4_attribute);
7357
7358         switch(attribute_number) {
7359         case FATTR4_SUPPORTED_ATTRS:
7360                 offset = dissect_nfs4_attr_request(tvb, offset, pinfo, attribute_tree, 0);
7361                 break;
7362
7363         case FATTR4_TYPE:
7364                 offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_ftype4, offset);
7365                 break;
7366
7367         case FATTR4_FH_EXPIRE_TYPE:
7368                 offset = dissect_nfs_fattr4_fh_expire_type(tvb, offset, attribute_tree);
7369                 break;
7370
7371         case FATTR4_CHANGE:
7372                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_changeid4, offset);
7373                 break;
7374
7375         case FATTR4_SIZE:
7376                 offset = dissect_rpc_uint64(tvb,attribute_tree, hf_nfs_fattr4_size, offset);
7377                 break;
7378
7379         case FATTR4_LINK_SUPPORT:
7380                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_link_support, offset);
7381                 break;
7382
7383         case FATTR4_SYMLINK_SUPPORT:
7384                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_symlink_support, offset);
7385                 break;
7386
7387         case FATTR4_NAMED_ATTR:
7388                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_named_attr, offset);
7389                 break;
7390
7391         case FATTR4_FSID:
7392                 offset = dissect_nfs_fsid4(tvb, offset, attribute_tree, "fattr4_fsid");
7393                 break;
7394
7395         case FATTR4_UNIQUE_HANDLES:
7396                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_unique_handles, offset);
7397                 break;
7398
7399         case FATTR4_LEASE_TIME:
7400                 offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_lease_time, offset);
7401                 break;
7402
7403         case FATTR4_RDATTR_ERROR:
7404                 offset = dissect_nfs_nfsstat4(tvb, offset, attribute_tree, NULL);
7405                 break;
7406
7407         case FATTR4_ACL:
7408                 offset = dissect_nfs_fattr4_acl(tvb, offset, pinfo, attribute_tree);
7409                 break;
7410
7411         case FATTR4_ACLSUPPORT:
7412                 offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_aclsupport, offset);
7413                 break;
7414
7415         case FATTR4_ARCHIVE:
7416                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_archive, offset);
7417                 break;
7418
7419         case FATTR4_CANSETTIME:
7420                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_cansettime, offset);
7421                 break;
7422
7423         case FATTR4_CASE_INSENSITIVE:
7424                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_case_insensitive, offset);
7425                 break;
7426
7427         case FATTR4_CASE_PRESERVING:
7428                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_case_preserving, offset);
7429                 break;
7430
7431         case FATTR4_CHOWN_RESTRICTED:
7432                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_chown_restricted, offset);
7433                 break;
7434
7435         case FATTR4_FILEID:
7436                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_fileid, offset);
7437                 break;
7438
7439         case FATTR4_FILES_AVAIL:
7440                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_files_avail, offset);
7441                 break;
7442
7443         case FATTR4_FILEHANDLE:
7444                 offset = dissect_nfs_fh4(tvb, offset, pinfo, attribute_tree, "fattr4_filehandle", NULL);
7445                 break;
7446
7447         case FATTR4_FILES_FREE:
7448                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_files_free, offset);
7449                 break;
7450
7451         case FATTR4_FILES_TOTAL:
7452                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_files_total, offset);
7453                 break;
7454
7455         case FATTR4_FS_LOCATIONS:
7456                 offset = dissect_nfs_fs_locations4(tvb, pinfo, offset, attribute_tree, "fattr4_fs_locations");
7457                 break;
7458
7459         case FATTR4_HIDDEN:
7460                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_hidden, offset);
7461                 break;
7462
7463         case FATTR4_HOMOGENEOUS:
7464                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_homogeneous, offset);
7465                 break;
7466
7467         case FATTR4_MAXFILESIZE:
7468                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_maxfilesize, offset);
7469                 break;
7470
7471         case FATTR4_MAXLINK:
7472                 offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_maxlink, offset);
7473                 break;
7474
7475         case FATTR4_MAXNAME:
7476                 offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_maxname, offset);
7477                 break;
7478
7479         case FATTR4_MAXREAD:
7480                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_maxread, offset);
7481                 break;
7482
7483         case FATTR4_MAXWRITE:
7484                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_maxwrite, offset);
7485                 break;
7486
7487         case FATTR4_MIMETYPE:
7488                 offset = dissect_nfs_utf8string(tvb, offset, attribute_tree, hf_nfs_fattr4_mimetype, NULL);
7489                 break;
7490
7491         case FATTR4_MODE:
7492                 offset = dissect_nfs_mode4(tvb, offset, attribute_tree, "fattr4_mode");
7493                 break;
7494
7495         case FATTR4_NO_TRUNC:
7496                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_no_trunc, offset);
7497                 break;
7498
7499         case FATTR4_NUMLINKS:
7500                 offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_numlinks, offset);
7501                 break;
7502
7503         case FATTR4_OWNER:
7504                 offset = dissect_nfs_utf8string(tvb, offset, attribute_tree, hf_nfs_fattr4_owner, NULL);
7505                 break;
7506
7507         case FATTR4_OWNER_GROUP:
7508                 offset = dissect_nfs_utf8string(tvb, offset, attribute_tree, hf_nfs_fattr4_owner_group, NULL);
7509                 break;
7510
7511         case FATTR4_QUOTA_AVAIL_HARD:
7512                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_quota_hard, offset);
7513                 break;
7514
7515         case FATTR4_QUOTA_AVAIL_SOFT:
7516                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_quota_soft, offset);
7517                 break;
7518
7519         case FATTR4_QUOTA_USED:
7520                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_quota_used, offset);
7521                 break;
7522
7523         case FATTR4_RAWDEV:
7524                 offset = dissect_nfs_specdata4(tvb, offset, attribute_tree);
7525                 break;
7526
7527         case FATTR4_SPACE_AVAIL:
7528                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_avail, offset);
7529                 break;
7530
7531         case FATTR4_SPACE_FREE:
7532                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_free, offset);
7533                 break;
7534
7535         case FATTR4_SPACE_TOTAL:
7536                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_total, offset);
7537                 break;
7538
7539         case FATTR4_SPACE_USED:
7540                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_used, offset);
7541                 break;
7542
7543         case FATTR4_SYSTEM:
7544                 offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_system, offset);
7545                 break;
7546
7547         case FATTR4_TIME_ACCESS:
7548         case FATTR4_TIME_BACKUP:
7549         case FATTR4_TIME_CREATE:
7550         case FATTR4_TIME_DELTA:
7551         case FATTR4_TIME_METADATA:
7552         case FATTR4_TIME_MODIFY:
7553                 offset = dissect_nfs_nfstime4(tvb, offset, attribute_tree);
7554                 break;
7555
7556         case FATTR4_TIME_ACCESS_SET:
7557         case FATTR4_TIME_MODIFY_SET:
7558                 offset = dissect_nfs_settime4(tvb, offset, attribute_tree, "settime4");
7559                 break;
7560
7561         case FATTR4_MOUNTED_ON_FILEID:
7562                 offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_mounted_on_fileid, offset);
7563                 break;
7564
7565         case FATTR4_FS_LAYOUT_TYPE:
7566                 offset = dissect_nfs_fs_layout_type(tvb, attribute_tree, offset);
7567                 break;
7568
7569         case FATTR4_LAYOUT_BLKSIZE:
7570                 offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_layout_blksize, offset);
7571                 break;
7572
7573         default:
7574                 break;
7575         }
7576
7577         return offset;
7578 }
7579
7580 static int
7581 dissect_nfs4_attrlist4(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_, proto_tree *tree _U_,
7582                        guint32 bitmap_size, guint32 *bitmap, guint32 attr_count _U_)
7583 {
7584
7585         guint32 i,j,attribute_number;
7586         guint32 bitmask = 0x00000000;
7587
7588         for(i = 0; i < bitmap_size; i++) {
7589                 bitmask = 0x00000001;
7590                 for(j = 0; j < 32; j++) {
7591                         attribute_number = 32 * i + j;
7592                         if((bitmap[i] & bitmask) == bitmask) {
7593                                 offset = dissect_nfs4_attribute(tvb, offset, pinfo, tree, attribute_number);
7594                         }
7595                         bitmask <<= 1;
7596                 }
7597         }
7598
7599         return offset;
7600 }
7601
7602 static int
7603 dissect_nfs_fattr4_new(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
7604 {
7605         guint32 bitmap_size = 0;
7606         guint32 *bitmap = NULL;
7607         guint32 attr_count = 0;
7608         guint32 attrlist4_size;
7609
7610         proto_item *fattr_item;
7611         proto_tree *fattr_tree;
7612
7613         bitmap_size = tvb_get_ntohl(tvb, offset);
7614         if(bitmap_size > MAX_BITMAP_LEN) {
7615                 proto_tree_add_text(tree, tvb, offset, 4, "attrmask length is too big: %u", bitmap_size);
7616                 THROW(ReportedBoundsError);
7617         }
7618         tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_size * 4);
7619         offset += 4;
7620
7621         fattr_item = proto_tree_add_text(tree, tvb, offset - 4, 4 + bitmap_size * 4, "attrmask");
7622         fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs4_fattr4_attrmask);
7623         offset = dissect_nfs4_bitmap4(tvb, offset, pinfo, fattr_tree, bitmap_size, &bitmap, &attr_count);
7624
7625         attrlist4_size = tvb_get_ntohl(tvb, offset);
7626         offset += 4;
7627         fattr_item = proto_tree_add_text(tree, tvb, offset, attrlist4_size, "attr_vals");
7628         fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs4_fattr4_new_attr_vals);
7629         if(tree) {
7630                 offset = dissect_nfs4_attrlist4(tvb, offset, pinfo, fattr_tree, bitmap_size, bitmap, attr_count);
7631         } else {
7632                 offset += attrlist4_size;
7633         }
7634
7635         return offset;
7636 }
7637
7638 static int
7639 dissect_nfs4_attr_resp_ok(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
7640 {
7641
7642         proto_item *getattr_res_item = NULL;
7643         proto_tree *getattr_res_tree = NULL;
7644
7645         getattr_res_item = proto_tree_add_text(tree, tvb, offset, 0, "obj_attributes");
7646         getattr_res_tree = proto_item_add_subtree(getattr_res_item, ett_nfs4_obj_attrs);
7647
7648         offset = dissect_nfs_fattr4_new(tvb, offset, pinfo, getattr_res_tree);
7649
7650         return offset;
7651 }
7652
7653 static int
7654 dissect_nfs4_attr_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
7655 {
7656         proto_item *getattr_res_item = NULL;
7657         proto_tree *getattr_res_tree = NULL;
7658
7659         getattr_res_item = proto_tree_add_text(tree, tvb, offset, 0, "resok4");
7660         getattr_res_tree = proto_item_add_subtree(getattr_res_item, ett_nfs4_resok4);
7661
7662         offset = dissect_nfs4_attr_resp_ok(tvb, offset, pinfo, getattr_res_tree);
7663
7664         return offset;
7665 }
7666
7667 static int
7668 dissect_nfs_fattr4(tvbuff_t *tvb, int offset, packet_info *pinfo,
7669                    proto_tree *tree)
7670 {
7671         proto_tree *newftree = NULL;
7672         proto_item *fitem = NULL;
7673
7674         fitem = proto_tree_add_text(tree, tvb, offset, 4, "obj_attributes");
7675
7676         newftree = proto_item_add_subtree(fitem, ett_nfs_fattr4);
7677
7678         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
7679                                         FATTR4_FULL_DISSECT);
7680
7681         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_attrlist4);
7682
7683         return offset;
7684 }
7685
7686 static const value_string names_open4_share_access[] = {
7687 #define OPEN4_SHARE_ACCESS_READ 0x00000001
7688         { OPEN4_SHARE_ACCESS_READ, "OPEN4_SHARE_ACCESS_READ" },
7689 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002
7690         { OPEN4_SHARE_ACCESS_WRITE, "OPEN4_SHARE_ACCESS_WRITE" },
7691 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003
7692         { OPEN4_SHARE_ACCESS_BOTH, "OPEN4_SHARE_ACCESS_BOTH" },
7693 #define  OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE     0x0000
7694         { OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE, "OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE" },
7695 #define  OPEN4_SHARE_ACCESS_WANT_READ_DELEG        0x0100
7696         { OPEN4_SHARE_ACCESS_WANT_READ_DELEG, "OPEN4_SHARE_ACCESS_WANT_READ_DELEG" },
7697 #define  OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG       0x0200
7698         { OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG, "OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG" },
7699 #define  OPEN4_SHARE_ACCESS_WANT_ANY_DELEG         0x0300
7700         { OPEN4_SHARE_ACCESS_WANT_ANY_DELEG, "OPEN4_SHARE_ACCESS_WANT_ANY_DELEG" },
7701 #define  OPEN4_SHARE_ACCESS_WANT_NO_DELEG          0x0400
7702         { OPEN4_SHARE_ACCESS_WANT_NO_DELEG, "OPEN4_SHARE_ACCESS_WANT_NO_DELEG" },
7703 #define  OPEN4_SHARE_ACCESS_WANT_CANCEL            0x0500
7704         { OPEN4_SHARE_ACCESS_WANT_CANCEL, "OPEN4_SHARE_ACCESS_WANT_CANCEL" },
7705 #define OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000
7706         { OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL, "OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL"},
7707 #define OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED  0x20000
7708         { OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED, "OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED"},
7709         { 0, NULL }
7710 };
7711
7712 static int
7713 dissect_nfs_open4_share_access(tvbuff_t *tvb, int offset,
7714                                proto_tree *tree)
7715 {
7716         guint share_access;
7717
7718         share_access = tvb_get_ntohl(tvb, offset);
7719         proto_tree_add_uint(tree, hf_nfs_open4_share_access, tvb, offset, 4,
7720                             share_access);
7721         offset += 4;
7722
7723         return offset;
7724 }
7725
7726 static const value_string names_open4_share_deny[] = {
7727 #define OPEN4_SHARE_DENY_NONE 0x00000000
7728         { OPEN4_SHARE_DENY_NONE, "OPEN4_SHARE_DENY_NONE" },
7729 #define OPEN4_SHARE_DENY_READ 0x00000001
7730         { OPEN4_SHARE_DENY_READ, "OPEN4_SHARE_DENY_READ" },
7731 #define OPEN4_SHARE_DENY_WRITE 0x00000002
7732         { OPEN4_SHARE_DENY_WRITE, "OPEN4_SHARE_DENY_WRITE" },
7733 #define OPEN4_SHARE_DENY_BOTH 0x00000003
7734         { OPEN4_SHARE_DENY_BOTH, "OPEN4_SHARE_DENY_BOTH" },
7735         { 0, NULL }
7736 };
7737
7738 static int
7739 dissect_nfs_open4_share_deny(tvbuff_t *tvb, int offset,
7740                              proto_tree *tree)
7741 {
7742         guint deny_access;
7743
7744         deny_access = tvb_get_ntohl(tvb, offset);
7745         proto_tree_add_uint(tree, hf_nfs_open4_share_deny, tvb, offset, 4,
7746                 deny_access);
7747         offset += 4;
7748
7749         return offset;
7750 }
7751
7752 static int
7753 dissect_nfs_open_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
7754 {
7755         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_clientid4, offset);
7756         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_open_owner4);
7757
7758         return offset;
7759 }
7760
7761 static int
7762 dissect_nfs_open_claim_delegate_cur4(tvbuff_t *tvb, int offset,
7763                                      proto_tree *tree)
7764 {
7765         offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
7766         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_component4, NULL);
7767
7768         return offset;
7769 }
7770
7771 #define CLAIM_NULL              0
7772 #define CLAIM_PREVIOUS          1
7773 #define CLAIM_DELEGATE_CUR      2
7774 #define CLAIM_DELEGATE_PREV     3
7775 #define CLAIM_FH                4
7776 #define CLAIM_DELEG_CUR_FH      5
7777 #define CLAIM_DELEG_CUR_PREV_FH 6
7778
7779 static const value_string names_claim_type4[] = {
7780         {       CLAIM_NULL,             "CLAIM_NULL"  },
7781         {       CLAIM_PREVIOUS,         "CLAIM_PREVIOUS" },
7782         {       CLAIM_DELEGATE_CUR,     "CLAIM_DELEGATE_CUR" },
7783         {       CLAIM_DELEGATE_PREV,    "CLAIM_DELEGATE_PREV" },
7784         {       CLAIM_FH,               "CLAIM_FH" },
7785         {       CLAIM_DELEG_CUR_FH,     "CLAIM_DELEG_CUR_FH"},
7786         {       CLAIM_DELEG_CUR_PREV_FH,"CLAIN_DELEG_CUR_PREV_FH"},
7787         {       0, NULL }
7788 };
7789
7790 /* XXX - need a better place to populate name than here, maybe? */
7791 static int
7792 dissect_nfs_open_claim4(tvbuff_t *tvb, int offset, packet_info *pinfo,
7793         proto_tree *tree, char **name)
7794 {
7795         guint open_claim_type4;
7796         proto_item *fitem = NULL;
7797         proto_tree *newftree = NULL;
7798         guint32 name_offset, name_len;
7799
7800         open_claim_type4 = tvb_get_ntohl(tvb, offset);
7801         fitem = proto_tree_add_uint(tree, hf_nfs_open_claim_type4, tvb,
7802                                     offset+0, 4, open_claim_type4);
7803         offset += 4;
7804
7805         if (open_claim_type4==CLAIM_NULL) {
7806                 dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, name);
7807                 if (nfs_file_name_snooping) {
7808                         rpc_call_info_value *civ=pinfo->private_data;
7809
7810                         name_offset=offset+4;
7811                         name_len=tvb_get_ntohl(tvb, offset);
7812
7813                         nfs_name_snoop_add_name(civ->xid, tvb,
7814                                 name_offset, name_len, 0, 0, NULL);
7815                 }
7816         }
7817
7818         if (fitem) {
7819                 newftree = proto_item_add_subtree(fitem, ett_nfs_open_claim4);
7820
7821
7822                 switch(open_claim_type4)
7823                 {
7824                         case CLAIM_NULL:
7825                                 offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, name);
7826                                 break;
7827
7828                         case CLAIM_PREVIOUS:
7829                                 offset = dissect_rpc_uint32(tvb, newftree,
7830                                         hf_nfs_delegate_type, offset);
7831                                 break;
7832
7833                         case CLAIM_DELEGATE_CUR:
7834                                 offset = dissect_nfs_open_claim_delegate_cur4(tvb, offset,
7835                                         newftree);
7836                                 break;
7837
7838                         case CLAIM_DELEGATE_PREV:
7839                                 offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
7840                                 break;
7841
7842                         default:
7843                                 break;
7844                 }
7845         }
7846
7847         return offset;
7848 }
7849
7850 static const value_string names_createmode4[] = {
7851         {       UNCHECKED4,     "UNCHECKED4" },
7852         {       GUARDED4,       "GUARDED4" },
7853         {       EXCLUSIVE4,     "EXCLUSIVE4" },
7854         {       EXCLUSIVE4_1,   "EXCLUSIVE4_1" },
7855         {       0, NULL }
7856 };
7857
7858 static int
7859 dissect_nfs_createhow4(tvbuff_t *tvb, int offset, packet_info *pinfo,
7860                        proto_tree *tree)
7861 {
7862         guint mode;
7863
7864         mode = tvb_get_ntohl(tvb, offset);
7865         proto_tree_add_uint(tree, hf_nfs_createmode4, tvb, offset, 4, mode);
7866         offset += 4;
7867
7868         switch(mode)
7869         {
7870         case UNCHECKED4:
7871         case GUARDED4:
7872                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree);
7873                 break;
7874
7875         case EXCLUSIVE4:
7876                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_verifier4, offset);
7877                 break;
7878
7879         case EXCLUSIVE4_1:
7880                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_verifier4, offset);
7881                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree);
7882                 break;
7883
7884         default:
7885                 break;
7886         }
7887
7888         return offset;
7889 }
7890
7891 #define OPEN4_NOCREATE                          0
7892 #define OPEN4_CREATE                            1
7893 static const value_string names_opentype4[] = {
7894         {       OPEN4_NOCREATE, "OPEN4_NOCREATE"  },
7895         {       OPEN4_CREATE,   "OPEN4_CREATE" },
7896         {       0, NULL }
7897 };
7898
7899 static int
7900 dissect_nfs_openflag4(tvbuff_t *tvb, int offset, packet_info *pinfo,
7901         proto_tree *tree)
7902 {
7903         guint opentype4;
7904         proto_item *fitem = NULL;
7905         proto_tree *newftree = NULL;
7906
7907         opentype4 = tvb_get_ntohl(tvb, offset);
7908         fitem = proto_tree_add_uint(tree, hf_nfs_opentype4, tvb,
7909                 offset+0, 4, opentype4);
7910         offset += 4;
7911
7912         if (fitem) {
7913                 newftree = proto_item_add_subtree(fitem, ett_nfs_opentype4);
7914
7915                 switch(opentype4)
7916                 {
7917                         case OPEN4_CREATE:
7918                                 offset = dissect_nfs_createhow4(tvb, offset, pinfo, newftree);
7919                                 break;
7920
7921                         default:
7922                                 break;
7923                 }
7924         }
7925
7926         return offset;
7927 }
7928
7929 static int
7930 dissect_nfs_clientaddr4(tvbuff_t *tvb, int offset, proto_tree *tree)
7931 {
7932         char *universal_ip_address = NULL;
7933         char *protocol = NULL;
7934         guint b1, b2, b3, b4, b5, b6, b7, b8, b9, b10;
7935         guint16 port;
7936         int addr_offset;
7937
7938         offset = dissect_rpc_string(tvb, tree, hf_nfs_r_netid, offset, &protocol);
7939         addr_offset = offset;
7940         offset = dissect_rpc_string(tvb, tree, hf_nfs_r_addr, offset, &universal_ip_address);
7941
7942         if(strlen(protocol) == 3 && strncmp(protocol,"tcp",3) == 0) {
7943                 if (universal_ip_address && sscanf(universal_ip_address, "%u.%u.%u.%u.%u.%u",
7944                                                    &b1, &b2, &b3, &b4, &b5, &b6) == 6) {
7945                         /* IPv4: h1.h2.h3.h4.p1.p2 */
7946                         port = (b5<<8) | b6;
7947                         proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset,
7948                                 "[callback IPv4 address %u.%u.%u.%u, protocol=%s, port=%u]",
7949                                 b1, b2, b3, b4, protocol, port);
7950                 } else if (universal_ip_address && sscanf(universal_ip_address, "%u.%u",
7951                                                    &b1, &b2) == 2) {
7952                         /* Some clients (linux) sometimes send only the port. */
7953                         port = (b1<<8) | b2;
7954                         proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset,
7955                                 "[callback ip address NOT SPECIFIED, protocol=%s, port=%u]", protocol, port);
7956                 } else if (universal_ip_address && sscanf(universal_ip_address,
7957                                                 "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x.%u.%u",
7958                                                 &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &b9, &b10) == 10) {
7959                         port = (b9<<8) | b10;
7960                         proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset,
7961                                 "[callback IPv6 address %2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x, protocol=%s, port=%u]",
7962                                 b1, b2, b3, b4, b5, b6, b7, b8, protocol, port);
7963                 } else {
7964                         proto_tree_add_text(tree, tvb, addr_offset, offset-addr_offset, "[Invalid address]");
7965                 }
7966         }
7967         return offset;
7968 }
7969
7970
7971 static int
7972 dissect_nfs_cb_client4(tvbuff_t *tvb, int offset, proto_tree *tree)
7973 {
7974         proto_tree *cb_location = NULL;
7975         proto_item *fitem = NULL;
7976         int cbprog;
7977
7978         cbprog = tvb_get_ntohl(tvb, offset);
7979         reg_callback(cbprog);
7980         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_cb_program, offset);
7981         fitem = proto_tree_add_text(tree, tvb, offset, 0, "cb_location");
7982
7983         if (fitem)
7984         {
7985                 cb_location = proto_item_add_subtree(fitem, ett_nfs_clientaddr4);
7986                 offset = dissect_nfs_clientaddr4(tvb, offset, cb_location);
7987         }
7988
7989         return offset;
7990 }
7991
7992 static const value_string names_stable_how4[] = {
7993 #define UNSTABLE4 0
7994         {       UNSTABLE4,      "UNSTABLE4"     },
7995 #define DATA_SYNC4 1
7996         {       DATA_SYNC4,     "DATA_SYNC4"    },
7997 #define FILE_SYNC4 2
7998         {       FILE_SYNC4,     "FILE_SYNC4"    },
7999         {       0,      NULL    }
8000 };
8001
8002 static int
8003 dissect_nfs_stable_how4(tvbuff_t *tvb, int offset,
8004         proto_tree *tree, const char *name)
8005 {
8006         guint stable_how4;
8007
8008         stable_how4 = tvb_get_ntohl(tvb, offset);
8009         proto_tree_add_uint_format(tree, hf_nfs_stable_how4, tvb,
8010                         offset+0, 4, stable_how4, "%s: %s (%u)", name,
8011                         val_to_str(stable_how4, names_stable_how4, "%u"), stable_how4);
8012         offset += 4;
8013
8014         return offset;
8015 }
8016
8017 static const value_string names_nfsv4_operation[] = {
8018         {       NFS4_OP_ACCESS,                 "ACCESS"                },
8019         {       NFS4_OP_CLOSE,                  "CLOSE"                 },
8020         {       NFS4_OP_COMMIT,                 "COMMIT"                },
8021         {       NFS4_OP_CREATE,                 "CREATE"                },
8022         {       NFS4_OP_DELEGPURGE,             "DELEGPURGE"            },
8023         {       NFS4_OP_DELEGRETURN,            "DELEGRETURN"           },
8024         {       NFS4_OP_GETATTR,                "GETATTR"               },
8025         {       NFS4_OP_GETFH,                  "GETFH"                 },
8026         {       NFS4_OP_LINK,                   "LINK"                  },
8027         {       NFS4_OP_LOCK,                   "LOCK"                  },
8028         {       NFS4_OP_LOCKT,                  "LOCKT"                 },
8029         {       NFS4_OP_LOCKU,                  "LOCKU"                 },
8030         {       NFS4_OP_LOOKUP,                 "LOOKUP"                },
8031         {       NFS4_OP_LOOKUPP,                "LOOKUPP"               },
8032         {       NFS4_OP_NVERIFY,                "NVERIFY"               },
8033         {       NFS4_OP_OPEN,                   "OPEN"                  },
8034         {       NFS4_OP_OPENATTR,               "OPENATTR"              },
8035         {       NFS4_OP_OPEN_CONFIRM,           "OPEN_CONFIRM"          },
8036         {       NFS4_OP_OPEN_DOWNGRADE,         "OPEN_DOWNGRADE"        },
8037         {       NFS4_OP_PUTFH,                  "PUTFH"                 },
8038         {       NFS4_OP_PUTPUBFH,               "PUTPUBFH"              },
8039         {       NFS4_OP_PUTROOTFH,              "PUTROOTFH"             },
8040         {       NFS4_OP_READ,                   "READ"                  },
8041         {       NFS4_OP_READDIR,                "READDIR"               },
8042         {       NFS4_OP_READLINK,               "READLINK"              },
8043         {       NFS4_OP_REMOVE,                 "REMOVE"                },
8044         {       NFS4_OP_RENAME,                 "RENAME"                },
8045         {       NFS4_OP_RENEW,                  "RENEW"                 },
8046         {       NFS4_OP_RESTOREFH,              "RESTOREFH"             },
8047         {       NFS4_OP_SAVEFH,                 "SAVEFH"                },
8048         {       NFS4_OP_SECINFO,                "SECINFO"               },
8049         {       NFS4_OP_SETATTR,                "SETATTR"               },
8050         {       NFS4_OP_SETCLIENTID,            "SETCLIENTID"           },
8051         {       NFS4_OP_SETCLIENTID_CONFIRM,    "SETCLIENTID_CONFIRM"   },
8052         {       NFS4_OP_VERIFY,                 "VERIFY"                },
8053         {       NFS4_OP_WRITE,                  "WRITE"                 },
8054         {       NFS4_OP_RELEASE_LOCKOWNER,      "RELEASE_LOCKOWNER"     },
8055         {       NFS4_OP_EXCHANGE_ID,            "EXCHANGE_ID"           },
8056         {       NFS4_OP_CREATE_SESSION,         "CREATE_SESSION"        },
8057         {       NFS4_OP_DESTROY_SESSION,        "DESTROY_SESSION"       },
8058         {       NFS4_OP_FREE_STATEID,           "FREE_STATEID"          },
8059         {       NFS4_OP_GET_DIR_DELEGATION,     "GET_DIR_DELEGATION"    },
8060         {       NFS4_OP_GETDEVINFO,             "GETDEVINFO"            },
8061         {       NFS4_OP_GETDEVLIST,             "GETDEVLIST"            },
8062         {       NFS4_OP_LAYOUTCOMMIT,           "LAYOUTCOMMIT"          },
8063         {       NFS4_OP_LAYOUTGET,              "LAYOUTGET"             },
8064         {       NFS4_OP_LAYOUTRETURN,           "LAYOUTRETURN"          },
8065         {       NFS4_OP_SECINFO_NO_NAME,        "SECINFO_NO_NAME"       },
8066         {       NFS4_OP_SEQUENCE,               "SEQUENCE"              },
8067         {       NFS4_OP_SET_SSV,                "SET_SSV"               },
8068         {       NFS4_OP_TEST_STATEID,           "TEST_STATEID"          },
8069         {       NFS4_OP_WANT_DELEGATION,        "WANT_DELEG"            },
8070         {       NFS4_OP_DESTROY_CLIENTID,       "DESTROY_CLIENTID"      },
8071         {       NFS4_OP_RECLAIM_COMPLETE,       "RECLAIM_COMPLETE"      },
8072         {       NFS4_OP_ILLEGAL,                "ILLEGAL"               },
8073         {       0,      NULL }
8074 };
8075 static value_string_ext names_nfsv4_operation_ext = VALUE_STRING_EXT_INIT(names_nfsv4_operation);
8076
8077 static gint *nfsv4_operation_ett[] =
8078 {
8079          &ett_nfs_access4 ,
8080          &ett_nfs_access_supp4,
8081          &ett_nfs_close4 ,
8082          &ett_nfs_commit4 ,
8083          &ett_nfs_create4 ,
8084          &ett_nfs_delegpurge4 ,
8085          &ett_nfs_delegreturn4 ,
8086          &ett_nfs_getattr4 ,
8087          &ett_nfs_getfh4 ,
8088          &ett_nfs_link4 ,
8089          &ett_nfs_lock4 ,
8090          &ett_nfs_lockt4 ,
8091          &ett_nfs_locku4 ,
8092          &ett_nfs_lookup4 ,
8093          &ett_nfs_lookupp4 ,
8094          &ett_nfs_nverify4 ,
8095          &ett_nfs_open4 ,
8096          &ett_nfs_openattr4 ,
8097          &ett_nfs_open_confirm4 ,
8098          &ett_nfs_open_downgrade4 ,
8099          &ett_nfs_putfh4 ,
8100          &ett_nfs_putpubfh4 ,
8101          &ett_nfs_putrootfh4 ,
8102          &ett_nfs_read4 ,
8103          &ett_nfs_readdir4 ,
8104          &ett_nfs_readlink4 ,
8105          &ett_nfs_remove4 ,
8106          &ett_nfs_rename4 ,
8107          &ett_nfs_renew4 ,
8108          &ett_nfs_restorefh4 ,
8109          &ett_nfs_savefh4 ,
8110          &ett_nfs_secinfo4 ,
8111          &ett_nfs_setattr4 ,
8112          &ett_nfs_setclientid4 ,
8113          &ett_nfs_setclientid_confirm4 ,
8114          &ett_nfs_verify4 ,
8115          &ett_nfs_write4,
8116          &ett_nfs_release_lockowner4,
8117          NULL, /* backchannel_ctl */
8118          NULL, /* bind connection to session */
8119          &ett_nfs_exchange_id4,
8120          &ett_nfs_create_session4,
8121          &ett_nfs_destroy_session4,
8122          NULL, /* free stateid */
8123          NULL, /* get dir delegation */
8124          &ett_nfs_getdevinfo4,
8125          &ett_nfs_getdevlist4,
8126          &ett_nfs_layoutcommit4,
8127          &ett_nfs_layoutget4,
8128          &ett_nfs_layoutreturn4,
8129          NULL, /* secinfo no name */
8130          &ett_nfs_sequence4,
8131          NULL, /* set ssv */
8132          NULL, /* test stateid */
8133          NULL, /* want delegation */
8134          NULL, /* destroy clientid */
8135          &ett_nfs_reclaim_complete4
8136 };
8137
8138 static int
8139 dissect_nfs_entry4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
8140                    proto_tree *tree)
8141 {
8142         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie4, offset);
8143         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_component4, NULL);
8144         offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree);
8145
8146         return offset;
8147 }
8148
8149 static int
8150 dissect_nfs_dirlist4(tvbuff_t *tvb, int offset, packet_info *pinfo,
8151                      proto_tree *tree)
8152 {
8153         proto_tree *newftree = NULL;
8154         proto_tree *fitem = NULL;
8155
8156         fitem = proto_tree_add_text(tree, tvb, offset, 0, "Directory Listing");
8157         newftree = proto_item_add_subtree(fitem, ett_nfs_dirlist4);
8158
8159         offset = dissect_rpc_list(tvb, pinfo, newftree, offset, dissect_nfs_entry4);
8160         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_dirlist4_eof, offset);
8161
8162         return offset;
8163 }
8164
8165 static int
8166 dissect_nfs_change_info4(tvbuff_t *tvb, int offset,
8167                          proto_tree *tree, const char *name)
8168 {
8169         proto_tree *newftree = NULL;
8170         proto_tree *fitem = NULL;
8171
8172         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
8173         newftree = proto_item_add_subtree(fitem, ett_nfs_change_info4);
8174
8175         offset = dissect_rpc_bool(tvb, newftree,
8176                         hf_nfs_change_info4_atomic, offset);
8177         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_changeid4_before,
8178                         offset);
8179         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_changeid4_after,
8180                         offset);
8181
8182
8183
8184         return offset;
8185 }
8186
8187 static const value_string names_nfs_lock_type4[] =
8188 {
8189 #define READ_LT 1
8190         {       READ_LT,        "READ_LT"       },
8191 #define WRITE_LT 2
8192         {       WRITE_LT,       "WRITE_LT"      },
8193 #define READW_LT 3
8194         {       READW_LT,       "READW_LT"      },
8195 #define WRITEW_LT 4
8196         {       WRITEW_LT,      "WRITEW_LT"     },
8197 #define RELEASE_STATE 5
8198         {       RELEASE_STATE,  "RELEASE_STATE" },
8199         {       0,      NULL    }
8200 };
8201
8202 static int
8203 dissect_nfs_lock4denied(tvbuff_t *tvb, int offset, proto_tree *tree)
8204 {
8205         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset4, offset);
8206         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_length4, offset);
8207         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_type4, offset);
8208         offset = dissect_nfs_lock_owner4(tvb, offset, tree);
8209
8210         return offset;
8211 }
8212
8213
8214 static const value_string names_open4_result_flags[] = {
8215 #define OPEN4_RESULT_MLOCK 0x00000001
8216         { OPEN4_RESULT_MLOCK, "OPEN4_RESULT_MLOCK" },
8217 #define OPEN4_RESULT_CONFIRM 0x00000002
8218         { OPEN4_RESULT_CONFIRM, "OPEN4_RESULT_CONFIRM" },
8219 #define OPEN4_RESULT_LOCKTYPE_POSIX 0x00000004
8220         { OPEN4_RESULT_LOCKTYPE_POSIX, "OPEN4_RESULT_LOCKTYPE_POSIX" },
8221         { 0, NULL }
8222 };
8223
8224 static int
8225 dissect_nfs_open4_rflags(tvbuff_t *tvb, int offset,
8226                          proto_tree *tree, const char *name)
8227 {
8228         guint rflags;
8229         proto_item *rflags_item = NULL;
8230         proto_item *rflags_tree = NULL;
8231
8232         rflags = tvb_get_ntohl(tvb, offset);
8233
8234         if (tree)
8235         {
8236                 rflags_item = proto_tree_add_text(tree, tvb, offset, 4,
8237                         "%s: 0x%08x", name, rflags);
8238
8239                 {
8240                         rflags_tree = proto_item_add_subtree(rflags_item,
8241                                 ett_nfs_open4_result_flags);
8242
8243                         proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
8244                                         decode_enumerated_bitfield(rflags, OPEN4_RESULT_MLOCK, 2,
8245                                         names_open4_result_flags, "%s"));
8246
8247                         proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
8248                                         decode_enumerated_bitfield(rflags, OPEN4_RESULT_CONFIRM, 2,
8249                                         names_open4_result_flags, "%s"));
8250                 }
8251         }
8252
8253         offset += 4;
8254
8255         return offset;
8256 }
8257
8258 static int
8259 dissect_nfs_stateid4(tvbuff_t *tvb, int offset,
8260                      proto_tree *tree, guint16 *hash)
8261 {
8262         proto_item *fitem = NULL;
8263         proto_item *sh_item;
8264         proto_tree *newftree = NULL;
8265         guint16 sid_hash;
8266         guint8 *sidh_array;
8267
8268
8269         if(tree){
8270                 fitem = proto_tree_add_text(tree, tvb, offset, 4, "stateid");
8271                 newftree = proto_item_add_subtree(fitem, ett_nfs_stateid4);
8272         }
8273
8274         sidh_array = tvb_get_string(tvb, offset, 16);
8275         sid_hash = crc16_ccitt(sidh_array, 16);
8276
8277         sh_item=proto_tree_add_uint(newftree, hf_nfs_stateid4_hash, tvb, offset,
8278                                                                         +               16, sid_hash);
8279         PROTO_ITEM_SET_GENERATED(sh_item);
8280
8281
8282         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset);
8283
8284         proto_tree_add_item(newftree, hf_nfs_stateid4_other, tvb, offset, 12, FALSE);
8285         offset+=12;
8286
8287         if (hash)
8288                 *hash=sid_hash;
8289
8290
8291         return offset;
8292 }
8293
8294 static int
8295 dissect_nfs_open_read_delegation4(tvbuff_t *tvb, int offset,
8296                         packet_info *pinfo, proto_tree *tree)
8297 {
8298         offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
8299         offset = dissect_rpc_bool(tvb, tree, hf_nfs_recall4, offset);
8300         offset = dissect_nfs_ace4(tvb, offset, pinfo, tree);
8301
8302         return offset;
8303 }
8304
8305 static int
8306 dissect_nfs_modified_limit4(tvbuff_t *tvb, int offset, proto_tree *tree)
8307 {
8308         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_num_blocks, offset);
8309         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_bytes_per_block, offset);
8310
8311         return offset;
8312 }
8313
8314 /*
8315  * No FULL DISECT yet.
8316  */
8317 static int
8318 dissect_nfs_state_protect_bitmap4(tvbuff_t *tvb, int offset,
8319                                   proto_tree *tree)
8320 {
8321         guint32 bitmap_len;
8322         proto_item *fitem = NULL;
8323         proto_tree *newftree = NULL;
8324         proto_item *op_fitem = NULL;
8325         proto_tree *op_newftree = NULL;
8326         guint32 *bitmap=NULL;
8327         guint32 fattr;
8328         guint32 i;
8329         gint j;
8330         guint32 sl;
8331
8332         bitmap_len = tvb_get_ntohl(tvb, offset);
8333         if (bitmap_len > MAX_BITMAP_LEN) {
8334                 proto_tree_add_text(tree, tvb, offset, 4,
8335                                 "Huge bitmap length: %u", bitmap_len);
8336                 THROW(ReportedBoundsError);
8337         }
8338         tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_len * 4);
8339         fitem = proto_tree_add_text(tree, tvb, offset, 4 + bitmap_len * 4,
8340                                         "%s", "operation mask");
8341         offset += 4;
8342         if (fitem == NULL) return offset;
8343
8344         newftree = proto_item_add_subtree(fitem, ett_nfs_bitmap4);
8345         if (newftree == NULL) return offset;
8346
8347         if(bitmap_len)
8348                 bitmap = ep_alloc(bitmap_len * sizeof(guint32));
8349
8350         if (bitmap == NULL) return offset;
8351         for (i = 0; i < bitmap_len; i++) {
8352                 bitmap[i] = tvb_get_ntohl(tvb, offset);
8353                 sl = 0x00000001;
8354                 for (j = 0; j < 32; j++) {
8355                         fattr = 32 * i + j;
8356                         if (bitmap[i] & sl) {
8357                                 op_fitem = proto_tree_add_uint(newftree,
8358                                 hf_nfs_recc_attr, tvb, offset, 4, fattr);
8359                                 if (op_fitem == NULL) break;
8360                                         op_newftree = proto_item_add_subtree(op_fitem, ett_nfs_bitmap4);
8361                                 if (op_newftree == NULL) break;
8362                         }
8363                         sl <<= 1;
8364                 }
8365                 offset += 4;
8366         }
8367         return offset;
8368 }
8369
8370 #define SP4_NONE                                0
8371 #define SP4_MACH_CRED                           1
8372 #define SP4_SSV                                 2
8373 static const value_string names_state_protect_how4[] = {
8374         {       SP4_NONE,       "SP4_NONE"  },
8375         {       SP4_MACH_CRED,  "SP4_MACH_CRED" },
8376         {       SP4_SSV,        "SP4_SSV" },
8377         {       0,              NULL }
8378 };
8379
8380 static int
8381 dissect_nfs_state_protect_ops4(tvbuff_t *tvb, int offset, proto_tree *tree)
8382 {
8383         offset = dissect_nfs_state_protect_bitmap4(tvb, offset, tree);
8384         offset = dissect_nfs_state_protect_bitmap4(tvb, offset, tree);
8385         return offset;
8386 }
8387
8388 static int
8389 dissect_nfs_ssv_sp_parms4(tvbuff_t *tvb, int offset, proto_tree *tree)
8390 {
8391         offset = dissect_nfs_state_protect_ops4(tvb, offset, tree);
8392         offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
8393                                 hf_nfs_sec_oid4, FALSE, 0, FALSE, NULL, NULL);
8394         offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
8395                                 hf_nfs_sec_oid4, FALSE, 0, FALSE, NULL, NULL);
8396         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_state_protect_window, offset);
8397         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_state_protect_num_gss_handles, offset);
8398         return offset;
8399 }
8400
8401 static int
8402 dissect_nfs_ssv_prot_info4(tvbuff_t *tvb, int offset, proto_tree *tree)
8403 {
8404         offset = dissect_nfs_state_protect_ops4(tvb, offset, tree);
8405         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_prot_info4_hash_alg, offset);
8406         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_prot_info4_encr_alg, offset);
8407         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_prot_info4_svv_length, offset);
8408         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_prot_info4_spi_window, offset);
8409         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_gsshandle4);
8410         return offset;
8411 }
8412
8413 static int
8414 dissect_nfs_state_protect4_a(tvbuff_t *tvb, int offset, proto_tree *tree)
8415 {
8416         guint stateprotect;
8417
8418         stateprotect = tvb_get_ntohl(tvb, offset);
8419         proto_tree_add_uint(tree, hf_nfs_state_protect_how4, tvb, offset+0, 4,
8420                             stateprotect);
8421         offset += 4;
8422
8423         switch(stateprotect) {
8424                 case SP4_NONE:
8425                         break;
8426                 case SP4_MACH_CRED:
8427                         offset = dissect_nfs_state_protect_ops4(tvb, offset, tree);
8428                         break;
8429                 case SP4_SSV:
8430                         offset = dissect_nfs_ssv_sp_parms4(tvb, offset, tree);
8431                         break;
8432                 default:
8433                         break;
8434         }
8435         return offset;
8436 }
8437
8438 static int
8439 dissect_nfs_state_protect4_r(tvbuff_t *tvb, int offset, proto_tree *tree)
8440 {
8441         guint stateprotect;
8442
8443         stateprotect = tvb_get_ntohl(tvb, offset);
8444         proto_tree_add_uint(tree, hf_nfs_state_protect_how4, tvb, offset+0, 4,
8445                             stateprotect);
8446         offset += 4;
8447
8448         switch(stateprotect) {
8449                 case SP4_NONE:
8450                         break;
8451                 case SP4_MACH_CRED:
8452                         offset = dissect_nfs_state_protect_ops4(tvb, offset, tree);
8453                         break;
8454                 case SP4_SSV:
8455                         offset = dissect_nfs_ssv_prot_info4(tvb, offset, tree);
8456                         break;
8457                 default:
8458                         break;
8459         }
8460         return offset;
8461 }
8462
8463 #define NFS_LIMIT_SIZE                                          1
8464 #define NFS_LIMIT_BLOCKS                                        2
8465 static const value_string names_limit_by4[] = {
8466         {       NFS_LIMIT_SIZE,         "NFS_LIMIT_SIZE"  },
8467         {       NFS_LIMIT_BLOCKS,       "NFS_LIMIT_BLOCKS" },
8468         {       0,                      NULL }
8469 };
8470
8471 static int
8472 dissect_nfs_space_limit4(tvbuff_t *tvb, int offset,
8473                          proto_tree *tree)
8474 {
8475         guint limitby;
8476
8477         limitby = tvb_get_ntohl(tvb, offset);
8478         proto_tree_add_uint(tree, hf_nfs_limit_by4, tvb, offset+0, 4, limitby);
8479         offset += 4;
8480
8481         switch(limitby)
8482         {
8483         case NFS_LIMIT_SIZE:
8484                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_filesize,
8485                         offset);
8486                 break;
8487
8488         case NFS_LIMIT_BLOCKS:
8489                 offset = dissect_nfs_modified_limit4(tvb, offset, tree);
8490                 break;
8491
8492         default:
8493                 break;
8494         }
8495
8496         return offset;
8497 }
8498
8499 static int
8500 dissect_nfs_open_write_delegation4(tvbuff_t *tvb, int offset,
8501         packet_info *pinfo, proto_tree *tree)
8502 {
8503         offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
8504         offset = dissect_rpc_bool(tvb, tree, hf_nfs_recall, offset);
8505         offset = dissect_nfs_space_limit4(tvb, offset, tree);
8506         offset = dissect_nfs_ace4(tvb, offset, pinfo, tree);
8507
8508         return offset;
8509 }
8510
8511 #define OPEN_DELEGATE_NONE 0
8512 #define OPEN_DELEGATE_READ 1
8513 #define OPEN_DELEGATE_WRITE 2
8514 #define OPEN_DELEGATE_NONE_EXT 3 /* new to v4.1 */
8515 static const value_string names_open_delegation_type4[] = {
8516         {       OPEN_DELEGATE_NONE,     "OPEN_DELEGATE_NONE" },
8517         {       OPEN_DELEGATE_READ,     "OPEN_DELEGATE_READ" },
8518         {       OPEN_DELEGATE_WRITE,    "OPEN_DELEGATE_WRITE" },
8519         {       OPEN_DELEGATE_NONE_EXT, "OPEN_DELEGATE_NONE_EXT"},
8520         {       0,      NULL }
8521 };
8522
8523 static int
8524 dissect_nfs_open_delegation4(tvbuff_t *tvb, int offset, packet_info *pinfo,
8525         proto_tree *tree)
8526 {
8527         guint delegation_type;
8528         proto_tree *newftree = NULL;
8529         proto_item *fitem = NULL;
8530
8531         delegation_type = tvb_get_ntohl(tvb, offset);
8532         fitem = proto_tree_add_uint(tree, hf_nfs_open_delegation_type4, tvb,
8533                 offset+0, 4, delegation_type);
8534         offset += 4;
8535
8536         if (fitem) {
8537                 newftree = proto_item_add_subtree(fitem, ett_nfs_open_delegation4);
8538
8539                 switch(delegation_type)
8540                 {
8541                 case OPEN_DELEGATE_NONE:
8542                         break;
8543
8544                 case OPEN_DELEGATE_READ:
8545                         offset = dissect_nfs_open_read_delegation4(tvb, offset, pinfo,
8546                                 newftree);
8547                         break;
8548
8549                 case OPEN_DELEGATE_WRITE:
8550                         offset = dissect_nfs_open_write_delegation4(tvb, offset, pinfo,
8551                                 newftree);
8552                         break;
8553
8554                 default:
8555                         break;
8556                 }
8557         }
8558
8559         return offset;
8560 }
8561
8562 static int
8563 dissect_nfs_rpcsec_gss_info(tvbuff_t *tvb, int offset, proto_tree *tree)
8564 {
8565         offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
8566             hf_nfs_sec_oid4, FALSE, 0, FALSE, NULL, NULL);
8567         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_qop4, offset);
8568         offset = dissect_rpc_uint32(tvb, tree,
8569                 hf_nfs_secinfo_rpcsec_gss_info_service, offset);
8570
8571         return offset;
8572 }
8573
8574 static int
8575 dissect_nfs_open_to_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
8576 {
8577         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_seqid4, offset);
8578         offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
8579         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_seqid4, offset);
8580         offset = dissect_nfs_lock_owner4(tvb, offset, tree);
8581
8582         return offset;
8583 }
8584
8585 static int
8586 dissect_nfs_exist_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
8587 {
8588         offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
8589         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_seqid4, offset);
8590
8591         return offset;
8592 }
8593
8594 static int
8595 dissect_nfs_locker4(tvbuff_t *tvb, int offset, proto_tree *tree)
8596 {
8597         guint new_lock_owner;
8598
8599         new_lock_owner = tvb_get_ntohl(tvb, offset);
8600         offset = dissect_rpc_bool(tvb, tree, hf_nfs_new_lock_owner, offset);
8601
8602         if (new_lock_owner)
8603                 offset = dissect_nfs_open_to_lock_owner4(tvb, offset, tree);
8604         else
8605                 offset = dissect_nfs_exist_lock_owner4(tvb, offset, tree);
8606
8607         return offset;
8608 }
8609
8610 static int
8611 dissect_nfs_client_id4(tvbuff_t *tvb, int offset, proto_tree *tree)
8612 {
8613         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_verifier4, offset);
8614         offset = dissect_rpc_data(tvb, tree, hf_nfs_client_id4_id, offset);
8615
8616         return offset;
8617 }
8618
8619
8620 static int
8621 dissect_nfs_newtime4(tvbuff_t *tvb, int offset, proto_tree *tree)
8622 {
8623         guint new_time;
8624
8625         new_time = tvb_get_ntohl(tvb, offset);
8626         offset = dissect_rpc_bool(tvb, tree, hf_nfs_newtime4, offset);
8627
8628         if (new_time) {
8629                 offset = dissect_nfs_nfstime4(tvb, offset, tree);
8630         }
8631
8632         return offset;
8633 }
8634
8635 static int
8636 dissect_nfs_newsize4(tvbuff_t *tvb, int offset, proto_tree *tree)
8637 {
8638         guint new_size;
8639
8640         new_size = tvb_get_ntohl(tvb, offset);
8641         offset = dissect_rpc_bool(tvb, tree, hf_nfs_newsize4, offset);
8642
8643         if (new_size) {
8644                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_length4, offset);
8645         }
8646
8647         return offset;
8648 }
8649
8650 static int
8651 dissect_nfs_newoffset4(tvbuff_t *tvb, int offset, proto_tree *tree)
8652 {
8653         guint new_offset;
8654
8655         new_offset = tvb_get_ntohl(tvb, offset);
8656         offset = dissect_rpc_bool(tvb, tree, hf_nfs_newoffset4, offset);
8657
8658         if (new_offset) {
8659                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset4, offset);
8660         }
8661
8662         return offset;
8663 }
8664
8665 static int
8666 dissect_nfs_layoutreturn4(tvbuff_t *tvb, int offset, proto_tree *tree)
8667 {
8668         guint returntype;
8669
8670         returntype = tvb_get_ntohl(tvb, offset);
8671         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_layoutreturn_type4, offset);
8672         if (returntype == 1) { /* RETURN_FILE */
8673                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset4, offset);
8674                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_length4, offset);
8675                 offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
8676                 offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_lrf_body_content);
8677         }
8678
8679         return offset;
8680 }
8681
8682 static int
8683 dissect_nfs_layoutreturn_stateid(tvbuff_t *tvb, proto_tree *tree, int offset)
8684 {
8685         guint lrs_present;
8686
8687         lrs_present = tvb_get_ntohl(tvb, offset);
8688         offset = dissect_rpc_bool(tvb, tree, hf_nfs_lrs_present, offset);
8689
8690         if (lrs_present) {
8691                 offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
8692         }
8693
8694         return offset;
8695 }
8696
8697 static int
8698 dissect_nfs_notification_bitmap4(tvbuff_t *tvb, proto_tree *tree, int offset)
8699 {
8700         guint32 bitmap_num;
8701         guint i;
8702
8703         bitmap_num = tvb_get_ntohl(tvb, offset);
8704         offset += 4;
8705         for (i = 0; i < bitmap_num; i++) {
8706                 offset = dissect_rpc_uint32(tvb, tree, hf_nfs_notification_bitmap4, offset);
8707         }
8708
8709         return offset;
8710 }
8711
8712 static int
8713 dissect_nfs_devices4(tvbuff_t *tvb, int offset, proto_tree *tree)
8714 {
8715         guint i,j;
8716         guint32 num_indices,num_multipath, num_addr;
8717
8718         /* No layout type - argh */
8719
8720         /* Assume file layout for now */
8721
8722         /* disect indices */
8723         num_indices = tvb_get_ntohl(tvb, offset);
8724         offset += 4;
8725         for (i = 0; i < num_indices; i++) {
8726                 offset = dissect_rpc_uint32(tvb, tree, hf_nfs_deviceidx4,offset);
8727         }
8728
8729         num_multipath = tvb_get_ntohl(tvb, offset);
8730         offset += 4;
8731         for (i = 0; i < num_multipath; i++) {
8732                 num_addr = tvb_get_ntohl(tvb, offset);
8733                 offset += 4;
8734                 for (j = 0; j < num_addr; j++) {
8735                         offset = dissect_rpc_string(tvb, tree, hf_nfs_r_netid, offset, NULL);
8736                         offset = dissect_rpc_string(tvb, tree, hf_nfs_r_addr, offset, NULL);
8737                 }
8738         }
8739
8740         return offset;
8741 }
8742
8743
8744 static int
8745 dissect_nfs_deviceaddr4(tvbuff_t *tvb, int offset, proto_tree *tree)
8746 {
8747
8748         /* layout type */
8749         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_layouttype4, offset);
8750
8751         /* skip da_addr_body size */
8752         offset+=4;
8753
8754         offset = dissect_nfs_devices4(tvb, offset, tree);
8755
8756         return offset;
8757 }
8758
8759 static int
8760 dissect_nfs_devicelist4(tvbuff_t *tvb, int offset, proto_tree *tree)
8761 {
8762         guint count;
8763         guint i;
8764
8765         count = tvb_get_ntohl(tvb, offset);
8766         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_devicenum4, offset);
8767         for (i = 0; i < count; i++) {
8768                 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
8769                                                 hf_nfs_deviceid4, TRUE, 16,
8770                                                 FALSE, NULL, NULL);
8771         }
8772         return offset;
8773 }
8774
8775 static int
8776 dissect_rpc_serverowner4(tvbuff_t *tvb, int offset, proto_tree *tree)
8777 {
8778         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_minorid4, offset);
8779         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_majorid4);
8780         return offset;
8781 }
8782
8783 static int
8784 dissect_rpc_chanattrs4(tvbuff_t *tvb, int offset, proto_tree *tree)
8785 {
8786         guint i, count;
8787         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_padsize4, offset);
8788         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_maxreqsize4, offset);
8789         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_maxrespsize4, offset);
8790         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_maxrespsizecached4, offset);
8791         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_maxops4, offset);
8792         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_maxreqs4, offset);
8793         count = tvb_get_ntohl(tvb, offset);
8794         offset += 4;
8795         for (i = 0; i < count; i++) {
8796                 offset = dissect_rpc_uint32(tvb, tree, hf_nfs_rdmachanattrs4, offset);
8797         }
8798         return offset;
8799 }
8800
8801 static int
8802 dissect_rpc_nfs_impl_id4(tvbuff_t *tvb, int offset, proto_tree *tree)
8803 {
8804         proto_item *eia_client_impl_id_item = NULL;
8805         proto_tree *eia_client_impl_id_tree = NULL;
8806         guint i, count;
8807
8808         count = tvb_get_ntohl(tvb, offset);
8809         eia_client_impl_id_item = proto_tree_add_text(tree, tvb, offset, 4, "eia_client_impl_idi<%u>", count);
8810         eia_client_impl_id_tree = proto_item_add_subtree(eia_client_impl_id_item, ett_nfs_clientowner4);
8811         offset += 4;
8812
8813         for (i = 0; i < count; i++) {
8814                 proto_item *date_item = NULL;
8815                 proto_tree *date_tree = NULL;
8816
8817                 offset = dissect_nfs_utf8string(tvb, offset, eia_client_impl_id_tree, hf_nfs_nii_domain4, NULL);
8818                 offset = dissect_nfs_utf8string(tvb, offset, eia_client_impl_id_tree, hf_nfs_nii_name4, NULL);
8819
8820                 date_item = proto_tree_add_text(eia_client_impl_id_tree, tvb, offset, 12, "Build timestamp(nii_date)");
8821                 date_tree = proto_item_add_subtree(date_item, ett_nfs_clientowner4);
8822                 offset = dissect_nfs_nfstime4(tvb, offset, date_tree);
8823         }
8824         return offset;
8825 }
8826
8827 static int
8828 dissect_rpc_secparms4(tvbuff_t *tvb, int offset, proto_tree *tree)
8829 {
8830         guint count, i;
8831         count = tvb_get_ntohl(tvb, offset);
8832         offset += 4;
8833
8834         for (i = 0; i < count; i++) {
8835                 guint j, flavor = tvb_get_ntohl(tvb, offset);
8836                 offset = dissect_rpc_uint32(tvb, tree, hf_nfs_flavor4, offset);
8837
8838                 switch(flavor) {
8839                 case 1: { /* AUTH_SYS */
8840                         guint count2;
8841                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_stamp4, offset);
8842                         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_machinename4, NULL);
8843                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_uid4, offset);
8844                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_gid4, offset);
8845                         count2 = tvb_get_ntohl(tvb, offset);
8846                         offset += 4;
8847                         for (j = 0; j < count2; j++) {
8848                                 offset = dissect_rpc_uint32(tvb, tree, hf_nfs_gid4, offset);
8849                         }
8850                         break;
8851                 }
8852                 case 6: /* RPCSEC_GSS */
8853                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_service4, offset);
8854                         proto_item_append_text(tree, ", Handle from server");
8855                         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
8856                         proto_item_append_text(tree, ", Handle from client");
8857                         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
8858                         break;
8859                 default:
8860                         break;
8861                 }
8862         }
8863         return offset;
8864 }
8865
8866 static int
8867 dissect_nfs_layout(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
8868 {
8869         guint layout_type;
8870         guint fh_num;
8871         guint lo_seg_count;
8872         guint i, lo_seg;
8873         proto_item *fitem;
8874         proto_item *fh_fitem;
8875         proto_tree *newtree = NULL;
8876         proto_tree *fh_tree = NULL;
8877
8878         lo_seg_count = tvb_get_ntohl(tvb, offset);
8879
8880         fitem = proto_tree_add_text(tree, tvb, offset, 4,
8881                         "Layout Segment (count: %u)", lo_seg_count);
8882         offset += 4;
8883
8884         newtree = proto_item_add_subtree(fitem, ett_nfs_layoutseg);
8885
8886         for (lo_seg = 0; lo_seg < lo_seg_count; lo_seg++) {
8887                 offset = dissect_rpc_uint64(tvb, newtree, hf_nfs_offset4, offset);
8888                 offset = dissect_rpc_uint64(tvb, newtree, hf_nfs_length4, offset);
8889
8890                 offset = dissect_rpc_uint32(tvb, newtree, hf_nfs_iomode4, offset);
8891
8892                 layout_type = tvb_get_ntohl(tvb, offset);
8893                 offset = dissect_rpc_uint32(tvb, newtree, hf_nfs_layouttype4, offset);
8894
8895                 /* If not files layout type eat the rest and move on.. */
8896                 if (layout_type != LAYOUT4_NFSV4_1_FILES) {
8897                         offset = dissect_nfsdata(tvb, offset, newtree, hf_nfs_layout4);
8898                         continue;
8899                 }
8900
8901                 /* NFS Files */
8902                 offset += 4; /* Skip past opaque count */
8903
8904                 offset = dissect_rpc_opaque_data(tvb, offset, newtree, NULL,
8905                                 hf_nfs_deviceid4, TRUE, 16, FALSE, NULL, NULL);
8906
8907                 offset = dissect_rpc_uint32(tvb, newtree, hf_nfs_nfl_util, offset);
8908                 offset = dissect_rpc_uint32(tvb, newtree, hf_nfs_nfl_first_stripe_index, offset);
8909                 offset = dissect_rpc_uint64(tvb, newtree, hf_nfs_offset4, offset);
8910
8911                 fh_num = tvb_get_ntohl(tvb, offset); /* Len of FH list */
8912
8913                 fh_fitem = proto_tree_add_text(newtree, tvb, offset, 4,
8914                                 "File Handles (count: %u)", fh_num);
8915                 offset += 4;
8916
8917                 fh_tree = proto_item_add_subtree(fh_fitem, ett_nfs_layoutseg_fh);
8918                 for (i = 0; i < fh_num; i++) {
8919                         offset = dissect_nfs_fh4(tvb, offset, pinfo, fh_tree, "lo_filehandle", NULL);
8920                 }
8921         }
8922         return offset;
8923 }
8924
8925 static int
8926 dissect_nfs_argop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
8927                    proto_tree *tree)
8928 {
8929         guint32 ops, ops_counter, summary_counter;
8930         guint opcode;
8931         guint name_offset=0;
8932         proto_item *fitem;
8933         proto_tree *ftree = NULL;
8934         proto_tree *newftree = NULL;
8935         guint32 string_length;
8936         int cbprog;
8937         char *name = NULL, *source_name = NULL, *dest_name=NULL;
8938         const char *opname=NULL;
8939         guint32 last_fh_hash=0;
8940         guint32 saved_fh_hash=0;
8941         guint16 sid_hash, clientid_hash=0;
8942         guint8 *clientid_array;
8943         guint64 lock_length, file_offset;
8944         guint32 length;
8945         guint highest_tier=5;
8946         guint current_tier=5;
8947         guint first_operation=1;
8948
8949         nfsv4_operation_summary *op_summary;
8950
8951         ops = tvb_get_ntohl(tvb, offset+0);
8952
8953         fitem = proto_tree_add_uint_format(tree, hf_nfs_ops_count4, tvb, offset+0, 4, ops,
8954                 "Operations (count: %u)", ops);
8955         offset += 4;
8956
8957 #define MAX_NFSV4_OPS 128
8958         if (ops > MAX_NFSV4_OPS) {
8959                 /*  Limit the number of operations to something "reasonable."
8960                  *  This is an arbitrary number to keep us from attempting to
8961                  *  allocate too much memory below.
8962                  */
8963                 expert_add_info_format(pinfo, fitem, PI_MALFORMED, PI_NOTE, "Too many operations");
8964                 ops = MAX_NFSV4_OPS;
8965         }
8966
8967         op_summary = g_malloc(sizeof(nfsv4_operation_summary) * ops);
8968
8969         if (fitem) {
8970                 ftree = proto_item_add_subtree(fitem, ett_nfs_argop4);
8971         }
8972
8973         for (ops_counter=0; ops_counter<ops; ops_counter++)
8974         {
8975                 op_summary[ops_counter].optext = g_string_new("");
8976
8977                 opcode = tvb_get_ntohl(tvb, offset);
8978
8979                 op_summary[ops_counter].opcode = opcode;
8980
8981                 fitem = proto_tree_add_uint(ftree, hf_nfs_op4, tvb, offset, 4,
8982                         opcode);
8983
8984                 /* the opcodes are not contiguous */
8985                 if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_RECLAIM_COMPLETE)      &&
8986                         (opcode != NFS4_OP_ILLEGAL))
8987                         break;
8988
8989                 /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
8990                 if (opcode == NFS4_OP_ILLEGAL) {
8991                         newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4);
8992                 } else if (nfsv4_operation_ett[opcode - 3]) {
8993                         newftree = proto_item_add_subtree(fitem,
8994                                 *nfsv4_operation_ett[opcode - 3]);
8995                 } else {
8996                         break;
8997                 }
8998
8999                 opname=val_to_str_ext_const(opcode, &names_nfsv4_operation_ext, "Unknown");
9000                 offset += 4;
9001
9002                 g_string_append_printf (op_summary[ops_counter].optext, "%s", opname);
9003                 g_string_printf (op_summary[ops_counter].optext, "%s",
9004                                  val_to_str_ext_const(opcode, &names_nfsv4_operation_ext, "Unknown"));
9005
9006
9007                 switch(opcode)
9008                 {
9009                 case NFS4_OP_ACCESS:
9010                 {
9011                         guint32 *acc_request, amask;
9012                         rpc_call_info_value *civ;
9013
9014                         /* Get access mask to check and save it for comparison in the reply. */
9015                         amask = tvb_get_ntohl(tvb, offset);
9016                         acc_request = se_memdup( &amask, sizeof(guint32));
9017                         civ = pinfo->private_data;
9018                         civ->private_data = acc_request;
9019
9020                         g_string_append_printf (op_summary[ops_counter].optext, " FH:0x%08x",
9021                                                 last_fh_hash);
9022                         display_access_items(tvb, offset, pinfo, fitem, amask, 'C', 4,
9023                                              op_summary[ops_counter].optext, "Check") ;
9024                         offset+=4;
9025                 }
9026                         break;
9027
9028                 case NFS4_OP_CLOSE:
9029                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
9030                                 offset);
9031                         offset = dissect_nfs_stateid4(tvb, offset, newftree, &sid_hash);
9032                         g_string_append_printf (op_summary[ops_counter].optext, " StateID:0x%04x", sid_hash);
9033                         break;
9034
9035                 case NFS4_OP_COMMIT:
9036                         file_offset = tvb_get_ntoh64(tvb, offset);
9037                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4,
9038                                 offset);
9039                         length = tvb_get_ntohl(tvb, offset);
9040                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
9041                                 offset);
9042                         g_string_append_printf (op_summary[ops_counter].optext, " FH:0x%08x Offset:%"G_GINT64_MODIFIER"u Len:%u", last_fh_hash, file_offset, length);
9043
9044                         break;
9045
9046                 case NFS4_OP_CREATE:
9047                         {
9048                                 guint create_type;
9049
9050                                 create_type = tvb_get_ntohl(tvb, offset);
9051                                 offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_ftype4,
9052                                         offset);
9053
9054                                 switch(create_type)
9055                                 {
9056                                 case NF4LNK:
9057                                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9058                                                 hf_nfs_linktext4, NULL);
9059                                         break;
9060
9061                                 case NF4BLK:
9062                                 case NF4CHR:
9063                                         offset = dissect_nfs_specdata4(tvb, offset, newftree);
9064                                         break;
9065
9066                                 case NF4SOCK:
9067                                 case NF4FIFO:
9068                                 case NF4DIR:
9069                                         break;
9070
9071                                 default:
9072                                         break;
9073                                 }
9074
9075                                 offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
9076
9077                                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
9078                         }
9079                         break;
9080
9081                 case NFS4_OP_DELEGPURGE:
9082                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
9083                         break;
9084
9085                 case NFS4_OP_DELEGRETURN:
9086                         offset = dissect_nfs_stateid4(tvb, offset, newftree, &sid_hash);
9087                         g_string_append_printf (op_summary[ops_counter].optext, " StateID:0x%04x", sid_hash);
9088                         break;
9089
9090                 case NFS4_OP_GETATTR:
9091                         {
9092                                 proto_item *getattr_req_item = NULL;
9093                                 proto_tree *getattr_req_tree = NULL;
9094
9095                                 getattr_req_item = proto_tree_add_text(newftree,tvb,offset,0,"%s","GETATTR4args");
9096                                 getattr_req_tree = proto_item_add_subtree(getattr_req_item,ett_nfs_getattr4_args);
9097                                 offset = dissect_nfs4_attr_request(tvb, offset, pinfo, getattr_req_tree, 1);
9098                         }
9099
9100                         if (last_fh_hash != 0)
9101                                 g_string_append_printf (op_summary[ops_counter].optext, " FH:0x%08x", last_fh_hash);
9102
9103                         break;
9104
9105                 case NFS4_OP_GETFH:
9106                         last_fh_hash=0;
9107                         break;
9108
9109                 case NFS4_OP_LINK:
9110                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9111                                 hf_nfs_component4, NULL);
9112                         break;
9113
9114                 case NFS4_OP_LOCK:
9115                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
9116                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_lock4_reclaim, offset);
9117                         file_offset = tvb_get_ntoh64(tvb, offset);
9118                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
9119                         lock_length = tvb_get_ntoh64(tvb, offset);
9120                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
9121                         offset = dissect_nfs_locker4(tvb, offset, newftree);
9122                         if (lock_length == G_GINT64_CONSTANT(0xffffffffffffffffU))
9123                                 g_string_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: <End of File>",
9124                                                                          last_fh_hash,file_offset);
9125                         else {
9126                                 g_string_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: %"G_GINT64_MODIFIER"u ",
9127                                                                          last_fh_hash,file_offset,lock_length);
9128                         }
9129
9130                         break;
9131
9132                 case NFS4_OP_LOCKT:
9133                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
9134                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
9135                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
9136                         offset = dissect_nfs_lock_owner4(tvb, offset, newftree);
9137                         break;
9138
9139                 case NFS4_OP_LOCKU:
9140                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
9141                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_seqid4, offset);
9142                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9143                         file_offset = tvb_get_ntoh64(tvb, offset);
9144                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
9145                         lock_length = tvb_get_ntoh64(tvb, offset);
9146                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
9147                         if (lock_length == G_GINT64_CONSTANT(0xffffffffffffffffU))
9148                                 g_string_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: <End of File>",
9149                                                                         last_fh_hash,file_offset);
9150                         else {
9151                                 g_string_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: %"G_GINT64_MODIFIER"u ",
9152                                                                         last_fh_hash,file_offset,lock_length);
9153                         }
9154                         break;
9155
9156                 case NFS4_OP_LOOKUP:
9157                         name_offset=offset;
9158                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9159                                                                 hf_nfs_component4, &name);
9160                         if (nfs_file_name_snooping){
9161                                 rpc_call_info_value *civ=pinfo->private_data;
9162                                 nfs_name_snoop_add_name(civ->xid, tvb,
9163                                                                                 /*name_offset, strlen(name),*/
9164                                                                                 0, 0,
9165                                                                                 0, 0, name);
9166                         }
9167                         g_string_append_printf (op_summary[ops_counter].optext, " ");
9168                         if (last_fh_hash != 0)
9169                                                 g_string_append_printf (op_summary[ops_counter].optext, "DH:0x%08x/", last_fh_hash);
9170                         if (name != NULL)
9171                                                 g_string_append_printf (op_summary[ops_counter].optext, "%s", name);
9172
9173                         break;
9174
9175                 case NFS4_OP_LOOKUPP:
9176                         break;
9177
9178                 case NFS4_OP_NVERIFY:
9179                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
9180                         if (last_fh_hash != 0)
9181                                 g_string_append_printf (op_summary[ops_counter].optext, " FH:0x%08x", last_fh_hash);
9182
9183                         break;
9184
9185                 case NFS4_OP_OPEN:
9186                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
9187                                 offset);
9188                         offset = dissect_nfs_open4_share_access(tvb, offset, newftree);
9189                         offset = dissect_nfs_open4_share_deny(tvb, offset, newftree);
9190                         offset = dissect_nfs_open_owner4(tvb, offset, newftree);
9191                         offset = dissect_nfs_openflag4(tvb, offset, pinfo, newftree);
9192                         offset = dissect_nfs_open_claim4(tvb, offset, pinfo, newftree, &name);
9193                                 g_string_append_printf (op_summary[ops_counter].optext, " ");
9194                                 if (last_fh_hash != 0)
9195                                         g_string_append_printf (op_summary[ops_counter].optext, "DH:0x%08x/", last_fh_hash);
9196                                 if (name != NULL)
9197                                         g_string_append_printf (op_summary[ops_counter].optext, "%s", name);
9198                         break;
9199
9200                 case NFS4_OP_OPENATTR:
9201                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_attrdircreate,
9202                                 offset);
9203                         break;
9204
9205                 case NFS4_OP_OPEN_CONFIRM:
9206                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9207                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
9208                                 offset);
9209                         break;
9210
9211                 case NFS4_OP_OPEN_DOWNGRADE:
9212                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9213                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
9214                                 offset);
9215                         offset = dissect_nfs_open4_share_access(tvb, offset, newftree);
9216                         offset = dissect_nfs_open4_share_deny(tvb, offset, newftree);
9217                         break;
9218
9219                 case NFS4_OP_PUTFH:
9220                         offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "filehandle", &last_fh_hash);
9221                         break;
9222
9223                 case NFS4_OP_PUTPUBFH:
9224                 case NFS4_OP_PUTROOTFH:
9225                         break;
9226
9227                 case NFS4_OP_READ:
9228                         offset = dissect_nfs_stateid4(tvb, offset, newftree, &sid_hash);
9229                         file_offset = tvb_get_ntoh64(tvb, offset);
9230                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4,
9231                                 offset);
9232                         length = tvb_get_ntohl(tvb, offset);
9233                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
9234                                 offset);
9235                         if (sid_hash != 0)
9236                                 g_string_append_printf (op_summary[ops_counter].optext, " StateID:0x%04x Offset:%" G_GINT64_MODIFIER "u Len:%u", sid_hash, file_offset, length);
9237                         break;
9238
9239                 case NFS4_OP_READDIR:
9240                                 offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookie4,
9241                                         offset);
9242                                 offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookieverf4,
9243                                                         offset);
9244                                 offset = dissect_rpc_uint32(tvb, newftree,
9245                                                                 hf_nfs_count4_dircount, offset);
9246                                 offset = dissect_rpc_uint32(tvb, newftree,
9247                                                                 hf_nfs_count4_maxcount, offset);
9248                                 offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
9249                                                                 FATTR4_BITMAP_ONLY);
9250                                 if (last_fh_hash != 0)
9251                                         g_string_append_printf (op_summary[ops_counter].optext, " FH:0x%08x", last_fh_hash);
9252                         break;
9253
9254                 case NFS4_OP_READLINK:
9255                         break;
9256
9257                 case NFS4_OP_RECLAIM_COMPLETE:
9258                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_reclaim_one_fs4, offset);
9259                         break;
9260
9261                 case NFS4_OP_REMOVE:
9262                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9263                                 hf_nfs_component4, &name);
9264                         g_string_append_printf (op_summary[ops_counter].optext, " ");
9265                         if (last_fh_hash != 0)
9266                                 g_string_append_printf (op_summary[ops_counter].optext, "DH:0x%08x/", last_fh_hash);
9267                         if (name != NULL)
9268                                 g_string_append_printf (op_summary[ops_counter].optext, "%s", name);
9269                         break;
9270
9271                 case NFS4_OP_RENAME:
9272                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9273                                 hf_nfs_component4, &source_name);
9274                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9275                                 hf_nfs_component4, &dest_name);
9276                         g_string_append_printf (op_summary[ops_counter].optext, " From: %s To: %s",
9277                                                 source_name ? source_name : "Unknown",
9278                                                 dest_name ? dest_name : "Unknown");
9279                         break;
9280
9281                 case NFS4_OP_RENEW:
9282                         clientid_array = tvb_get_string(tvb, offset, 8);
9283                         clientid_hash = crc16_ccitt(clientid_array, 8);
9284                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
9285                         g_string_append_printf (op_summary[ops_counter].optext, " CID: 0x%04x", clientid_hash);
9286
9287                         break;
9288
9289                 case NFS4_OP_RESTOREFH:
9290                         last_fh_hash = saved_fh_hash;
9291                         break;
9292
9293                 case NFS4_OP_SAVEFH:
9294                         saved_fh_hash = last_fh_hash;
9295                         break;
9296
9297                 case NFS4_OP_SECINFO:
9298                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9299                                 hf_nfs_component4, NULL);
9300                         break;
9301
9302                 case NFS4_OP_SETATTR:
9303                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9304                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
9305                         g_string_append_printf (op_summary[ops_counter].optext, " FH:0x%08x", last_fh_hash);
9306                         break;
9307
9308                 case NFS4_OP_SETCLIENTID:
9309                         {
9310                                 proto_tree *client_tree = NULL;
9311                                 proto_tree *callback_tree = NULL;
9312
9313                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "client");
9314
9315                                 client_tree = proto_item_add_subtree(fitem, ett_nfs_client_id4);
9316
9317                                 offset = dissect_nfs_client_id4(tvb, offset, client_tree);
9318
9319                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "callback");
9320                                 callback_tree = proto_item_add_subtree(fitem,
9321                                                 ett_nfs_cb_client4);
9322
9323                                 offset = dissect_nfs_cb_client4(tvb, offset, callback_tree);
9324
9325                                 offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_callback_ident,
9326                                         offset);
9327                         }
9328                         break;
9329
9330                 case NFS4_OP_SETCLIENTID_CONFIRM:
9331                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
9332                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4, offset);
9333                         break;
9334
9335                 case NFS4_OP_VERIFY:
9336                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
9337                         break;
9338
9339                 case NFS4_OP_WRITE:
9340                         offset = dissect_nfs_stateid4(tvb, offset, newftree, &sid_hash);
9341                         file_offset = tvb_get_ntoh64(tvb, offset);
9342                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
9343                         offset = dissect_nfs_stable_how4(tvb, offset, newftree, "stable");
9344                         string_length = tvb_get_ntohl(tvb,offset+0);
9345                         dissect_rpc_uint32(tvb, newftree, hf_write_data_length, offset); /* don't change offset */
9346                         offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
9347                         if (sid_hash != 0)
9348                                 g_string_append_printf (op_summary[ops_counter].optext, " StateID:0x%04x Offset:%"G_GINT64_MODIFIER"u Len:%u", sid_hash, file_offset, string_length);
9349                         break;
9350
9351                 case NFS4_OP_RELEASE_LOCKOWNER:
9352                         offset = dissect_nfs_lock_owner4(tvb, offset, newftree);
9353                         break;
9354
9355                         /* Minor Version 1 */
9356                 case NFS4_OP_EXCHANGE_ID: {
9357 #define EXCHGID4_FLAG_SUPP_MOVED_REFER    0x00000001
9358 #define EXCHGID4_FLAG_SUPP_MOVED_MIGR     0x00000002
9359 #define EXCHGID4_FLAG_BIND_PRINC_STATEID  0x00000100
9360 #define EXCHGID4_FLAG_USE_NON_PNFS        0x00010000
9361 #define EXCHGID4_FLAG_USE_PNFS_MDS        0x00020000
9362 #define EXCHGID4_FLAG_USE_PNFS_DS         0x00040000
9363 #define EXCHGID4_FLAG_MASK_PNFS           0x00070000
9364 #define EXCHGID4_FLAG_UPD_CONFIRMED_REC_A 0x40000000
9365 #define EXCHGID4_FLAG_CONFIRMED_R         0x80000000
9366                                 proto_tree *eia_clientowner_tree = NULL;
9367                                 proto_tree *eia_flags_tree = NULL;
9368                                 guint32 exchange_id_flags = 0;
9369
9370                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "eia_clientowner");
9371                                 eia_clientowner_tree = proto_item_add_subtree(fitem, ett_nfs_clientowner4);
9372                                 offset = dissect_rpc_uint64(tvb, eia_clientowner_tree, hf_nfs_verifier4, offset);
9373                                 offset = dissect_nfsdata(tvb, offset, eia_clientowner_tree, hf_nfs_data);
9374
9375                                 exchange_id_flags = tvb_get_ntohl(tvb, offset);
9376                                 fitem = proto_tree_add_text(newftree, tvb, offset, 4, "eia_flags:0x%08x", exchange_id_flags);
9377                                 eia_flags_tree = proto_item_add_subtree(fitem, ett_exchangeid_flags);
9378                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_confirmed_r, tvb, offset, 1, exchange_id_flags);
9379                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_upd_conf_rec_a, tvb, offset, 1, exchange_id_flags);
9380                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_pnfs_ds, tvb, offset, 1, exchange_id_flags);
9381                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_pnfs_mds, tvb, offset, 1, exchange_id_flags);
9382                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_non_pnfs, tvb, offset, 1, exchange_id_flags);
9383                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_bind_princ, tvb, offset, 1, exchange_id_flags);
9384                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_moved_migr, tvb, offset, 1, exchange_id_flags);
9385                                 proto_tree_add_boolean(eia_flags_tree, hf_nfs_exchid_flags_moved_refer, tvb, offset, 1, exchange_id_flags);
9386                                 offset +=4;
9387
9388                                 offset = dissect_nfs_state_protect4_a(tvb, offset, newftree);
9389                                 offset = dissect_rpc_nfs_impl_id4(tvb, offset, newftree);
9390                         }
9391                         break;
9392
9393                 case NFS4_OP_CREATE_SESSION:
9394                         offset = dissect_rpc_uint64(tvb, newftree,
9395                                         hf_nfs_clientid4, offset);
9396                         offset = dissect_rpc_uint32(tvb, newftree,
9397                                         hf_nfs_seqid4, offset);
9398                         offset = dissect_rpc_uint32(tvb, newftree,
9399                                         hf_nfs_create_session_flags4, offset);
9400                         offset = dissect_rpc_chanattrs4(tvb, offset, newftree);
9401                         offset = dissect_rpc_chanattrs4(tvb, offset, newftree);
9402                         cbprog = tvb_get_ntohl(tvb, offset);
9403                         reg_callback(cbprog);
9404                         offset = dissect_rpc_uint32(tvb, newftree,
9405                                         hf_nfs_cb_program, offset);
9406                         offset = dissect_rpc_secparms4(tvb, offset, newftree);
9407                         break;
9408
9409                 case NFS4_OP_DESTROY_SESSION:
9410                         offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL,
9411                                                                                          hf_nfs_sessionid4, TRUE, 16,
9412                                                                                          FALSE, NULL, NULL);
9413                         break;
9414
9415                         /* pNFS */
9416                 case NFS4_OP_LAYOUTGET:
9417                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_layout_avail4,
9418                                                                           offset);
9419                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_layouttype4,
9420                                                                                 offset);
9421                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_iomode4, offset);
9422                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
9423                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
9424                         offset = dissect_rpc_uint64(tvb, newftree,
9425                                                                                 hf_nfs_length4_minlength, offset);
9426                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9427                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4_maxcount,
9428                                                                                 offset);
9429                         break;
9430
9431                 case NFS4_OP_LAYOUTCOMMIT:
9432                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
9433                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
9434                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_reclaim4, offset);
9435                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9436                         offset = dissect_nfs_newoffset4(tvb, offset, newftree);
9437                         offset = dissect_nfs_newtime4(tvb, offset, newftree);
9438                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_layouttype4,
9439                                                                                 offset);
9440                         offset = dissect_nfsdata(tvb, offset, newftree,
9441                                                                          hf_nfs_layoutupdate4);
9442                         break;
9443
9444                 case NFS4_OP_LAYOUTRETURN:
9445                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_reclaim4, offset);
9446                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_layouttype4,
9447                                                                                 offset);
9448                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_iomode4, offset);
9449                         offset = dissect_nfs_layoutreturn4(tvb, offset, newftree);
9450                         break;
9451
9452                 case NFS4_OP_GETDEVINFO:
9453                         offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL,
9454                                                         hf_nfs_deviceid4, TRUE, 16,
9455                                                         FALSE, NULL, NULL);
9456
9457                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_layouttype4,
9458                                                                                 offset);
9459                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4_maxcount,
9460                                                                                 offset);
9461                         offset = dissect_nfs_notification_bitmap4(tvb, newftree, offset);
9462                         break;
9463
9464                 case NFS4_OP_GETDEVLIST:
9465                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_layouttype4,
9466                                                                                 offset);
9467                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4_maxcount,
9468                                                                                 offset);
9469                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookie4, offset);
9470                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookieverf4,
9471                                                                                 offset);
9472                         break;
9473
9474                 case NFS4_OP_SEQUENCE:
9475                         offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL,
9476                                                                                          hf_nfs_sessionid4, TRUE, 16,
9477                                                                                          FALSE, NULL, NULL);
9478                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset);
9479                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset);
9480                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_high_slotid4, offset);
9481                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_cachethis4, offset);
9482                         break;
9483
9484                 /* In theory, it's possible to get this opcode */
9485                 case NFS4_OP_ILLEGAL:
9486                         break;
9487
9488                 default:
9489                         break;
9490                 }
9491         }
9492
9493         /* Detect which tiers are present in this packet */
9494         for (summary_counter=0; summary_counter < ops_counter; summary_counter++)
9495         {
9496                 current_tier = nfsv4_operation_tiers[op_summary[summary_counter].opcode];
9497                 if (current_tier < highest_tier)
9498                         highest_tier=current_tier;
9499         }
9500
9501         /* Display packet summary */
9502         for (summary_counter=0; summary_counter < ops_counter; summary_counter++)
9503         {
9504                 guint main_opcode;
9505                 proto_item *main_op_item;
9506
9507                 main_opcode=op_summary[summary_counter].opcode;
9508                 current_tier = nfsv4_operation_tiers[op_summary[summary_counter].opcode];
9509
9510                 /* Display summary info only for operations that are "most significant".
9511                    Controlled by a user option. */
9512                 if (current_tier == highest_tier || !display_major_nfsv4_ops) {
9513                         if (current_tier == highest_tier) {
9514                                 const char *main_opname=NULL;
9515
9516                                 /* Display a filterable field of the most significant operations in all cases. */
9517                                 main_opname=val_to_str_ext_const(main_opcode, &names_nfsv4_operation_ext, "Unknown");
9518                                 main_op_item=proto_tree_add_uint_format_value(ftree, hf_nfs_main_opcode, tvb, 0, 0,
9519                                                                               main_opcode, "%s (%u)", main_opname, main_opcode);
9520                                 PROTO_ITEM_SET_GENERATED(main_op_item);
9521                         }
9522
9523                         if (first_operation==0)
9524                                 /* Seperator between operation text */
9525                                 col_append_fstr(pinfo->cinfo, COL_INFO, " |");
9526
9527                         if (op_summary[summary_counter].optext->len > 0)
9528                                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", op_summary[summary_counter].optext->str);
9529
9530                         first_operation=0;
9531                 }
9532         }
9533
9534
9535         return offset;
9536 }
9537
9538 static int
9539 dissect_nfs4_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
9540         proto_tree* tree)
9541 {
9542         char *tag=NULL;
9543
9544         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, &tag);
9545         /* Display the NFSv4 tag.  If it is empty, string generator will have returned "<EMPTY>", in which case don't display anything */
9546         if (nfs_display_v4_tag && strncmp(tag,"<EMPTY>",7)!=0) {
9547                 col_append_fstr(pinfo->cinfo, COL_INFO," %s", tag);
9548         }
9549
9550         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_minorversion, offset);
9551         offset = dissect_nfs_argop4(tvb, offset, pinfo, tree);
9552
9553         return offset;
9554 }
9555
9556 static int
9557 dissect_nfs_secinfo4_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
9558         proto_tree *tree)
9559 {
9560         guint flavor;
9561         proto_item *fitem;
9562         proto_tree *secftree;
9563
9564         flavor = tvb_get_ntohl(tvb, offset);
9565         fitem = proto_tree_add_uint(tree, hf_nfs_secinfo_flavor, tvb, offset, 4,
9566                 flavor);
9567         offset += 4;
9568
9569         if (fitem)
9570         {
9571                 switch(flavor)
9572                 {
9573                 case RPCSEC_GSS:
9574                         secftree = proto_item_add_subtree(fitem, ett_nfs_secinfo4_flavor_info);
9575                         if (secftree)
9576                                 offset = dissect_nfs_rpcsec_gss_info(tvb, offset, secftree);
9577                         break;
9578
9579                 default:
9580                         break;
9581                 }
9582         }
9583
9584         return offset;
9585 }
9586
9587 static int
9588 dissect_nfs_resop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
9589                    proto_tree *tree)
9590 {
9591         guint32 ops, ops_counter, summary_counter;
9592         guint32 opcode;
9593         proto_item *fitem;
9594         proto_tree *ftree = NULL;
9595         proto_tree *newftree = NULL;
9596         guint32 string_length;
9597         guint32 status;
9598         const char *opname=NULL;
9599         guint32 last_fh_hash=0;
9600         guint16 sid_hash=0;
9601         guint highest_tier=5;
9602         guint current_tier=5;
9603         guint first_operation=1;
9604
9605         nfsv4_operation_summary *op_summary;
9606
9607         ops = tvb_get_ntohl(tvb, offset+0);
9608
9609         fitem = proto_tree_add_uint_format(tree, hf_nfs_ops_count4, tvb, offset+0, 4, ops,
9610                 "Operations (count: %u)", ops);
9611         offset += 4;
9612
9613         if (ops > MAX_NFSV4_OPS) {
9614                 expert_add_info_format(pinfo, fitem, PI_MALFORMED, PI_NOTE, "Too many operations");
9615                 ops = MAX_NFSV4_OPS;
9616         }
9617
9618         op_summary = g_malloc(sizeof(nfsv4_operation_summary) * ops);
9619
9620         if (fitem) {
9621                 ftree = proto_item_add_subtree(fitem, ett_nfs_resop4);
9622         }
9623
9624         for (ops_counter = 0; ops_counter < ops; ops_counter++)
9625         {
9626                 op_summary[ops_counter].optext = g_string_new("");
9627
9628                 opcode = tvb_get_ntohl(tvb, offset);
9629
9630                 op_summary[ops_counter].iserror=FALSE;
9631                 op_summary[ops_counter].opcode = opcode;
9632
9633                 /* sanity check for bogus packets */
9634                 if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_RECLAIM_COMPLETE) &&
9635                         (opcode != NFS4_OP_ILLEGAL))
9636                         break;
9637
9638                 fitem = proto_tree_add_uint(ftree, hf_nfs_op4, tvb, offset, 4,
9639                         opcode);
9640
9641                 /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
9642                 if (opcode == NFS4_OP_ILLEGAL) {
9643                         newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4);
9644                 } else if (nfsv4_operation_ett[opcode - 3]) {
9645                         newftree = proto_item_add_subtree(fitem,
9646                                 *nfsv4_operation_ett[opcode - 3]);
9647                 } else {
9648                         break;
9649                 }
9650
9651                 opname=val_to_str_ext_const(opcode, &names_nfsv4_operation_ext, "Unknown");
9652                 offset += 4;
9653
9654                 g_string_append_printf (op_summary[ops_counter].optext, "%s", opname);
9655
9656                 offset = dissect_nfs_nfsstat4(tvb, offset, newftree, &status);
9657
9658                 /*
9659                  * With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT, and
9660                  * NFS4_OP_SETATTR, all other ops do *not* return data with the
9661                  * failed status code.
9662                  */
9663                 if ((status != NFS4_OK) &&
9664                         ((opcode != NFS4_OP_LOCK) && (opcode != NFS4_OP_LOCKT) &&
9665                          (opcode != NFS4_OP_SETATTR))) {
9666                         op_summary[ops_counter].iserror=TRUE;
9667                         continue;
9668                 }
9669
9670                 /* These parsing routines are only executed if the status is NFS4_OK */
9671                 switch(opcode)
9672                 {
9673                 case NFS4_OP_ACCESS:
9674                         offset = dissect_access_reply(tvb, offset, pinfo, fitem, 4,
9675                                 op_summary[ops_counter].optext);
9676                         break;
9677
9678                 case NFS4_OP_CLOSE:
9679                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9680                         break;
9681
9682                 case NFS4_OP_COMMIT:
9683                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
9684                                 offset);
9685                         break;
9686
9687                 case NFS4_OP_CREATE:
9688                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
9689                                 "change_info");
9690                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
9691                                 FATTR4_BITMAP_ONLY);
9692                         break;
9693
9694                 case NFS4_OP_GETATTR:
9695                         {
9696                                 proto_item *getattr_res_item = NULL;
9697                                 proto_tree *getattr_res_tree = NULL;
9698
9699                                 getattr_res_item = proto_tree_add_text(newftree,tvb,offset,0,"%s","GETATTR4res");
9700                                 getattr_res_tree = proto_item_add_subtree(getattr_res_item,ett_nfs_getattr4_resp);
9701                                 offset = dissect_nfs4_attr_resp(tvb, offset, pinfo, getattr_res_tree);
9702                         }
9703                         break;
9704
9705                 case NFS4_OP_GETFH:
9706                         offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "Filehandle", &last_fh_hash);
9707                         break;
9708
9709                 case NFS4_OP_LINK:
9710                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
9711                                 "change_info");
9712                         break;
9713
9714                 case NFS4_OP_LOCK:
9715                 case NFS4_OP_LOCKT:
9716                         if (status == NFS4_OK)
9717                         {
9718                                 if (opcode == NFS4_OP_LOCK)
9719                                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9720                         }
9721                         else
9722                         if (status == NFS4ERR_DENIED)
9723                                 offset = dissect_nfs_lock4denied(tvb, offset, newftree);
9724                         break;
9725
9726                 case NFS4_OP_LOCKU:
9727                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9728                         break;
9729
9730                 case NFS4_OP_OPEN:
9731                         offset = dissect_nfs_stateid4(tvb, offset, newftree, &sid_hash);
9732                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
9733                                 "change_info");
9734                         offset = dissect_nfs_open4_rflags(tvb, offset, newftree,
9735                                 "result_flags");
9736                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
9737                                 FATTR4_BITMAP_ONLY);
9738                         offset = dissect_nfs_open_delegation4(tvb, offset, pinfo, newftree);
9739                         g_string_append_printf (op_summary[ops_counter].optext, " StateID:0x%04x", sid_hash);
9740                         break;
9741
9742                 case NFS4_OP_OPEN_CONFIRM:
9743                 case NFS4_OP_OPEN_DOWNGRADE:
9744                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9745                         break;
9746
9747                 case NFS4_OP_RESTOREFH:
9748                 case NFS4_OP_SAVEFH:
9749                 case NFS4_OP_PUTFH:
9750                         break;
9751
9752                 case NFS4_OP_READ:
9753                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_eof, offset);
9754                         string_length = tvb_get_ntohl(tvb,offset+0);
9755                         dissect_rpc_uint32(tvb, newftree, hf_read_data_length, offset); /* don't change offset */
9756                         offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
9757                         break;
9758
9759                 case NFS4_OP_READDIR:
9760                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4, offset);
9761                         offset = dissect_nfs_dirlist4(tvb, offset, pinfo, newftree);
9762                         break;
9763
9764                 case NFS4_OP_READLINK:
9765                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
9766                                 hf_nfs_linktext4, NULL);
9767                         break;
9768
9769                 case NFS4_OP_RECLAIM_COMPLETE:
9770                         break;
9771
9772                 case NFS4_OP_REMOVE:
9773                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
9774                                 "change_info");
9775                         break;
9776
9777                 case NFS4_OP_RENAME:
9778                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
9779                                 "source_cinfo");
9780                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
9781                                 "target_cinfo");
9782                         break;
9783
9784                 case NFS4_OP_SECINFO:
9785                         offset = dissect_rpc_array(tvb, pinfo, newftree, offset,
9786                                 dissect_nfs_secinfo4_res, hf_nfs_secinfo_arr4);
9787                         break;
9788
9789                 case NFS4_OP_SETATTR:
9790                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
9791                                 FATTR4_BITMAP_ONLY);
9792                         break;
9793
9794                 case NFS4_OP_SETCLIENTID:
9795                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4,
9796                                 offset);
9797                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
9798                                 offset);
9799                         break;
9800
9801                 case NFS4_OP_WRITE:
9802                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
9803                                 offset);
9804                         offset = dissect_nfs_stable_how4(tvb, offset, newftree,
9805                                 "committed");
9806                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
9807                                 offset);
9808                         break;
9809
9810                         /* Minor Version 1 */
9811                 case NFS4_OP_EXCHANGE_ID: {
9812                                 proto_tree *eir_flags_tree = NULL;
9813                                 proto_tree *eir_server_owner_tree = NULL;
9814                                 guint32 exchange_id_flags = 0;
9815
9816                                 offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
9817                                 offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset);
9818
9819                                 exchange_id_flags = tvb_get_ntohl(tvb, offset);
9820                                 fitem = proto_tree_add_text(newftree, tvb, offset, 4, "eir_flags:0x%08x", exchange_id_flags);
9821                                 eir_flags_tree = proto_item_add_subtree(fitem, ett_exchangeid_flags);
9822                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_confirmed_r, tvb, offset, 1, exchange_id_flags);
9823                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_upd_conf_rec_a, tvb, offset, 1, exchange_id_flags);
9824                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_pnfs_ds, tvb, offset, 1, exchange_id_flags);
9825                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_pnfs_mds, tvb, offset, 1, exchange_id_flags);
9826                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_non_pnfs, tvb, offset, 1, exchange_id_flags);
9827                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_bind_princ, tvb, offset, 1, exchange_id_flags);
9828                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_moved_migr, tvb, offset, 1, exchange_id_flags);
9829                                 proto_tree_add_boolean(eir_flags_tree, hf_nfs_exchid_flags_moved_refer, tvb, offset, 1, exchange_id_flags);
9830                                 offset += 4;
9831
9832                                 offset = dissect_nfs_state_protect4_r(tvb, offset, newftree);
9833
9834                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "eir_server_owner");
9835                                 eir_server_owner_tree = proto_item_add_subtree(fitem, ett_server_owner4);
9836                                 offset = dissect_rpc_serverowner4(tvb, offset, eir_server_owner_tree);
9837
9838                                 offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_serverscope4);
9839                                 offset = dissect_rpc_nfs_impl_id4(tvb, offset, newftree);
9840                         }
9841                         break;
9842                 case NFS4_OP_CREATE_SESSION:
9843                         offset = dissect_rpc_opaque_data(tvb, offset, newftree,
9844                                         NULL, hf_nfs_sessionid4, TRUE, 16,
9845                                         FALSE, NULL, NULL);
9846                         offset = dissect_rpc_uint32(tvb, newftree,
9847                                         hf_nfs_seqid4, offset);
9848                         offset = dissect_rpc_uint32(tvb, newftree,
9849                                         hf_nfs_create_session_flags4, offset);
9850                         offset = dissect_rpc_chanattrs4(tvb, offset, newftree);
9851
9852                         offset = dissect_rpc_chanattrs4(tvb, offset, newftree);
9853                         break;
9854
9855                 case NFS4_OP_DESTROY_SESSION:
9856                         break;
9857
9858                 case NFS4_OP_LAYOUTGET:
9859                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_return_on_close4,
9860                                                                           offset);
9861                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
9862                         offset = dissect_nfs_layout(tvb, offset, pinfo, newftree);
9863                         break;
9864
9865                 case NFS4_OP_LAYOUTCOMMIT:
9866                         offset = dissect_nfs_newsize4(tvb, offset, newftree);
9867                         break;
9868
9869                 case NFS4_OP_LAYOUTRETURN:
9870                         offset = dissect_nfs_layoutreturn_stateid(tvb, newftree, offset);
9871                         break;
9872
9873                 case NFS4_OP_GETDEVINFO:
9874                         offset = dissect_nfs_deviceaddr4(tvb, offset, newftree);
9875                         offset = dissect_nfs_notification_bitmap4(tvb, newftree, offset);
9876                         break;
9877
9878                 case NFS4_OP_GETDEVLIST:
9879                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookie4,
9880                                                                                 offset);
9881                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookieverf4,
9882                                                                                 offset);
9883                         offset = dissect_nfs_devicelist4(tvb, offset, newftree);
9884                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_eof, offset);
9885                         break;
9886
9887                 case NFS4_OP_SEQUENCE:
9888                         offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL,
9889                                                                                          hf_nfs_sessionid4, TRUE, 16,
9890                                                                                          FALSE, NULL, NULL);
9891                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset);
9892                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset);
9893                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_high_slotid4, offset);
9894                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_target_high_slotid4, offset);
9895                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_sr_status4,
9896                                                                                 offset);
9897                         break;
9898
9899                 default:
9900                         break;
9901                 }
9902         }
9903
9904         /* Detect which tiers are present in this packet */
9905         for (summary_counter=0; summary_counter < ops_counter; summary_counter++)
9906         {
9907                 current_tier = nfsv4_operation_tiers[op_summary[summary_counter].opcode];
9908                 if (current_tier < highest_tier)
9909                         highest_tier=current_tier;
9910         }
9911
9912         /* Display packet summary */
9913         for (summary_counter=0; summary_counter < ops_counter; summary_counter++)
9914         {
9915                 guint main_opcode;
9916                 proto_item *main_op_item;
9917
9918                 main_opcode=op_summary[summary_counter].opcode;
9919                 current_tier = nfsv4_operation_tiers[op_summary[summary_counter].opcode];
9920
9921                 /* Display summary info only for operations that are "most significant".
9922                  Controlled by a user option.
9923                  Display summary info for operations that return an error as well.  */
9924                 if (current_tier == highest_tier || !display_major_nfsv4_ops || op_summary[summary_counter].iserror==TRUE) {
9925                         if (current_tier == highest_tier) {
9926                                 const char *main_opname=NULL;
9927
9928                                 /* Display a filterable field of the most significant operations in all cases. */
9929                                 main_opname=val_to_str_ext_const(main_opcode, &names_nfsv4_operation_ext, "Unknown");
9930                                 main_op_item=proto_tree_add_uint_format_value(ftree, hf_nfs_main_opcode, tvb, 0, 0,
9931                                                                               main_opcode, "%s (%u)", main_opname, main_opcode);
9932                                 PROTO_ITEM_SET_GENERATED(main_op_item);
9933                         }
9934
9935                         if (first_operation==0)
9936                         /* Seperator between operation text */
9937                                 col_append_fstr(pinfo->cinfo, COL_INFO, " |");
9938
9939                         if (op_summary[summary_counter].optext->len > 0)
9940                                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", op_summary[summary_counter].optext->str);
9941                         first_operation=0;
9942                 }
9943         }
9944
9945
9946         return offset;
9947 }
9948
9949 static int
9950 dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
9951         proto_tree* tree)
9952 {
9953         guint32 status;
9954         char *tag=NULL;
9955
9956         offset = dissect_nfs_nfsstat4(tvb, offset, tree, &status);
9957         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, &tag);
9958         /* Display the NFSv4 tag. If it is empty, string generator will have returned "<EMPTY>", in which case don't display anything */
9959         if (nfs_display_v4_tag && strncmp(tag,"<EMPTY>",7)!=0) {
9960                 col_append_fstr(pinfo->cinfo, COL_INFO," %s", tag);
9961         }
9962
9963         offset = dissect_nfs_resop4(tvb, offset, pinfo, tree);
9964
9965         if (status != NFS4_OK)
9966                 col_append_fstr(pinfo->cinfo, COL_INFO," Status: %s",
9967                                 val_to_str_ext(status, &names_nfs_nfsstat4_ext, "Unknown error:%u"));
9968
9969         return offset;
9970 }
9971
9972
9973 /* proc number, "proc name", dissect_request, dissect_reply */
9974 /* NULL as function pointer means: type of arguments is "void". */
9975 static const vsff nfs3_proc[] = {
9976         { 0,    "NULL",         /* OK */
9977         dissect_nfs3_null_call,         dissect_nfs3_null_reply },
9978         { 1,    "GETATTR",      /* OK */
9979         dissect_nfs3_getattr_call,      dissect_nfs3_getattr_reply },
9980         { 2,    "SETATTR",      /* OK */
9981         dissect_nfs3_setattr_call,      dissect_nfs3_setattr_reply },
9982         { 3,    "LOOKUP",       /* OK */
9983         dissect_nfs3_lookup_call,       dissect_nfs3_lookup_reply },
9984         { 4,    "ACCESS",       /* OK */
9985         dissect_nfs3_access_call,       dissect_nfs3_access_reply },
9986         { 5,    "READLINK",     /* OK */
9987         dissect_nfs3_readlink_call,     dissect_nfs3_readlink_reply },
9988         { 6,    "READ",         /* OK */
9989         dissect_nfs3_read_call,         dissect_nfs3_read_reply },
9990         { 7,    "WRITE",        /* OK */
9991         dissect_nfs3_write_call,        dissect_nfs3_write_reply },
9992         { 8,    "CREATE",       /* OK */
9993         dissect_nfs3_create_call,       dissect_nfs3_create_reply },
9994         { 9,    "MKDIR",        /* OK */
9995         dissect_nfs3_mkdir_call,        dissect_nfs3_mkdir_reply },
9996         { 10,   "SYMLINK",      /* OK */
9997         dissect_nfs3_symlink_call,      dissect_nfs3_symlink_reply },
9998         { 11,   "MKNOD",        /* OK */
9999         dissect_nfs3_mknod_call,        dissect_nfs3_mknod_reply },
10000         { 12,   "REMOVE",       /* OK */
10001         dissect_nfs3_remove_call,       dissect_nfs3_remove_reply },
10002         { 13,   "RMDIR",        /* OK */
10003         dissect_nfs3_rmdir_call,        dissect_nfs3_rmdir_reply },
10004         { 14,   "RENAME",       /* OK */
10005         dissect_nfs3_rename_call,       dissect_nfs3_rename_reply },
10006         { 15,   "LINK",         /* OK */
10007         dissect_nfs3_link_call,         dissect_nfs3_link_reply },
10008         { 16,   "READDIR",      /* OK */
10009         dissect_nfs3_readdir_call,      dissect_nfs3_readdir_reply },
10010         { 17,   "READDIRPLUS",  /* OK */
10011         dissect_nfs3_readdirplus_call,  dissect_nfs3_readdirplus_reply },
10012         { 18,   "FSSTAT",       /* OK */
10013         dissect_nfs3_fsstat_call,       dissect_nfs3_fsstat_reply },
10014         { 19,   "FSINFO",       /* OK */
10015         dissect_nfs3_fsinfo_call,       dissect_nfs3_fsinfo_reply },
10016         { 20,   "PATHCONF",     /* OK */
10017         dissect_nfs3_pathconf_call,     dissect_nfs3_pathconf_reply },
10018         { 21,   "COMMIT",       /* OK */
10019         dissect_nfs3_commit_call,       dissect_nfs3_commit_reply },
10020         { 0,    NULL,   NULL,   NULL }
10021 };
10022
10023 static const value_string nfsv3_proc_vals[] = {
10024         { 0,    "NULL" },
10025         { 1,    "GETATTR" },
10026         { 2,    "SETATTR" },
10027         { 3,    "LOOKUP" },
10028         { 4,    "ACCESS" },
10029         { 5,    "READLINK" },
10030         { 6,    "READ" },
10031         { 7,    "WRITE" },
10032         { 8,    "CREATE" },
10033         { 9,    "MKDIR" },
10034         { 10,   "SYMLINK" },
10035         { 11,   "MKNOD" },
10036         { 12,   "REMOVE" },
10037         { 13,   "RMDIR" },
10038         { 14,   "RENAME" },
10039         { 15,   "LINK" },
10040         { 16,   "READDIR" },
10041         { 17,   "READDIRPLUS" },
10042         { 18,   "FSSTAT" },
10043         { 19,   "FSINFO" },
10044         { 20,   "PATHCONF" },
10045         { 21,   "COMMIT" },
10046         { 0,    NULL }
10047 };
10048
10049 /* end of NFS Version 3 */
10050
10051 /* the call to dissect_nfs3_null_call & dissect_nfs3_null_reply is
10052  * intentional.  The V4 NULLPROC is the same as V3.
10053  */
10054 static const vsff nfs4_proc[] = {
10055         { 0, "NULL",
10056         dissect_nfs3_null_call,         dissect_nfs3_null_reply },
10057         { 1, "COMPOUND",
10058         dissect_nfs4_compound_call, dissect_nfs4_compound_reply },
10059         { 0, NULL, NULL, NULL }
10060 };
10061
10062 static const value_string nfsv4_proc_vals[] = {
10063         { 0, "NULL" },
10064         { 1, "COMPOUND" },
10065         { 0, NULL }
10066 };
10067
10068 /*
10069  * Union of the NFSv2, NFSv3, and NFSv4 status codes.
10070  * Use for the "nfs.status" hidden field.
10071  */
10072 static const value_string names_nfs_nfsstat[] = {
10073         {       0,      "OK"                                            },
10074         {       1,      "ERR_PERM"                                      },
10075         {       2,      "ERR_NOENT"                                     },
10076         {       5,      "ERR_IO"                                        },
10077         {       6,      "ERR_NXIO"                                      },
10078         {       13,     "ERR_ACCES"                                     },
10079         {       17,     "ERR_EXIST"                                     },
10080         {       18,     "ERR_XDEV"                                      },
10081         {       19,     "ERR_NODEV"                                     },
10082         {       20,     "ERR_NOTDIR"                                    },
10083         {       21,     "ERR_ISDIR"                                     },
10084         {       22,     "ERR_INVAL"                                     },
10085         {       26,     "ERR_TXTBSY"                                    },
10086         {       27,     "ERR_FBIG"                                      },
10087         {       28,     "ERR_NOSPC"                                     },
10088         {       30,     "ERR_ROFS"                                      },
10089         {       31,     "ERR_MLINK"                                     },
10090         {       45,     "ERR_OPNOTSUPP"                                 },
10091         {       63,     "ERR_NAMETOOLONG"                               },
10092         {       66,     "ERR_NOTEMPTY"                                  },
10093         {       69,     "ERR_DQUOT"                                     },
10094         {       70,     "ERR_STALE"                                     },
10095         {       71,     "ERR_REMOTE"                                    },
10096         {       99,     "ERR_WFLUSH"                                    },
10097         {       10001,  "ERR_BADHANDLE"                                 },
10098         {       10002,  "ERR_NOT_SYNC"                                  },
10099         {       10003,  "ERR_BAD_COOKIE"                                },
10100         {       10004,  "ERR_NOTSUPP"                                   },
10101         {       10005,  "ERR_TOOSMALL"                                  },
10102         {       10006,  "ERR_SERVERFAULT"                               },
10103         {       10007,  "ERR_BADTYPE"                                   },
10104         {       10008,  "ERR_DELAY"                                     },
10105         {       10009,  "ERR_SAME"                                      },
10106         {       10010,  "ERR_DENIED"                                    },
10107         {       10011,  "ERR_EXPIRED"                                   },
10108         {       10012,  "ERR_LOCKED"                                    },
10109         {       10013,  "ERR_GRACE"                                     },
10110         {       10014,  "ERR_FHEXPIRED"                                 },
10111         {       10015,  "ERR_SHARE_DENIED"                              },
10112         {       10016,  "ERR_WRONGSEC"                                  },
10113         {       10017,  "ERR_CLID_INUSE"                                },
10114         {       10018,  "ERR_RESOURCE"                                  },
10115         {       10019,  "ERR_MOVED"                                     },
10116         {       10020,  "ERR_NOFILEHANDLE"                              },
10117         {       10021,  "ERR_MINOR_VERS_MISMATCH"                       },
10118         {       10022,  "ERR_STALE_CLIENTID"                            },
10119         {       10023,  "ERR_STALE_STATEID"                             },
10120         {       10024,  "ERR_OLD_STATEID"                               },
10121         {       10025,  "ERR_BAD_STATEID"                               },
10122         {       10026,  "ERR_BAD_SEQID"                                 },
10123         {       10027,  "ERR_NOT_SAME"                                  },
10124         {       10028,  "ERR_LOCK_RANGE"                                },
10125         {       10029,  "ERR_SYMLINK"                                   },
10126         {       10030,  "ERR_READDIR_NOSPC"                             },
10127         {       10031,  "ERR_LEASE_MOVED"                               },
10128         {       10032,  "ERR_ATTRNOTSUPP"                               },
10129         {       10033,  "ERR_NO_GRACE"                                  },
10130         {       10034,  "ERR_RECLAIM_BAD"                               },
10131         {       10035,  "ERR_RECLAIM_CONFLICT"                          },
10132         {       10036,  "ERR_BADXDR"                                    },
10133         {       10037,  "ERR_LOCKS_HELD"                                },
10134         {       10038,  "ERR_OPENMODE"                                  },
10135         {       10039,  "ERR_BADOWNER"                                  },
10136         {       10040,  "ERR_BADCHAR"                                   },
10137         {       10041,  "ERR_BADNAME"                                   },
10138         {       10042,  "ERR_BAD_RANGE"                                 },
10139         {       10043,  "ERR_LOCK_NOTSUPP"                              },
10140         {       10044,  "ERR_OP_ILLEGAL"                                },
10141         {       10045,  "ERR_DEADLOCK"                                  },
10142         {       10046,  "ERR_FILE_OPEN"                                 },
10143         {       10047,  "ERR_ADMIN_REVOKED"                             },
10144         {       10048,  "ERR_CB_PATH_DOWN"                              },
10145         {       0,      NULL }
10146 };
10147
10148 static const value_string iomode_names[] = {
10149         { 1, "IOMODE_READ"},
10150         { 2, "IOMODE_RW"},
10151         { 3, "IOMODE_ANY"},
10152         { 0, NULL }
10153 };
10154
10155 static const value_string stripetype_names[] = {
10156         { 1, "STRIPE_SPARSE"},
10157         { 2, "STRIPE_DENSE"},
10158         { 0, NULL }
10159 };
10160
10161 static const value_string layouttype_names[] = {
10162         { 1, "LAYOUT4_NFSV4_1_FILES"},
10163         { 2, "LAYOUT4_OSD2_OBJECTS"},
10164         { 3, "LAYOUT4_BLOCK_VOLUME"},
10165         { 0, NULL }
10166 };
10167
10168 static const value_string layoutreturn_names[] = {
10169         { 1, "RETURN_FILE"},
10170         { 2, "RETURN_FSID"},
10171         { 3, "RETURN_ALL"},
10172         { 0, NULL }
10173 };
10174
10175 static const value_string nfs_fh_obj_id[] = {
10176         { 1, "NF4REG"},
10177         { 2, "NF4DIR"},
10178         { 3, "NF4BLK"},
10179         { 4, "NF4CHR"},
10180         { 5, "NF4LNK"},
10181         { 6, "NF4SOCK"},
10182         { 7, "NF4FIFO"},
10183         { 8, "NF4ATTRDIR"},
10184         { 9, "NF4NAMEDATTR"},
10185         { 0, NULL }
10186 };
10187
10188 static const true_false_string nfsv4_ro_boolean = {
10189         "object is read only",
10190         "object is *not* read-only"
10191 };
10192
10193 static const value_string layoutrecall_names[] = {
10194         { 1, "RECALL_FILE"},
10195         { 2, "RECALL_FSID"},
10196         { 3, "RECALL_ALL"},
10197         { 0, NULL }
10198 };
10199
10200 /* NFS Callback */
10201 static int hf_nfs_cb_procedure = -1;
10202 static int hf_nfs_cb_op = -1;
10203 static int hf_nfs_cb_truncate = -1;
10204 static int hf_nfs_cb_layoutrecall_type = -1;
10205 static int hf_nfs_cb_clorachanged = -1;
10206
10207 static gint ett_nfs_cb_argop = -1;
10208 static gint ett_nfs_cb_resop = -1;
10209 static gint ett_nfs_cb_getattr = -1;
10210 static gint ett_nfs_cb_recall = -1;
10211 static gint ett_nfs_cb_layoutrecall = -1;
10212 static gint ett_nfs_cb_pushdeleg = -1;
10213 static gint ett_nfs_cb_recallany = -1;
10214 static gint ett_nfs_cb_recallableobjavail = -1;
10215 static gint ett_nfs_cb_recallslot = -1;
10216 static gint ett_nfs_cb_sequence = -1;
10217 static gint ett_nfs_cb_wantscancelled = -1;
10218 static gint ett_nfs_cb_notifylock = -1;
10219 static gint ett_nfs_cb_notifydeviceid = -1;
10220 static gint ett_nfs_cb_notify = -1;
10221 static gint ett_nfs_cb_reflists = -1;
10222 static gint ett_nfs_cb_refcalls = -1;
10223 static gint ett_nfs_cb_illegal = -1;
10224
10225 static const value_string names_nfs_cb_operation[] = {
10226         {       NFS4_OP_CB_GETATTR,                             "CB_GETATTR" },
10227         {       NFS4_OP_CB_RECALL,                              "CB_RECALL"     },
10228         {       NFS4_OP_CB_LAYOUTRECALL,                        "CB_LAYOUTRECALL" },
10229         {       NFS4_OP_CB_NOTIFY,                              "CB_NOTIFY" },
10230         {       NFS4_OP_CB_PUSH_DELEG,                          "CB_PUSH_DELEG" },
10231         {       NFS4_OP_CB_RECALL_ANY,                          "CB_RECALL_ANY" },
10232         {       NFS4_OP_CB_RECALLABLE_OBJ_AVAIL,                "CB_RECALLABLE_OBJ_AVAIL" },
10233         {       NFS4_OP_CB_RECALL_SLOT,                         "CB_RECALL_SLOT"},
10234         {       NFS4_OP_CB_SEQUENCE,                            "CB_SEQUENCE"   },
10235         {       NFS4_OP_CB_WANTS_CANCELLED,                     "CB_WANTS_CANCELLED" },
10236         {       NFS4_OP_CB_NOTIFY_LOCK,                         "CB_NOTIFY_LOCK"},
10237         {       NFS4_OP_CB_NOTIFY_DEVICEID,                     "CB_NOTIFY_DEVICEID"    },
10238         {       NFS4_OP_CB_ILLEGAL,                             "CB_ILLEGAL"},
10239         {       0,      NULL }
10240 };
10241 static value_string_ext names_nfs_cb_operation_ext = VALUE_STRING_EXT_INIT(names_nfs_cb_operation);
10242
10243 static gint *nfs_cb_operation_ett[] =
10244 {
10245          &ett_nfs_cb_getattr,
10246          &ett_nfs_cb_recall,
10247          &ett_nfs_cb_layoutrecall,
10248          &ett_nfs_cb_notify,
10249          &ett_nfs_cb_pushdeleg,
10250          &ett_nfs_cb_recallany,
10251          &ett_nfs_cb_recallableobjavail,
10252          &ett_nfs_cb_recallslot,
10253          &ett_nfs_cb_sequence,
10254          &ett_nfs_cb_wantscancelled,
10255          &ett_nfs_cb_notifylock,
10256          &ett_nfs_cb_notifydeviceid,
10257          &ett_nfs_cb_illegal
10258 };
10259
10260 static int
10261 dissect_nfs_cb_referring_calls(tvbuff_t *tvb, int offset, proto_tree *tree)
10262 {
10263         guint num_reflists, num_refcalls, i, j;
10264         proto_item *rl_item, *rc_item;
10265         proto_tree *rl_tree = NULL, *rc_tree = NULL;
10266
10267         num_reflists = tvb_get_ntohl(tvb, offset);
10268         rl_item = proto_tree_add_text(tree, tvb, offset, 4,
10269                         "referring call lists (count: %u)", num_reflists);
10270         offset += 4;
10271         if (num_reflists == 0)
10272                 return offset;
10273
10274         rl_tree = proto_item_add_subtree(rl_item, ett_nfs_cb_reflists);
10275
10276         for (i = 0; i < num_reflists; i++) {
10277                 offset = dissect_rpc_opaque_data(tvb, offset, rl_tree, NULL,
10278                                 hf_nfs_sessionid4, TRUE, 16, FALSE, NULL, NULL);
10279                 num_refcalls = tvb_get_ntohl(tvb, offset);
10280                 rc_item = proto_tree_add_text(rl_tree, tvb, offset, 4,
10281                                 "referring calls (count: %u)", num_refcalls);
10282                 offset += 4;
10283                 for (j = 0; j < num_refcalls; j++) {
10284                         rc_tree = proto_item_add_subtree(rc_item, ett_nfs_cb_refcalls);
10285                         offset = dissect_rpc_uint32(tvb, rc_tree, hf_nfs_seqid4, offset);
10286                         offset = dissect_rpc_uint32(tvb, rc_tree, hf_nfs_slotid4, offset);
10287                 }
10288         }
10289
10290         return offset;
10291 }
10292
10293 static int
10294 dissect_nfs_cb_layoutrecall(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo)
10295 {
10296         guint recall_type;
10297
10298         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_layouttype4, offset);
10299         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_iomode4, offset);
10300         offset = dissect_rpc_bool(tvb, tree, hf_nfs_cb_clorachanged, offset);
10301
10302         recall_type = tvb_get_ntohl(tvb, offset);
10303         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_cb_layoutrecall_type, offset);
10304
10305         if (recall_type == 1) { /* RECALL_FILE */
10306                 offset = dissect_nfs_fh4(tvb, offset, pinfo, tree, "filehandle", NULL);
10307                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset4, offset);
10308                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_length4, offset);
10309                 offset = dissect_nfs_stateid4(tvb, offset, tree, NULL);
10310         } else if (recall_type == 2) { /* RECALL_FSID */
10311                 offset = dissect_nfs_fsid4(tvb, offset, tree, "fsid");
10312         }
10313
10314         return offset;
10315 }
10316
10317 static int
10318 dissect_nfs_cb_argop(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
10319 {
10320         guint32 ops, ops_counter;
10321         guint opcode;
10322         proto_item *fitem;
10323         proto_tree *ftree = NULL;
10324         proto_tree *newftree = NULL;
10325
10326         ops = tvb_get_ntohl(tvb, offset+0);
10327
10328         fitem = proto_tree_add_text(tree, tvb, offset, 4, "Operations (count: %u)", ops);
10329         offset += 4;
10330
10331         if (fitem)
10332                 ftree = proto_item_add_subtree(fitem, ett_nfs_cb_argop);
10333
10334         for (ops_counter=0; ops_counter<ops; ops_counter++)
10335         {
10336                 opcode = tvb_get_ntohl(tvb, offset);
10337                 col_append_fstr(pinfo->cinfo, COL_INFO, "%c%s", ops_counter==0?' ':';',
10338                                 val_to_str_ext_const(opcode, &names_nfs_cb_operation_ext, "Unknown"));
10339
10340                 fitem = proto_tree_add_uint(ftree, hf_nfs_cb_op, tvb, offset, 4, opcode);
10341                 offset += 4;
10342
10343         /* the opcodes are not contiguous */
10344                 if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) &&
10345                     (opcode != NFS4_OP_CB_ILLEGAL))
10346                         break;
10347
10348         /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
10349                 if (opcode == NFS4_OP_CB_ILLEGAL)
10350                         newftree = proto_item_add_subtree(fitem, ett_nfs_cb_illegal);
10351                 else if (nfs_cb_operation_ett[opcode - 3])
10352                         newftree = proto_item_add_subtree(fitem, *nfs_cb_operation_ett[opcode - 3]);
10353                 else
10354                         break;
10355
10356                 switch (opcode)
10357                 {
10358                 case NFS4_OP_CB_RECALL:
10359                         offset = dissect_nfs_stateid4(tvb, offset, newftree, NULL);
10360                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_cb_truncate, offset);
10361                         offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "filehandle", NULL);
10362                         break;
10363                 case NFS4_OP_CB_GETATTR:
10364                 case NFS4_OP_CB_LAYOUTRECALL:
10365                         offset = dissect_nfs_cb_layoutrecall(tvb, offset, newftree, pinfo);
10366                         break;
10367                 case NFS4_OP_CB_NOTIFY:
10368                 case NFS4_OP_CB_PUSH_DELEG:
10369                 case NFS4_OP_CB_RECALL_ANY:
10370                 case NFS4_OP_CB_RECALLABLE_OBJ_AVAIL:
10371                 case NFS4_OP_CB_RECALL_SLOT:
10372                   break;
10373                 case NFS4_OP_CB_SEQUENCE:
10374                         offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL, hf_nfs_sessionid4,
10375                                                          TRUE, 16, FALSE, NULL, NULL);
10376                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset);
10377                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset);
10378                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset);
10379                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_cachethis4, offset);
10380                         offset = dissect_nfs_cb_referring_calls(tvb, offset, newftree);
10381                         break;
10382                 case NFS4_OP_CB_WANTS_CANCELLED:
10383                 case NFS4_OP_CB_NOTIFY_LOCK:
10384                 case NFS4_OP_CB_NOTIFY_DEVICEID:
10385                         break;
10386                 case NFS4_OP_ILLEGAL:
10387                         break;
10388                 default:
10389                         break;
10390                 }
10391         }
10392
10393         return offset;
10394 }
10395
10396 static int
10397 dissect_nfs_cb_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree* tree)
10398 {
10399         char *tag=NULL;
10400
10401         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, &tag);
10402
10403         col_append_fstr(pinfo->cinfo, COL_INFO," %s", tag);
10404
10405         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_minorversion, offset);
10406         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_callback_ident, offset);
10407         offset = dissect_nfs_cb_argop(tvb, offset, pinfo, tree);
10408
10409         return offset;
10410 }
10411
10412 static int
10413 dissect_nfs_cb_resop(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
10414 {
10415         guint32 ops, ops_counter;
10416         guint32 opcode;
10417         proto_item *fitem;
10418         proto_tree *ftree = NULL;
10419         proto_tree *newftree = NULL;
10420         guint32 status;
10421
10422         ops = tvb_get_ntohl(tvb, offset+0);
10423         fitem = proto_tree_add_text(tree, tvb, offset, 4, "Operations (count: %u)", ops);
10424         offset += 4;
10425
10426         if (fitem)
10427                 ftree = proto_item_add_subtree(fitem, ett_nfs_cb_resop);
10428
10429         for (ops_counter = 0; ops_counter < ops; ops_counter++)
10430         {
10431                 opcode = tvb_get_ntohl(tvb, offset);
10432
10433         /* sanity check for bogus packets */
10434                 if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) &&
10435                     (opcode != NFS4_OP_ILLEGAL))
10436                         break;
10437
10438                 col_append_fstr(pinfo->cinfo, COL_INFO, "%c%s", ops_counter==0?' ':';',
10439                                 val_to_str_ext_const(opcode, &names_nfs_cb_operation_ext, "Unknown"));
10440
10441                 fitem = proto_tree_add_uint(ftree, hf_nfs_cb_op, tvb, offset, 4, opcode);
10442                 offset += 4;
10443
10444           /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
10445                 if (opcode == NFS4_OP_ILLEGAL)
10446                   newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4);
10447                 else if (nfs_cb_operation_ett[opcode - 3])
10448                   newftree = proto_item_add_subtree(fitem, *nfs_cb_operation_ett[opcode - 3]);
10449                 else
10450                   break;
10451
10452                 offset = dissect_nfs_nfsstat4(tvb, offset, newftree, &status);
10453
10454           /* are there any ops that return data with a failure (?) */
10455                 if (status != NFS4_OK)
10456                         continue;
10457
10458           /* These parsing routines are only executed if the status is NFS4_OK */
10459                 switch (opcode)
10460                 {
10461                 case NFS4_OP_CB_RECALL:
10462                         break;
10463                 case NFS4_OP_CB_GETATTR:
10464                 case NFS4_OP_CB_LAYOUTRECALL:
10465                         break;
10466                 case NFS4_OP_CB_NOTIFY:
10467                 case NFS4_OP_CB_PUSH_DELEG:
10468                 case NFS4_OP_CB_RECALL_ANY:
10469                 case NFS4_OP_CB_RECALLABLE_OBJ_AVAIL:
10470                 case NFS4_OP_CB_RECALL_SLOT:
10471                         break;
10472                 case NFS4_OP_CB_SEQUENCE:
10473                         offset = dissect_rpc_opaque_data(tvb, offset, newftree, NULL,
10474                                                          hf_nfs_sessionid4, TRUE, 16,
10475                                                          FALSE, NULL, NULL);
10476                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4, offset);
10477                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset);
10478                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset);
10479                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_slotid4, offset);
10480                         break;
10481                 case NFS4_OP_CB_WANTS_CANCELLED:
10482                 case NFS4_OP_CB_NOTIFY_LOCK:
10483                 case NFS4_OP_CB_NOTIFY_DEVICEID:
10484                         break;
10485                 case NFS4_OP_ILLEGAL:
10486                         break;
10487                 default:
10488                         break;
10489                   }
10490         }
10491
10492         return offset;
10493 }
10494
10495 static int
10496 dissect_nfs_cb_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
10497                               proto_tree* tree)
10498 {
10499         guint32 status;
10500         char *tag=NULL;
10501
10502         offset = dissect_nfs_nfsstat4(tvb, offset, tree, &status);
10503         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, &tag);
10504         col_append_fstr(pinfo->cinfo, COL_INFO," %s", tag);
10505
10506         offset = dissect_nfs_cb_resop(tvb, offset, pinfo, tree);
10507
10508         return offset;
10509 }
10510
10511 static const vsff nfs_cb_proc[] = {
10512         { 0, "CB_NULL",
10513           dissect_nfs3_null_call, dissect_nfs3_null_reply },
10514         { 1, "CB_COMPOUND",
10515           dissect_nfs_cb_compound_call, dissect_nfs_cb_compound_reply },
10516         { 0, NULL, NULL, NULL }
10517 };
10518
10519 static const value_string nfs_cb_proc_vals[] = {
10520         { 0, "CB_NULL" },
10521         { 1, "CB_COMPOUND" },
10522         { 0, NULL }
10523 };
10524
10525 void reg_callback(int cbprog)
10526 {
10527         /* Register the protocol as RPC */
10528         rpc_init_prog(proto_nfs, cbprog, ett_nfs);
10529
10530         /*
10531          * Register the procedure tables.  The version should be 4,
10532          * but some Linux kernels set this field to 1.  "Temporarily",
10533          * accomodate these servers.
10534          */
10535         rpc_init_proc_table(cbprog, 1, nfs_cb_proc, hf_nfs_cb_procedure);
10536         rpc_init_proc_table(cbprog, 4, nfs_cb_proc, hf_nfs_cb_procedure);
10537 }
10538
10539 void
10540 proto_register_nfs(void)
10541 {
10542         static hf_register_info hf[] = {
10543                 { &hf_nfs_procedure_v2, {
10544                         "V2 Procedure", "nfs.procedure_v2", FT_UINT32, BASE_DEC,
10545                         VALS(nfsv2_proc_vals), 0, NULL, HFILL }},
10546                 { &hf_nfs_procedure_v3, {
10547                         "V3 Procedure", "nfs.procedure_v3", FT_UINT32, BASE_DEC,
10548                         VALS(nfsv3_proc_vals), 0, NULL, HFILL }},
10549                 { &hf_nfs_procedure_v4, {
10550                         "V4 Procedure", "nfs.procedure_v4", FT_UINT32, BASE_DEC,
10551                         VALS(nfsv4_proc_vals), 0, NULL, HFILL }},
10552                 { &hf_nfs_impl_id4_len, {
10553                         "Implemetation ID length", "nfs.impl_id4.length", FT_UINT32, BASE_DEC,
10554                         NULL, 0, NULL, HFILL }},
10555                 { &hf_nfs_fh_length, {
10556                         "length", "nfs.fh.length", FT_UINT32, BASE_DEC,
10557                         NULL, 0, "file handle length", HFILL }},
10558                 { &hf_nfs_fh_hash, {
10559                         "hash (CRC-32)", "nfs.fh.hash", FT_UINT32, BASE_HEX,
10560                         NULL, 0, "file handle hash", HFILL }},
10561                 { &hf_nfs_fh_mount_fileid, {
10562                         "fileid", "nfs.fh.mount.fileid", FT_UINT32, BASE_DEC,
10563                         NULL, 0, "mount point fileid", HFILL }},
10564                 { &hf_nfs_fh_mount_generation, {
10565                         "generation", "nfs.fh.mount.generation", FT_UINT32, BASE_HEX,
10566                         NULL, 0, "mount point generation", HFILL }},
10567                 { &hf_nfs_fh_flags, {
10568                         "flags", "nfs.fh.flags", FT_UINT16, BASE_HEX,
10569                         NULL, 0, "file handle flags", HFILL }},
10570                 { &hf_nfs_fh_snapid, {
10571                         "snapid", "nfs.fh.snapid", FT_UINT8, BASE_DEC,
10572                         NULL, 0, "snapshot ID", HFILL }},
10573                 { &hf_nfs_fh_unused, {
10574                         "unused", "nfs.fh.unused", FT_UINT8, BASE_DEC,
10575                         NULL, 0, NULL, HFILL }},
10576                 { &hf_nfs_fh_fileid, {
10577                         "fileid", "nfs.fh.fileid", FT_UINT32, BASE_DEC,
10578                         NULL, 0, "file ID", HFILL }},
10579                 { &hf_nfs_fh_generation, {
10580                         "generation", "nfs.fh.generation", FT_UINT32, BASE_HEX,
10581                         NULL, 0, "inode generation", HFILL }},
10582                 { &hf_nfs_fh_fsid, {
10583                         "fsid", "nfs.fh.fsid", FT_UINT32, BASE_HEX,
10584                         NULL, 0, "file system ID", HFILL }},
10585                 { &hf_nfs_fh_export_fileid, {
10586                         "fileid", "nfs.fh.export.fileid", FT_UINT32, BASE_DEC,
10587                         NULL, 0, "export point fileid", HFILL }},
10588                 { &hf_nfs_fh_export_generation, {
10589                         "generation", "nfs.fh.export.generation", FT_UINT32, BASE_HEX,
10590                         NULL, 0, "export point generation", HFILL }},
10591                 { &hf_nfs_fh_export_snapid, {
10592                         "snapid", "nfs.fh.export.snapid", FT_UINT8, BASE_DEC,
10593                         NULL, 0, "export point snapid", HFILL }},
10594                 { &hf_nfs_fh_handle_type, {
10595                         "handletype", "nfs.fh.handletype", FT_UINT32, BASE_DEC,
10596                         NULL, 0, "v4 handle type", HFILL }},
10597                 { &hf_nfs_fh_file_flag_mntpoint, {
10598                         "mount point", "nfs.fh.file.flag.mntpoint", FT_UINT16, BASE_HEX,
10599                         VALS(netapp_file_flag_vals), 0x0001, "file flag: mountpoint", HFILL }},
10600                 { &hf_nfs_fh_file_flag_snapdir, {
10601                         "snapdir", "nfs.fh.file.flag.snapdir", FT_UINT16, BASE_HEX,
10602                         VALS(netapp_file_flag_vals), 0x0002, "file flag: snapdir", HFILL }},
10603                 { &hf_nfs_fh_file_flag_snapdir_ent, {
10604                         "snapdir_ent", "nfs.fh.file.flag.snadir_ent", FT_UINT16, BASE_HEX,
10605                         VALS(netapp_file_flag_vals), 0x0004, "file flag: snapdir_ent", HFILL }},
10606                 { &hf_nfs_fh_file_flag_empty, {
10607                         "empty", "nfs.fh.file.flag.empty", FT_UINT16, BASE_HEX,
10608                         VALS(netapp_file_flag_vals), 0x0008, "file flag: empty", HFILL }},
10609                 { &hf_nfs_fh_file_flag_vbn_access, {
10610                         "vbn_access", "nfs.fh.file.flag.vbn_access", FT_UINT16, BASE_HEX,
10611                         VALS(netapp_file_flag_vals), 0x0010, "file flag: vbn_access", HFILL }},
10612                 { &hf_nfs_fh_file_flag_multivolume, {
10613                         "multivolume", "nfs.fh.file.flag.multivolume", FT_UINT16, BASE_HEX,
10614                         VALS(netapp_file_flag_vals), 0x0020, "file flag: multivolume", HFILL }},
10615                 { &hf_nfs_fh_file_flag_metadata, {
10616                         "metadata", "nfs.fh.file.flag.metadata", FT_UINT16, BASE_HEX,
10617                         VALS(netapp_file_flag_vals), 0x0040, "file flag: metadata", HFILL }},
10618                 { &hf_nfs_fh_file_flag_orphan, {
10619                         "orphan", "nfs.fh.file.flag.orphan", FT_UINT16, BASE_HEX,
10620                         VALS(netapp_file_flag_vals), 0x0080, "file flag: orphan", HFILL }},
10621                 { &hf_nfs_fh_file_flag_foster, {
10622                         "foster", "nfs.fh.file.flag.foster", FT_UINT16, BASE_HEX,
10623                         VALS(netapp_file_flag_vals), 0x0100, "file flag: foster", HFILL }},
10624                 { &hf_nfs_fh_file_flag_named_attr, {
10625                         "named_attr", "nfs.fh.file.flag.named_attr", FT_UINT16, BASE_HEX,
10626                         VALS(netapp_file_flag_vals), 0x0200, "file flag: named_attr", HFILL }},
10627                 { &hf_nfs_fh_file_flag_exp_snapdir, {
10628                         "exp_snapdir", "nfs.fh.file.flag.exp_snapdir", FT_UINT16, BASE_HEX,
10629                         VALS(netapp_file_flag_vals), 0x0400, "file flag: exp_snapdir", HFILL }},
10630                 { &hf_nfs_fh_file_flag_vfiler, {
10631                         "vfiler", "nfs.fh.file.flag.vfiler", FT_UINT16, BASE_HEX,
10632                         VALS(netapp_file_flag_vals), 0x0800, "file flag: vfiler", HFILL }},
10633                 { &hf_nfs_fh_file_flag_aggr, {
10634                         "aggr", "nfs.fh.file.flag.aggr", FT_UINT16, BASE_HEX,
10635                         VALS(netapp_file_flag_vals), 0x1000, "file flag: aggr", HFILL }},
10636                 { &hf_nfs_fh_file_flag_striped, {
10637                         "striped", "nfs.fh.file.flag.striped", FT_UINT16, BASE_HEX,
10638                         VALS(netapp_file_flag_vals), 0x2000, "file flag: striped", HFILL }},
10639                 { &hf_nfs_fh_file_flag_private, {
10640                         "private", "nfs.fh.file.flag.private", FT_UINT16, BASE_HEX,
10641                         VALS(netapp_file_flag_vals), 0x4000, "file flag: private", HFILL }},
10642                 { &hf_nfs_fh_file_flag_next_gen, {
10643                         "next_gen", "nfs.fh.file.flag.next_gen", FT_UINT16, BASE_HEX,
10644                         VALS(netapp_file_flag_vals), 0x8000, "file flag: next_gen", HFILL }},
10645                 { &hf_nfs_fh_fsid_major, {
10646                         "major", "nfs.fh.fsid.major", FT_UINT32, BASE_DEC,
10647                         NULL, 0, "major file system ID", HFILL }},
10648                 { &hf_nfs_fh_fsid_minor, {
10649                         "minor", "nfs.fh.fsid.minor", FT_UINT32, BASE_DEC,
10650                         NULL, 0, "minor file system ID", HFILL }},
10651                 { &hf_nfs_fh_fsid_inode, {
10652                         "inode", "nfs.fh.fsid.inode", FT_UINT32, BASE_DEC,
10653                         NULL, 0, "file system inode", HFILL }},
10654                 { &hf_nfs_fh_xfsid_major, {
10655                         "exported major", "nfs.fh.xfsid.major", FT_UINT32, BASE_DEC,
10656                         NULL, 0, "exported major file system ID", HFILL }},
10657                 { &hf_nfs_fh_xfsid_minor, {
10658                         "exported minor", "nfs.fh.xfsid.minor", FT_UINT32, BASE_DEC,
10659                         NULL, 0, "exported minor file system ID", HFILL }},
10660                 { &hf_nfs_fh_fstype, {
10661                         "file system type", "nfs.fh.fstype", FT_UINT32, BASE_DEC,
10662                         NULL, 0, NULL, HFILL }},
10663                 { &hf_nfs_fh_fn, {
10664                         "file number", "nfs.fh.fn", FT_UINT32, BASE_DEC,
10665                         NULL, 0, NULL, HFILL }},
10666                 { &hf_nfs_fh_fn_len, {
10667                         "length", "nfs.fh.fn.len", FT_UINT32, BASE_DEC,
10668                         NULL, 0, "file number length", HFILL }},
10669                 { &hf_nfs_fh_fn_inode, {
10670                         "inode", "nfs.fh.fn.inode", FT_UINT32, BASE_DEC,
10671                         NULL, 0, "file number inode", HFILL }},
10672                 { &hf_nfs_fh_fn_generation, {
10673                         "generation", "nfs.fh.fn.generation", FT_UINT32, BASE_DEC,
10674                         NULL, 0, "file number generation", HFILL }},
10675                 { &hf_nfs_fh_xfn, {
10676                         "exported file number", "nfs.fh.xfn", FT_UINT32, BASE_DEC,
10677                         NULL, 0, NULL, HFILL }},
10678                 { &hf_nfs_fh_xfn_len, {
10679                         "length", "nfs.fh.xfn.len", FT_UINT32, BASE_DEC,
10680                         NULL, 0, "exported file number length", HFILL }},
10681                 { &hf_nfs_fh_xfn_inode, {
10682                         "exported inode", "nfs.fh.xfn.inode", FT_UINT32, BASE_DEC,
10683                         NULL, 0, "exported file number inode", HFILL }},
10684                 { &hf_nfs_fh_xfn_generation, {
10685                         "generation", "nfs.fh.xfn.generation", FT_UINT32, BASE_DEC,
10686                         NULL, 0, "exported file number generation", HFILL }},
10687                 { &hf_nfs_fh_dentry, {
10688                         "dentry", "nfs.fh.dentry", FT_UINT32, BASE_HEX,
10689                         NULL, 0, "dentry (cookie)", HFILL }},
10690                 { &hf_nfs_fh_dev, {
10691                         "device", "nfs.fh.dev", FT_UINT32, BASE_DEC,
10692                         NULL, 0, NULL, HFILL }},
10693                 { &hf_nfs_fh_xdev, {
10694                         "exported device", "nfs.fh.xdev", FT_UINT32, BASE_DEC,
10695                         NULL, 0, NULL, HFILL }},
10696                 { &hf_nfs_fh_dirinode, {
10697                         "directory inode", "nfs.fh.dirinode", FT_UINT32, BASE_DEC,
10698                         NULL, 0, NULL, HFILL }},
10699                 { &hf_nfs_fh_pinode, {
10700                         "pseudo inode", "nfs.fh.pinode", FT_UINT32, BASE_HEX,
10701                         NULL, 0, NULL, HFILL }},
10702                 { &hf_nfs_fh_hp_len, {
10703                         "length", "nfs.fh.hp.len", FT_UINT32, BASE_DEC,
10704                         NULL, 0, "hash path length", HFILL }},
10705                 { &hf_nfs_fh_version, {
10706                         "version", "nfs.fh.version", FT_UINT8, BASE_DEC,
10707                         NULL, 0, "file handle layout version", HFILL }},
10708                 { &hf_nfs_fh_auth_type, {
10709                         "auth_type", "nfs.fh.auth_type", FT_UINT8, BASE_DEC,
10710                         VALS(auth_type_names), 0, "authentication type", HFILL }},
10711                 { &hf_nfs_fh_fsid_type, {
10712                         "fsid_type", "nfs.fh.fsid_type", FT_UINT8, BASE_DEC,
10713                         VALS(fsid_type_names), 0, "file system ID type", HFILL }},
10714                 { &hf_nfs_fh_fileid_type, {
10715                         "fileid_type", "nfs.fh.fileid_type", FT_UINT8, BASE_DEC,
10716                         VALS(fileid_type_names), 0, "file ID type", HFILL }},
10717                 { &hf_nfs_fh_obj_id, {
10718                         "Object type", "nfs.fh.obj.id", FT_UINT32, BASE_DEC,
10719                         VALS(nfs_fh_obj_id), 0, "Object ID", HFILL }},
10720                 { &hf_nfs_fh_ro_node, {
10721                         "RO_node", "nfs.fh.ro.node", FT_BOOLEAN, BASE_NONE,
10722                         TFS(&nfsv4_ro_boolean), 0, "Read Only Node", HFILL }},
10723                 { &hf_nfs_fh_obj, {
10724                         "Object info", "nfs.fh.obj.info", FT_BYTES, BASE_NONE,
10725                         NULL, 0,"File/Dir/Object Info", HFILL }},
10726                 { &hf_nfs_fh_obj_fsid, {
10727                         "obj_fsid", "nfs.fh.obj.fsid", FT_UINT32, BASE_DEC,
10728                         NULL, 0, "File system ID of the object", HFILL }},
10729                 { &hf_nfs_fh_obj_kindid, {
10730                         "obj_kindid", "nfs.fh.obj.kindid", FT_UINT16, BASE_DEC,
10731                         NULL, 0, "KindID of the object", HFILL }},
10732                 { &hf_nfs_fh_obj_treeid, {
10733                         "obj_treeid", "nfs.fh.obj.treeid", FT_UINT16, BASE_DEC,
10734                         NULL, 0, "TreeID of the object", HFILL }},
10735                 { &hf_nfs_fh_obj_inode, {
10736                         "obj_inode", "nfs.fh.obj.inode", FT_UINT32, BASE_DEC,
10737                         NULL, 0, "Inode of the object", HFILL }},
10738                 { &hf_nfs_fh_obj_gen, {
10739                         "obj_gen", "nfs.fh.obj.gen", FT_UINT32, BASE_DEC,
10740                         NULL, 0, "Generation ID of the object", HFILL }},
10741                 { &hf_nfs_fh_ex, {
10742                         "Export info", "nfs.fh.ex.info", FT_BYTES, BASE_NONE,
10743                         NULL, 0, "Export Info (16 bytes)", HFILL }},
10744                 { &hf_nfs_fh_ex_fsid, {
10745                         "ex_fsid", "nfs.fh.ex.fsid", FT_UINT32, BASE_DEC,
10746                         NULL, 0, "File system ID of the object", HFILL }},
10747                 { &hf_nfs_fh_ex_kindid, {
10748                         "ex_kindid", "nfs.fh.ex.kindid", FT_UINT16, BASE_DEC,
10749                         NULL, 0, "KindID of the object", HFILL }},
10750                 { &hf_nfs_fh_ex_treeid, {
10751                         "ex_treeid", "nfs.fh.ex.treeid", FT_UINT16, BASE_DEC,
10752                         NULL, 0, "TreeID of the object", HFILL }},
10753                 { &hf_nfs_fh_ex_inode, {
10754                         "ex_inode", "nfs.fh.ex.inode", FT_UINT32, BASE_DEC,
10755                         NULL, 0, "Inode of the object", HFILL }},
10756                 { &hf_nfs_fh_ex_gen, {
10757                         "ex_gen", "nfs.fh.ex.gen", FT_UINT32, BASE_DEC,
10758                         NULL, 0, "Generation ID of the object", HFILL }},
10759                 { &hf_nfs_fh_flag, {
10760                         "flag", "nfs.fh.flag", FT_UINT32, BASE_HEX,
10761                         NULL, 0, "file handle flag", HFILL }},
10762                 { &hf_nfs_fh_endianness, {
10763                         "endianness", "nfs.fh.endianness", FT_BOOLEAN, BASE_NONE,
10764                         TFS(&tfs_endianness), 0x0, "server native endianness", HFILL }},
10765                 { &hf_nfs_stat, {
10766                         "Status", "nfs.stat", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
10767                         &names_nfs_stat_ext, 0, "Reply status", HFILL }},
10768                 { &hf_nfs_full_name, {
10769                         "Full Name", "nfs.full_name", FT_STRING, BASE_NONE,
10770                         NULL, 0, NULL, HFILL }},
10771                 { &hf_nfs_name, {
10772                         "Name", "nfs.name", FT_STRING, BASE_NONE,
10773                         NULL, 0, NULL, HFILL }},
10774                 { &hf_nfs_readlink_data, {
10775                         "Data", "nfs.readlink.data", FT_STRING, BASE_NONE,
10776                         NULL, 0, "Symbolic Link Data", HFILL }},
10777                 { &hf_nfs_read_offset, {
10778                         "Offset", "nfs.read.offset", FT_UINT32, BASE_DEC,
10779                         NULL, 0, "Read Offset", HFILL }},
10780                 { &hf_nfs_read_count, {
10781                         "Count", "nfs.read.count", FT_UINT32, BASE_DEC,
10782                         NULL, 0, "Read Count", HFILL }},
10783                 { &hf_nfs_read_totalcount, {
10784                         "Total Count", "nfs.read.totalcount", FT_UINT32, BASE_DEC,
10785                         NULL, 0, "Total Count (obsolete)", HFILL }},
10786                 { &hf_nfs_data, {
10787                         "Data", "nfs.data", FT_BYTES, BASE_NONE,
10788                         NULL, 0, NULL, HFILL }},
10789                 { &hf_read_data_length, {
10790                         "Read length", "nfs.read.data_length", FT_UINT32, BASE_DEC,
10791                         NULL, 0, "Length of read response", HFILL }},
10792                 { &hf_write_data_length, {
10793                         "Write length", "nfs.write.data_length", FT_UINT32, BASE_DEC,
10794                         NULL, 0, "Length of write request", HFILL }},
10795                 { &hf_nfs_write_beginoffset, {
10796                         "Begin Offset", "nfs.write.beginoffset", FT_UINT32, BASE_DEC,
10797                         NULL, 0, "Begin offset (obsolete)", HFILL }},
10798                 { &hf_nfs_write_offset, {
10799                         "Offset", "nfs.write.offset", FT_UINT32, BASE_DEC,
10800                         NULL, 0, NULL, HFILL }},
10801                 { &hf_nfs_write_totalcount, {
10802                         "Total Count", "nfs.write.totalcount", FT_UINT32, BASE_DEC,
10803                         NULL, 0, "Total Count (obsolete)", HFILL }},
10804                 { &hf_nfs_symlink_to, {
10805                         "To", "nfs.symlink.to", FT_STRING, BASE_NONE,
10806                         NULL, 0, "Symbolic link destination name", HFILL }},
10807                 { &hf_nfs_readdir_cookie, {
10808                         "Cookie", "nfs.readdir.cookie", FT_UINT32, BASE_DEC,
10809                         NULL, 0, "Directory Cookie", HFILL }},
10810                 { &hf_nfs_readdir_count, {
10811                         "Count", "nfs.readdir.count", FT_UINT32, BASE_DEC,
10812                         NULL, 0, "Directory Count", HFILL }},
10813
10814                 { &hf_nfs_readdir_entry, {
10815                         "Entry", "nfs.readdir.entry", FT_NONE, BASE_NONE,
10816                         NULL, 0, "Directory Entry", HFILL }},
10817
10818                 { &hf_nfs_readdir_entry_fileid, {
10819                         "File ID", "nfs.readdir.entry.fileid", FT_UINT32, BASE_DEC,
10820                         NULL, 0, NULL, HFILL }},
10821
10822                 { &hf_nfs_readdir_entry_name, {
10823                         "Name", "nfs.readdir.entry.name", FT_STRING, BASE_NONE,
10824                         NULL, 0, NULL, HFILL }},
10825
10826                 { &hf_nfs_readdir_entry_cookie, {
10827                         "Cookie", "nfs.readdir.entry.cookie", FT_UINT32, BASE_DEC,
10828                         NULL, 0, "Directory Cookie", HFILL }},
10829
10830                 { &hf_nfs_readdir_entry3_fileid, {
10831                         "File ID", "nfs.readdir.entry3.fileid", FT_UINT64, BASE_DEC,
10832                         NULL, 0, NULL, HFILL }},
10833
10834                 { &hf_nfs_readdir_entry3_name, {
10835                         "Name", "nfs.readdir.entry3.name", FT_STRING, BASE_NONE,
10836                         NULL, 0, NULL, HFILL }},
10837
10838                 { &hf_nfs_readdir_entry3_cookie, {
10839                         "Cookie", "nfs.readdir.entry3.cookie", FT_UINT64, BASE_DEC,
10840                         NULL, 0, "Directory Cookie", HFILL }},
10841
10842                 { &hf_nfs_readdirplus_entry_fileid, {
10843                         "File ID", "nfs.readdirplus.entry.fileid", FT_UINT64, BASE_DEC,
10844                         NULL, 0, NULL, HFILL }},
10845
10846                 { &hf_nfs_readdirplus_entry_name, {
10847                         "Name", "nfs.readdirplus.entry.name", FT_STRING, BASE_NONE,
10848                         NULL, 0, NULL, HFILL }},
10849
10850                 { &hf_nfs_readdirplus_entry_cookie, {
10851                         "Cookie", "nfs.readdirplus.entry.cookie", FT_UINT64, BASE_DEC,
10852                         NULL, 0, "Directory Cookie", HFILL }},
10853
10854                 { &hf_nfs_readdir_eof, {
10855                         "EOF", "nfs.readdir.eof", FT_UINT32, BASE_DEC,
10856                         NULL, 0, NULL, HFILL }},
10857
10858                 { &hf_nfs_statfs_tsize, {
10859                         "Transfer Size", "nfs.statfs.tsize", FT_UINT32, BASE_DEC,
10860                         NULL, 0, NULL, HFILL }},
10861                 { &hf_nfs_statfs_bsize, {
10862                         "Block Size", "nfs.statfs.bsize", FT_UINT32, BASE_DEC,
10863                         NULL, 0, NULL, HFILL }},
10864                 { &hf_nfs_statfs_blocks, {
10865                         "Total Blocks", "nfs.statfs.blocks", FT_UINT32, BASE_DEC,
10866                         NULL, 0, NULL, HFILL }},
10867                 { &hf_nfs_statfs_bfree, {
10868                         "Free Blocks", "nfs.statfs.bfree", FT_UINT32, BASE_DEC,
10869                         NULL, 0, NULL, HFILL }},
10870                 { &hf_nfs_statfs_bavail, {
10871                         "Available Blocks", "nfs.statfs.bavail", FT_UINT32, BASE_DEC,
10872                         NULL, 0, NULL, HFILL }},
10873                 { &hf_nfs_ftype3, {
10874                         "Type", "nfs.type", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
10875                         &names_nfs_ftype3_ext, 0, "File Type", HFILL }},
10876                 { &hf_nfs_nfsstat3, {
10877                         "Status", "nfs.nfsstat3", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
10878                         &names_nfs_nfsstat3_ext, 0, "Reply status", HFILL }},
10879                 { &hf_nfs_read_eof, {
10880                         "EOF", "nfs.read.eof", FT_BOOLEAN, BASE_NONE,
10881                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
10882                 { &hf_nfs_write_stable, {
10883                         "Stable", "nfs.write.stable", FT_UINT32, BASE_DEC,
10884                         VALS(names_stable_how), 0, NULL, HFILL }},
10885                 { &hf_nfs_write_committed, {
10886                         "Committed", "nfs.write.committed", FT_UINT32, BASE_DEC,
10887                         VALS(names_stable_how), 0, NULL, HFILL }},
10888                 { &hf_nfs_createmode3, {
10889                         "Create Mode", "nfs.createmode", FT_UINT32, BASE_DEC,
10890                         VALS(names_createmode3), 0, NULL, HFILL }},
10891                 { &hf_nfs_fsstat_invarsec, {
10892                         "invarsec", "nfs.fsstat.invarsec", FT_UINT32, BASE_DEC,
10893                         NULL, 0, "probable number of seconds of file system invariance", HFILL }},
10894                 { &hf_nfs_fsinfo_rtmax, {
10895                         "rtmax", "nfs.fsinfo.rtmax", FT_UINT32, BASE_DEC,
10896                         NULL, 0, "maximum READ request", HFILL }},
10897                 { &hf_nfs_fsinfo_rtpref, {
10898                         "rtpref", "nfs.fsinfo.rtpref", FT_UINT32, BASE_DEC,
10899                         NULL, 0, "Preferred READ request size", HFILL }},
10900                 { &hf_nfs_fsinfo_rtmult, {
10901                         "rtmult", "nfs.fsinfo.rtmult", FT_UINT32, BASE_DEC,
10902                         NULL, 0, "Suggested READ multiple", HFILL }},
10903                 { &hf_nfs_fsinfo_wtmax, {
10904                         "wtmax", "nfs.fsinfo.wtmax", FT_UINT32, BASE_DEC,
10905                         NULL, 0, "Maximum WRITE request size", HFILL }},
10906                 { &hf_nfs_fsinfo_wtpref, {
10907                         "wtpref", "nfs.fsinfo.wtpref", FT_UINT32, BASE_DEC,
10908                         NULL, 0, "Preferred WRITE request size", HFILL }},
10909                 { &hf_nfs_fsinfo_wtmult, {
10910                         "wtmult", "nfs.fsinfo.wtmult", FT_UINT32, BASE_DEC,
10911                         NULL, 0, "Suggested WRITE multiple", HFILL }},
10912                 { &hf_nfs_fsinfo_dtpref, {
10913                         "dtpref", "nfs.fsinfo.dtpref", FT_UINT32, BASE_DEC,
10914                         NULL, 0, "Preferred READDIR request", HFILL }},
10915                 { &hf_nfs_fsinfo_maxfilesize, {
10916                         "maxfilesize", "nfs.fsinfo.maxfilesize", FT_UINT64, BASE_DEC,
10917                         NULL, 0, "Maximum file size", HFILL }},
10918                 { &hf_nfs_fsinfo_properties, {
10919                         "Properties", "nfs.fsinfo.properties", FT_UINT32, BASE_HEX,
10920                         NULL, 0, "File System Properties", HFILL }},
10921                 { &hf_nfs_pathconf_linkmax, {
10922                         "linkmax", "nfs.pathconf.linkmax", FT_UINT32, BASE_DEC,
10923                         NULL, 0, "Maximum number of hard links", HFILL }},
10924                 { &hf_nfs_pathconf_name_max, {
10925                         "name_max", "nfs.pathconf.name_max", FT_UINT32, BASE_DEC,
10926                         NULL, 0, "Maximum file name length", HFILL }},
10927                 { &hf_nfs_pathconf_no_trunc, {
10928                         "no_trunc", "nfs.pathconf.no_trunc", FT_BOOLEAN, BASE_NONE,
10929                         TFS(&tfs_yes_no), 0x0, "No long file name truncation", HFILL }},
10930                 { &hf_nfs_pathconf_chown_restricted, {
10931                         "chown_restricted", "nfs.pathconf.chown_restricted", FT_BOOLEAN, BASE_NONE,
10932                         TFS(&tfs_yes_no), 0x0, "chown is restricted to root", HFILL }},
10933                 { &hf_nfs_pathconf_case_insensitive, {
10934                         "case_insensitive", "nfs.pathconf.case_insensitive", FT_BOOLEAN, BASE_NONE,
10935                         TFS(&tfs_yes_no), 0x0, "file names are treated case insensitive", HFILL }},
10936                 { &hf_nfs_pathconf_case_preserving, {
10937                         "case_preserving", "nfs.pathconf.case_preserving", FT_BOOLEAN, BASE_NONE,
10938                         TFS(&tfs_yes_no), 0x0, "file name cases are preserved", HFILL }},
10939
10940                 { &hf_nfs_fattr_type, {
10941                         "type", "nfs.fattr.type", FT_UINT32, BASE_DEC,
10942                         NULL, 0, NULL, HFILL }},
10943
10944                 { &hf_nfs_fattr_nlink, {
10945                         "nlink", "nfs.fattr.nlink", FT_UINT32, BASE_DEC,
10946                         NULL, 0, NULL, HFILL }},
10947
10948                 { &hf_nfs_fattr_uid, {
10949                         "uid", "nfs.fattr.uid", FT_UINT32, BASE_DEC,
10950                         NULL, 0, NULL, HFILL }},
10951
10952                 { &hf_nfs_fattr_gid, {
10953                         "gid", "nfs.fattr.gid", FT_UINT32, BASE_DEC,
10954                         NULL, 0, NULL, HFILL }},
10955
10956                 { &hf_nfs_fattr_size, {
10957                         "size", "nfs.fattr.size", FT_UINT32, BASE_DEC,
10958                         NULL, 0, NULL, HFILL }},
10959
10960                 { &hf_nfs_fattr_blocksize, {
10961                         "blocksize", "nfs.fattr.blocksize", FT_UINT32, BASE_DEC,
10962                         NULL, 0, NULL, HFILL }},
10963
10964                 { &hf_nfs_fattr_rdev, {
10965                         "rdev", "nfs.fattr.rdev", FT_UINT32, BASE_DEC,
10966                         NULL, 0, NULL, HFILL }},
10967
10968                 { &hf_nfs_fattr_blocks, {
10969                         "blocks", "nfs.fattr.blocks", FT_UINT32, BASE_DEC,
10970                         NULL, 0, NULL, HFILL }},
10971
10972                 { &hf_nfs_fattr_fsid, {
10973                         "fsid", "nfs.fattr.fsid", FT_UINT32, BASE_HEX,
10974                         NULL, 0, NULL, HFILL }},
10975
10976                 { &hf_nfs_fattr_fileid, {
10977                         "fileid", "nfs.fattr.fileid", FT_UINT32, BASE_DEC,
10978                         NULL, 0, NULL, HFILL }},
10979
10980                 { &hf_nfs_fattr3_type, {
10981                         "Type", "nfs.fattr3.type", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
10982                         &names_nfs_ftype3_ext, 0, NULL, HFILL }},
10983
10984                 { &hf_nfs_fattr3_nlink, {
10985                         "nlink", "nfs.fattr3.nlink", FT_UINT32, BASE_DEC,
10986                         NULL, 0, NULL, HFILL }},
10987
10988                 { &hf_nfs_fattr3_uid, {
10989                         "uid", "nfs.fattr3.uid", FT_UINT32, BASE_DEC,
10990                         NULL, 0, NULL, HFILL }},
10991
10992                 { &hf_nfs_fattr3_gid, {
10993                         "gid", "nfs.fattr3.gid", FT_UINT32, BASE_DEC,
10994                         NULL, 0, NULL, HFILL }},
10995
10996                 { &hf_nfs_fattr3_size, {
10997                         "size", "nfs.fattr3.size", FT_UINT64, BASE_DEC,
10998                         NULL, 0, NULL, HFILL }},
10999
11000                 { &hf_nfs_fattr3_used, {
11001                         "used", "nfs.fattr3.used", FT_UINT64, BASE_DEC,
11002                         NULL, 0, NULL, HFILL }},
11003
11004                 { &hf_nfs_fattr3_rdev, {
11005                         "rdev", "nfs.fattr3.rdev", FT_UINT32, BASE_DEC,
11006                         NULL, 0, NULL, HFILL }},
11007
11008                 { &hf_nfs_fattr3_fsid, {
11009                         "fsid", "nfs.fattr3.fsid", FT_UINT64, BASE_HEX_DEC,
11010                         NULL, 0, NULL, HFILL }},
11011
11012                 { &hf_nfs_fattr3_fileid, {
11013                         "fileid", "nfs.fattr3.fileid", FT_UINT64, BASE_DEC,
11014                         NULL, 0, NULL, HFILL }},
11015
11016                 { &hf_nfs_wcc_attr_size, {
11017                         "size", "nfs.wcc_attr.size", FT_UINT64, BASE_DEC,
11018                         NULL, 0, NULL, HFILL }},
11019
11020                 { &hf_nfs_set_size3_size, {
11021                         "size", "nfs.set_size3.size", FT_UINT64, BASE_DEC,
11022                         NULL, 0, NULL, HFILL }},
11023
11024                 { &hf_nfs_uid3, {
11025                         "uid", "nfs.uid3", FT_UINT32, BASE_DEC,
11026                         NULL, 0, NULL, HFILL }},
11027
11028                 { &hf_nfs_gid3, {
11029                         "gid", "nfs.gid3", FT_UINT32, BASE_DEC,
11030                         NULL, 0, NULL, HFILL }},
11031
11032                 { &hf_nfs_cookie3, {
11033                         "cookie", "nfs.cookie3", FT_UINT64, BASE_DEC,
11034                         NULL, 0, NULL, HFILL }},
11035
11036                 { &hf_nfs_offset3, {
11037                         "offset", "nfs.offset3", FT_UINT64, BASE_DEC,
11038                         NULL, 0, NULL, HFILL }},
11039
11040                 { &hf_nfs_count3, {
11041                         "count", "nfs.count3", FT_UINT32, BASE_DEC,
11042                         NULL, 0, NULL, HFILL }},
11043
11044                 { &hf_nfs_count3_maxcount, {
11045                         "maxcount", "nfs.count3_maxcount", FT_UINT32, BASE_DEC,
11046                         NULL, 0, NULL, HFILL }},
11047
11048                 { &hf_nfs_count3_dircount, {
11049                         "dircount", "nfs.count3_dircount", FT_UINT32, BASE_DEC,
11050                         NULL, 0, NULL, HFILL }},
11051
11052                 { &hf_nfs_fsstat3_resok_tbytes, {
11053                         "Total bytes", "nfs.fsstat3_resok.tbytes", FT_UINT64, BASE_DEC,
11054                         NULL, 0, NULL, HFILL }},
11055
11056                 { &hf_nfs_fsstat3_resok_fbytes, {
11057                         "Free bytes", "nfs.fsstat3_resok.fbytes", FT_UINT64, BASE_DEC,
11058                         NULL, 0, NULL, HFILL }},
11059
11060                 { &hf_nfs_fsstat3_resok_abytes, {
11061                         "Available free bytes", "nfs.fsstat3_resok.abytes", FT_UINT64, BASE_DEC,
11062                         NULL, 0, NULL, HFILL }},
11063
11064                 { &hf_nfs_fsstat3_resok_tfiles, {
11065                         "Total file slots", "nfs.fsstat3_resok.tfiles", FT_UINT64, BASE_DEC,
11066                         NULL, 0, NULL, HFILL }},
11067
11068                 { &hf_nfs_fsstat3_resok_ffiles, {
11069                         "Free file slots", "nfs.fsstat3_resok.ffiles", FT_UINT64, BASE_DEC,
11070                         NULL, 0, NULL, HFILL }},
11071
11072                 { &hf_nfs_fsstat3_resok_afiles, {
11073                         "Available free file slots", "nfs.fsstat3_resok.afiles", FT_UINT64, BASE_DEC,
11074                         NULL, 0, NULL, HFILL }},
11075
11076                 /* NFSv4 */
11077
11078                 { &hf_nfs_nfsstat4, {
11079                         "Status", "nfs.nfsstat4", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
11080                         &names_nfs_nfsstat4_ext, 0, "Reply status", HFILL }},
11081
11082                 { &hf_nfs_op4, {
11083                         "Opcode", "nfs.opcode", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
11084                         &names_nfsv4_operation_ext, 0, NULL, HFILL }},
11085
11086                 { &hf_nfs_main_opcode, {
11087                         "Main Opcode", "nfs.main_opcode", FT_UINT32, BASE_DEC,
11088                         NULL, 0, "Main Operation number", HFILL }},
11089
11090                 { &hf_nfs_linktext4, {
11091                         "Name", "nfs.symlink.linktext", FT_STRING, BASE_NONE,
11092                         NULL, 0, "Symbolic link contents", HFILL }},
11093
11094                 { &hf_nfs_component4, {
11095                         "Filename", "nfs.pathname.component", FT_STRING, BASE_NONE,
11096                         NULL, 0, "Pathname component", HFILL }},
11097
11098                 { &hf_nfs_tag4, {
11099                         "Tag", "nfs.tag", FT_STRING, BASE_NONE,
11100                         NULL, 0, NULL, HFILL }},
11101
11102                 { &hf_nfs_ops_count4, {
11103                         "Operations", "nfs.ops.count", FT_UINT32, BASE_DEC,
11104                         NULL, 0, "Number of Operations", HFILL }},
11105
11106                 { &hf_nfs_clientid4, {
11107                         "clientid", "nfs.clientid", FT_UINT64, BASE_HEX,
11108                         NULL, 0, "Client ID", HFILL }},
11109
11110                 { &hf_nfs_ace4, {
11111                         "ace", "nfs.ace", FT_STRING, BASE_NONE,
11112                         NULL, 0, "Access Control Entry", HFILL }},
11113
11114                 { &hf_nfs_recall, {
11115                         "Recall", "nfs.recall", FT_BOOLEAN, BASE_NONE,
11116                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11117
11118                 { &hf_nfs_open_claim_type4, {
11119                         "Claim Type", "nfs.open.claim_type", FT_UINT32, BASE_DEC,
11120                         VALS(names_claim_type4), 0, NULL, HFILL }},
11121
11122                 { &hf_nfs_opentype4, {
11123                         "Open Type", "nfs.open.opentype", FT_UINT32, BASE_DEC,
11124                         VALS(names_opentype4), 0, NULL, HFILL }},
11125
11126                 { &hf_nfs_state_protect_how4, {
11127                         "eia_state_protect", "nfs.exchange_id.state_protect", FT_UINT32, BASE_DEC,
11128                         VALS(names_state_protect_how4), 0, "State Protect How", HFILL }},
11129
11130                 { &hf_nfs_limit_by4, {
11131                         "Space Limit", "nfs.open.limit_by", FT_UINT32, BASE_DEC,
11132                         VALS(names_limit_by4), 0, "Limit By", HFILL }},
11133
11134                 { &hf_nfs_open_delegation_type4, {
11135                         "Delegation Type", "nfs.open.delegation_type", FT_UINT32, BASE_DEC,
11136                         VALS(names_open_delegation_type4), 0, NULL, HFILL }},
11137
11138                 { &hf_nfs_ftype4, {
11139                         "nfs_ftype4", "nfs.nfs_ftype4", FT_UINT32, BASE_DEC,
11140                         VALS(names_ftype4), 0, NULL, HFILL }},
11141
11142                 { &hf_nfs_change_info4_atomic, {
11143                         "Atomic", "nfs.change_info.atomic", FT_BOOLEAN, BASE_NONE,
11144                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11145
11146                 { &hf_nfs_open4_share_access, {
11147                         "share_access", "nfs.open4.share_access", FT_UINT32, BASE_DEC,
11148                         VALS(names_open4_share_access), 0, NULL, HFILL }},
11149
11150                 { &hf_nfs_open4_share_deny, {
11151                         "share_deny", "nfs.open4.share_deny", FT_UINT32, BASE_DEC,
11152                         VALS(names_open4_share_deny), 0, NULL, HFILL }},
11153
11154                 { &hf_nfs_seqid4, {
11155                         "seqid", "nfs.seqid", FT_UINT32, BASE_HEX,
11156                         NULL, 0, "Sequence ID", HFILL }},
11157
11158                 { &hf_nfs_lock_seqid4, {
11159                         "lock_seqid", "nfs.lock_seqid", FT_UINT32, BASE_HEX,
11160                         NULL, 0, "Lock Sequence ID", HFILL }},
11161
11162                 { &hf_nfs_mand_attr, {
11163                         "mand_attr", "nfs.attr", FT_UINT32, BASE_DEC,
11164                         VALS(names_fattr4), 0, "Mandatory Attribute", HFILL }},
11165
11166                 { &hf_nfs_recc_attr, {
11167                         "recc_attr", "nfs.attr", FT_UINT32, BASE_DEC,
11168                         VALS(names_fattr4), 0, "Recommended Attribute", HFILL }},
11169
11170                 { &hf_nfs_time_how4,    {
11171                         "set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
11172                         VALS(names_time_how4), 0, "How To Set Time", HFILL }},
11173
11174                 { &hf_nfs_attrlist4, {
11175                         "attr_vals", "nfs.fattr4.attr_vals", FT_BYTES, BASE_NONE,
11176                         NULL, 0, NULL, HFILL }},
11177
11178                 { &hf_nfs_fattr4_link_support, {
11179                         "fattr4_link_support", "nfs.fattr4_link_support", FT_BOOLEAN, BASE_NONE,
11180                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11181
11182                 { &hf_nfs_fattr4_symlink_support, {
11183                         "fattr4_symlink_support", "nfs.fattr4_symlink_support", FT_BOOLEAN, BASE_NONE,
11184                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11185
11186                 { &hf_nfs_fattr4_named_attr, {
11187                         "fattr4_named_attr", "nfs.fattr4_named_attr", FT_BOOLEAN, BASE_NONE,
11188                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11189
11190                 { &hf_nfs_fattr4_unique_handles, {
11191                         "fattr4_unique_handles", "nfs.fattr4_unique_handles", FT_BOOLEAN, BASE_NONE,
11192                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11193
11194                 { &hf_nfs_fattr4_archive, {
11195                         "fattr4_archive", "nfs.fattr4_archive", FT_BOOLEAN, BASE_NONE,
11196                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11197
11198                 { &hf_nfs_fattr4_cansettime, {
11199                         "fattr4_cansettime", "nfs.fattr4_cansettime", FT_BOOLEAN, BASE_NONE,
11200                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11201
11202                 { &hf_nfs_fattr4_case_insensitive, {
11203                         "fattr4_case_insensitive", "nfs.fattr4_case_insensitive", FT_BOOLEAN, BASE_NONE,
11204                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11205
11206                 { &hf_nfs_fattr4_case_preserving, {
11207                         "fattr4_case_preserving", "nfs.fattr4_case_preserving", FT_BOOLEAN, BASE_NONE,
11208                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11209
11210                 { &hf_nfs_fattr4_chown_restricted, {
11211                         "fattr4_chown_restricted", "nfs.fattr4_chown_restricted", FT_BOOLEAN, BASE_NONE,
11212                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11213
11214                 { &hf_nfs_fattr4_hidden, {
11215                         "fattr4_hidden", "nfs.fattr4_hidden", FT_BOOLEAN, BASE_NONE,
11216                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11217
11218                 { &hf_nfs_fattr4_homogeneous, {
11219                         "fattr4_homogeneous", "nfs.fattr4_homogeneous", FT_BOOLEAN, BASE_NONE,
11220                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11221
11222                 { &hf_nfs_fattr4_mimetype, {
11223                         "fattr4_mimetype", "nfs.fattr4_mimetype", FT_STRING, BASE_NONE,
11224                         NULL, 0, NULL, HFILL }},
11225
11226                 { &hf_nfs_fattr4_no_trunc, {
11227                         "fattr4_no_trunc", "nfs.fattr4_no_trunc", FT_BOOLEAN, BASE_NONE,
11228                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11229
11230                 { &hf_nfs_fattr4_system, {
11231                         "fattr4_system", "nfs.fattr4_system", FT_BOOLEAN, BASE_NONE,
11232                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11233
11234                 { &hf_nfs_who, {
11235                         "who", "nfs.who", FT_STRING, BASE_NONE,
11236                         NULL, 0, NULL, HFILL }},
11237
11238                 { &hf_nfs_server, {
11239                         "server", "nfs.server", FT_STRING, BASE_NONE,
11240                         NULL, 0, NULL, HFILL }},
11241
11242                 { &hf_nfs_fslocation4, {
11243                         "fs_location4", "nfs.fattr4.fs_location", FT_STRING, BASE_NONE,
11244                         NULL, 0, NULL, HFILL }},
11245
11246                 { &hf_nfs_fattr4_owner, {
11247                         "fattr4_owner", "nfs.fattr4_owner", FT_STRING, BASE_NONE,
11248                         NULL, 0, NULL, HFILL }},
11249
11250                 { &hf_nfs_fattr4_owner_group, {
11251                         "fattr4_owner_group", "nfs.fattr4_owner_group", FT_STRING, BASE_NONE,
11252                         NULL, 0, NULL, HFILL }},
11253
11254                 { &hf_nfs_stable_how4, {
11255                         "stable_how4", "nfs.stable_how4", FT_UINT32, BASE_DEC,
11256                         VALS(names_stable_how4), 0, NULL, HFILL }},
11257
11258                 { &hf_nfs_dirlist4_eof, {
11259                         "eof", "nfs.dirlist4.eof", FT_BOOLEAN, BASE_NONE,
11260                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11261
11262                 { &hf_nfs_stateid4, {
11263                         "stateid", "nfs.stateid4", FT_UINT64, BASE_DEC,
11264                         NULL, 0, NULL, HFILL }},
11265
11266                 { &hf_nfs_offset4, {
11267                         "offset", "nfs.offset4", FT_UINT64, BASE_DEC,
11268                         NULL, 0, NULL, HFILL }},
11269
11270                 { &hf_nfs_specdata1, {
11271                         "specdata1", "nfs.specdata1", FT_UINT32, BASE_DEC,
11272                         NULL, 0, NULL, HFILL }},
11273
11274                 { &hf_nfs_specdata2, {
11275                         "specdata2", "nfs.specdata2", FT_UINT32, BASE_DEC,
11276                         NULL, 0, NULL, HFILL }},
11277
11278                 { &hf_nfs_lock_type4, {
11279                         "locktype", "nfs.locktype4", FT_UINT32, BASE_DEC,
11280                         VALS(names_nfs_lock_type4), 0, NULL, HFILL }},
11281
11282                 { &hf_nfs_reclaim4, {
11283                         "reclaim", "nfs.reclaim4", FT_BOOLEAN, BASE_NONE,
11284                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11285
11286                 { &hf_nfs_length4, {
11287                         "length", "nfs.length4", FT_UINT64, BASE_DEC,
11288                         NULL, 0, NULL, HFILL }},
11289
11290                 { &hf_nfs_changeid4, {
11291                         "changeid", "nfs.changeid4", FT_UINT64, BASE_DEC,
11292                         NULL, 0, NULL, HFILL }},
11293
11294                 { &hf_nfs_changeid4_before, {
11295                         "changeid (before)", "nfs.changeid4.before", FT_UINT64, BASE_DEC,
11296                         NULL, 0, NULL, HFILL }},
11297
11298                 { &hf_nfs_changeid4_after, {
11299                         "changeid (after)", "nfs.changeid4.after", FT_UINT64, BASE_DEC,
11300                         NULL, 0, NULL, HFILL }},
11301
11302                 { &hf_nfs_nfstime4_seconds, {
11303                         "seconds", "nfs.nfstime4.seconds", FT_UINT64, BASE_DEC,
11304                         NULL, 0, NULL, HFILL }},
11305
11306                 { &hf_nfs_nfstime4_nseconds, {
11307                         "nseconds", "nfs.nfstime4.nseconds", FT_UINT32, BASE_DEC,
11308                         NULL, 0, NULL, HFILL }},
11309
11310                 { &hf_nfs_fsid4_major, {
11311                         "fsid4.major", "nfs.fsid4.major", FT_UINT64, BASE_DEC,
11312                         NULL, 0, NULL, HFILL }},
11313
11314                 { &hf_nfs_fsid4_minor, {
11315                         "fsid4.minor", "nfs.fsid4.minor", FT_UINT64, BASE_DEC,
11316                         NULL, 0, NULL, HFILL }},
11317
11318                 { &hf_nfs_acetype4, {
11319                         "acetype", "nfs.acetype4", FT_UINT32, BASE_DEC,
11320                         VALS(names_acetype4), 0, NULL, HFILL }},
11321
11322                 { &hf_nfs_aceflag4, {
11323                         "aceflag", "nfs.aceflag4", FT_UINT32, BASE_DEC,
11324                         NULL, 0, NULL, HFILL }},
11325
11326                 { &hf_nfs_acemask4, {
11327                         "acemask", "nfs.acemask4", FT_UINT32, BASE_DEC,
11328                         NULL, 0, NULL, HFILL }},
11329
11330                 { &hf_nfs_fattr4_size, {
11331                         "size", "nfs.fattr4.size", FT_UINT64, BASE_DEC,
11332                         NULL, 0, NULL, HFILL }},
11333
11334                 { &hf_nfs_fattr4_lease_time, {
11335                         "lease_time", "nfs.fattr4.lease_time", FT_UINT32, BASE_DEC,
11336                         NULL, 0, NULL, HFILL }},
11337
11338                 { &hf_nfs_fattr4_aclsupport, {
11339                         "aclsupport", "nfs.fattr4.aclsupport", FT_UINT32, BASE_DEC,
11340                         NULL, 0, NULL, HFILL }},
11341
11342                 { &hf_nfs_fattr4_fileid, {
11343                         "fileid", "nfs.fattr4.fileid", FT_UINT64, BASE_DEC,
11344                         NULL, 0, NULL, HFILL }},
11345
11346                 { &hf_nfs_fattr4_files_avail, {
11347                         "files_avail", "nfs.fattr4.files_avail", FT_UINT64, BASE_DEC,
11348                         NULL, 0, NULL, HFILL }},
11349
11350                 { &hf_nfs_fattr4_files_free, {
11351                         "files_free", "nfs.fattr4.files_free", FT_UINT64, BASE_DEC,
11352                         NULL, 0, NULL, HFILL }},
11353
11354                 { &hf_nfs_fattr4_files_total, {
11355                         "files_total", "nfs.fattr4.files_total", FT_UINT64, BASE_DEC,
11356                         NULL, 0, NULL, HFILL }},
11357
11358                 { &hf_nfs_fattr4_maxfilesize, {
11359                         "maxfilesize", "nfs.fattr4.maxfilesize", FT_UINT64, BASE_DEC,
11360                         NULL, 0, NULL, HFILL }},
11361
11362                 { &hf_nfs_fattr4_maxlink, {
11363                         "maxlink", "nfs.fattr4.maxlink", FT_UINT32, BASE_DEC,
11364                         NULL, 0, NULL, HFILL }},
11365
11366                 { &hf_nfs_fattr4_maxname, {
11367                         "maxname", "nfs.fattr4.maxname", FT_UINT32, BASE_DEC,
11368                         NULL, 0, NULL, HFILL }},
11369
11370                 { &hf_nfs_fattr4_numlinks, {
11371                         "numlinks", "nfs.fattr4.numlinks", FT_UINT32, BASE_DEC,
11372                         NULL, 0, NULL, HFILL }},
11373
11374                 { &hf_nfs_delegate_type, {
11375                         "delegate_type", "nfs.delegate_type", FT_UINT32, BASE_DEC,
11376                         NULL, 0, NULL, HFILL }},
11377
11378                 { &hf_nfs_secinfo_flavor, {
11379                         "flavor", "nfs.secinfo.flavor", FT_UINT32, BASE_DEC,
11380                         VALS(rpc_auth_flavor), 0, NULL, HFILL }},
11381
11382                 { &hf_nfs_num_blocks, {
11383                         "num_blocks", "nfs.num_blocks", FT_UINT32, BASE_DEC,
11384                         NULL, 0, NULL, HFILL }},
11385
11386                 { &hf_nfs_bytes_per_block, {
11387                         "bytes_per_block", "nfs.bytes_per_block", FT_UINT32, BASE_DEC,
11388                         NULL, 0, NULL, HFILL }},
11389
11390                 { &hf_nfs_eof, {
11391                         "eof", "nfs.eof", FT_UINT32, BASE_DEC,
11392                         NULL, 0, NULL, HFILL }},
11393
11394                 { &hf_nfs_fattr4_maxread, {
11395                         "maxread", "nfs.fattr4.maxread", FT_UINT64, BASE_DEC,
11396                         NULL, 0, NULL, HFILL }},
11397
11398                 { &hf_nfs_fattr4_maxwrite, {
11399                         "maxwrite", "nfs.fattr4.maxwrite", FT_UINT64, BASE_DEC,
11400                         NULL, 0, NULL, HFILL }},
11401
11402                 { &hf_nfs_fattr4_quota_hard, {
11403                         "quota_hard", "nfs.fattr4.quota_hard", FT_UINT64, BASE_DEC,
11404                         NULL, 0, NULL, HFILL }},
11405
11406                 { &hf_nfs_fattr4_quota_soft, {
11407                         "quota_soft", "nfs.fattr4.quota_soft", FT_UINT64, BASE_DEC,
11408                         NULL, 0, NULL, HFILL }},
11409
11410                 { &hf_nfs_fattr4_quota_used, {
11411                         "quota_used", "nfs.fattr4.quota_used", FT_UINT64, BASE_DEC,
11412                         NULL, 0, NULL, HFILL }},
11413
11414                 { &hf_nfs_fattr4_space_avail, {
11415                         "space_avail", "nfs.fattr4.space_avail", FT_UINT64, BASE_DEC,
11416                         NULL, 0, NULL, HFILL }},
11417
11418                 { &hf_nfs_fattr4_space_free, {
11419                         "space_free", "nfs.fattr4.space_free", FT_UINT64, BASE_DEC,
11420                         NULL, 0, NULL, HFILL }},
11421
11422                 { &hf_nfs_fattr4_space_total, {
11423                         "space_total", "nfs.fattr4.space_total", FT_UINT64, BASE_DEC,
11424                         NULL, 0, NULL, HFILL }},
11425
11426                 { &hf_nfs_fattr4_space_used, {
11427                         "space_used", "nfs.fattr4.space_used", FT_UINT64, BASE_DEC,
11428                         NULL, 0, NULL, HFILL }},
11429
11430                 { &hf_nfs_fattr4_mounted_on_fileid, {
11431                         "fileid", "nfs.fattr4.mounted_on_fileid", FT_UINT64, BASE_HEX,
11432                         NULL, 0, NULL, HFILL }},
11433
11434                 { &hf_nfs_fattr4_layout_blksize, {
11435                         "fileid", "nfs.fattr4.layout_blksize", FT_UINT32, BASE_DEC,
11436                         NULL, 0, NULL, HFILL }},
11437
11438                 { &hf_nfs_verifier4, {
11439                         "verifier", "nfs.verifier4", FT_UINT64, BASE_HEX,
11440                         NULL, 0, NULL, HFILL }},
11441
11442                 { &hf_nfs_cookie4, {
11443                         "cookie", "nfs.cookie4", FT_UINT64, BASE_DEC,
11444                         NULL, 0, NULL, HFILL }},
11445
11446                 { &hf_nfs_cookieverf4, {
11447                         "cookieverf", "nfs.cookieverf4", FT_UINT64, BASE_DEC,
11448                         NULL, 0, NULL, HFILL }},
11449
11450                 { &hf_nfs_cb_location, {
11451                         "cb_location", "nfs.cb_location", FT_UINT32, BASE_DEC,
11452                         NULL, 0, NULL, HFILL }},
11453
11454                 { &hf_nfs_cb_program, {
11455                         "cb_program", "nfs.cb_program", FT_UINT32, BASE_HEX,
11456                         NULL, 0, NULL, HFILL }},
11457
11458                 { &hf_nfs_recall4, {
11459                         "recall", "nfs.recall4", FT_BOOLEAN, BASE_NONE,
11460                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11461
11462                 { &hf_nfs_filesize, {
11463                         "filesize", "nfs.filesize", FT_UINT64, BASE_DEC,
11464                         NULL, 0, NULL, HFILL }},
11465
11466                 { &hf_nfs_count4, {
11467                         "count", "nfs.count4", FT_UINT32, BASE_DEC,
11468                         NULL, 0, NULL, HFILL }},
11469
11470                 { &hf_nfs_count4_dircount, {
11471                         "dircount", "nfs.dircount", FT_UINT32, BASE_DEC,
11472                         NULL, 0, NULL, HFILL }},
11473
11474                 { &hf_nfs_count4_maxcount, {
11475                         "maxcount", "nfs.maxcount", FT_UINT32, BASE_DEC,
11476                         NULL, 0, NULL, HFILL }},
11477
11478                 { &hf_nfs_minorversion, {
11479                         "minorversion", "nfs.minorversion", FT_UINT32, BASE_DEC,
11480                         NULL, 0, NULL, HFILL }},
11481
11482                 { &hf_nfs_atime, {
11483                         "atime", "nfs.atime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
11484                         NULL, 0, "Access Time", HFILL }},
11485
11486                 { &hf_nfs_atime_sec, {
11487                         "seconds", "nfs.atime.sec", FT_UINT32, BASE_DEC,
11488                         NULL, 0, "Access Time, Seconds", HFILL }},
11489
11490                 { &hf_nfs_atime_nsec, {
11491                         "nano seconds", "nfs.atime.nsec", FT_UINT32, BASE_DEC,
11492                         NULL, 0, "Access Time, Nano-seconds", HFILL }},
11493
11494                 { &hf_nfs_atime_usec, {
11495                         "micro seconds", "nfs.atime.usec", FT_UINT32, BASE_DEC,
11496                         NULL, 0, "Access Time, Micro-seconds", HFILL }},
11497
11498                 { &hf_nfs_mtime, {
11499                         "mtime", "nfs.mtime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
11500                         NULL, 0, "Modify Time", HFILL }},
11501
11502                 { &hf_nfs_mtime_sec, {
11503                         "seconds", "nfs.mtime.sec", FT_UINT32, BASE_DEC,
11504                         NULL, 0, "Modify Seconds", HFILL }},
11505
11506                 { &hf_nfs_mtime_nsec, {
11507                         "nano seconds", "nfs.mtime.nsec", FT_UINT32, BASE_DEC,
11508                         NULL, 0, "Modify Time, Nano-seconds", HFILL }},
11509
11510                 { &hf_nfs_mtime_usec, {
11511                         "micro seconds", "nfs.mtime.usec", FT_UINT32, BASE_DEC,
11512                         NULL, 0, "Modify Time, Micro-seconds", HFILL }},
11513
11514                 { &hf_nfs_ctime, {
11515                         "ctime", "nfs.ctime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
11516                         NULL, 0, "Creation Time", HFILL }},
11517
11518                 { &hf_nfs_ctime_sec, {
11519                         "seconds", "nfs.ctime.sec", FT_UINT32, BASE_DEC,
11520                         NULL, 0, "Creation Time, Seconds", HFILL }},
11521
11522                 { &hf_nfs_ctime_nsec, {
11523                         "nano seconds", "nfs.ctime.nsec", FT_UINT32, BASE_DEC,
11524                         NULL, 0, "Creation Time, Nano-seconds", HFILL }},
11525
11526                 { &hf_nfs_ctime_usec, {
11527                         "micro seconds", "nfs.ctime.usec", FT_UINT32, BASE_DEC,
11528                         NULL, 0, "Creation Time, Micro-seconds", HFILL }},
11529
11530                 { &hf_nfs_dtime, {
11531                         "time delta", "nfs.dtime", FT_RELATIVE_TIME, BASE_NONE,
11532                         NULL, 0, NULL, HFILL }},
11533
11534                 { &hf_nfs_dtime_sec, {
11535                         "seconds", "nfs.dtime.sec", FT_UINT32, BASE_DEC,
11536                         NULL, 0, "Time Delta, Seconds", HFILL }},
11537
11538                 { &hf_nfs_dtime_nsec, {
11539                         "nano seconds", "nfs.dtime.nsec", FT_UINT32, BASE_DEC,
11540                         NULL, 0, "Time Delta, Nano-seconds", HFILL }},
11541
11542                 { &hf_nfs_open_owner4, {
11543                         "owner", "nfs.open_owner4", FT_BYTES, BASE_NONE,
11544                         NULL, 0, NULL, HFILL }},
11545
11546                 { &hf_nfs_lock_owner4, {
11547                         "owner", "nfs.lock_owner4", FT_BYTES, BASE_NONE,
11548                         NULL, 0, NULL, HFILL }},
11549
11550                 { &hf_nfs_createmode4, {
11551                         "Create Mode", "nfs.createmode4", FT_UINT32, BASE_DEC,
11552                         VALS(names_createmode4), 0, NULL, HFILL }},
11553
11554                 { &hf_nfs_secinfo_rpcsec_gss_info_service, {
11555                         "service", "nfs.secinfo.rpcsec_gss_info.service", FT_UINT32, BASE_DEC,
11556                         VALS(rpc_authgss_svc), 0, NULL, HFILL }},
11557
11558                 { &hf_nfs_attrdircreate, {
11559                         "attribute dir create", "nfs.openattr4.createdir", FT_BOOLEAN, BASE_NONE,
11560                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11561
11562                 { &hf_nfs_new_lock_owner, {
11563                         "new lock owner?", "nfs.lock.locker.new_lock_owner", FT_BOOLEAN, BASE_NONE,
11564                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11565
11566                 { &hf_nfs_lock4_reclaim, {
11567                         "reclaim?", "nfs.lock.reclaim", FT_BOOLEAN, BASE_NONE,
11568                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11569
11570                 { &hf_nfs_sec_oid4, {
11571                         "oid", "nfs.secinfo.flavor_info.rpcsec_gss_info.oid", FT_BYTES, BASE_NONE,
11572                         NULL, 0, NULL, HFILL }},
11573
11574                 { &hf_nfs_qop4, {
11575                         "qop", "nfs.secinfo.flavor_info.rpcsec_gss_info.qop", FT_UINT32, BASE_DEC,
11576                         NULL, 0, NULL, HFILL }},
11577
11578                 { &hf_nfs_client_id4_id, {
11579                         "id", "nfs.nfs_client_id4.id", FT_BYTES, BASE_NONE,
11580                         NULL, 0, NULL, HFILL }},
11581
11582                 { &hf_nfs_stateid4_other, {
11583                         "Data", "nfs.stateid4.other", FT_BYTES, BASE_NONE,
11584                         NULL, 0, NULL, HFILL }},
11585
11586                 { &hf_nfs_stateid4_hash, {
11587                         "StateID Hash", "nfs.stateid4.hash", FT_UINT16, BASE_HEX,
11588                         NULL, 0, NULL, HFILL }},
11589
11590                 { &hf_nfs_acl4, {
11591                         "ACL", "nfs.acl", FT_NONE, BASE_NONE,
11592                         NULL, 0, "Access Control List", HFILL }},
11593
11594                 { &hf_nfs_callback_ident, {
11595                         "callback_ident", "nfs.callback.ident", FT_UINT32, BASE_HEX,
11596                         NULL, 0, "Callback Identifier", HFILL }},
11597
11598                 { &hf_nfs_gsshandle4, {
11599                         "gsshandle4", "nfs.gsshandle4", FT_BYTES, BASE_NONE,
11600                         NULL, 0, NULL, HFILL }},
11601
11602                 { &hf_nfs_r_netid, {
11603                         "r_netid", "nfs.r_netid", FT_STRING, BASE_NONE,
11604                         NULL, 0, NULL, HFILL }},
11605
11606                 { &hf_nfs_r_addr, {
11607                         "r_addr", "nfs.r_addr", FT_STRING, BASE_NONE,
11608                         NULL, 0, NULL, HFILL }},
11609
11610                 { &hf_nfs_fh_fhandle_data, {
11611                         "filehandle", "nfs.fhandle", FT_BYTES, BASE_NONE,
11612                         NULL, 0, "Opaque nfs filehandle", HFILL }},
11613
11614                 { &hf_nfs_secinfo_arr4, {
11615                         "Flavors Info", "nfs.flavors.info", FT_NONE, BASE_NONE,
11616                         NULL, 0, NULL, HFILL }},
11617
11618                 { &hf_gxfh3_utlfield, {
11619                         "utility", "nfs.gxfh3.utility", FT_UINT8, BASE_HEX,
11620                         NULL, 0, NULL, HFILL }},
11621
11622                 { &hf_gxfh3_utlfield_tree_r, {
11623                         "tree R", "nfs.gxfh3.utlfield.treeR", FT_UINT8, BASE_HEX,
11624                         NULL, NFS3GX_FH_TREE_MASK, NULL, HFILL }},
11625
11626                 { &hf_gxfh3_utlfield_tree_w, {
11627                         "tree W", "nfs.gxfh3.utlfield.treeW", FT_UINT8, BASE_HEX,
11628                         NULL, NFS3GX_FH_TREE_MASK, NULL, HFILL }},
11629
11630                 { &hf_gxfh3_utlfield_jun, {
11631                         "broken junction", "nfs.gxfh3.utlfield.junction", FT_UINT8, BASE_HEX,
11632                         NULL, NFS3GX_FH_JUN_MASK, NULL, HFILL }},
11633
11634                 { &hf_gxfh3_utlfield_jun_not, {
11635                         "not broken junction", "nfs.gxfh3.utlfield.notjunction", FT_UINT8, BASE_HEX,
11636                         NULL, NFS3GX_FH_JUN_MASK, NULL, HFILL }},
11637
11638                 { &hf_gxfh3_utlfield_ver, {
11639                         "file handle version","nfs.gxfh3.utlfield.version", FT_UINT8, BASE_HEX,
11640                         NULL, NFS3GX_FH_VER_MASK, NULL, HFILL }},
11641
11642                 { &hf_gxfh3_volcnt, {
11643                         "volume count", "nfs.gxfh3.volcnt", FT_UINT8, BASE_HEX,
11644                         NULL, 0, NULL, HFILL }},
11645
11646                 { &hf_gxfh3_epoch, {
11647                         "epoch", "nfs.gxfh3.epoch", FT_UINT16, BASE_HEX,
11648                         NULL, 0, NULL, HFILL }},
11649
11650                 { &hf_gxfh3_ldsid, {
11651                         "local dsid", "nfs.gxfh3.ldsid", FT_UINT32, BASE_HEX,
11652                         NULL, 0, NULL, HFILL }},
11653
11654                 { &hf_gxfh3_cid, {
11655                         "cluster id", "nfs.gxfh3.cid", FT_UINT16, BASE_HEX,
11656                         NULL, 0, NULL, HFILL }},
11657
11658                 { &hf_gxfh3_resv, {
11659                         "reserved", "nfs.gxfh3.reserved", FT_UINT16, BASE_HEX,
11660                         NULL, 0, NULL, HFILL }},
11661
11662                 { &hf_gxfh3_sfhflags, {
11663                         "flags", "nfs.gxfh3.sfhflags", FT_UINT8, BASE_HEX,
11664                         NULL, 0, NULL, HFILL }},
11665
11666                 { &hf_gxfh3_sfhflags_resv1, {
11667                         "reserved", "nfs.gxfh3.sfhflags.reserve1", FT_UINT8, BASE_HEX,
11668                         NULL, SPINNP_FH_FLAG_RESV1, NULL, HFILL }},
11669
11670                 { &hf_gxfh3_sfhflags_resv2, {
11671                         "reserved", "nfs.gxfh3.sfhflags.reserv2", FT_UINT8, BASE_HEX,
11672                         NULL, SPINNP_FH_FLAG_RESV2, NULL, HFILL }},
11673
11674                 { &hf_gxfh3_sfhflags_ontap7G, {
11675                         "ontap-7g", "nfs.gxfh3.sfhflags.ontap7g", FT_UINT8, BASE_HEX,
11676                         NULL, SPINNP_FH_FLAG_ONTAP_MASK, NULL, HFILL }},
11677
11678                 { &hf_gxfh3_sfhflags_ontapGX, {
11679                         "ontap-gx", "nfs.gxfh3.sfhflags.ontapgx", FT_UINT8, BASE_HEX,
11680                         NULL, SPINNP_FH_FLAG_ONTAP_MASK, NULL, HFILL }},
11681
11682                 { &hf_gxfh3_sfhflags_striped, {
11683                         "striped", "nfs.gxfh3.sfhflags.striped", FT_BOOLEAN, 8,
11684                         TFS(&tfs_set_notset), SPINNP_FH_FLAG_STRIPED_MASK, NULL, HFILL }},
11685
11686                 { &hf_gxfh3_sfhflags_empty, {
11687                         "empty", "nfs.gxfh3.sfhflags.empty", FT_BOOLEAN, 8,
11688                         TFS(&tfs_set_notset), SPINNP_FH_FLAG_EMPTY_MASK, NULL, HFILL }},
11689
11690                 { &hf_gxfh3_sfhflags_snapdirent, {
11691                         "snap dir ent", "nfs.gxfh3.sfhflags.snapdirent", FT_BOOLEAN, 8,
11692                         TFS(&tfs_set_notset), SPINNP_FH_FLAG_SNAPDIR_ENT_MASK, NULL, HFILL }},
11693
11694                 { &hf_gxfh3_sfhflags_snapdir, {
11695                         "snap dir", "nfs.gxfh3.sfhflags.snapdir", FT_BOOLEAN, 8,
11696                         TFS(&tfs_set_notset), SPINNP_FH_FLAG_SNAPDIR_MASK, NULL, HFILL }},
11697
11698                 { &hf_gxfh3_sfhflags_streamdir, {
11699                         "stream dir", "nfs.gxfh3.sfhflags.streamdir", FT_BOOLEAN, 8,
11700                         TFS(&tfs_set_notset), SPINNP_FH_FLAG_STREAMDIR_MASK, NULL, HFILL }},
11701
11702                 { &hf_gxfh3_spinfid, {
11703                         "spin file id", "nfs.gxfh3.spinfid", FT_UINT32, BASE_HEX,
11704                         NULL, 0, NULL, HFILL }},
11705
11706                 { &hf_gxfh3_spinfuid, {
11707                         "spin file unique id", "nfs.gxfh3.spinfuid", FT_UINT32, BASE_HEX,
11708                         NULL, 0, NULL, HFILL }},
11709
11710                 { &hf_gxfh3_exportptid, {
11711                         "export point id", "nfs.gxfh3.exportptid", FT_UINT32, BASE_HEX,
11712                         NULL, 0, NULL, HFILL }},
11713
11714                 { &hf_gxfh3_exportptuid, {
11715                         "export point unique id", "nfs.gxfh3.exportptuid", FT_UINT32, BASE_HEX,
11716                         NULL, 0, NULL, HFILL }},
11717
11718                 { &hf_nfs_length4_minlength, {
11719                         "min length", "nfs.minlength4", FT_UINT64, BASE_DEC,
11720                         NULL, 0, NULL, HFILL }},
11721
11722                 { &hf_nfs_layouttype4, {
11723                         "layout type", "nfs.layouttype", FT_UINT32, BASE_DEC,
11724                         VALS(layouttype_names), 0, NULL, HFILL }},
11725
11726                 { &hf_nfs_layoutreturn_type4, {
11727                         "return type", "nfs.returntype", FT_UINT32, BASE_DEC,
11728                         VALS(layoutreturn_names), 0, NULL, HFILL }},
11729
11730                 { &hf_nfs_lrf_body_content, {
11731                         "lrf_body_content", "nfs.lrf_body_content", FT_BYTES, BASE_NONE,
11732                         NULL, 0, NULL, HFILL }},
11733
11734                 { &hf_nfs_iomode4, {
11735                         "IO mode", "nfs.iomode", FT_UINT32, BASE_DEC,
11736                         VALS(iomode_names), 0, NULL, HFILL }},
11737
11738                 { &hf_nfs_stripetype4, {
11739                         "stripe type", "nfs.stripetype", FT_UINT32, BASE_DEC,
11740                         VALS(stripetype_names), 0, NULL, HFILL }},
11741
11742                 { &hf_nfs_stripeunit4, {
11743                         "stripe unit", "nfs.stripeunit", FT_UINT64, BASE_DEC,
11744                         NULL, 0, NULL, HFILL }},
11745
11746                 { &hf_nfs_util4, {
11747                         "util", "nfs.util", FT_UINT32, BASE_DEC,
11748                         NULL, 0, NULL, HFILL }},
11749
11750                 { &hf_nfs_first_stripe_idx4, {
11751                         "first stripe index", "nfs.stripeindex", FT_UINT32, BASE_DEC,
11752                         NULL, 0, NULL, HFILL }},
11753
11754                 { &hf_nfs_pattern_offset, {
11755                         "layout pattern offset", "nfs.patternoffset", FT_UINT64, BASE_DEC,
11756                         NULL, 0, NULL, HFILL }},
11757
11758                 { &hf_nfs_notification_bitmap4, {
11759                         "notification bitmap", "nfs.notificationbitmap", FT_UINT32, BASE_DEC,
11760                         NULL, 0, NULL, HFILL }},
11761
11762                 { &hf_nfs_newtime4, {
11763                         "new time?", "nfs.newtime", FT_BOOLEAN, BASE_NONE,
11764                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11765
11766                 { &hf_nfs_newoffset4, {
11767                         "new offset?", "nfs.newoffset", FT_BOOLEAN, BASE_NONE,
11768                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11769
11770                 { &hf_nfs_newsize4, {
11771                         "new size?", "nfs.newsize", FT_BOOLEAN, BASE_NONE,
11772                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11773
11774                 { &hf_nfs_layout_avail4, {
11775                         "layout available?", "nfs.layoutavail", FT_BOOLEAN, BASE_NONE,
11776                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11777
11778                 { &hf_nfs_mdscommit4, {
11779                         "MDS commit?", "nfs.mdscommit", FT_BOOLEAN, BASE_NONE,
11780                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11781
11782                 { &hf_nfs_layoutupdate4, {
11783                         "layout update", "nfs.layoutupdate", FT_BYTES, BASE_NONE,
11784                         NULL, 0, NULL, HFILL }},
11785
11786                 { &hf_nfs_deviceid4, {
11787                         "device ID", "nfs.deviceid", FT_BYTES, BASE_NONE,
11788                         NULL, 0, NULL, HFILL }},
11789
11790                 { &hf_nfs_devicenum4, {
11791                         "num devices", "nfs.devicenum4", FT_UINT32, BASE_DEC,
11792                         NULL, 0, NULL, HFILL }},
11793
11794                 { &hf_nfs_deviceidx4, {
11795                         "device index", "nfs.deviceidx", FT_UINT32, BASE_DEC,
11796                         NULL, 0, NULL, HFILL }},
11797
11798                 { &hf_nfs_layout4, {
11799                         "layout", "nfs.layout", FT_BYTES, BASE_NONE,
11800                         NULL, 0, NULL, HFILL }},
11801
11802                 { &hf_nfs_layout_count, {
11803                         "layout", "nfs.layoutcount", FT_UINT32, BASE_DEC,
11804                         NULL, 0, "layout count", HFILL }},
11805
11806
11807                 { &hf_nfs_stripedevs4, {
11808                         "stripe devs", "nfs.stripedevs", FT_UINT32, BASE_DEC,
11809                         NULL, 0, NULL, HFILL }},
11810
11811                 { &hf_nfs_devaddr4, {
11812                         "device addr", "nfs.devaddr", FT_BYTES, BASE_NONE,
11813                         NULL, 0, NULL, HFILL }},
11814
11815                 { &hf_nfs_return_on_close4, {
11816                         "return on close?", "nfs.retclose4", FT_BOOLEAN, BASE_NONE,
11817                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11818
11819                 { &hf_nfs_nfl_util, {
11820                         "nfl_util", "nfs.nfl_util", FT_UINT32, BASE_HEX,
11821                         NULL, 0, NULL, HFILL }},
11822
11823                 { &hf_nfs_nfl_first_stripe_index, {
11824                         "first stripe to use index", "nfs.nfl_first_stripe_index", FT_UINT32, BASE_DEC,
11825                         NULL, 0, NULL, HFILL }},
11826
11827                 { &hf_nfs_slotid4, {
11828                         "slot ID", "nfs.slotid4", FT_UINT32, BASE_DEC,
11829                         NULL, 0, NULL, HFILL }},
11830
11831                 { &hf_nfs_high_slotid4, {
11832                         "high slot id", "nfs.high.slotid4", FT_UINT32, BASE_DEC,
11833                         NULL, 0, NULL, HFILL }},
11834                 { &hf_nfs_target_high_slotid4, {
11835                         "target high slot id", "nfs.target.high.slotid4", FT_UINT32, BASE_DEC,
11836                         NULL, 0, NULL, HFILL }},
11837
11838                 { &hf_nfs_sr_status4, {
11839                         "status", "nfs.status", FT_UINT32, BASE_DEC,
11840                         NULL, 0, NULL, HFILL }},
11841
11842                 { &hf_nfs_serverscope4, {
11843                         "server scope", "nfs.scope", FT_BYTES, BASE_NONE,
11844                         NULL, 0, NULL, HFILL }},
11845
11846                 { &hf_nfs_minorid4, {
11847                         "minor ID", "nfs.minorid4", FT_UINT64, BASE_DEC,
11848                         NULL, 0, NULL, HFILL }},
11849
11850                 { &hf_nfs_majorid4, {
11851                         "major ID", "nfs.majorid4", FT_BYTES, BASE_NONE,
11852                         NULL, 0, NULL, HFILL }},
11853
11854                 { &hf_nfs_padsize4, {
11855                         "hdr pad size", "nfs.padsize4", FT_UINT32, BASE_DEC,
11856                         NULL, 0, NULL, HFILL }},
11857
11858                 { &hf_nfs_cbrenforce4, {
11859                         "binding enforce?", "nfs.cbrenforce4", FT_BOOLEAN, BASE_NONE,
11860                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
11861
11862                 { &hf_nfs_hashalg4, {
11863                         "hash alg", "nfs.hashalg4", FT_UINT32, BASE_DEC,
11864                         NULL, 0, NULL, HFILL }},
11865
11866                 { &hf_nfs_ssvlen4, {
11867                         "ssv len", "nfs.ssvlen4", FT_UINT32, BASE_DEC,
11868                         NULL, 0, NULL, HFILL }},
11869
11870                 { &hf_nfs_maxreqsize4, {
11871                         "max req size", "nfs.maxreqsize4", FT_UINT32, BASE_DEC,
11872                         NULL, 0, NULL, HFILL }},
11873
11874                 { &hf_nfs_maxrespsize4, {
11875                         "max resp size", "nfs.maxrespsize4", FT_UINT32, BASE_DEC,
11876                         NULL, 0, NULL, HFILL }},
11877
11878                 { &hf_nfs_maxrespsizecached4, {
11879                         "max resp size cached", "nfs.maxrespsizecached4", FT_UINT32, BASE_DEC,
11880                         NULL, 0, NULL, HFILL }},
11881
11882                 { &hf_nfs_maxops4, {
11883                         "max ops", "nfs.maxops4", FT_UINT32, BASE_DEC,
11884                         NULL, 0, NULL, HFILL }},
11885
11886                 { &hf_nfs_maxreqs4, {
11887                         "max reqs", "nfs.maxreqs4", FT_UINT32, BASE_DEC,
11888                         NULL, 0, NULL, HFILL }},
11889
11890                 { &hf_nfs_rdmachanattrs4, {
11891                         "RDMA chan attrs", "nfs.rdmachanattrs4", FT_UINT32, BASE_DEC,
11892                         NULL, 0, NULL, HFILL }},
11893
11894                 { &hf_nfs_machinename4, {
11895                         "machine name", "nfs.machinename4", FT_STRING, BASE_NONE,
11896                         NULL, 0, NULL, HFILL }},
11897
11898                 { &hf_nfs_flavor4, {
11899                         "flavor", "nfs.flavor4", FT_UINT32, BASE_DEC,
11900                         NULL, 0, NULL, HFILL }},
11901
11902                 { &hf_nfs_stamp4, {
11903                         "stamp", "nfs.stamp4", FT_UINT32, BASE_DEC,
11904                         NULL, 0, NULL, HFILL }},
11905
11906                 { &hf_nfs_uid4, {
11907                         "uid", "nfs.uid4", FT_UINT32, BASE_DEC,
11908                         NULL, 0, NULL, HFILL }},
11909
11910                 { &hf_nfs_gid4, {
11911                         "gid", "nfs.gid4", FT_UINT32, BASE_DEC,
11912                         NULL, 0, NULL, HFILL }},
11913
11914                 { &hf_nfs_service4, {
11915                         "gid", "nfs.service4", FT_UINT32, BASE_DEC,
11916                         NULL, 0, NULL, HFILL }},
11917
11918                 { &hf_nfs_access_check,
11919                         { "Check access", "nfs.access_check",
11920                         FT_UINT8, BASE_HEX,
11921                         NULL, 0x0,
11922                         "Access type(s) to be checked", HFILL }
11923                 },
11924                 { &hf_nfs_access_supported,
11925                         { "Supported types (of requested)", "nfs.access_supported",
11926                         FT_UINT8, BASE_HEX,
11927                         NULL, 0x0,
11928                         "Access types (of those requested) that the server can reliably verify", HFILL }
11929                 },
11930                 { &hf_nfs_access_rights,
11931                         { "Access rights (of requested)", "nfs.access_rights",
11932                         FT_UINT8, BASE_HEX,
11933                         NULL, 0x0,
11934                         "Access rights for the types requested", HFILL }
11935                 },
11936                 { &hf_nfs_access_supp_read,
11937                         { "0x01 READ", "nfs.access_supp_read",
11938                         FT_BOOLEAN, 8,
11939                         TFS(&tfs_access_supp), NFS_ACCESS_MASK_READ,
11940                         NULL, HFILL }
11941                 },
11942                 { &hf_nfs_access_supp_lookup,
11943                         { "0x02 LOOKUP", "nfs.access_supp_lookup",
11944                         FT_BOOLEAN, 8,
11945                         TFS(&tfs_access_supp), NFS_ACCESS_MASK_LOOKUP,
11946                         NULL, HFILL }
11947                 },
11948                 { &hf_nfs_access_supp_modify,
11949                         { "0x04 MODIFY", "nfs.access_supp_modify",
11950                         FT_BOOLEAN, 8,
11951                         TFS(&tfs_access_supp), NFS_ACCESS_MASK_MODIFY,
11952                         NULL, HFILL }
11953                 },
11954                 { &hf_nfs_access_supp_extend,
11955                         { "0x08 EXTEND", "nfs.access_supp_extend",
11956                         FT_BOOLEAN, 8,
11957                         TFS(&tfs_access_supp), NFS_ACCESS_MASK_EXTEND,
11958                         NULL, HFILL }
11959                 },
11960                 { &hf_nfs_access_supp_delete,
11961                         { "0x10 DELETE", "nfs.access_supp_delete",
11962                         FT_BOOLEAN, 8,
11963                         TFS(&tfs_access_supp), NFS_ACCESS_MASK_DELETE,
11964                         NULL, HFILL }
11965                 },
11966                 { &hf_nfs_access_supp_execute,
11967                         { "0x20 EXECUTE", "nfs.access_supp_execute",
11968                         FT_BOOLEAN, 8,
11969                         TFS(&tfs_access_supp), NFS_ACCESS_MASK_EXECUTE,
11970                         NULL, HFILL }
11971                 },
11972                 { &hf_nfs_access_read,
11973                         { "0x01 READ", "nfs.access_read",
11974                         FT_BOOLEAN, 8,
11975                         TFS(&tfs_access_rights), NFS_ACCESS_MASK_READ,
11976                         NULL, HFILL }
11977                 },
11978                 { &hf_nfs_access_lookup,
11979                         { "0x02 LOOKUP", "nfs.access_lookup",
11980                         FT_BOOLEAN, 8,
11981                         TFS(&tfs_access_rights), NFS_ACCESS_MASK_LOOKUP,
11982                         NULL, HFILL }
11983                 },
11984                 { &hf_nfs_access_modify,
11985                         { "0x04 MODIFY", "nfs.access_modify",
11986                         FT_BOOLEAN, 8,
11987                         TFS(&tfs_access_rights), NFS_ACCESS_MASK_MODIFY,
11988                         NULL, HFILL }
11989                 },
11990                 { &hf_nfs_access_extend,
11991                         { "0x08 EXTEND", "nfs.access_extend",
11992                         FT_BOOLEAN, 8,
11993                         TFS(&tfs_access_rights), NFS_ACCESS_MASK_EXTEND,
11994                         NULL, HFILL }
11995                 },
11996                 { &hf_nfs_access_delete,
11997                         { "0x10 DELETE", "nfs.access_delete",
11998                         FT_BOOLEAN, 8,
11999                         TFS(&tfs_access_rights), NFS_ACCESS_MASK_DELETE,
12000                         NULL, HFILL }
12001                 },
12002                 { &hf_nfs_access_execute,
12003                         { "0x20 EXECUTE", "nfs.access_execute",
12004                         FT_BOOLEAN, 8,
12005                         TFS(&tfs_access_rights), NFS_ACCESS_MASK_EXECUTE,
12006                         NULL, HFILL }
12007                 },
12008                 { &hf_nfs_access_denied,
12009                         { "Access Denied", "nfs.access_denied",
12010                         FT_BOOLEAN, BASE_NONE,
12011                         NULL, 0x0,
12012                         "True if access has been denied to one or more of the requested types", HFILL }
12013                 },
12014                 { &hf_nfs_sessionid4, {
12015                         "sessionid", "nfs.session_id4", FT_BYTES, BASE_NONE,
12016                         NULL, 0, NULL, HFILL }},
12017                 { &hf_nfs_exch_id_flags4, {
12018                         "eia_flags", "nfs.exch_id_flags", FT_UINT32, BASE_HEX,
12019                         NULL, 0, NULL, HFILL }},
12020                 { &hf_nfs_exchid_flags_moved_refer, {
12021                         "EXCHGID4_FLAG_SUPP_MOVED_REFER", "nfs.exchange_id.flags.moved_refer", FT_BOOLEAN, 32,
12022                         TFS(&tfs_set_notset), EXCHGID4_FLAG_SUPP_MOVED_REFER, NULL, HFILL}},
12023                 { &hf_nfs_exchid_flags_moved_migr, {
12024                         "EXCHGID4_FLAG_SUPP_MOVED_MIGR", "nfs.exchange_id.flags.moved_migr", FT_BOOLEAN, 32,
12025                         TFS(&tfs_set_notset), EXCHGID4_FLAG_SUPP_MOVED_MIGR, NULL, HFILL}},
12026                 { &hf_nfs_exchid_flags_bind_princ, {
12027                         "EXCHGID4_FLAG_BIND_PRINC_STATEID", "nfs.exchange_id.flags.bind_princ", FT_BOOLEAN, 32,
12028                         TFS(&tfs_set_notset), EXCHGID4_FLAG_BIND_PRINC_STATEID, NULL, HFILL}},
12029                 { &hf_nfs_exchid_flags_non_pnfs, {
12030                         "EXCHGID4_FLAG_USE_NON_PNFS", "nfs.exchange_id.flags.non_pnfs", FT_BOOLEAN, 32,
12031                         TFS(&tfs_set_notset), EXCHGID4_FLAG_USE_NON_PNFS, NULL, HFILL}},
12032                 { &hf_nfs_exchid_flags_pnfs_mds, {
12033                         "EXCHGID4_FLAG_USE_PNFS_MDS", "nfs.exchange_id.flags.pnfs_mds", FT_BOOLEAN, 32,
12034                         TFS(&tfs_set_notset), EXCHGID4_FLAG_USE_PNFS_MDS, NULL, HFILL}},
12035                 { &hf_nfs_exchid_flags_pnfs_ds, {
12036                         "EXCHGID4_FLAG_USE_PNFS_DS", "nfs.exchange_id.flags.pnfs_ds", FT_BOOLEAN, 32,
12037                         TFS(&tfs_set_notset), EXCHGID4_FLAG_USE_PNFS_DS, NULL, HFILL}},
12038                 { &hf_nfs_exchid_flags_upd_conf_rec_a, {
12039                         "EXCHGID4_FLAG_UPD_CONFIRMED_REC_A", "nfs.exchange_id.flags.confirmed_rec_a", FT_BOOLEAN, 32,
12040                         TFS(&tfs_set_notset), EXCHGID4_FLAG_UPD_CONFIRMED_REC_A, NULL, HFILL}},
12041                 { &hf_nfs_exchid_flags_confirmed_r, {
12042                         "EXCHGID4_FLAG_CONFIRMED_R", "nfs.exchange_id.flags.confirmed_r", FT_BOOLEAN, 32,
12043                         TFS(&tfs_set_notset), EXCHGID4_FLAG_CONFIRMED_R, NULL, HFILL}},
12044                 { &hf_nfs_prot_info4_hash_alg, {
12045                         "Prot Info hash algorithm", "nfs.prot_info4_hash_alg", FT_UINT32, BASE_HEX,
12046                         NULL, 0, NULL, HFILL }},
12047                 { &hf_nfs_prot_info4_encr_alg, {
12048                         "Prot Info encryption algorithm", "nfs.prot_info4_encr_alg", FT_UINT32, BASE_HEX,
12049                         NULL, 0, NULL, HFILL }},
12050                 { &hf_nfs_prot_info4_svv_length, {
12051                         "Prot Info svv_length", "nfs.prot_info4_svv_length", FT_UINT32, BASE_HEX,
12052                         NULL, 0, NULL, HFILL }},
12053                 { &hf_nfs_prot_info4_spi_window, {
12054                         "Prot Info spi window", "nfs.prot_info4_spi_window", FT_UINT32, BASE_HEX,
12055                         NULL, 0, NULL, HFILL }},
12056                 { &hf_nfs_state_protect_window, {
12057                         "State Protect window", "nfs.state_protect_window", FT_UINT32, BASE_HEX,
12058                         NULL, 0, NULL, HFILL }},
12059                 { &hf_nfs_state_protect_num_gss_handles, {
12060                         "State Protect num gss handles", "nfs.state_protect_num_gss_handles", FT_UINT32, BASE_HEX,
12061                         NULL, 0, NULL, HFILL }},
12062                 { &hf_nfs_nii_domain4, {
12063                         "Implementor DNS domain name(nii_domain)", "nfs.nii_domain4", FT_STRING, BASE_NONE,
12064                         NULL, 0, NULL, HFILL }},
12065                 { &hf_nfs_nii_name4, {
12066                         "Implementation product name(nii_name)", "nfs.nii_name4", FT_STRING, BASE_NONE,
12067                         NULL, 0, NULL, HFILL }},
12068                 { &hf_nfs_create_session_flags4, {
12069                         "CREATE_SESSION flags", "nfs.create_session_flags", FT_UINT32, BASE_HEX,
12070                         NULL, 0, NULL, HFILL }},
12071                 { &hf_nfs_cachethis4, {
12072                         "cache this?", "nfs.cachethis4", FT_BOOLEAN, BASE_NONE,
12073                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12074                 { &hf_nfs_reclaim_one_fs4, {
12075                         "reclaim one fs?", "nfs.reclaim_one_fs4", FT_BOOLEAN,
12076                         BASE_NONE, TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12077                 { &hf_nfs_cb_procedure, {
12078                    "CB Procedure", "nfs.cb_procedure", FT_UINT32, BASE_DEC,
12079                         VALS(nfs_cb_proc_vals), 0, NULL, HFILL }},
12080                 { &hf_nfs_cb_op, {
12081                     "Opcode", "nfs.cb.operation", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12082                     &names_nfs_cb_operation_ext, 0, NULL, HFILL }},
12083                 { &hf_nfs_lrs_present, {
12084                         "Stateid present?", "nfs.lrs_present", FT_BOOLEAN, BASE_NONE,
12085                         TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12086                 { &hf_nfs_cb_truncate, {
12087                     "Truncate?", "nfs.truncate", FT_BOOLEAN, BASE_NONE,
12088                     TFS(&tfs_yes_no), 0, NULL, HFILL }},
12089                 { &hf_nfs_cb_layoutrecall_type, {
12090                         "recall type", "nfs.recalltype", FT_UINT32, BASE_DEC,
12091                         VALS(layoutrecall_names), 0, NULL, HFILL }},
12092                 { &hf_nfs_cb_clorachanged, {
12093                         "Clora changed", "nfs.clorachanged", FT_BOOLEAN, BASE_NONE,
12094                         TFS(&tfs_yes_no), 0, NULL, HFILL }},
12095
12096                 { &hf_nfs_mode3, {
12097                         "Mode", "nfs.mode3", FT_UINT32, BASE_OCT,
12098                         NULL, 0, NULL, HFILL }},
12099
12100                 { &hf_nfs_mode3_suid, {
12101                         "S_ISUID", "nfs.mode3.suid", FT_BOOLEAN, 32,
12102                         TFS(&tfs_yes_no), 0x800, NULL, HFILL }},
12103
12104                 { &hf_nfs_mode3_sgid, {
12105                         "S_ISGID", "nfs.mode3.sgid", FT_BOOLEAN, 32,
12106                         TFS(&tfs_yes_no), 0x400, NULL, HFILL }},
12107
12108                 { &hf_nfs_mode3_sticky, {
12109                         "S_ISVTX", "nfs.mode3.sticky", FT_BOOLEAN, 32,
12110                         TFS(&tfs_yes_no), 0x200, NULL, HFILL }},
12111
12112                 { &hf_nfs_mode3_rusr, {
12113                         "S_IRUSR", "nfs.mode3.rusr", FT_BOOLEAN, 32,
12114                         TFS(&tfs_yes_no), 0x100, NULL, HFILL }},
12115
12116                 { &hf_nfs_mode3_wusr, {
12117                         "S_IWUSR", "nfs.mode3.wusr", FT_BOOLEAN, 32,
12118                         TFS(&tfs_yes_no), 0x080, NULL, HFILL }},
12119
12120                 { &hf_nfs_mode3_xusr, {
12121                         "S_IXUSR", "nfs.mode3.xusr", FT_BOOLEAN, 32,
12122                         TFS(&tfs_yes_no), 0x040, NULL, HFILL }},
12123
12124                 { &hf_nfs_mode3_rgrp, {
12125                         "S_IRGRP", "nfs.mode3.rgrp", FT_BOOLEAN, 32,
12126                         TFS(&tfs_yes_no), 0x020, NULL, HFILL }},
12127
12128                 { &hf_nfs_mode3_wgrp, {
12129                         "S_IWGRP", "nfs.mode3.wgrp", FT_BOOLEAN, 32,
12130                         TFS(&tfs_yes_no), 0x010, NULL, HFILL }},
12131
12132                 { &hf_nfs_mode3_xgrp, {
12133                         "S_IXGRP", "nfs.mode3.xgrp", FT_BOOLEAN, 32,
12134                         TFS(&tfs_yes_no), 0x008, NULL, HFILL }},
12135
12136                 { &hf_nfs_mode3_roth, {
12137                         "S_IROTH", "nfs.mode3.roth", FT_BOOLEAN, 32,
12138                         TFS(&tfs_yes_no), 0x004, NULL, HFILL }},
12139
12140                 { &hf_nfs_mode3_woth, {
12141                         "S_IWOTH", "nfs.mode3.woth", FT_BOOLEAN, 32,
12142                         TFS(&tfs_yes_no), 0x002, NULL, HFILL }},
12143
12144                 { &hf_nfs_mode3_xoth, {
12145                         "S_IXOTH", "nfs.mode3.xoth", FT_BOOLEAN, 32,
12146                         TFS(&tfs_yes_no), 0x001, NULL, HFILL }},
12147
12148         /* Hidden field for v2, v3, and v4 status */
12149                 { &hf_nfs_nfsstat, {
12150                         "Status", "nfs.status", FT_UINT32, BASE_DEC,
12151                         VALS(names_nfs_nfsstat), 0, "Reply status", HFILL }}
12152         };
12153
12154         static gint *ett[] = {
12155                 &ett_nfs,
12156                 &ett_nfs_fh_encoding,
12157                 &ett_nfs_fh_fsid,
12158                 &ett_nfs_fh_file,
12159                 &ett_nfs_fh_mount,
12160                 &ett_nfs_fh_export,
12161                 &ett_nfsv4_fh_export,
12162                 &ett_nfsv4_fh_file,
12163                 &ett_nfsv4_fh_handle_type,
12164                 &ett_nfsv4_fh_export_snapgen,
12165                 &ett_nfsv4_fh_file_flags,
12166                 &ett_nfs_fh_xfsid,
12167                 &ett_nfs_fh_fn,
12168                 &ett_nfs_fh_xfn,
12169                 &ett_nfs_fh_hp,
12170                 &ett_nfs_fh_auth,
12171                 &ett_nfs_fhandle,
12172                 &ett_nfs_timeval,
12173                 &ett_nfs_mode,
12174                 &ett_nfs_fattr,
12175                 &ett_nfs_sattr,
12176                 &ett_nfs_diropargs,
12177                 &ett_nfs_readdir_entry,
12178                 &ett_nfs_mode3,
12179                 &ett_nfs_specdata3,
12180                 &ett_nfs_fh3,
12181                 &ett_nfs_nfstime3,
12182                 &ett_nfs_fattr3,
12183                 &ett_nfs_post_op_fh3,
12184                 &ett_nfs_sattr3,
12185                 &ett_nfs_diropargs3,
12186                 &ett_nfs_sattrguard3,
12187                 &ett_nfs_set_mode3,
12188                 &ett_nfs_set_uid3,
12189                 &ett_nfs_set_gid3,
12190                 &ett_nfs_set_size3,
12191                 &ett_nfs_set_atime,
12192                 &ett_nfs_set_mtime,
12193                 &ett_nfs_pre_op_attr,
12194                 &ett_nfs_post_op_attr,
12195                 &ett_nfs_wcc_attr,
12196                 &ett_nfs_wcc_data,
12197                 &ett_nfs_access3,
12198                 &ett_nfs_fsinfo_properties,
12199                 &ett_nfs_compound_call4,
12200                 &ett_nfs_utf8string,
12201                 &ett_nfs_argop4,
12202                 &ett_nfs_resop4,
12203                 &ett_nfs_access4,
12204                 &ett_nfs_access_supp4,
12205                 &ett_nfs_close4,
12206                 &ett_nfs_commit4,
12207                 &ett_nfs_create4,
12208                 &ett_nfs_delegpurge4,
12209                 &ett_nfs_delegreturn4,
12210                 &ett_nfs_getattr4,
12211                 &ett_nfs_getattr4_args,
12212                 &ett_nfs_getattr4_resp,
12213                 &ett_nfs4_resok4,
12214                 &ett_nfs4_obj_attrs,
12215                 &ett_nfs4_fattr4_new_attr_vals,
12216                 &ett_nfs4_fattr4_attrmask,
12217                 &ett_nfs4_attribute,
12218                 &ett_nfs_getfh4,
12219                 &ett_nfs_link4,
12220                 &ett_nfs_lock4,
12221                 &ett_nfs_lockt4,
12222                 &ett_nfs_locku4,
12223                 &ett_nfs_lookup4,
12224                 &ett_nfs_lookupp4,
12225                 &ett_nfs_nverify4,
12226                 &ett_nfs_open4,
12227                 &ett_nfs_openattr4,
12228                 &ett_nfs_open_confirm4,
12229                 &ett_nfs_open_downgrade4,
12230                 &ett_nfs_putfh4,
12231                 &ett_nfs_putpubfh4,
12232                 &ett_nfs_putrootfh4,
12233                 &ett_nfs_read4,
12234                 &ett_nfs_readdir4,
12235                 &ett_nfs_readlink4,
12236                 &ett_nfs_reclaim_complete4,
12237                 &ett_nfs_remove4,
12238                 &ett_nfs_rename4,
12239                 &ett_nfs_renew4,
12240                 &ett_nfs_restorefh4,
12241                 &ett_nfs_savefh4,
12242                 &ett_nfs_setattr4,
12243                 &ett_nfs_setclientid4,
12244                 &ett_nfs_setclientid_confirm4,
12245                 &ett_nfs_verify4,
12246                 &ett_nfs_write4,
12247                 &ett_nfs_release_lockowner4,
12248                 &ett_nfs_exchange_id4,
12249                 &ett_nfs_create_session4,
12250                 &ett_nfs_destroy_session4,
12251                 &ett_nfs_sequence4,
12252                 &ett_nfs_layoutget4,
12253                 &ett_nfs_layoutcommit4,
12254                 &ett_nfs_layoutreturn4,
12255                 &ett_nfs_getdevinfo4,
12256                 &ett_nfs_getdevlist4,
12257                 &ett_nfs_illegal4,
12258                 &ett_nfs_verifier4,
12259                 &ett_nfs_opaque,
12260                 &ett_nfs_dirlist4,
12261                 &ett_nfs_pathname4,
12262                 &ett_nfs_change_info4,
12263                 &ett_nfs_open_delegation4,
12264                 &ett_nfs_open_claim4,
12265                 &ett_nfs_opentype4,
12266                 &ett_nfs_lock_owner4,
12267                 &ett_nfs_cb_client4,
12268                 &ett_nfs_client_id4,
12269                 &ett_nfs_clientowner4,
12270                 &ett_exchangeid_flags,
12271                 &ett_server_owner4,
12272                 &ett_nfs_bitmap4,
12273                 &ett_nfs_attr_request,
12274                 &ett_nfs_fattr4,
12275                 &ett_nfs_fsid4,
12276                 &ett_nfs_fs_locations4,
12277                 &ett_nfs_fs_location4,
12278                 &ett_nfs_open4_result_flags,
12279                 &ett_nfs_secinfo4,
12280                 &ett_nfs_secinfo4_flavor_info,
12281                 &ett_nfs_stateid4,
12282                 &ett_nfs_fattr4_fh_expire_type,
12283                 &ett_nfs_ace4,
12284                 &ett_nfs_clientaddr4,
12285                 &ett_nfs_aceflag4,
12286                 &ett_nfs_acemask4,
12287                 &ett_nfs_gxfh3_utlfield,
12288                 &ett_nfs_gxfh3_sfhfield,
12289                 &ett_nfs_gxfh3_sfhflags,
12290                 &ett_nfs_slotid4,
12291                 &ett_nfs_sr_status4,
12292                 &ett_nfs_serverscope4,
12293                 &ett_nfs_minorid4,
12294                 &ett_nfs_majorid4,
12295                 &ett_nfs_persist4,
12296                 &ett_nfs_backchan4,
12297                 &ett_nfs_rdmamode4,
12298                 &ett_nfs_padsize4,
12299                 &ett_nfs_cbrenforce4,
12300                 &ett_nfs_hashalg4,
12301                 &ett_nfs_ssvlen4,
12302                 &ett_nfs_maxreqsize4,
12303                 &ett_nfs_maxrespsize4,
12304                 &ett_nfs_maxrespsizecached4,
12305                 &ett_nfs_maxops4,
12306                 &ett_nfs_maxreqs4,
12307                 &ett_nfs_streamchanattrs4,
12308                 &ett_nfs_rdmachanattrs4,
12309                 &ett_nfs_machinename4,
12310                 &ett_nfs_flavor4,
12311                 &ett_nfs_stamp4,
12312                 &ett_nfs_uid4,
12313                 &ett_nfs_gid4,
12314                 &ett_nfs_service4,
12315                 &ett_nfs_sessionid4,
12316                 &ett_nfs_layoutseg,
12317                 &ett_nfs_layoutseg_fh,
12318                 &ett_nfs_fh_obj,
12319                 &ett_nfs_fh_ex,
12320                 &ett_nfs_cb_argop,
12321                 &ett_nfs_cb_resop,
12322                 &ett_nfs_cb_getattr,
12323                 &ett_nfs_cb_recall,
12324                 &ett_nfs_cb_layoutrecall,
12325                 &ett_nfs_cb_pushdeleg,
12326                 &ett_nfs_cb_recallany,
12327                 &ett_nfs_cb_recallableobjavail,
12328                 &ett_nfs_cb_recallslot,
12329                 &ett_nfs_cb_sequence,
12330                 &ett_nfs_cb_wantscancelled,
12331                 &ett_nfs_cb_notifylock,
12332                 &ett_nfs_cb_notifydeviceid,
12333                 &ett_nfs_cb_notify,
12334                 &ett_nfs_cb_reflists,
12335                 &ett_nfs_cb_refcalls,
12336                 &ett_nfs_cb_illegal,
12337         };
12338         module_t *nfs_module;
12339
12340         proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs");
12341         proto_register_field_array(proto_nfs, hf, array_length(hf));
12342         proto_register_subtree_array(ett, array_length(ett));
12343
12344         nfs_module=prefs_register_protocol(proto_nfs, NULL);
12345         prefs_register_bool_preference(nfs_module, "file_name_snooping",
12346                                        "Snoop FH to filename mappings",
12347                                        "Whether the dissector should snoop the FH to filename mappings by looking inside certain packets",
12348                                        &nfs_file_name_snooping);
12349         prefs_register_bool_preference(nfs_module, "file_full_name_snooping",
12350                                        "Snoop full path to filenames",
12351                                        "Whether the dissector should snoop the full pathname for files for matching FH's",
12352                                        &nfs_file_name_full_snooping);
12353         prefs_register_bool_preference(nfs_module, "fhandle_find_both_reqrep",
12354                                        "Fhandle filters finds both request/response",
12355                                        "With this option display filters for nfs fhandles (nfs.fh.{name|full_name|hash}) will find both the request \
12356                                                 and response packets for a RPC call, even if the actual fhandle is only present in one of the packets",
12357                                         &nfs_fhandle_reqrep_matching);
12358
12359         prefs_register_bool_preference(nfs_module, "display_nfsv4_tag",
12360                                                 "Display NFSv4 tag in info Column",
12361                                                 "When enabled, this option will print the NFSv4 tag (if one exists) in the Info column in the Summary pane",
12362                                         &nfs_display_v4_tag);
12363         prefs_register_bool_preference(nfs_module, "display_major_nfsv4_ops",
12364                                            "Display only 'significant' NFSv4 Operations in info Column",
12365                                            "When enabled, shows only the significant NFSv4 Operations in the info column.  Others (like GETFH, PUTFH, etc) are not displayed",
12366                                         &display_major_nfsv4_ops);
12367         nfs_fhandle_table = register_dissector_table("nfs_fhandle.type",
12368             "NFS Filehandle types", FT_UINT8, BASE_HEX);
12369
12370         prefs_register_enum_preference(nfs_module,
12371                 "default_fhandle_type",
12372                 "Decode nfs fhandles as",
12373                 "Decode all NFS file handles as if they are of this type",
12374                 &default_nfs_fhandle_type,
12375                 nfs_fhandle_types,
12376                 FALSE);
12377
12378         nfs_name_snoop_known=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "nfs_name_snoop_known");
12379         nfs_file_handles=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "nfs_file_handles");
12380         nfs_fhandle_frame_table=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "nfs_fhandle_frame_table");
12381         register_init_routine(nfs_name_snoop_init);
12382 }
12383
12384
12385 void
12386 proto_reg_handoff_nfs(void)
12387 {
12388         dissector_handle_t fhandle_handle;
12389
12390         /* Register the protocol as RPC */
12391         rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
12392
12393         /* Register the procedure tables */
12394         rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc, hf_nfs_procedure_v2);
12395         rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc, hf_nfs_procedure_v3);
12396         rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc, hf_nfs_procedure_v4);
12397
12398         fhandle_handle=create_dissector_handle(dissect_fhandle_data_SVR4, proto_nfs);
12399         dissector_add_uint("nfs_fhandle.type", FHT_SVR4, fhandle_handle);
12400
12401         fhandle_handle=create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_LE, proto_nfs);
12402         dissector_add_uint("nfs_fhandle.type", FHT_LINUX_KNFSD_LE, fhandle_handle);
12403
12404         fhandle_handle=create_dissector_handle(dissect_fhandle_data_LINUX_NFSD_LE, proto_nfs);
12405         dissector_add_uint("nfs_fhandle.type", FHT_LINUX_NFSD_LE, fhandle_handle);
12406
12407         fhandle_handle=create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_NEW, proto_nfs);
12408         dissector_add_uint("nfs_fhandle.type", FHT_LINUX_KNFSD_NEW, fhandle_handle);
12409
12410         fhandle_handle=create_dissector_handle(dissect_fhandle_data_NETAPP, proto_nfs);
12411         dissector_add_uint("nfs_fhandle.type", FHT_NETAPP, fhandle_handle);
12412
12413         fhandle_handle=create_dissector_handle(dissect_fhandle_data_NETAPP_V4, proto_nfs);
12414         dissector_add_uint("nfs_fhandle.type", FHT_NETAPP_V4, fhandle_handle);
12415
12416         fhandle_handle=create_dissector_handle(dissect_fhandle_data_NETAPP_GX_v3, proto_nfs);
12417         dissector_add_uint("nfs_fhandle.type", FHT_NETAPP_GX_V3, fhandle_handle);
12418
12419         fhandle_handle=create_dissector_handle(dissect_fhandle_data_CELERRA, proto_nfs);
12420         dissector_add_uint("nfs_fhandle.type", FHT_CELERRA, fhandle_handle);
12421
12422         fhandle_handle=create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs);
12423         dissector_add_uint("nfs_fhandle.type", FHT_UNKNOWN, fhandle_handle);
12424 }