5156559d8072e6ce3886da5324035aaa12d1d977
[obnox/wireshark/wip.git] / 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  * $Id: packet-nfs.c,v 1.97 2004/06/02 06:50:28 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from packet-smb.c
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32
33 #include <string.h>
34
35
36 #include "packet-rpc.h"
37 #include "packet-nfs.h"
38 #include "prefs.h"
39 #include "epan/int-64bit.h"
40
41 static int proto_nfs = -1;
42
43 static int hf_nfs_procedure_v2 = -1;
44 static int hf_nfs_procedure_v3 = -1;
45 static int hf_nfs_procedure_v4 = -1;
46 static int hf_nfs_fh_length = -1;
47 static int hf_nfs_fh_hash = -1;
48 static int hf_nfs_fh_mount_fileid = -1;
49 static int hf_nfs_fh_mount_generation = -1;
50 static int hf_nfs_fh_snapid = -1;
51 static int hf_nfs_fh_unused = -1;
52 static int hf_nfs_fh_flags = -1;
53 static int hf_nfs_fh_fileid = -1;
54 static int hf_nfs_fh_generation = -1;
55 static int hf_nfs_fh_fsid = -1;
56 static int hf_nfs_fh_export_fileid = -1;
57 static int hf_nfs_fh_export_generation = -1;
58 static int hf_nfs_fh_export_snapid = -1;
59 static int hf_nfs_fh_fsid_major = -1;
60 static int hf_nfs_fh_fsid_minor = -1;
61 static int hf_nfs_fh_fsid_inode = -1;
62 static int hf_nfs_fh_xfsid_major = -1;
63 static int hf_nfs_fh_xfsid_minor = -1;
64 static int hf_nfs_fh_fstype = -1;
65 static int hf_nfs_fh_fn = -1;
66 static int hf_nfs_fh_fn_len = -1;
67 static int hf_nfs_fh_fn_inode = -1;
68 static int hf_nfs_fh_fn_generation = -1;
69 static int hf_nfs_fh_xfn = -1;
70 static int hf_nfs_fh_xfn_len = -1;
71 static int hf_nfs_fh_xfn_inode = -1;
72 static int hf_nfs_fh_xfn_generation = -1;
73 static int hf_nfs_fh_dentry = -1;
74 static int hf_nfs_fh_dev = -1;
75 static int hf_nfs_fh_xdev = -1;
76 static int hf_nfs_fh_dirinode = -1;
77 static int hf_nfs_fh_pinode = -1;
78 static int hf_nfs_fh_hp_len = -1;
79 static int hf_nfs_fh_version = -1;
80 static int hf_nfs_fh_auth_type = -1;
81 static int hf_nfs_fh_fsid_type = -1;
82 static int hf_nfs_fh_fileid_type = -1;
83 static int hf_nfs_stat = -1;
84 static int hf_nfs_name = -1;
85 static int hf_nfs_full_name = -1;
86 static int hf_nfs_readlink_data = -1;
87 static int hf_nfs_read_offset = -1;
88 static int hf_nfs_read_count = -1;
89 static int hf_nfs_read_totalcount = -1;
90 static int hf_nfs_data = -1;
91 static int hf_nfs_write_beginoffset = -1;
92 static int hf_nfs_write_offset = -1;
93 static int hf_nfs_write_totalcount = -1;
94 static int hf_nfs_symlink_to = -1;
95 static int hf_nfs_readdir_cookie = -1;
96 static int hf_nfs_readdir_count = -1;
97 static int hf_nfs_readdir_entry = -1;
98 static int hf_nfs_readdir_entry_fileid = -1;
99 static int hf_nfs_readdir_entry_name = -1;
100 static int hf_nfs_readdir_entry_cookie = -1;
101 static int hf_nfs_readdir_entry3_fileid = -1;
102 static int hf_nfs_readdir_entry3_name = -1;
103 static int hf_nfs_readdir_entry3_cookie = -1;
104 static int hf_nfs_readdirplus_entry_fileid = -1;
105 static int hf_nfs_readdirplus_entry_name = -1;
106 static int hf_nfs_readdirplus_entry_cookie = -1;
107 static int hf_nfs_readdir_eof = -1;
108 static int hf_nfs_statfs_tsize = -1;
109 static int hf_nfs_statfs_bsize = -1;
110 static int hf_nfs_statfs_blocks = -1;
111 static int hf_nfs_statfs_bfree = -1;
112 static int hf_nfs_statfs_bavail = -1;
113 static int hf_nfs_ftype3 = -1;
114 static int hf_nfs_nfsstat3 = -1;
115 static int hf_nfs_read_eof = -1;
116 static int hf_nfs_write_stable = -1;
117 static int hf_nfs_write_committed = -1;
118 static int hf_nfs_createmode3 = -1;
119 static int hf_nfs_fsstat_invarsec = -1;
120 static int hf_nfs_fsinfo_rtmax = -1;
121 static int hf_nfs_fsinfo_rtpref = -1;
122 static int hf_nfs_fsinfo_rtmult = -1;
123 static int hf_nfs_fsinfo_wtmax = -1;
124 static int hf_nfs_fsinfo_wtpref = -1;
125 static int hf_nfs_fsinfo_wtmult = -1;
126 static int hf_nfs_fsinfo_dtpref = -1;
127 static int hf_nfs_fsinfo_maxfilesize = -1;
128 static int hf_nfs_fsinfo_properties = -1;
129 static int hf_nfs_pathconf_linkmax = -1;
130 static int hf_nfs_pathconf_name_max = -1;
131 static int hf_nfs_pathconf_no_trunc = -1;
132 static int hf_nfs_pathconf_chown_restricted = -1;
133 static int hf_nfs_pathconf_case_insensitive = -1;
134 static int hf_nfs_pathconf_case_preserving = -1;
135
136 static int hf_nfs_atime = -1;
137 static int hf_nfs_atime_sec = -1;
138 static int hf_nfs_atime_nsec = -1;
139 static int hf_nfs_atime_usec = -1;
140 static int hf_nfs_mtime = -1;
141 static int hf_nfs_mtime_sec = -1;
142 static int hf_nfs_mtime_nsec = -1;
143 static int hf_nfs_mtime_usec = -1;
144 static int hf_nfs_ctime = -1;
145 static int hf_nfs_ctime_sec = -1;
146 static int hf_nfs_ctime_nsec = -1;
147 static int hf_nfs_ctime_usec = -1;
148 static int hf_nfs_dtime = -1;
149 static int hf_nfs_dtime_sec = -1;
150 static int hf_nfs_dtime_nsec = -1;
151
152 static int hf_nfs_fattr_type = -1;
153 static int hf_nfs_fattr_nlink = -1;
154 static int hf_nfs_fattr_uid = -1;
155 static int hf_nfs_fattr_gid = -1;
156 static int hf_nfs_fattr_size = -1;
157 static int hf_nfs_fattr_blocksize = -1;
158 static int hf_nfs_fattr_rdev = -1;
159 static int hf_nfs_fattr_blocks = -1;
160 static int hf_nfs_fattr_fsid = -1;
161 static int hf_nfs_fattr_fileid = -1;
162 static int hf_nfs_fattr3_type = -1;
163 static int hf_nfs_fattr3_nlink = -1;
164 static int hf_nfs_fattr3_uid = -1;
165 static int hf_nfs_fattr3_gid = -1;
166 static int hf_nfs_fattr3_size = -1;
167 static int hf_nfs_fattr3_used = -1;
168 static int hf_nfs_fattr3_rdev = -1;
169 static int hf_nfs_fattr3_fsid = -1;
170 static int hf_nfs_fattr3_fileid = -1;
171 static int hf_nfs_wcc_attr_size = -1;
172 static int hf_nfs_set_size3_size = -1;
173 static int hf_nfs_cookie3 = -1;
174 static int hf_nfs_fsstat3_resok_tbytes = -1;
175 static int hf_nfs_fsstat3_resok_fbytes = -1;
176 static int hf_nfs_fsstat3_resok_abytes = -1;
177 static int hf_nfs_fsstat3_resok_tfiles = -1;
178 static int hf_nfs_fsstat3_resok_ffiles = -1;
179 static int hf_nfs_fsstat3_resok_afiles = -1;
180 static int hf_nfs_uid3 = -1;
181 static int hf_nfs_gid3 = -1;
182 static int hf_nfs_offset3 = -1;
183 static int hf_nfs_count3 = -1;
184 static int hf_nfs_count3_maxcount = -1;
185 static int hf_nfs_count3_dircount= -1;
186
187 /* NFSv4 */
188 static int hf_nfs_argop4 = -1;
189 static int hf_nfs_resop4 = -1;
190 static int hf_nfs_linktext4 = -1;
191 static int hf_nfs_tag4 = -1;
192 static int hf_nfs_component4 = -1;
193 static int hf_nfs_clientid4 = -1;
194 static int hf_nfs_ace4 = -1;
195 static int hf_nfs_recall = -1;
196 static int hf_nfs_open_claim_type4 = -1;
197 static int hf_nfs_opentype4 = -1;
198 static int hf_nfs_limit_by4 = -1;
199 static int hf_nfs_open_delegation_type4 = -1;
200 static int hf_nfs_ftype4 = -1;
201 static int hf_nfs_change_info4_atomic = -1;
202 static int hf_nfs_open4_share_access = -1;
203 static int hf_nfs_open4_share_deny = -1;
204 static int hf_nfs_seqid4 = -1;
205 static int hf_nfs_lock_seqid4 = -1;
206 static int hf_nfs_mand_attr = -1;
207 static int hf_nfs_recc_attr = -1;
208 static int hf_nfs_time_how4 = -1;
209 static int hf_nfs_attrlist4 = -1;
210 static int hf_nfs_fattr4_link_support = -1;
211 static int hf_nfs_fattr4_symlink_support = -1;
212 static int hf_nfs_fattr4_named_attr = -1;
213 static int hf_nfs_fattr4_unique_handles = -1;
214 static int hf_nfs_fattr4_archive = -1;
215 static int hf_nfs_fattr4_cansettime = -1;
216 static int hf_nfs_fattr4_case_insensitive = -1;
217 static int hf_nfs_fattr4_case_preserving = -1;
218 static int hf_nfs_fattr4_chown_restricted = -1;
219 static int hf_nfs_fattr4_hidden = -1;
220 static int hf_nfs_fattr4_homogeneous = -1;
221 static int hf_nfs_fattr4_mimetype = -1;
222 static int hf_nfs_fattr4_no_trunc = -1;
223 static int hf_nfs_fattr4_system = -1;
224 static int hf_nfs_fattr4_owner = -1;
225 static int hf_nfs_fattr4_owner_group = -1;
226 static int hf_nfs_fattr4_size = -1;
227 static int hf_nfs_fattr4_aclsupport = -1;
228 static int hf_nfs_fattr4_lease_time = -1;
229 static int hf_nfs_fattr4_fileid = -1;
230 static int hf_nfs_fattr4_files_avail = -1;
231 static int hf_nfs_fattr4_files_free = -1;
232 static int hf_nfs_fattr4_files_total = -1;
233 static int hf_nfs_fattr4_maxfilesize = -1;
234 static int hf_nfs_fattr4_maxlink = -1;
235 static int hf_nfs_fattr4_maxname = -1;
236 static int hf_nfs_fattr4_numlinks = -1;
237 static int hf_nfs_fattr4_maxread = -1;
238 static int hf_nfs_fattr4_maxwrite = -1;
239 static int hf_nfs_fattr4_quota_hard = -1;
240 static int hf_nfs_fattr4_quota_soft = -1;
241 static int hf_nfs_fattr4_quota_used = -1;
242 static int hf_nfs_fattr4_space_avail = -1;
243 static int hf_nfs_fattr4_space_free = -1;
244 static int hf_nfs_fattr4_space_total = -1;
245 static int hf_nfs_fattr4_space_used = -1;
246 static int hf_nfs_who = -1;
247 static int hf_nfs_server = -1;
248 static int hf_nfs_stable_how4 = -1;
249 static int hf_nfs_dirlist4_eof = -1;
250 static int hf_nfs_stateid4 = -1;
251 static int hf_nfs_offset4 = -1;
252 static int hf_nfs_specdata1 = -1;
253 static int hf_nfs_specdata2 = -1;
254 static int hf_nfs_lock_type4 = -1;
255 static int hf_nfs_reclaim4 = -1;
256 static int hf_nfs_length4 = -1;
257 static int hf_nfs_changeid4 = -1;
258 static int hf_nfs_changeid4_before = -1;
259 static int hf_nfs_changeid4_after = -1;
260 static int hf_nfs_nfstime4_seconds = -1;
261 static int hf_nfs_nfstime4_nseconds = -1;
262 static int hf_nfs_fsid4_major = -1;
263 static int hf_nfs_fsid4_minor = -1;
264 static int hf_nfs_acetype4 = -1;
265 static int hf_nfs_aceflag4 = -1;
266 static int hf_nfs_acemask4 = -1;
267 static int hf_nfs_delegate_type = -1;
268 static int hf_nfs_secinfo_flavor = -1;
269 static int hf_nfs_secinfo_arr4 = -1;
270 static int hf_nfs_num_blocks = -1;
271 static int hf_nfs_bytes_per_block = -1;
272 static int hf_nfs_eof = -1;
273 static int hf_nfs_stateid4_delegate_stateid = -1;
274 static int hf_nfs_verifier4 = -1;
275 static int hf_nfs_cookie4 = -1;
276 static int hf_nfs_cookieverf4 = -1;
277 static int hf_nfs_cb_program = -1;
278 static int hf_nfs_cb_location = -1;
279 static int hf_nfs_recall4 = -1;
280 static int hf_nfs_filesize = -1;
281 static int hf_nfs_count4 = -1;
282 static int hf_nfs_count4_dircount = -1;
283 static int hf_nfs_count4_maxcount = -1;
284 static int hf_nfs_minorversion = -1;
285 static int hf_nfs_open_owner4 = -1;
286 static int hf_nfs_lock_owner4 = -1;
287 static int hf_nfs_new_lock_owner = -1;
288 static int hf_nfs_sec_oid4 = -1;
289 static int hf_nfs_qop4 = -1;
290 static int hf_nfs_secinfo_rpcsec_gss_info_service = -1;
291 static int hf_nfs_attrdircreate = -1;
292 static int hf_nfs_client_id4_id = -1;
293 static int hf_nfs_stateid4_other = -1;
294 static int hf_nfs_lock4_reclaim = -1;
295 static int hf_nfs_acl4 = -1;
296 static int hf_nfs_callback_ident = -1;
297 static int hf_nfs_r_netid = -1;
298 static int hf_nfs_r_addr = -1;
299
300 static gint ett_nfs = -1;
301 static gint ett_nfs_fh_encoding = -1;
302 static gint ett_nfs_fh_mount = -1;
303 static gint ett_nfs_fh_file = -1;
304 static gint ett_nfs_fh_export = -1;
305 static gint ett_nfs_fh_fsid = -1;
306 static gint ett_nfs_fh_xfsid = -1;
307 static gint ett_nfs_fh_fn = -1;
308 static gint ett_nfs_fh_xfn = -1;
309 static gint ett_nfs_fh_hp = -1;
310 static gint ett_nfs_fh_auth = -1;
311 static gint ett_nfs_fhandle = -1;
312 static gint ett_nfs_timeval = -1;
313 static gint ett_nfs_mode = -1;
314 static gint ett_nfs_fattr = -1;
315 static gint ett_nfs_sattr = -1;
316 static gint ett_nfs_diropargs = -1;
317 static gint ett_nfs_readdir_entry = -1;
318 static gint ett_nfs_mode3 = -1;
319 static gint ett_nfs_specdata3 = -1;
320 static gint ett_nfs_fh3 = -1;
321 static gint ett_nfs_nfstime3 = -1;
322 static gint ett_nfs_fattr3 = -1;
323 static gint ett_nfs_post_op_fh3 = -1;
324 static gint ett_nfs_sattr3 = -1;
325 static gint ett_nfs_diropargs3 = -1;
326 static gint ett_nfs_sattrguard3 = -1;
327 static gint ett_nfs_set_mode3 = -1;
328 static gint ett_nfs_set_uid3 = -1;
329 static gint ett_nfs_set_gid3 = -1;
330 static gint ett_nfs_set_size3 = -1;
331 static gint ett_nfs_set_atime = -1;
332 static gint ett_nfs_set_mtime = -1;
333 static gint ett_nfs_pre_op_attr = -1;
334 static gint ett_nfs_post_op_attr = -1;
335 static gint ett_nfs_wcc_attr = -1;
336 static gint ett_nfs_wcc_data = -1;
337 static gint ett_nfs_access = -1;
338 static gint ett_nfs_fsinfo_properties = -1;
339
340 /* NFSv4 */
341 static gint ett_nfs_compound_call4 = -1;
342 static gint ett_nfs_utf8string = -1;
343 static gint ett_nfs_argop4 = -1;
344 static gint ett_nfs_resop4 = -1;
345 static gint ett_nfs_access4 = -1;
346 static gint ett_nfs_close4 = -1;
347 static gint ett_nfs_commit4 = -1;
348 static gint ett_nfs_create4 = -1;
349 static gint ett_nfs_delegpurge4 = -1;
350 static gint ett_nfs_delegreturn4 = -1;
351 static gint ett_nfs_getattr4 = -1;
352 static gint ett_nfs_getfh4 = -1;
353 static gint ett_nfs_link4 = -1;
354 static gint ett_nfs_lock4 = -1;
355 static gint ett_nfs_lockt4 = -1;
356 static gint ett_nfs_locku4 = -1;
357 static gint ett_nfs_lookup4 = -1;
358 static gint ett_nfs_lookupp4 = -1;
359 static gint ett_nfs_nverify4 = -1;
360 static gint ett_nfs_open4 = -1;
361 static gint ett_nfs_openattr4 = -1;
362 static gint ett_nfs_open_confirm4 = -1;
363 static gint ett_nfs_open_downgrade4 = -1;
364 static gint ett_nfs_putfh4 = -1;
365 static gint ett_nfs_putpubfh4 = -1;
366 static gint ett_nfs_putrootfh4 = -1;
367 static gint ett_nfs_read4 = -1;
368 static gint ett_nfs_readdir4 = -1;
369 static gint ett_nfs_readlink4 = -1;
370 static gint ett_nfs_remove4 = -1;
371 static gint ett_nfs_rename4 = -1;
372 static gint ett_nfs_renew4 = -1;
373 static gint ett_nfs_restorefh4 = -1;
374 static gint ett_nfs_savefh4 = -1;
375 static gint ett_nfs_secinfo4 = -1;
376 static gint ett_nfs_setattr4 = -1;
377 static gint ett_nfs_setclientid4 = -1;
378 static gint ett_nfs_setclientid_confirm4 = -1;
379 static gint ett_nfs_verify4 = -1;
380 static gint ett_nfs_write4 = -1;
381 static gint ett_nfs_release_lockowner4 = -1;
382 static gint ett_nfs_illegal4 = -1;
383 static gint ett_nfs_verifier4 = -1;
384 static gint ett_nfs_opaque = -1;
385 static gint ett_nfs_dirlist4 = -1;
386 static gint ett_nfs_pathname4 = -1;
387 static gint ett_nfs_change_info4 = -1;
388 static gint ett_nfs_open_delegation4 = -1;
389 static gint ett_nfs_open_claim4 = -1;
390 static gint ett_nfs_opentype4 = -1;
391 static gint ett_nfs_lock_owner4 = -1;
392 static gint ett_nfs_cb_client4 = -1;
393 static gint ett_nfs_client_id4 = -1;
394 static gint ett_nfs_bitmap4 = -1;
395 static gint ett_nfs_fattr4 = -1;
396 static gint ett_nfs_fsid4 = -1;
397 static gint ett_nfs_fs_locations4 = -1;
398 static gint ett_nfs_fs_location4 = -1;
399 static gint ett_nfs_open4_result_flags = -1;
400 static gint ett_nfs_secinfo4_flavor_info = -1;
401 static gint ett_nfs_stateid4 = -1;
402 static gint ett_nfs_fattr4_fh_expire_type = -1;
403 static gint ett_nfs_ace4 = -1;
404 static gint ett_nfs_clientaddr4 = -1;
405 static gint ett_nfs_aceflag4 = -1;
406 static gint ett_nfs_acemask4 = -1;
407
408
409 /* fhandle displayfilters to match also corresponding request/response
410    packet in addition to the one containing the actual filehandle */
411 gboolean nfs_fhandle_reqrep_matching = FALSE;
412 static GMemChunk *nfs_fhandle_data_chunk = NULL;
413 static int nfs_fhandle_data_init_count = 100;
414 static GHashTable *nfs_fhandle_data_table = NULL;
415 GHashTable *nfs_fhandle_frame_table = NULL;
416
417 static gint
418 nfs_fhandle_data_equal(gconstpointer k1, gconstpointer k2)
419 {
420         const nfs_fhandle_data_t *key1 = (const nfs_fhandle_data_t *)k1;
421         const nfs_fhandle_data_t *key2 = (const nfs_fhandle_data_t *)k2;
422
423         return (key1->len==key2->len)
424              &&(!memcmp(key1->fh, key2->fh, key1->len));
425 }
426 static guint
427 nfs_fhandle_data_hash(gconstpointer k)
428 {
429         const nfs_fhandle_data_t *key = (const nfs_fhandle_data_t *)k;
430         int i;
431         int hash;
432
433         hash=0;
434         for(i=0;i<key->len;i++)
435                 hash ^= key->fh[i];
436
437         return hash;
438 }
439 static gboolean
440 nfs_fhandle_data_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
441 {
442         nfs_fhandle_data_t *nns = (nfs_fhandle_data_t *)value;
443
444         if(nns->fh){
445                 tvb_free(nns->tvb);
446                 nns->tvb=NULL;
447                 g_free((gpointer)nns->fh);
448                 nns->fh=NULL;
449                 nns->len=0;
450         }
451
452         return TRUE;
453 }
454 static gint
455 nfs_fhandle_frame_equal(gconstpointer k1, gconstpointer k2)
456 {
457         guint32 key1 = (guint32)k1;
458         guint32 key2 = (guint32)k2;
459
460         return key1==key2;
461 }
462 static guint
463 nfs_fhandle_frame_hash(gconstpointer k)
464 {
465         guint32 key = (guint32)k;
466
467         return key;
468 }
469 static gboolean
470 nfs_fhandle_frame_free_all(gpointer key_arg _U_, gpointer value _U_, gpointer user_data _U_)
471 {
472         return TRUE;
473 }
474 static void
475 nfs_fhandle_reqrep_matching_init(void)
476 {
477         if (nfs_fhandle_frame_table != NULL) {
478                 g_hash_table_foreach_remove(nfs_fhandle_frame_table,
479                                 nfs_fhandle_frame_free_all, NULL);
480         } else {
481                 nfs_fhandle_frame_table=g_hash_table_new(nfs_fhandle_frame_hash,
482                         nfs_fhandle_frame_equal);
483         }
484
485
486         if (nfs_fhandle_data_table != NULL) {
487                 g_hash_table_foreach_remove(nfs_fhandle_data_table,
488                                 nfs_fhandle_data_free_all, NULL);
489         } else {
490                 nfs_fhandle_data_table=g_hash_table_new(nfs_fhandle_data_hash,
491                         nfs_fhandle_data_equal);
492         }
493
494         if(nfs_fhandle_data_chunk){
495                 g_mem_chunk_destroy(nfs_fhandle_data_chunk);
496                 nfs_fhandle_data_chunk = NULL;
497         }
498
499         if(nfs_fhandle_reqrep_matching){
500                 nfs_fhandle_data_chunk = g_mem_chunk_new("nfs_fhandle_data_chunk",
501                         sizeof(nfs_fhandle_data_t),
502                         nfs_fhandle_data_init_count * sizeof(nfs_fhandle_data_t),
503                         G_ALLOC_ONLY);
504         }
505
506 }
507
508
509 /* file name snooping */
510 gboolean nfs_file_name_snooping = FALSE;
511 gboolean nfs_file_name_full_snooping = FALSE;
512 typedef struct nfs_name_snoop {
513         int fh_length;
514         unsigned char *fh;
515         int name_len;
516         unsigned char *name;
517         int parent_len;
518         unsigned char *parent;
519         int full_name_len;
520         unsigned char *full_name;
521 } nfs_name_snoop_t;
522
523 typedef struct nfs_name_snoop_key {
524         int key;
525         int fh_length;
526         const unsigned char *fh;
527 } nfs_name_snoop_key_t;
528
529 static GMemChunk *nfs_name_snoop_chunk = NULL;
530 static int nfs_name_snoop_init_count = 100;
531 static GHashTable *nfs_name_snoop_unmatched = NULL;
532
533 static GMemChunk *nfs_name_snoop_key_chunk = NULL;
534 static int nfs_name_snoop_key_init_count = 100;
535 static GHashTable *nfs_name_snoop_matched = NULL;
536
537 static GHashTable *nfs_name_snoop_known = NULL;
538
539 static gint
540 nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer k2)
541 {
542         const nfs_name_snoop_key_t *key1 = (const nfs_name_snoop_key_t *)k1;
543         const nfs_name_snoop_key_t *key2 = (const nfs_name_snoop_key_t *)k2;
544
545         return (key1->key==key2->key)
546              &&(key1->fh_length==key2->fh_length)
547              &&(!memcmp(key1->fh, key2->fh, key1->fh_length));
548 }
549 static guint
550 nfs_name_snoop_matched_hash(gconstpointer k)
551 {
552         const nfs_name_snoop_key_t *key = (const nfs_name_snoop_key_t *)k;
553         int i;
554         guint hash;
555
556         hash=key->key;
557         for(i=0;i<key->fh_length;i++)
558                 hash ^= key->fh[i];
559
560         return hash;
561 }
562 static gint
563 nfs_name_snoop_unmatched_equal(gconstpointer k1, gconstpointer k2)
564 {
565         guint32 key1 = (guint32)k1;
566         guint32 key2 = (guint32)k2;
567
568         return key1==key2;
569 }
570 static guint
571 nfs_name_snoop_unmatched_hash(gconstpointer k)
572 {
573         guint32 key = (guint32)k;
574
575         return key;
576 }
577 static gboolean
578 nfs_name_snoop_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
579 {
580         nfs_name_snoop_t *nns = (nfs_name_snoop_t *)value;
581
582         if(nns->name){
583                 g_free((gpointer)nns->name);
584                 nns->name=NULL;
585                 nns->name_len=0;
586         }
587         if(nns->full_name){
588                 g_free((gpointer)nns->full_name);
589                 nns->full_name=NULL;
590                 nns->full_name_len=0;
591         }
592         if(nns->parent){
593                 g_free((gpointer)nns->parent);
594                 nns->parent=NULL;
595                 nns->parent_len=0;
596         }
597         if(nns->fh){
598                 g_free((gpointer)nns->fh);
599                 nns->fh=NULL;
600                 nns->fh_length=0;
601         }
602         return TRUE;
603 }
604
605 static void
606 nfs_name_snoop_init(void)
607 {
608         if (nfs_name_snoop_unmatched != NULL) {
609                 g_hash_table_foreach_remove(nfs_name_snoop_unmatched,
610                                 nfs_name_snoop_unmatched_free_all, NULL);
611         } else {
612                 /* The fragment table does not exist. Create it */
613                 nfs_name_snoop_unmatched=g_hash_table_new(nfs_name_snoop_unmatched_hash,
614                         nfs_name_snoop_unmatched_equal);
615         }
616         if (nfs_name_snoop_matched != NULL) {
617                 g_hash_table_foreach_remove(nfs_name_snoop_matched,
618                                 nfs_name_snoop_unmatched_free_all, NULL);
619         } else {
620                 /* The fragment table does not exist. Create it */
621                 nfs_name_snoop_matched=g_hash_table_new(nfs_name_snoop_matched_hash,
622                         nfs_name_snoop_matched_equal);
623         }
624         if (nfs_name_snoop_known != NULL) {
625                 g_hash_table_foreach_remove(nfs_name_snoop_known,
626                                 nfs_name_snoop_unmatched_free_all, NULL);
627         } else {
628                 /* The fragment table does not exist. Create it */
629                 nfs_name_snoop_known=g_hash_table_new(nfs_name_snoop_matched_hash,
630                         nfs_name_snoop_matched_equal);
631         }
632
633         if(nfs_name_snoop_chunk){
634                 g_mem_chunk_destroy(nfs_name_snoop_chunk);
635                 nfs_name_snoop_chunk = NULL;
636         }
637         if(nfs_name_snoop_key_chunk){
638                 g_mem_chunk_destroy(nfs_name_snoop_key_chunk);
639                 nfs_name_snoop_key_chunk = NULL;
640         }
641
642         if(nfs_file_name_snooping){
643                 nfs_name_snoop_chunk = g_mem_chunk_new("nfs_name_snoop_chunk",
644                         sizeof(nfs_name_snoop_t),
645                         nfs_name_snoop_init_count * sizeof(nfs_name_snoop_t),
646                         G_ALLOC_ONLY);
647                 nfs_name_snoop_key_chunk = g_mem_chunk_new("nfs_name_snoop_key_chunk",
648                         sizeof(nfs_name_snoop_key_t),
649                         nfs_name_snoop_key_init_count * sizeof(nfs_name_snoop_key_t),
650                         G_ALLOC_ONLY);
651         }
652
653 }
654
655 void
656 nfs_name_snoop_add_name(int xid, tvbuff_t *tvb, int name_offset, int name_len, int parent_offset, int parent_len, unsigned char *name)
657 {
658         nfs_name_snoop_t *nns, *old_nns;
659         const unsigned char *ptr=NULL;
660
661         /* filter out all '.' and '..' names */
662         if(!name){
663                 ptr=(const unsigned char *)tvb_get_ptr(tvb, name_offset, name_len);
664                 if(ptr[0]=='.'){
665                         if(ptr[1]==0){
666                                 return;
667                         }
668                         if(ptr[1]=='.'){
669                                 if(ptr[2]==0){
670                                         return;
671                                 }
672                         }
673                 }
674         }
675
676         nns=g_mem_chunk_alloc(nfs_name_snoop_chunk);
677
678         nns->fh_length=0;
679         nns->fh=NULL;
680
681         if(parent_len){
682                 nns->parent_len=parent_len;
683                 nns->parent=tvb_memdup(tvb, parent_offset, parent_len);
684         } else {
685                 nns->parent_len=0;
686                 nns->parent=NULL;
687         }
688
689         nns->name_len=name_len;
690         if(name){
691                 nns->name=name;
692         } else {
693                 nns->name=g_malloc(name_len+1);
694                 memcpy(nns->name, ptr, name_len);
695         }
696         nns->name[name_len]=0;
697
698         nns->full_name_len=0;
699         nns->full_name=NULL;
700
701         /* remove any old entry for this */
702         old_nns=g_hash_table_lookup(nfs_name_snoop_unmatched, (gconstpointer)xid);
703         if(old_nns){
704                 /* if we haven't seen the reply yet, then there are no
705                    matched entries for it, thus we can dealloc the arrays*/
706                 if(!old_nns->fh){
707                         g_free(old_nns->name);
708                         old_nns->name=NULL;
709                         old_nns->name_len=0;
710
711                         g_free(old_nns->parent);
712                         old_nns->parent=NULL;
713                         old_nns->parent_len=0;
714
715                         g_mem_chunk_free(nfs_name_snoop_chunk, old_nns);
716                 }
717                 g_hash_table_remove(nfs_name_snoop_unmatched, (gconstpointer)xid);
718         }
719
720         g_hash_table_insert(nfs_name_snoop_unmatched, (gpointer)xid, nns);
721 }
722
723 static void
724 nfs_name_snoop_add_fh(int xid, tvbuff_t *tvb, int fh_offset, int fh_length)
725 {
726         unsigned char *fh;
727         nfs_name_snoop_t *nns, *old_nns;
728         nfs_name_snoop_key_t *key;
729
730         /* find which request we correspond to */
731         nns=g_hash_table_lookup(nfs_name_snoop_unmatched, (gconstpointer)xid);
732         if(!nns){
733                 /* oops couldnt find matching request, bail out */
734                 return;
735         }
736
737         /* if we have already seen this response earlier */
738         if(nns->fh){
739                 return;
740         }
741
742         /* oki, we have a new entry */
743         fh=tvb_memdup(tvb, fh_offset, fh_length);
744         nns->fh=fh;
745         nns->fh_length=fh_length;
746
747         key=g_mem_chunk_alloc(nfs_name_snoop_key_chunk);
748         key->key=0;
749         key->fh_length=nns->fh_length;
750         key->fh    =nns->fh;
751
752         /* already have something matched for this fh, remove it from
753            the table */
754         old_nns=g_hash_table_lookup(nfs_name_snoop_matched, key);
755         if(old_nns){
756                 g_hash_table_remove(nfs_name_snoop_matched, key);
757         }
758
759         g_hash_table_remove(nfs_name_snoop_unmatched, (gconstpointer)xid);
760         g_hash_table_insert(nfs_name_snoop_matched, key, nns);
761 }
762
763 static void
764 nfs_full_name_snoop(nfs_name_snoop_t *nns, int *len, unsigned char **name, unsigned char **pos)
765 {
766         nfs_name_snoop_t *parent_nns = NULL;
767         nfs_name_snoop_key_t key;
768
769         /* check if the nns component ends with a '/' else we just allocate
770            an extra byte to len to accommodate for it later */
771         if(nns->name[nns->name_len-1]!='/'){
772                 (*len)++;
773         }
774
775         (*len) += nns->name_len;
776
777         if(nns->parent==NULL){
778                 *name = g_malloc((*len)+1);
779                 *pos = *name;
780
781                 strcpy(*pos, nns->name);
782                 *pos += nns->name_len;
783                 return;
784         }
785
786         key.key=0;
787         key.fh_length=nns->parent_len;
788         key.fh=nns->parent;
789
790         parent_nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
791
792         if(parent_nns){
793                 nfs_full_name_snoop(parent_nns, len, name, pos);
794                 if(*name){
795                         /* make sure components are '/' separated */
796                         if( (*pos)[-1] != '/'){
797                                 **pos='/';
798                                 (*pos)++;
799                                 **pos=0;
800                         }
801                         strcpy(*pos, nns->name);
802                         *pos += nns->name_len;
803                 }
804                 return;
805         }
806
807         return;
808 }
809
810 static void
811 nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_offset, int fh_length, gboolean hidden)
812 {
813         nfs_name_snoop_key_t key;
814         nfs_name_snoop_t *nns = NULL;
815
816         /* if this is a new packet, see if we can register the mapping */
817         if(!pinfo->fd->flags.visited){
818                 key.key=0;
819                 key.fh_length=fh_length;
820                 key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
821
822                 nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
823                 if(nns){
824                         nfs_name_snoop_key_t *k;
825                         k=g_mem_chunk_alloc(nfs_name_snoop_key_chunk);
826                         k->key=pinfo->fd->num;
827                         k->fh_length=nns->fh_length;
828                         k->fh=nns->fh;
829                         g_hash_table_insert(nfs_name_snoop_known, k, nns);
830
831                         if(nfs_file_name_full_snooping){
832                                 unsigned char *name=NULL, *pos=NULL;
833                                 int len=0;
834
835                                 nfs_full_name_snoop(nns, &len, &name, &pos);
836                                 if(name){
837                                         nns->full_name=name;
838                                         nns->full_name_len=len;
839                                 }
840                         }
841                 }
842         }
843
844         /* see if we know this mapping */
845         if(!nns){
846                 key.key=pinfo->fd->num;
847                 key.fh_length=fh_length;
848                 key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
849
850                 nns=g_hash_table_lookup(nfs_name_snoop_known, &key);
851         }
852
853         /* if we know the mapping, print the filename */
854         if(nns){
855                 if(hidden){
856                         proto_tree_add_string_hidden(tree, hf_nfs_name, tvb,
857                                 fh_offset, 0, nns->name);
858                 }else {
859                         proto_tree_add_string_format(tree, hf_nfs_name, tvb,
860                                 fh_offset, 0, nns->name, "Name: %s", nns->name);
861                 }
862                 if(nns->full_name){
863                         if(hidden){
864                                 proto_tree_add_string_hidden(tree, hf_nfs_full_name, tvb,
865                                         fh_offset, 0, nns->name);
866                         } else {
867                                 proto_tree_add_string_format(tree, hf_nfs_full_name, tvb,
868                                         fh_offset, 0, nns->name, "Full Name: %s", nns->full_name);
869                         }
870                 }
871         }
872 }
873
874 /* file handle dissection */
875
876 #define FHT_UNKNOWN             0
877 #define FHT_SVR4                1
878 #define FHT_LINUX_KNFSD_LE      2
879 #define FHT_LINUX_NFSD_LE       3
880 #define FHT_LINUX_KNFSD_NEW     4
881 #define FHT_NETAPP              5
882
883 static const value_string names_fhtype[] =
884 {
885         {       FHT_UNKNOWN,            "unknown"                               },
886         {       FHT_SVR4,               "System V R4"                           },
887         {       FHT_LINUX_KNFSD_LE,     "Linux knfsd (little-endian)"           },
888         {       FHT_LINUX_NFSD_LE,      "Linux user-land nfsd (little-endian)"  },
889         {       FHT_LINUX_KNFSD_NEW,    "Linux knfsd (new)"                     },
890         {       FHT_NETAPP,             "NetApp file handle"                    },
891         {       0,      NULL    }
892 };
893
894
895 /* SVR4: checked with ReliantUNIX (5.43, 5.44, 5.45) */
896
897 static void
898 dissect_fhandle_data_SVR4(tvbuff_t* tvb, int offset, proto_tree *tree,
899     int fhlen _U_)
900 {
901         guint32 nof = offset;
902
903         /* file system id */
904         {
905         guint32 fsid_O;
906         guint32 fsid_L;
907         guint32 temp;
908         guint32 fsid_major;
909         guint32 fsid_minor;
910
911         fsid_O = nof;
912         fsid_L = 4;
913         temp = tvb_get_ntohl(tvb, fsid_O);
914         fsid_major = ( temp>>18 ) &  0x3fff; /* 14 bits */
915         fsid_minor = ( temp     ) & 0x3ffff; /* 18 bits */
916         if (tree) {
917                 proto_item* fsid_item = NULL;
918                 proto_tree* fsid_tree = NULL;
919
920                 fsid_item = proto_tree_add_text(tree, tvb,
921                         fsid_O, fsid_L,
922                         "file system ID: %d,%d", fsid_major, fsid_minor);
923                 if (fsid_item) {
924                         fsid_tree = proto_item_add_subtree(fsid_item,
925                                         ett_nfs_fh_fsid);
926                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
927                                 tvb, fsid_O,   2, fsid_major);
928                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
929                                 tvb, fsid_O+1, 3, fsid_minor);
930                 }
931         }
932         nof = fsid_O + fsid_L;
933         }
934
935         /* file system type */
936         {
937         guint32 fstype_O;
938         guint32 fstype_L;
939         guint32 fstype;
940
941         fstype_O = nof;
942         fstype_L = 4;
943         fstype = tvb_get_ntohl(tvb, fstype_O);
944         if (tree) {
945                 proto_tree_add_uint(tree, hf_nfs_fh_fstype, tvb,
946                         fstype_O, fstype_L, fstype);
947         }
948         nof = fstype_O + fstype_L;
949         }
950
951         /* file number */
952         {
953         guint32 fn_O;
954         guint32 fn_len_O;
955         guint32 fn_len_L;
956         guint32 fn_len;
957         guint32 fn_data_O;
958         guint32 fn_data_inode_O;
959         guint32 fn_data_inode_L;
960         guint32 inode;
961         guint32 fn_data_gen_O;
962         guint32 fn_data_gen_L;
963         guint32 gen;
964         guint32 fn_L;
965
966         fn_O = nof;
967         fn_len_O = fn_O;
968         fn_len_L = 2;
969         fn_len = tvb_get_ntohs(tvb, fn_len_O);
970         fn_data_O = fn_O + fn_len_L;
971         fn_data_inode_O = fn_data_O + 2;
972         fn_data_inode_L = 4;
973         inode = tvb_get_ntohl(tvb, fn_data_inode_O);
974         fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
975         fn_data_gen_L = 4;
976         gen = tvb_get_ntohl(tvb, fn_data_gen_O);
977         fn_L = fn_len_L + fn_len;
978         if (tree) {
979                 proto_item* fn_item = NULL;
980                 proto_tree* fn_tree = NULL;
981
982                 fn_item = proto_tree_add_uint(tree, hf_nfs_fh_fn, tvb,
983                         fn_O, fn_L, inode);
984                 if (fn_item) {
985                         fn_tree = proto_item_add_subtree(fn_item,
986                                         ett_nfs_fh_fn);
987                         proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_len,
988                                 tvb, fn_len_O, fn_len_L, fn_len);
989                         proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_inode,
990                                 tvb, fn_data_inode_O, fn_data_inode_L, inode);
991                         proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_generation,
992                                 tvb, fn_data_gen_O, fn_data_gen_L, gen);
993                 }
994         }
995         nof = fn_O + fn_len_L + fn_len;
996         }
997
998         /* exported file number */
999         {
1000         guint32 xfn_O;
1001         guint32 xfn_len_O;
1002         guint32 xfn_len_L;
1003         guint32 xfn_len;
1004         guint32 xfn_data_O;
1005         guint32 xfn_data_inode_O;
1006         guint32 xfn_data_inode_L;
1007         guint32 xinode;
1008         guint32 xfn_data_gen_O;
1009         guint32 xfn_data_gen_L;
1010         guint32 xgen;
1011         guint32 xfn_L;
1012
1013         xfn_O = nof;
1014         xfn_len_O = xfn_O;
1015         xfn_len_L = 2;
1016         xfn_len = tvb_get_ntohs(tvb, xfn_len_O);
1017         xfn_data_O = xfn_O + xfn_len_L;
1018         xfn_data_inode_O = xfn_data_O + 2;
1019         xfn_data_inode_L = 4;
1020         xinode = tvb_get_ntohl(tvb, xfn_data_inode_O);
1021         xfn_data_gen_O = xfn_data_inode_O + xfn_data_inode_L;
1022         xfn_data_gen_L = 4;
1023         xgen = tvb_get_ntohl(tvb, xfn_data_gen_O);
1024         xfn_L = xfn_len_L + xfn_len;
1025         if (tree) {
1026                 proto_item* xfn_item = NULL;
1027                 proto_tree* xfn_tree = NULL;
1028
1029                 xfn_item = proto_tree_add_uint(tree, hf_nfs_fh_xfn, tvb,
1030                         xfn_O, xfn_L, xinode);
1031                 if (xfn_item) {
1032                         xfn_tree = proto_item_add_subtree(xfn_item,
1033                                         ett_nfs_fh_xfn);
1034                         proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_len,
1035                                 tvb, xfn_len_O, xfn_len_L, xfn_len);
1036                         proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_inode,
1037                                 tvb, xfn_data_inode_O, xfn_data_inode_L, xinode);
1038                         proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_generation,
1039                                 tvb, xfn_data_gen_O, xfn_data_gen_L, xgen);
1040                 }
1041         }
1042         }
1043 }
1044
1045
1046 /* Checked with RedHat Linux 6.2 (kernel 2.2.14 knfsd) */
1047
1048 static void
1049 dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, int offset, proto_tree *tree,
1050     int fhlen _U_)
1051 {
1052         guint32 dentry;
1053         guint32 inode;
1054         guint32 dirinode;
1055         guint32 temp;
1056         guint32 fsid_major;
1057         guint32 fsid_minor;
1058         guint32 xfsid_major;
1059         guint32 xfsid_minor;
1060         guint32 xinode;
1061         guint32 gen;
1062
1063         dentry   = tvb_get_letohl(tvb, offset+0);
1064         inode    = tvb_get_letohl(tvb, offset+4);
1065         dirinode = tvb_get_letohl(tvb, offset+8);
1066         temp     = tvb_get_letohs (tvb,offset+12);
1067         fsid_major = (temp >> 8) & 0xff;
1068         fsid_minor = (temp     ) & 0xff;
1069         temp     = tvb_get_letohs(tvb,offset+16);
1070         xfsid_major = (temp >> 8) & 0xff;
1071         xfsid_minor = (temp     ) & 0xff;
1072         xinode   = tvb_get_letohl(tvb,offset+20);
1073         gen      = tvb_get_letohl(tvb,offset+24);
1074
1075         if (tree) {
1076                 proto_tree_add_uint(tree, hf_nfs_fh_dentry,
1077                         tvb, offset+0, 4, dentry);
1078                 proto_tree_add_uint(tree, hf_nfs_fh_fn_inode,
1079                         tvb, offset+4, 4, inode);
1080                 proto_tree_add_uint(tree, hf_nfs_fh_dirinode,
1081                         tvb, offset+8, 4, dirinode);
1082
1083                 /* file system id (device) */
1084                 {
1085                 proto_item* fsid_item = NULL;
1086                 proto_tree* fsid_tree = NULL;
1087
1088                 fsid_item = proto_tree_add_text(tree, tvb,
1089                         offset+12, 4,
1090                         "file system ID: %d,%d", fsid_major, fsid_minor);
1091                 if (fsid_item) {
1092                         fsid_tree = proto_item_add_subtree(fsid_item,
1093                                         ett_nfs_fh_fsid);
1094                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
1095                                 tvb, offset+13, 1, fsid_major);
1096                         proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
1097                                 tvb, offset+12, 1, fsid_minor);
1098                 }
1099                 }
1100
1101                 /* exported file system id (device) */
1102                 {
1103                 proto_item* xfsid_item = NULL;
1104                 proto_tree* xfsid_tree = NULL;
1105
1106                 xfsid_item = proto_tree_add_text(tree, tvb,
1107                         offset+16, 4,
1108                         "exported file system ID: %d,%d", xfsid_major, xfsid_minor);
1109                 if (xfsid_item) {
1110                         xfsid_tree = proto_item_add_subtree(xfsid_item,
1111                                         ett_nfs_fh_xfsid);
1112                         proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_major,
1113                                 tvb, offset+17, 1, xfsid_major);
1114                         proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_minor,
1115                                 tvb, offset+16, 1, xfsid_minor);
1116                 }
1117                 }
1118
1119                 proto_tree_add_uint(tree, hf_nfs_fh_xfn_inode,
1120                         tvb, offset+20, 4, xinode);
1121                 proto_tree_add_uint(tree, hf_nfs_fh_fn_generation,
1122                         tvb, offset+24, 4, gen);
1123         }
1124 }
1125
1126
1127 /* Checked with RedHat Linux 5.2 (nfs-server 2.2beta47 user-land nfsd) */
1128
1129 static void
1130 dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, int offset, proto_tree *tree,
1131     int fhlen _U_)
1132 {
1133         /* pseudo inode */
1134         {
1135         guint32 pinode;
1136         pinode   = tvb_get_letohl(tvb, offset+0);
1137         if (tree) {
1138                 proto_tree_add_uint(tree, hf_nfs_fh_pinode,
1139                         tvb, offset+0, 4, pinode);
1140         }
1141         }
1142
1143         /* hash path */
1144         {
1145         guint32 hashlen;
1146
1147         hashlen  = tvb_get_guint8(tvb, offset+4);
1148         if (tree) {
1149                 proto_item* hash_item = NULL;
1150                 proto_tree* hash_tree = NULL;
1151
1152                 hash_item = proto_tree_add_text(tree, tvb, offset+4,
1153                                 hashlen + 1,
1154                                 "hash path: %s",
1155                                 tvb_bytes_to_str(tvb,offset+5,hashlen));
1156                 if (hash_item) {
1157                         hash_tree = proto_item_add_subtree(hash_item,
1158                                         ett_nfs_fh_hp);
1159                         if (hash_tree) {
1160                                 proto_tree_add_uint(hash_tree,
1161                                         hf_nfs_fh_hp_len, tvb, offset+4, 1,
1162                                         hashlen);
1163                                 proto_tree_add_text(hash_tree, tvb, offset+5,
1164                                         hashlen,
1165                                         "key: %s",
1166                                         tvb_bytes_to_str(tvb,offset+5,hashlen));
1167                         }
1168                 }
1169         }
1170         }
1171 }
1172
1173
1174 /* Checked with SuSE 7.1 (kernel 2.4.0 knfsd) */
1175 /* read linux-2.4.5/include/linux/nfsd/nfsfh.h for more details */
1176
1177 #define AUTH_TYPE_NONE 0
1178 static const value_string auth_type_names[] = {
1179         {       AUTH_TYPE_NONE,                         "no authentication"             },
1180         {0,NULL}
1181 };
1182
1183 #define FSID_TYPE_MAJOR_MINOR_INODE 0
1184 static const value_string fsid_type_names[] = {
1185         {       FSID_TYPE_MAJOR_MINOR_INODE,            "major/minor/inode"             },
1186         {0,NULL}
1187 };
1188
1189 #define FILEID_TYPE_ROOT                        0
1190 #define FILEID_TYPE_INODE_GENERATION            1
1191 #define FILEID_TYPE_INODE_GENERATION_PARENT     2
1192 static const value_string fileid_type_names[] = {
1193         {       FILEID_TYPE_ROOT,                       "root"                          },
1194         {       FILEID_TYPE_INODE_GENERATION,           "inode/generation"              },
1195         {       FILEID_TYPE_INODE_GENERATION_PARENT,    "inode/generation/parent"       },
1196         {0,NULL}
1197 };
1198
1199 static void
1200 dissect_fhandle_data_NETAPP(tvbuff_t* tvb, int offset, proto_tree *tree,
1201     int fhlen _U_)
1202 {
1203         if (tree) {
1204                 guint32 mount = tvb_get_letohl(tvb, offset + 0);
1205                 guint32 mount_gen = tvb_get_letohl(tvb, offset + 4);
1206                 guint16 flags = tvb_get_letohs(tvb, offset + 8);
1207                 guint8 snapid = tvb_get_guint8(tvb, offset + 10);
1208                 guint8 unused = tvb_get_guint8(tvb, offset + 11);
1209                 guint32 inum = tvb_get_ntohl(tvb, offset + 12);
1210                 guint32 generation = tvb_get_letohl(tvb, offset + 16);
1211                 guint32 fsid = tvb_get_letohl(tvb, offset + 20);
1212                 guint32 export = tvb_get_letohl(tvb, offset + 24);
1213                 guint32 export_snapgen = tvb_get_letohl(tvb, offset + 28);
1214                 proto_item *item;
1215                 proto_tree *subtree;
1216                 char flag_string[128] = "";
1217                 char *strings[] = { " MNT_PNT", " SNAPDIR", " SNAPDIR_ENT",
1218                                     " EMPTY", " VBN_ACCESS", " MULTIVOLUME",
1219                                     " METADATA" };
1220                 guint16 bit = sizeof(strings) / sizeof(strings[0]);
1221                 while (bit--)
1222                         if (flags & (1<<bit))
1223                                 strcat(flag_string, strings[bit]);
1224                 item = proto_tree_add_text(tree, tvb, offset + 0, 8,
1225                                            "mount (inode %u)", mount);
1226                 subtree = proto_item_add_subtree(item, ett_nfs_fh_mount);
1227                 item = proto_tree_add_uint(subtree, hf_nfs_fh_mount_fileid,
1228                                            tvb, offset + 0, 4, mount);
1229                 item = proto_tree_add_uint(subtree, hf_nfs_fh_mount_generation,
1230                                            tvb, offset + 4, 4, mount_gen);
1231                 item = proto_tree_add_text(tree, tvb, offset + 8, 16,
1232                                            "file (inode %u)", inum);
1233                 subtree = proto_item_add_subtree(item, ett_nfs_fh_file);
1234                 item = proto_tree_add_uint_format(subtree, hf_nfs_fh_flags,
1235                                                   tvb, offset + 8, 2, flags,
1236                                                   "Flags: %#02x%s", flags,
1237                                                   flag_string);
1238                 item = proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
1239                                            offset + 10, 1, snapid);
1240                 item = proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
1241                                            offset + 11, 1, unused);
1242                 item = proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
1243                                            offset + 12, 4, inum);
1244                 item = proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
1245                                            offset + 16, 4, generation);
1246                 item = proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
1247                                            offset + 20, 4, fsid);
1248                 item = proto_tree_add_text(tree, tvb, offset + 24, 8,
1249                                            "export (inode %u)", export);
1250                 subtree = proto_item_add_subtree(item, ett_nfs_fh_export);
1251                 item = proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
1252                                            tvb, offset + 24, 4, export);
1253                 item = proto_tree_add_uint(subtree,
1254                                            hf_nfs_fh_export_generation,
1255                                            tvb, offset + 28, 3,
1256                                            export_snapgen & 0xffffff);
1257                 item = proto_tree_add_uint(subtree, hf_nfs_fh_export_snapid,
1258                                            tvb, offset + 31, 1,
1259                                            export_snapgen >> 24);
1260         }
1261 }
1262
1263 static void
1264 dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, int offset, proto_tree *tree,
1265     int fhlen _U_)
1266 {
1267         guint8 version;
1268         guint8 auth_type;
1269         guint8 fsid_type;
1270         guint8 fileid_type;
1271
1272         version     = tvb_get_guint8(tvb, offset + 0);
1273         if (tree) {
1274                 proto_tree_add_uint(tree, hf_nfs_fh_version,
1275                         tvb, offset+0, 1, version);
1276         }
1277
1278         switch (version) {
1279                 case 1: {
1280                         auth_type   = tvb_get_guint8(tvb, offset + 1);
1281                         fsid_type   = tvb_get_guint8(tvb, offset + 2);
1282                         fileid_type = tvb_get_guint8(tvb, offset + 3);
1283                         if (tree) {
1284                                 proto_item* encoding_item = proto_tree_add_text(tree, tvb,
1285                                         offset + 1, 3,
1286                                         "encoding: %u %u %u",
1287                                         auth_type, fsid_type, fileid_type);
1288                                 if (encoding_item) {
1289                                         proto_tree* encoding_tree = proto_item_add_subtree(encoding_item,
1290                                                 ett_nfs_fh_encoding);
1291                                         if (encoding_tree) {
1292                                                 proto_tree_add_uint(encoding_tree, hf_nfs_fh_auth_type,
1293                                                         tvb, offset+1, 1, auth_type);
1294                                                 proto_tree_add_uint(encoding_tree, hf_nfs_fh_fsid_type,
1295                                                         tvb, offset+2, 1, fsid_type);
1296                                                 proto_tree_add_uint(encoding_tree, hf_nfs_fh_fileid_type,
1297                                                         tvb, offset+3, 1, fileid_type);
1298                                         }
1299                                 }
1300                         }
1301                         offset += 4;
1302                 } break;
1303                 default: {
1304                         /* unknown version */
1305                         goto out;
1306                 }
1307         }
1308
1309         switch (auth_type) {
1310                 case 0: {
1311                         /* no authentication */
1312                         if (tree) {
1313                                 proto_tree_add_text(tree, tvb,
1314                                         offset + 0, 0,
1315                                         "authentication: none");
1316                         }
1317                 } break;
1318                 default: {
1319                         /* unknown authentication type */
1320                         goto out;
1321                 }
1322         }
1323
1324         switch (fsid_type) {
1325                 case 0: {
1326                         guint16 fsid_major;
1327                         guint16 fsid_minor;
1328                         guint32 fsid_inode;
1329
1330                         fsid_major = tvb_get_ntohs(tvb, offset + 0);
1331                         fsid_minor = tvb_get_ntohs(tvb, offset + 2);
1332                         fsid_inode = tvb_get_letohl(tvb, offset + 4);
1333                         if (tree) {
1334                                 proto_item* fsid_item = proto_tree_add_text(tree, tvb,
1335                                         offset+0, 8,
1336                                         "file system ID: %u,%u (inode %u)",
1337                                         fsid_major, fsid_minor, fsid_inode);
1338                                 if (fsid_item) {
1339                                         proto_tree* fsid_tree = proto_item_add_subtree(fsid_item,
1340                                                 ett_nfs_fh_fsid);
1341                                         if (fsid_tree) {
1342                                                 proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
1343                                                         tvb, offset+0, 2, fsid_major);
1344                                                 proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
1345                                                         tvb, offset+2, 2, fsid_minor);
1346                                                 proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_inode,
1347                                                         tvb, offset+4, 4, fsid_inode);
1348                                         }
1349                                 }
1350                         }
1351                         offset += 8;
1352                 } break;
1353                 default: {
1354                         /* unknown fsid type */
1355                         goto out;
1356                 }
1357         }
1358
1359         switch (fileid_type) {
1360                 case 0: {
1361                         if (tree) {
1362                                 proto_tree_add_text(tree, tvb,
1363                                         offset+0, 0,
1364                                         "file ID: root inode");
1365                         }
1366                 } break;
1367                 case 1: {
1368                         guint32 inode;
1369                         guint32 generation;
1370
1371                         inode = tvb_get_letohl(tvb, offset + 0);
1372                         generation = tvb_get_letohl(tvb, offset + 4);
1373
1374                         if (tree) {
1375                                 proto_item* fileid_item = proto_tree_add_text(tree, tvb,
1376                                         offset+0, 8,
1377                                         "file ID: %u (%u)",
1378                                         inode, generation);
1379                                 if (fileid_item) {
1380                                         proto_tree* fileid_tree = proto_item_add_subtree(
1381                                                 fileid_item, ett_nfs_fh_fn);
1382                                         if (fileid_tree) {
1383                                                 proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
1384                                                 tvb, offset+0, 4, inode);
1385                                                 proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
1386                                                 tvb, offset+4, 4, generation);
1387                                         }
1388                                 }
1389                         }
1390
1391                         offset += 8;
1392                 } break;
1393                 case 2: {
1394                         guint32 inode;
1395                         guint32 generation;
1396                         guint32 parent_inode;
1397
1398                         inode = tvb_get_letohl(tvb, offset + 0);
1399                         generation = tvb_get_letohl(tvb, offset + 4);
1400                         parent_inode = tvb_get_letohl(tvb, offset + 8);
1401
1402                         if (tree) {
1403                                  proto_item* fileid_item = proto_tree_add_text(tree, tvb,
1404                                         offset+0, 8,
1405                                         "file ID: %u (%u)",
1406                                         inode, generation);
1407                                 if (fileid_item) {
1408                                         proto_tree* fileid_tree = proto_item_add_subtree(
1409                                                 fileid_item, ett_nfs_fh_fn);
1410                                         if (fileid_tree) {
1411                                                 proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
1412                                                 tvb, offset+0, 4, inode);
1413                                                 proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
1414                                                 tvb, offset+4, 4, generation);
1415                                                 proto_tree_add_uint(fileid_tree, hf_nfs_fh_dirinode,
1416                                                 tvb, offset+8, 4, parent_inode);
1417                                         }
1418                                 }
1419                         }
1420
1421                         offset += 12;
1422                 } break;
1423                 default: {
1424                         /* unknown fileid type */
1425                         goto out;
1426                 }
1427         }
1428
1429 out:
1430         ;
1431 }
1432
1433
1434 static void
1435 dissect_fhandle_data_unknown(tvbuff_t *tvb, int offset, proto_tree *tree,
1436     guint fhlen)
1437 {
1438         guint sublen;
1439         guint bytes_left;
1440         gboolean first_line;
1441
1442         bytes_left = fhlen;
1443         first_line = TRUE;
1444         while (bytes_left != 0) {
1445                 sublen = 16;
1446                 if (sublen > bytes_left)
1447                         sublen = bytes_left;
1448                 proto_tree_add_text(tree, tvb, offset, sublen,
1449                                         "%s%s",
1450                                         first_line ? "data: " :
1451                                                      "      ",
1452                                         tvb_bytes_to_str(tvb,offset,sublen));
1453                 bytes_left -= sublen;
1454                 offset += sublen;
1455                 first_line = FALSE;
1456         }
1457 }
1458
1459
1460 static void
1461 dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
1462     proto_tree *tree, unsigned int fhlen, gboolean hidden, guint32 *hash)
1463 {
1464         unsigned int fhtype = FHT_UNKNOWN;
1465
1466         /* filehandle too long */
1467         if (fhlen>64) goto type_ready;
1468         /* Not all bytes there. Any attempt to deduce the type would be
1469            senseless. */
1470         if (!tvb_bytes_exist(tvb,offset,fhlen)) goto type_ready;
1471
1472         /* this is to set up fhandle display filters to find both packets
1473            of an RPC call */
1474         if(nfs_fhandle_reqrep_matching && (!hidden) ){
1475                 nfs_fhandle_data_t *old_fhd=NULL;
1476                 unsigned char *fh;
1477
1478                 if( !pinfo->fd->flags.visited ){
1479                         nfs_fhandle_data_t fhd;
1480
1481                         /* first check if we have seen this fhandle before */
1482                         fhd.len=fhlen;
1483                         fhd.fh=(const unsigned char *)tvb_get_ptr(tvb, offset, fhlen);
1484                         old_fhd=g_hash_table_lookup(nfs_fhandle_data_table,
1485                                 (gconstpointer)&fhd);
1486                         if(!old_fhd){
1487                                 /* oh, a new fhandle, alloc struct and store it in the table*/
1488                                 old_fhd=g_mem_chunk_alloc(nfs_fhandle_data_chunk);
1489                                 old_fhd->len=fhlen;
1490                                 fh=g_malloc(fhlen);
1491                                 memcpy(fh, fhd.fh, fhlen);
1492                                 old_fhd->fh=fh;
1493                                 old_fhd->tvb=tvb_new_real_data(old_fhd->fh, old_fhd->len, old_fhd->len);
1494                                 g_hash_table_insert(nfs_fhandle_data_table,
1495                                         (gpointer)old_fhd, (gpointer)old_fhd);
1496                         }
1497
1498                         /* XXX here we should really check that we havent stored
1499                            this fhandle for this frame number already.
1500                            We should also make sure we can handle when we have multiple
1501                            fhandles seen for the same frame, which WILL happen for certain
1502                            nfs calls. For now, we dont handle this and those calls will
1503                            not work properly with this feature
1504                         */
1505                         g_hash_table_insert(nfs_fhandle_frame_table,
1506                                         (gpointer)pinfo->fd->num,
1507                                         (gpointer)old_fhd);
1508                 }
1509         }
1510
1511         /* create a semiunique hash value for the filehandle */
1512         {
1513                 guint32 fhhash;
1514                 guint32 i;
1515
1516                 for(fhhash=0,i=0;i<(fhlen-3);i+=4){
1517                         guint32 val;
1518                         val = tvb_get_ntohl(tvb, offset+i);
1519                         fhhash ^= val;
1520                         fhhash += val;
1521                 }
1522                 if(hidden){
1523                         proto_tree_add_uint_hidden(tree, hf_nfs_fh_hash, tvb, offset,
1524                                 fhlen, fhhash);
1525                 } else {
1526                         proto_tree_add_uint(tree, hf_nfs_fh_hash, tvb, offset,
1527                                 fhlen, fhhash);
1528                 }
1529                 if(hash){
1530                         *hash=fhhash;
1531                 }
1532         }
1533         if(nfs_file_name_snooping){
1534                 nfs_name_snoop_fh(pinfo, tree, tvb, offset, fhlen, hidden);
1535         }
1536
1537         if(!hidden){
1538                 /* calculate (heuristically) fhtype */
1539                 switch (fhlen) {
1540                 case 12:
1541                         if (tvb_get_ntohl(tvb,offset) == 0x01000000) {
1542                                         fhtype=FHT_LINUX_KNFSD_NEW;
1543                                 }
1544                         break;
1545                 case 20:
1546                         if (tvb_get_ntohl(tvb,offset) == 0x01000001) {
1547                                 fhtype=FHT_LINUX_KNFSD_NEW;
1548                         }
1549                         break;
1550                 case 24:
1551                         if (tvb_get_ntohl(tvb,offset) == 0x01000002) {
1552                                 fhtype=FHT_LINUX_KNFSD_NEW;
1553                         }
1554                         break;
1555                 case 32: {
1556                         guint32 len1;
1557                         guint32 len2;
1558                         if (tvb_get_ntohs(tvb,offset+4) == 0) {
1559                                 len1=tvb_get_ntohs(tvb,offset+8);
1560                                 if (tvb_bytes_exist(tvb,offset+10+len1,2)) {
1561                                         len2=tvb_get_ntohs(tvb,
1562                                             offset+10+len1);
1563                                         if (fhlen==12+len1+len2) {
1564                                                 fhtype=FHT_SVR4;
1565                                                 goto type_ready;
1566                                         }
1567                                 }
1568                         }
1569                         /* For a NetApp filehandle, the flag bits must
1570                            include WAFL_FH_MULTIVOLUME, and the fileid
1571                            and generation number need to be nonzero in
1572                            the mount point, file, and export. */
1573                         if ((tvb_get_ntohl(tvb,offset+8) & 0x20000000)
1574                             && tvb_get_ntohl(tvb,offset+0)
1575                             && tvb_get_ntohl(tvb,offset+4)
1576                             && tvb_get_ntohl(tvb,offset+12)
1577                             && tvb_get_ntohl(tvb,offset+16)
1578                             && tvb_get_ntohl(tvb,offset+24)
1579                             && tvb_get_ntohl(tvb,offset+28)) {
1580                                 fhtype=FHT_NETAPP;
1581                                 goto type_ready;
1582                         }
1583                         len1 = tvb_get_guint8(tvb,offset+4);
1584                         if (len1<28 && tvb_bytes_exist(tvb,offset+5,len1)) {
1585                                 int wrong=0;
1586                                 for (len2=5+len1;len2<32;len2++) {
1587                                         if (tvb_get_guint8(tvb,offset+len2)) {
1588                                                 wrong=1;
1589                                                 break;
1590                                         }
1591                                 }
1592                                 if (!wrong) {
1593                                         fhtype=FHT_LINUX_NFSD_LE;
1594                                         goto type_ready;
1595                                 }
1596                         }
1597                         if (tvb_get_ntohl(tvb,offset+28) == 0) {
1598                                 if (tvb_get_ntohs(tvb,offset+14) == 0) {
1599                                         if (tvb_get_ntohs(tvb,offset+18) == 0) {
1600                                                 fhtype=FHT_LINUX_KNFSD_LE;
1601                                                 goto type_ready;
1602                                         }
1603                                 }
1604                         }
1605                         } break;
1606                 }
1607         }
1608
1609 type_ready:
1610
1611         if(!hidden){
1612                 proto_tree_add_text(tree, tvb, offset, 0,
1613                         "type: %s", val_to_str(fhtype, names_fhtype, "Unknown"));
1614
1615
1616                 switch (fhtype) {
1617                 case FHT_SVR4:
1618                         dissect_fhandle_data_SVR4          (tvb, offset, tree,
1619                             fhlen);
1620                 break;
1621                 case FHT_LINUX_KNFSD_LE:
1622                         dissect_fhandle_data_LINUX_KNFSD_LE(tvb, offset, tree,
1623                             fhlen);
1624                 break;
1625                 case FHT_LINUX_NFSD_LE:
1626                         dissect_fhandle_data_LINUX_NFSD_LE (tvb, offset, tree,
1627                             fhlen);
1628                 break;
1629                 case FHT_LINUX_KNFSD_NEW:
1630                         dissect_fhandle_data_LINUX_KNFSD_NEW (tvb, offset, tree,
1631                             fhlen);
1632                 break;
1633                 case FHT_NETAPP:
1634                         dissect_fhandle_data_NETAPP (tvb, offset, tree,
1635                             fhlen);
1636                 break;
1637                 case FHT_UNKNOWN:
1638                 default:
1639                         dissect_fhandle_data_unknown(tvb, offset, tree, fhlen);
1640                 break;
1641                 }
1642         }
1643 }
1644
1645 void
1646 dissect_fhandle_hidden(packet_info *pinfo, proto_tree *tree, nfs_fhandle_data_t *nfd)
1647 {
1648         if(nfd && nfd->len){
1649                 dissect_fhandle_data(nfd->tvb, 0, pinfo, tree, nfd->len, TRUE, NULL);
1650         }
1651 }
1652
1653
1654 /***************************/
1655 /* NFS Version 2, RFC 1094 */
1656 /***************************/
1657
1658
1659 /* RFC 1094, Page 12..14 */
1660 static const value_string names_nfs_stat[] =
1661 {
1662         {       0,      "OK" },
1663         {       1,      "ERR_PERM" },
1664         {       2,      "ERR_NOENT" },
1665         {       5,      "ERR_IO" },
1666         {       6,      "ERR_NX_IO" },
1667         {       13,     "ERR_ACCES" },
1668         {       17,     "ERR_EXIST" },
1669         {       18,     "ERR_XDEV" },   /* not in spec, but can happen */
1670         {       19,     "ERR_NODEV" },
1671         {       20,     "ERR_NOTDIR" },
1672         {       21,     "ERR_ISDIR" },
1673         {       22,     "ERR_INVAL" },  /* not in spec, but I think it can happen */
1674         {       26,     "ERR_TXTBSY" }, /* not in spec, but I think it can happen */
1675         {       27,     "ERR_FBIG" },
1676         {       28,     "ERR_NOSPC" },
1677         {       30,     "ERR_ROFS" },
1678         {       31,     "ERR_MLINK" },  /* not in spec, but can happen */
1679         {       45,     "ERR_OPNOTSUPP" }, /* not in spec, but I think it can happen */
1680         {       63,     "ERR_NAMETOOLONG" },
1681         {       66,     "ERR_NOTEMPTY" },
1682         {       69,     "ERR_DQUOT" },
1683         {       70,     "ERR_STALE" },
1684         {       99,     "ERR_WFLUSH" },
1685         {       0,      NULL }
1686 };
1687
1688 /* NFSv4 Draft Specification, Page 198-199 */
1689 static const value_string names_nfs_stat4[] = {
1690         {       0,      "NFS4_OK"                                       },
1691         {       1,      "NFS4ERR_PERM"                                  },
1692         {       2,      "NFS4ERR_NOENT"                                 },
1693         {       5,      "NFS4ERR_IO"                                    },
1694         {       6,      "NFS4ERR_NXIO"                                  },
1695         {       13,     "NFS4ERR_ACCES"                                 },
1696         {       17,     "NFS4ERR_EXIST"                                 },
1697         {       18,     "NFS4ERR_XDEV"                                  },
1698         {       19,     "NFS4ERR_NODEV"                                 },
1699         {       20,     "NFS4ERR_NOTDIR"                                },
1700         {       21,     "NFS4ERR_ISDIR"                                 },
1701         {       22,     "NFS4ERR_INVAL"                                 },
1702         {       27,     "NFS4ERR_FBIG"                                  },
1703         {       28,     "NFS4ERR_NOSPC"                                 },
1704         {       30,     "NFS4ERR_ROFS"                                  },
1705         {       31,     "NFS4ERR_MLINK"                                 },
1706         {       63,     "NFS4ERR_NAMETOOLONG"                           },
1707         {       66,     "NFS4ERR_NOTEMPTY"                              },
1708         {       69,     "NFS4ERR_DQUOT"                                 },
1709         {       70,     "NFS4ERR_STALE"                                 },
1710         {       10001,  "NFS4ERR_BADHANDLE"                             },
1711         {       10003,  "NFS4ERR_BAD_COOKIE"                            },
1712         {       10004,  "NFS4ERR_NOTSUPP"                               },
1713         {       10005,  "NFS4ERR_TOOSMALL"                              },
1714         {       10006,  "NFS4ERR_SERVERFAULT"                           },
1715         {       10007,  "NFS4ERR_BADTYPE"                               },
1716         {       10008,  "NFS4ERR_DELAY"                                 },
1717         {       10009,  "NFS4ERR_SAME"                                  },
1718         {       10010,  "NFS4ERR_DENIED"                                },
1719         {       10011,  "NFS4ERR_EXPIRED"                               },
1720         {       10012,  "NFS4ERR_LOCKED"                                },
1721         {       10013,  "NFS4ERR_GRACE"                                 },
1722         {       10014,  "NFS4ERR_FHEXPIRED"                             },
1723         {       10015,  "NFS4ERR_SHARE_DENIED"                          },
1724         {       10016,  "NFS4ERR_WRONGSEC"                              },
1725         {       10017,  "NFS4ERR_CLID_INUSE"                            },
1726         {       10018,  "NFS4ERR_RESOURCE"                              },
1727         {       10019,  "NFS4ERR_MOVED"                                 },
1728         {       10020,  "NFS4ERR_NOFILEHANDLE"                          },
1729         {       10021,  "NFS4ERR_MINOR_VERS_MISMATCH"                   },
1730         {       10022,  "NFS4ERR_STALE_CLIENTID"                        },
1731         {       10023,  "NFS4ERR_STALE_STATEID"                         },
1732         {       10024,  "NFS4ERR_OLD_STATEID"                           },
1733         {       10025,  "NFS4ERR_BAD_STATEID"                           },
1734         {       10026,  "NFS4ERR_BAD_SEQID"                             },
1735         {       10027,  "NFS4ERR_NOT_SAME"                              },
1736         {       10028,  "NFS4ERR_LOCK_RANGE"                            },
1737         {       10029,  "NFS4ERR_SYMLINK"                               },
1738         {       10030,  "NFS4ERR_READDIR_NOSPC"                         },
1739         {       10031,  "NFS4ERR_LEASE_MOVED"                           },
1740         {       10032,  "NFS4ERR_ATTRNOTSUPP"                           },
1741         {       10033,  "NFS4ERR_NO_GRACE"                              },
1742         {       10034,  "NFS4ERR_RECLAIM_BAD"                           },
1743         {       10035,  "NFS4ERR_RECLAIM_CONFLICT"                      },
1744         {       10036,  "NFS4ERR_BADXDR"                                },
1745         {       10037,  "NFS4ERR_LOCKS_HELD"                            },
1746         {       10038,  "NFS4ERR_OPENMODE"      },
1747         {       10039,  "NFS4ERR_BADOWNER"      },
1748         {       10040,  "NFS4ERR_BADCHAR"               },
1749         {       10041,  "NFS4ERR_BADNAME"    },
1750         {       10042,  "NFS4ERR_BAD_RANGE"     },
1751         {       10043,  "NFS4ERR_LOCK_NOTSUPP"  },
1752         {       10044,  "NFS4ERR_OP_ILLEGAL"    },
1753         {       10045,  "NFS4ERR_DEADLOCK"      },
1754         {       10046,  "NFS4ERR_FILE_OPEN"     },
1755         {       10047,  "NFS4ERR_ADMIN_REVOKED" },
1756         {       10048,  "NFS4ERR_CB_PATH_DOWN"  },
1757         { 0, NULL }
1758 };
1759
1760
1761 /* This function has been modified to support NFSv4 style error codes as
1762  * well as being backwards compatible with NFSv2 and NFSv3.
1763  */
1764 static int
1765 dissect_stat_internal(tvbuff_t *tvb, int offset,
1766         proto_tree *tree, guint32* status, int nfsvers)
1767 {
1768         guint32 stat;
1769
1770         stat = tvb_get_ntohl(tvb, offset+0);
1771
1772         if (tree) {
1773                 /* this gives the right NFSv2 number<->message relation */
1774                 /* and makes it searchable via "nfs.status" */
1775                 proto_tree_add_uint_format(tree, hf_nfs_nfsstat3, tvb,
1776                         offset+0, 4, stat, "Status: %s (%u)",
1777                         val_to_str(stat,
1778                                 (nfsvers != 4)? names_nfs_stat: names_nfs_stat4,"%u"), stat);
1779         }
1780
1781         offset += 4;
1782
1783         if (status) *status = stat;
1784
1785         return offset;
1786 }
1787
1788
1789 /* RFC 1094, Page 12..14 */
1790 static int
1791 dissect_stat(tvbuff_t *tvb, int offset, proto_tree *tree,
1792         guint32 *status)
1793 {
1794         return dissect_stat_internal(tvb, offset, tree, status, !4);
1795 }
1796
1797
1798 /* RFC 1094, Page 12..14 */
1799 static int
1800 dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
1801 {
1802         guint32 status;
1803         char *err;
1804
1805         offset = dissect_stat(tvb, offset, tree, &status);
1806         switch (status) {
1807                 case 0:
1808                         proto_item_append_text(tree, ", RMDIR Reply");
1809                         break;
1810                 default:
1811                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
1812                         if (check_col(pinfo->cinfo, COL_INFO)) {
1813                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
1814                         }
1815                         proto_item_append_text(tree, ", RMDIR Reply  Error:%s", err);
1816         }
1817
1818         return offset;
1819 }
1820
1821 static int
1822 dissect_nfs2_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
1823 {
1824         guint32 status;
1825         char *err;
1826
1827         offset = dissect_stat(tvb, offset, tree, &status);
1828         switch (status) {
1829                 case 0:
1830                         proto_item_append_text(tree, ", SYMLINK Reply");
1831                         break;
1832                 default:
1833                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
1834                         if (check_col(pinfo->cinfo, COL_INFO)) {
1835                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
1836                         }
1837                         proto_item_append_text(tree, ", SYMLINK Reply  Error:%s", err);
1838         }
1839
1840         return offset;
1841 }
1842
1843 static int
1844 dissect_nfs2_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
1845 {
1846         guint32 status;
1847         char *err;
1848
1849         offset = dissect_stat(tvb, offset, tree, &status);
1850         switch (status) {
1851                 case 0:
1852                         proto_item_append_text(tree, ", LINK Reply");
1853                         break;
1854                 default:
1855                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
1856                         if (check_col(pinfo->cinfo, COL_INFO)) {
1857                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
1858                         }
1859                         proto_item_append_text(tree, ", LINK Reply  Error:%s", err);
1860         }
1861
1862         return offset;
1863 }
1864
1865 static int
1866 dissect_nfs2_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
1867 {
1868         guint32 status;
1869         char *err;
1870
1871         offset = dissect_stat(tvb, offset, tree, &status);
1872         switch (status) {
1873                 case 0:
1874                         proto_item_append_text(tree, ", RENAME Reply");
1875                         break;
1876                 default:
1877                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
1878                         if (check_col(pinfo->cinfo, COL_INFO)) {
1879                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
1880                         }
1881                         proto_item_append_text(tree, ", RENAME Reply  Error:%s", err);
1882         }
1883
1884         return offset;
1885 }
1886
1887 static int
1888 dissect_nfs2_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
1889 {
1890         guint32 status;
1891         char *err;
1892
1893         offset = dissect_stat(tvb, offset, tree, &status);
1894         switch (status) {
1895                 case 0:
1896                         proto_item_append_text(tree, ", REMOVE Reply");
1897                         break;
1898                 default:
1899                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
1900                         if (check_col(pinfo->cinfo, COL_INFO)) {
1901                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
1902                         }
1903                         proto_item_append_text(tree, ", REMOVE Reply  Error:%s", err);
1904         }
1905
1906         return offset;
1907 }
1908
1909
1910 static int
1911 dissect_nfs_nfsstat4(tvbuff_t *tvb, int offset,
1912         proto_tree *tree, guint32 *status)
1913 {
1914         return dissect_stat_internal(tvb, offset, tree, status, 4);
1915 }
1916
1917
1918 /* RFC 1094, Page 15 */
1919 static int
1920 dissect_ftype(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
1921 {
1922         guint32 ftype;
1923         char* ftype_name = NULL;
1924
1925         const value_string nfs2_ftype[] =
1926         {
1927                 {       0,      "Non-File" },
1928                 {       1,      "Regular File" },
1929                 {       2,      "Directory" },
1930                 {       3,      "Block Special Device" },
1931                 {       4,      "Character Special Device" },
1932                 {       5,      "Symbolic Link" },
1933                 {       0,      NULL }
1934         };
1935
1936         ftype = tvb_get_ntohl(tvb, offset+0);
1937         ftype_name = val_to_str(ftype, nfs2_ftype, "%u");
1938
1939         if (tree) {
1940                 proto_tree_add_text(tree, tvb, offset, 4,
1941                         "%s: %s (%u)", name, ftype_name, ftype);
1942         }
1943
1944         offset += 4;
1945         return offset;
1946 }
1947
1948
1949 /* RFC 1094, Page 15 */
1950 int
1951 dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1952     char *name, guint32 *hash)
1953 {
1954         proto_item* fitem;
1955         proto_tree* ftree = NULL;
1956
1957         if (tree) {
1958                 fitem = proto_tree_add_text(tree, tvb, offset, FHSIZE,
1959                         "%s", name);
1960                 if (fitem)
1961                         ftree = proto_item_add_subtree(fitem, ett_nfs_fhandle);
1962         }
1963
1964         /* are we snooping fh to filenames ?*/
1965         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
1966                 rpc_call_info_value *civ=pinfo->private_data;
1967
1968                 /* NFS v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
1969                 if( (civ->prog==100003)
1970                   &&(civ->vers==2)
1971                   &&(!civ->request)
1972                   &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
1973                 ) {
1974                         nfs_name_snoop_add_fh(civ->xid, tvb,
1975                                 offset, 32);
1976                 }
1977
1978                 /* MOUNT v1,v2 MNT replies might give us a filehandle*/
1979                 if( (civ->prog==100005)
1980                   &&(civ->proc==1)
1981                   &&((civ->vers==1)||(civ->vers==2))
1982                   &&(!civ->request)
1983                 ) {
1984                         nfs_name_snoop_add_fh(civ->xid, tvb,
1985                                 offset, 32);
1986                 }
1987         }
1988
1989         dissect_fhandle_data(tvb, offset, pinfo, ftree, FHSIZE, FALSE, hash);
1990
1991         offset += FHSIZE;
1992         return offset;
1993 }
1994
1995 /* RFC 1094, Page 15 */
1996 static int
1997 dissect_nfs2_statfs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1998 {
1999         guint32 hash;
2000
2001         offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
2002
2003         if (check_col(pinfo->cinfo, COL_INFO)) {
2004                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2005         }
2006         proto_item_append_text(tree, ", STATFS Call FH:0x%08x", hash);
2007
2008         return offset;
2009 }
2010
2011 static int
2012 dissect_nfs2_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2013 {
2014         guint32 hash;
2015
2016         offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
2017
2018         if (check_col(pinfo->cinfo, COL_INFO)) {
2019                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2020         }
2021         proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
2022
2023         return offset;
2024 }
2025
2026 static int
2027 dissect_nfs2_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2028 {
2029         guint32 hash;
2030
2031         offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
2032
2033         if (check_col(pinfo->cinfo, COL_INFO)) {
2034                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2035         }
2036         proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
2037
2038         return offset;
2039 }
2040
2041
2042 /* RFC 1094, Page 15 */
2043 static int
2044 dissect_timeval(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_time, int hf_time_sec, int hf_time_usec)
2045 {
2046         guint32 seconds;
2047         guint32 useconds;
2048         nstime_t ts;
2049
2050         proto_item* time_item;
2051         proto_tree* time_tree = NULL;
2052
2053         seconds = tvb_get_ntohl(tvb, offset+0);
2054         useconds = tvb_get_ntohl(tvb, offset+4);
2055         ts.secs = seconds;
2056         ts.nsecs = useconds*1000;
2057
2058         if (tree) {
2059                 time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
2060                                 &ts);
2061                 if (time_item)
2062                         time_tree = proto_item_add_subtree(time_item, ett_nfs_timeval);
2063         }
2064
2065         if (time_tree) {
2066                 proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
2067                                         seconds);
2068                 proto_tree_add_uint(time_tree, hf_time_usec, tvb, offset+4, 4,
2069                                         useconds);
2070         }
2071         offset += 8;
2072         return offset;
2073 }
2074
2075
2076 /* RFC 1094, Page 16 */
2077 static const value_string nfs2_mode_names[] = {
2078         {       0040000,        "Directory"     },
2079         {       0020000,        "Character Special Device"      },
2080         {       0060000,        "Block Special Device"  },
2081         {       0100000,        "Regular File"  },
2082         {       0120000,        "Symbolic Link" },
2083         {       0140000,        "Named Socket"  },
2084         {       0000000,        NULL            },
2085 };
2086
2087 static int
2088 dissect_mode(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
2089 {
2090         guint32 mode;
2091         proto_item* mode_item = NULL;
2092         proto_tree* mode_tree = NULL;
2093
2094         mode = tvb_get_ntohl(tvb, offset+0);
2095
2096         if (tree) {
2097                 mode_item = proto_tree_add_text(tree, tvb, offset, 4,
2098                         "%s: 0%o", name, mode);
2099                 if (mode_item)
2100                         mode_tree = proto_item_add_subtree(mode_item, ett_nfs_mode);
2101         }
2102
2103         if (mode_tree) {
2104                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2105                         decode_enumerated_bitfield(mode,  0160000, 16,
2106                         nfs2_mode_names, "%s"));
2107                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2108                 decode_boolean_bitfield(mode,   04000, 16, "Set user id on exec", "not SUID"));
2109                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2110                 decode_boolean_bitfield(mode,   02000, 16, "Set group id on exec", "not SGID"));
2111                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2112                 decode_boolean_bitfield(mode,   01000, 16, "Save swapped text even after use", "not save swapped text"));
2113                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2114                 decode_boolean_bitfield(mode,    0400, 16, "Read permission for owner", "no Read permission for owner"));
2115                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2116                 decode_boolean_bitfield(mode,    0200, 16, "Write permission for owner", "no Write permission for owner"));
2117                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2118                 decode_boolean_bitfield(mode,    0100, 16, "Execute permission for owner", "no Execute permission for owner"));
2119                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2120                 decode_boolean_bitfield(mode,     040, 16, "Read permission for group", "no Read permission for group"));
2121                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2122                 decode_boolean_bitfield(mode,     020, 16, "Write permission for group", "no Write permission for group"));
2123                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2124                 decode_boolean_bitfield(mode,     010, 16, "Execute permission for group", "no Execute permission for group"));
2125                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2126                 decode_boolean_bitfield(mode,      04, 16, "Read permission for others", "no Read permission for others"));
2127                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2128                 decode_boolean_bitfield(mode,      02, 16, "Write permission for others", "no Write permission for others"));
2129                 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
2130                 decode_boolean_bitfield(mode,      01, 16, "Execute permission for others", "no Execute permission for others"));
2131         }
2132
2133         offset += 4;
2134         return offset;
2135 }
2136
2137
2138 /* RFC 1094, Page 15 */
2139 int
2140 dissect_fattr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
2141 {
2142         proto_item* fattr_item = NULL;
2143         proto_tree* fattr_tree = NULL;
2144         int old_offset = offset;
2145
2146         if (tree) {
2147                 fattr_item = proto_tree_add_text(tree, tvb, offset, -1,
2148                         "%s", name);
2149                 fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs_fattr);
2150         }
2151
2152         offset = dissect_ftype(tvb, offset, fattr_tree, "type");
2153         offset = dissect_mode(tvb, offset, fattr_tree, "mode");
2154         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_nlink, offset);
2155         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_uid, offset);
2156         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_gid, offset);
2157         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_size, offset);
2158         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocksize, offset);
2159         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_rdev, offset);
2160         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocks, offset);
2161         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fsid, offset);
2162         offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fileid, offset);
2163
2164         offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
2165         offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
2166         offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_usec);
2167
2168         /* now we know, that fattr is shorter */
2169         if (fattr_item) {
2170                 proto_item_set_len(fattr_item, offset - old_offset);
2171         }
2172
2173         return offset;
2174 }
2175
2176
2177 /* RFC 1094, Page 17 */
2178 static int
2179 dissect_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
2180 {
2181         proto_item* sattr_item = NULL;
2182         proto_tree* sattr_tree = NULL;
2183         int old_offset = offset;
2184
2185         if (tree) {
2186                 sattr_item = proto_tree_add_text(tree, tvb, offset, -1,
2187                         "%s", name);
2188                 sattr_tree = proto_item_add_subtree(sattr_item, ett_nfs_sattr);
2189         }
2190
2191         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2192                 offset = dissect_mode(tvb, offset, sattr_tree, "mode");
2193         else {
2194                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "mode: no value");
2195                 offset += 4;
2196         }
2197
2198         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2199                 offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_uid,
2200                         offset);
2201         else {
2202                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "uid: no value");
2203                 offset += 4;
2204         }
2205
2206         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2207                 offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_gid,
2208                         offset);
2209         else {
2210                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "gid: no value");
2211                 offset += 4;
2212         }
2213
2214         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2215                 offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_size,
2216                         offset);
2217         else {
2218                 proto_tree_add_text(sattr_tree, tvb, offset, 4, "size: no value");
2219                 offset += 4;
2220         }
2221
2222         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
2223                 offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
2224         } else {
2225                 proto_tree_add_text(sattr_tree, tvb, offset, 8, "atime: no value");
2226                 offset += 8;
2227         }
2228
2229         if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
2230                 offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
2231         } else {
2232                 proto_tree_add_text(sattr_tree, tvb, offset, 8, "mtime: no value");
2233                 offset += 8;
2234         }
2235
2236         /* now we know, that sattr is shorter */
2237         if (sattr_item) {
2238                 proto_item_set_len(sattr_item, offset - old_offset);
2239         }
2240
2241         return offset;
2242 }
2243
2244
2245 /* RFC 1094, Page 17 */
2246 static int
2247 dissect_filename(tvbuff_t *tvb, int offset,
2248     proto_tree *tree, int hf, char **string_ret)
2249 {
2250         offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
2251         return offset;
2252 }
2253
2254
2255 /* RFC 1094, Page 17 */
2256 static int
2257 dissect_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
2258 {
2259         offset = dissect_rpc_string(tvb, tree, hf, offset, name);
2260         return offset;
2261 }
2262
2263
2264 /* RFC 1094, Page 17,18 */
2265 static int
2266 dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, char *funcname)
2267 {
2268         guint32 status;
2269         char *err;
2270
2271         offset = dissect_stat(tvb, offset, tree, &status);
2272         switch (status) {
2273                 case 0:
2274                         offset = dissect_fattr(tvb, offset, tree, "attributes");
2275                         proto_item_append_text(tree, ", %s Reply", funcname);
2276                 break;
2277                 default:
2278                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
2279                         if (check_col(pinfo->cinfo, COL_INFO)) {
2280                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2281                         }
2282                         proto_item_append_text(tree, ", %s Reply  Error:%s", funcname, err);
2283                 break;
2284         }
2285
2286         return offset;
2287 }
2288
2289
2290 /* RFC 1094, Page 17,18 */
2291 static int
2292 dissect_nfs2_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2293 {
2294         offset = dissect_attrstat(tvb, offset, tree, pinfo, "WRITE");
2295
2296         return offset;
2297 }
2298
2299 static int
2300 dissect_nfs2_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2301 {
2302         offset = dissect_attrstat(tvb, offset, tree, pinfo, "SETATTR");
2303
2304         return offset;
2305 }
2306
2307 static int
2308 dissect_nfs2_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
2309 {
2310         offset = dissect_attrstat(tvb, offset, tree, pinfo, "GETATTR");
2311
2312         return offset;
2313 }
2314
2315
2316 /* RFC 1094, Page 18 */
2317 static int
2318 dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char* label, guint32 *hash, char **name)
2319 {
2320         proto_item* diropargs_item = NULL;
2321         proto_tree* diropargs_tree = NULL;
2322         int old_offset = offset;
2323
2324         if (tree) {
2325                 diropargs_item = proto_tree_add_text(tree, tvb, offset, -1,
2326                         "%s", label);
2327                 diropargs_tree = proto_item_add_subtree(diropargs_item, ett_nfs_diropargs);
2328         }
2329
2330         /* are we snooping fh to filenames ?*/
2331         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
2332                 /* v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
2333                 rpc_call_info_value *civ=pinfo->private_data;
2334
2335                 if( (civ->prog==100003)
2336                   &&(civ->vers==2)
2337                   &&(civ->request)
2338                   &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
2339                 ) {
2340                         nfs_name_snoop_add_name(civ->xid, tvb,
2341                                 offset+36, tvb_get_ntohl(tvb, offset+32),
2342                                 offset, 32, NULL);
2343                 }
2344         }
2345
2346         offset = dissect_fhandle(tvb, offset, pinfo, diropargs_tree, "dir", hash);
2347         offset = dissect_filename(tvb, offset, diropargs_tree, hf_nfs_name, name);
2348
2349         /* now we know, that diropargs is shorter */
2350         if (diropargs_item) {
2351                 proto_item_set_len(diropargs_item, offset - old_offset);
2352         }
2353
2354         return offset;
2355 }
2356
2357
2358 /* RFC 1094, Page 18 */
2359 static int
2360 dissect_nfs2_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2361 {
2362         guint32 hash;
2363         char *name=NULL;
2364
2365         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
2366
2367         if (check_col(pinfo->cinfo, COL_INFO)) {
2368                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
2369         }
2370         proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
2371         g_free(name);
2372
2373         return offset;
2374 }
2375
2376 static int
2377 dissect_nfs2_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2378 {
2379         guint32 hash;
2380         char *name=NULL;
2381
2382         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
2383
2384         if (check_col(pinfo->cinfo, COL_INFO)) {
2385                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
2386         }
2387         proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
2388         g_free(name);
2389
2390         return offset;
2391 }
2392
2393 static int
2394 dissect_nfs2_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2395 {
2396         guint32 hash;
2397         char *name=NULL;
2398
2399         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
2400
2401         if (check_col(pinfo->cinfo, COL_INFO)) {
2402                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
2403         }
2404         proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
2405         g_free(name);
2406
2407         return offset;
2408 }
2409
2410
2411 /* RFC 1094, Page 18 */
2412 static int
2413 dissect_diropres(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char *funcname)
2414 {
2415         guint32 status;
2416         guint32 hash;
2417         char *err;
2418
2419         offset = dissect_stat(tvb, offset, tree, &status);
2420         switch (status) {
2421                 case 0:
2422                         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
2423                         offset = dissect_fattr  (tvb, offset, tree, "attributes");
2424                         if (check_col(pinfo->cinfo, COL_INFO)) {
2425                                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2426                         }
2427                         proto_item_append_text(tree, ", %s Reply FH:0x%08x", funcname, hash);
2428                 break;
2429                 default:
2430                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
2431                         if (check_col(pinfo->cinfo, COL_INFO)) {
2432                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2433                         }
2434                         proto_item_append_text(tree, ", %s Reply  Error:%s", funcname, err);
2435                 break;
2436         }
2437
2438         return offset;
2439 }
2440
2441
2442 /* nfsdata is simply a chunk of RPC opaque data (length, data, fill bytes) */
2443 static int
2444 dissect_nfsdata(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
2445 {
2446         offset = dissect_rpc_data(tvb, tree, hf, offset);
2447         return offset;
2448 }
2449
2450
2451 /* RFC 1094, Page 18 */
2452 static int
2453 dissect_nfs2_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
2454         proto_tree* tree)
2455 {
2456         offset = dissect_diropres(tvb, offset, pinfo, tree, "MKDIR");
2457         return offset;
2458 }
2459
2460 static int
2461 dissect_nfs2_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
2462         proto_tree* tree)
2463 {
2464         offset = dissect_diropres(tvb, offset, pinfo, tree, "CREATE");
2465         return offset;
2466 }
2467
2468 static int
2469 dissect_nfs2_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
2470         proto_tree* tree)
2471 {
2472         offset = dissect_diropres(tvb, offset, pinfo, tree, "LOOKUP");
2473         return offset;
2474 }
2475
2476
2477 /* RFC 1094, Page 6 */
2478 static int
2479 dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2480         proto_tree *tree)
2481 {
2482         guint32 hash;
2483
2484         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
2485         offset = dissect_sattr  (tvb, offset,        tree, "attributes");
2486
2487         if (check_col(pinfo->cinfo, COL_INFO)) {
2488                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2489         }
2490         proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
2491         return offset;
2492 }
2493
2494
2495 /* RFC 1094, Page 6 */
2496 static int
2497 dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
2498         proto_tree *tree)
2499 {
2500         guint32 status;
2501         char *err;
2502         char *name=NULL;
2503
2504         offset = dissect_stat(tvb, offset, tree, &status);
2505         switch (status) {
2506                 case 0:
2507                         offset = dissect_path(tvb, offset, tree, hf_nfs_readlink_data, &name);
2508                         if (check_col(pinfo->cinfo, COL_INFO)) {
2509                                 col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
2510                         }
2511                         proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
2512                         g_free(name);
2513                 break;
2514                 default:
2515                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
2516                         if (check_col(pinfo->cinfo, COL_INFO)) {
2517                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2518                         }
2519                         proto_item_append_text(tree, ", READLINK Reply  Error:%s", err);
2520                 break;
2521         }
2522
2523         return offset;
2524 }
2525
2526
2527 /* RFC 1094, Page 7 */
2528 static int
2529 dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2530         proto_tree *tree)
2531 {
2532         guint32 offset_value;
2533         guint32 count;
2534         guint32 totalcount;
2535         guint32 hash;
2536
2537         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
2538         offset_value = tvb_get_ntohl(tvb, offset+0);
2539         count        = tvb_get_ntohl(tvb, offset+4);
2540         totalcount   = tvb_get_ntohl(tvb, offset+8);
2541         if (tree) {
2542                 proto_tree_add_uint(tree, hf_nfs_read_offset, tvb,
2543                 offset+0, 4, offset_value);
2544                 proto_tree_add_uint(tree, hf_nfs_read_count, tvb,
2545                 offset+4, 4, count);
2546                 proto_tree_add_uint(tree, hf_nfs_read_totalcount, tvb,
2547                 offset+8, 4, totalcount);
2548         }
2549         offset += 12;
2550
2551         if (check_col(pinfo->cinfo, COL_INFO)) {
2552                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
2553         }
2554         proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
2555
2556         return offset;
2557 }
2558
2559
2560 /* RFC 1094, Page 7 */
2561 static int
2562 dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
2563         proto_tree* tree)
2564 {
2565         guint32 status;
2566         char *err;
2567
2568         offset = dissect_stat(tvb, offset, tree, &status);
2569         switch (status) {
2570                 case 0:
2571                         offset = dissect_fattr(tvb, offset, tree, "attributes");
2572                         proto_item_append_text(tree, ", READ Reply");
2573                         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
2574                 break;
2575                 default:
2576                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
2577                         if (check_col(pinfo->cinfo, COL_INFO)) {
2578                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2579                         }
2580                         proto_item_append_text(tree, ", READ Reply  Error:%s", err);
2581                 break;
2582         }
2583
2584         return offset;
2585 }
2586
2587
2588 /* RFC 1094, Page 8 */
2589 static int
2590 dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2591         proto_tree *tree)
2592 {
2593         guint32 beginoffset;
2594         guint32 offset_value;
2595         guint32 totalcount;
2596         guint32 hash;
2597
2598         offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
2599         beginoffset  = tvb_get_ntohl(tvb, offset+0);
2600         offset_value = tvb_get_ntohl(tvb, offset+4);
2601         totalcount   = tvb_get_ntohl(tvb, offset+8);
2602         if (tree) {
2603                 proto_tree_add_uint(tree, hf_nfs_write_beginoffset, tvb,
2604                 offset+0, 4, beginoffset);
2605                 proto_tree_add_uint(tree, hf_nfs_write_offset, tvb,
2606                 offset+4, 4, offset_value);
2607                 proto_tree_add_uint(tree, hf_nfs_write_totalcount, tvb,
2608                 offset+8, 4, totalcount);
2609         }
2610         offset += 12;
2611
2612         if (check_col(pinfo->cinfo, COL_INFO)) {
2613                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
2614         }
2615         proto_item_append_text(tree, ", WRITE Call FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
2616
2617         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
2618
2619         return offset;
2620 }
2621
2622
2623 /* RFC 1094, Page 8 */
2624 static int
2625 dissect_nfs2_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2626         proto_tree *tree)
2627 {
2628         guint32 hash;
2629         char *name=NULL;
2630
2631         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
2632         offset = dissect_sattr    (tvb, offset,        tree, "attributes");
2633
2634         if (check_col(pinfo->cinfo, COL_INFO)) {
2635                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
2636         }
2637         proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
2638         g_free(name);
2639
2640         return offset;
2641 }
2642
2643 static int
2644 dissect_nfs2_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2645         proto_tree *tree)
2646 {
2647         guint32 hash;
2648         char *name=NULL;
2649
2650         offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
2651         offset = dissect_sattr    (tvb, offset,        tree, "attributes");
2652
2653         if (check_col(pinfo->cinfo, COL_INFO)) {
2654                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
2655         }
2656         proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s", hash, name);
2657         g_free(name);
2658
2659         return offset;
2660 }
2661
2662
2663 /* RFC 1094, Page 9 */
2664 static int
2665 dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2666         proto_tree *tree)
2667 {
2668         guint32 from_hash;
2669         char *from_name=NULL;
2670         guint32 to_hash;
2671         char *to_name=NULL;
2672
2673         offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
2674         offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
2675
2676         if (check_col(pinfo->cinfo, COL_INFO)) {
2677                 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);
2678         }
2679         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);
2680
2681         g_free(from_name);
2682         g_free(to_name);
2683         return offset;
2684 }
2685
2686
2687 /* RFC 1094, Page 9 */
2688 static int
2689 dissect_nfs2_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2690         proto_tree *tree)
2691 {
2692         guint32 from_hash;
2693         guint32 to_hash;
2694         char *to_name=NULL;
2695
2696         offset = dissect_fhandle(tvb, offset, pinfo, tree, "from", &from_hash);
2697         offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
2698
2699         if (check_col(pinfo->cinfo, COL_INFO)) {
2700                 col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
2701         }
2702         proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
2703
2704         g_free(to_name);
2705         return offset;
2706 }
2707
2708
2709 /* RFC 1094, Page 10 */
2710 static int
2711 dissect_nfs2_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2712         proto_tree *tree)
2713 {
2714         guint32 from_hash;
2715         char *from_name=NULL;
2716         char *to_name=NULL;
2717
2718         offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
2719         offset = dissect_path(tvb, offset, tree, hf_nfs_symlink_to, &to_name);
2720         offset = dissect_sattr(tvb, offset, tree, "attributes");
2721
2722         if (check_col(pinfo->cinfo, COL_INFO)) {
2723                 col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
2724         }
2725         proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
2726         g_free(from_name);
2727         g_free(to_name);
2728
2729         return offset;
2730 }
2731
2732
2733 /* RFC 1094, Page 11 */
2734 static int
2735 dissect_nfs2_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
2736         proto_tree *tree)
2737 {
2738         guint32 cookie;
2739         guint32 count;
2740         guint32 hash;
2741
2742         offset = dissect_fhandle(tvb, offset, pinfo, tree, "dir", &hash);
2743         cookie  = tvb_get_ntohl(tvb, offset+ 0);
2744         count = tvb_get_ntohl(tvb, offset+ 4);
2745         if (tree) {
2746                 proto_tree_add_uint(tree, hf_nfs_readdir_cookie, tvb,
2747                         offset+ 0, 4, cookie);
2748                 proto_tree_add_uint(tree, hf_nfs_readdir_count, tvb,
2749                         offset+ 4, 4, count);
2750         }
2751         offset += 8;
2752
2753         if (check_col(pinfo->cinfo, COL_INFO)) {
2754                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
2755         }
2756         proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
2757
2758         return offset;
2759 }
2760
2761
2762 /* RFC 1094, Page 11 */
2763 static int
2764 dissect_readdir_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
2765         proto_tree* tree)
2766 {
2767         proto_item* entry_item = NULL;
2768         proto_tree* entry_tree = NULL;
2769         int old_offset = offset;
2770         guint32 fileid;
2771         guint32 cookie;
2772         char *name;
2773
2774         if (tree) {
2775                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
2776                         offset+0, -1, FALSE);
2777                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
2778         }
2779
2780         fileid = tvb_get_ntohl(tvb, offset + 0);
2781         if (entry_tree)
2782                 proto_tree_add_uint(entry_tree, hf_nfs_readdir_entry_fileid, tvb,
2783                         offset+0, 4, fileid);
2784         offset += 4;
2785
2786         offset = dissect_filename(tvb, offset, entry_tree,
2787                 hf_nfs_readdir_entry_name, &name);
2788         if (entry_item)
2789                 proto_item_set_text(entry_item, "Entry: file ID %u, name %s",
2790                 fileid, name);
2791         g_free(name);
2792
2793         cookie = tvb_get_ntohl(tvb, offset + 0);
2794         if (entry_tree)
2795                 proto_tree_add_uint(entry_tree, hf_nfs_readdir_entry_cookie, tvb,
2796                         offset+0, 4, cookie);
2797         offset += 4;
2798
2799         /* now we know, that a readdir entry is shorter */
2800         if (entry_item) {
2801                 proto_item_set_len(entry_item, offset - old_offset);
2802         }
2803
2804         return offset;
2805 }
2806
2807 /* RFC 1094, Page 11 */
2808 static int
2809 dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
2810         proto_tree* tree)
2811 {
2812         guint32 status;
2813         guint32 eof_value;
2814         char *err;
2815
2816         offset = dissect_stat(tvb, offset, tree, &status);
2817         switch (status) {
2818                 case 0:
2819                         proto_item_append_text(tree, ", READDIR Reply");
2820
2821                         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
2822                                 dissect_readdir_entry);
2823                         eof_value = tvb_get_ntohl(tvb, offset+0);
2824                         if (tree)
2825                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
2826                                         offset+ 0, 4, eof_value);
2827                         offset += 4;
2828                 break;
2829                 default:
2830                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
2831                         if (check_col(pinfo->cinfo, COL_INFO)) {
2832                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2833                         }
2834                         proto_item_append_text(tree, ", READDIR Reply  Error:%s", err);
2835                 break;
2836         }
2837
2838         return offset;
2839 }
2840
2841
2842 /* RFC 1094, Page 12 */
2843 static int
2844 dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
2845         proto_tree* tree)
2846 {
2847         guint32 status;
2848         guint32 tsize;
2849         guint32 bsize;
2850         guint32 blocks;
2851         guint32 bfree;
2852         guint32 bavail;
2853         char *err;
2854
2855         offset = dissect_stat(tvb, offset, tree, &status);
2856         switch (status) {
2857                 case 0:
2858                         tsize  = tvb_get_ntohl(tvb, offset+ 0);
2859                         bsize  = tvb_get_ntohl(tvb, offset+ 4);
2860                         blocks = tvb_get_ntohl(tvb, offset+ 8);
2861                         bfree  = tvb_get_ntohl(tvb, offset+12);
2862                         bavail = tvb_get_ntohl(tvb, offset+16);
2863                         if (tree) {
2864                                 proto_tree_add_uint(tree, hf_nfs_statfs_tsize, tvb,
2865                                         offset+ 0, 4, tsize);
2866                                 proto_tree_add_uint(tree, hf_nfs_statfs_bsize, tvb,
2867                                         offset+ 4, 4, bsize);
2868                                 proto_tree_add_uint(tree, hf_nfs_statfs_blocks, tvb,
2869                                         offset+ 8, 4, blocks);
2870                                 proto_tree_add_uint(tree, hf_nfs_statfs_bfree, tvb,
2871                                         offset+12, 4, bfree);
2872                                 proto_tree_add_uint(tree, hf_nfs_statfs_bavail, tvb,
2873                                         offset+16, 4, bavail);
2874                         }
2875                         offset += 20;
2876                         proto_item_append_text(tree, ", STATFS Reply");
2877                 break;
2878                 default:
2879                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
2880                         if (check_col(pinfo->cinfo, COL_INFO)) {
2881                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
2882                         }
2883                         proto_item_append_text(tree, ", STATFS Reply  Error:%s", err);
2884                 break;
2885         }
2886
2887         return offset;
2888 }
2889
2890
2891 /* proc number, "proc name", dissect_request, dissect_reply */
2892 /* NULL as function pointer means: type of arguments is "void". */
2893 static const vsff nfs2_proc[] = {
2894         { 0,    "NULL",         /* OK */
2895         NULL,                           NULL },
2896         { 1,    "GETATTR",      /* OK */
2897         dissect_nfs2_getattr_call,      dissect_nfs2_getattr_reply },
2898         { 2,    "SETATTR",      /* OK */
2899         dissect_nfs2_setattr_call,      dissect_nfs2_setattr_reply },
2900         { 3,    "ROOT",         /* OK */
2901         NULL,                           NULL },
2902         { 4,    "LOOKUP",       /* OK */
2903         dissect_nfs2_lookup_call,       dissect_nfs2_lookup_reply },
2904         { 5,    "READLINK",     /* OK */
2905         dissect_nfs2_readlink_call,     dissect_nfs2_readlink_reply },
2906         { 6,    "READ",         /* OK */
2907         dissect_nfs2_read_call,         dissect_nfs2_read_reply },
2908         { 7,    "WRITECACHE",   /* OK */
2909         NULL,                           NULL },
2910         { 8,    "WRITE",        /* OK */
2911         dissect_nfs2_write_call,        dissect_nfs2_write_reply },
2912         { 9,    "CREATE",       /* OK */
2913         dissect_nfs2_create_call,       dissect_nfs2_create_reply },
2914         { 10,   "REMOVE",       /* OK */
2915         dissect_nfs2_remove_call,       dissect_nfs2_remove_reply },
2916         { 11,   "RENAME",       /* OK */
2917         dissect_nfs2_rename_call,       dissect_nfs2_rename_reply },
2918         { 12,   "LINK",         /* OK */
2919         dissect_nfs2_link_call,         dissect_nfs2_link_reply },
2920         { 13,   "SYMLINK",      /* OK */
2921         dissect_nfs2_symlink_call,      dissect_nfs2_symlink_reply },
2922         { 14,   "MKDIR",        /* OK */
2923         dissect_nfs2_mkdir_call,        dissect_nfs2_mkdir_reply },
2924         { 15,   "RMDIR",        /* OK */
2925         dissect_nfs2_rmdir_call,        dissect_nfs2_rmdir_reply },
2926         { 16,   "READDIR",      /* OK */
2927         dissect_nfs2_readdir_call,      dissect_nfs2_readdir_reply },
2928         { 17,   "STATFS",       /* OK */
2929         dissect_nfs2_statfs_call,       dissect_nfs2_statfs_reply },
2930         { 0,NULL,NULL,NULL }
2931 };
2932
2933 static const value_string nfsv2_proc_vals[] = {
2934         { 0,    "NULL" },
2935         { 1,    "GETATTR" },
2936         { 2,    "SETATTR" },
2937         { 3,    "ROOT" },
2938         { 4,    "LOOKUP" },
2939         { 5,    "READLINK" },
2940         { 6,    "READ" },
2941         { 7,    "WRITECACHE" },
2942         { 8,    "WRITE" },
2943         { 9,    "CREATE" },
2944         { 10,   "REMOVE" },
2945         { 11,   "RENAME" },
2946         { 12,   "LINK" },
2947         { 13,   "SYMLINK" },
2948         { 14,   "MKDIR" },
2949         { 15,   "RMDIR" },
2950         { 16,   "READDIR" },
2951         { 17,   "STATFS" },
2952         { 0,    NULL }
2953 };
2954
2955 /* end of NFS Version 2 */
2956
2957
2958 /***************************/
2959 /* NFS Version 3, RFC 1813 */
2960 /***************************/
2961
2962
2963 /* RFC 1813, Page 15 */
2964 static int
2965 dissect_filename3(tvbuff_t *tvb, int offset,
2966     proto_tree *tree, int hf, char **string_ret)
2967 {
2968         offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
2969         return offset;
2970 }
2971
2972
2973 /* RFC 1813, Page 15 */
2974 static int
2975 dissect_nfspath3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
2976 {
2977         offset = dissect_rpc_string(tvb, tree, hf, offset, name);
2978         return offset;
2979 }
2980
2981 /* RFC 1813, Page 15 */
2982 static int
2983 dissect_cookieverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
2984 {
2985         proto_tree_add_text(tree, tvb, offset, NFS3_COOKIEVERFSIZE,
2986                 "Verifier: Opaque Data");
2987         offset += NFS3_COOKIEVERFSIZE;
2988         return offset;
2989 }
2990
2991
2992 /* RFC 1813, Page 16 */
2993 static int
2994 dissect_createverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
2995 {
2996         proto_tree_add_text(tree, tvb, offset, NFS3_CREATEVERFSIZE,
2997                 "Verifier: Opaque Data");
2998         offset += NFS3_CREATEVERFSIZE;
2999         return offset;
3000 }
3001
3002
3003 /* RFC 1813, Page 16 */
3004 static int
3005 dissect_writeverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
3006 {
3007         proto_tree_add_text(tree, tvb, offset, NFS3_WRITEVERFSIZE,
3008                 "Verifier: Opaque Data");
3009         offset += NFS3_WRITEVERFSIZE;
3010         return offset;
3011 }
3012
3013 /* RFC 1813, Page 16 */
3014 static int
3015 dissect_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3016 {
3017         guint32 mode3;
3018         proto_item* mode3_item = NULL;
3019         proto_tree* mode3_tree = NULL;
3020
3021         mode3 = tvb_get_ntohl(tvb, offset+0);
3022
3023         if (tree) {
3024                 mode3_item = proto_tree_add_text(tree, tvb, offset, 4,
3025                         "%s: 0%o", name, mode3);
3026                 if (mode3_item)
3027                         mode3_tree = proto_item_add_subtree(mode3_item, ett_nfs_mode3);
3028         }
3029
3030         /* RFC 1813, Page 23 */
3031         if (mode3_tree) {
3032                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3033                 decode_boolean_bitfield(mode3,   0x800, 12, "Set user id on exec", "not SUID"));
3034                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3035                 decode_boolean_bitfield(mode3,   0x400, 12, "Set group id on exec", "not SGID"));
3036                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3037                 decode_boolean_bitfield(mode3,   0x200, 12, "Save swapped text even after use", "not save swapped text"));
3038                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3039                 decode_boolean_bitfield(mode3,   0x100, 12, "Read permission for owner", "no Read permission for owner"));
3040                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3041                 decode_boolean_bitfield(mode3,    0x80, 12, "Write permission for owner", "no Write permission for owner"));
3042                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3043                 decode_boolean_bitfield(mode3,    0x40, 12, "Execute permission for owner", "no Execute permission for owner"));
3044                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3045                 decode_boolean_bitfield(mode3,    0x20, 12, "Read permission for group", "no Read permission for group"));
3046                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3047                 decode_boolean_bitfield(mode3,    0x10, 12, "Write permission for group", "no Write permission for group"));
3048                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3049                 decode_boolean_bitfield(mode3,     0x8, 12, "Execute permission for group", "no Execute permission for group"));
3050                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3051                 decode_boolean_bitfield(mode3,     0x4, 12, "Read permission for others", "no Read permission for others"));
3052                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3053                 decode_boolean_bitfield(mode3,     0x2, 12, "Write permission for others", "no Write permission for others"));
3054                 proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
3055                 decode_boolean_bitfield(mode3,     0x1, 12, "Execute permission for others", "no Execute permission for others"));
3056         }
3057
3058         offset += 4;
3059         return offset;
3060 }
3061
3062 /* RFC 1813, Page 16,17 */
3063 static const value_string names_nfs_nfsstat3[] =
3064 {
3065         {       0,      "OK" },
3066         {       1,      "ERR_PERM" },
3067         {       2,      "ERR_NOENT" },
3068         {       5,      "ERR_IO" },
3069         {       6,      "ERR_NX_IO" },
3070         {       13,     "ERR_ACCES" },
3071         {       17,     "ERR_EXIST" },
3072         {       18,     "ERR_XDEV" },
3073         {       19,     "ERR_NODEV" },
3074         {       20,     "ERR_NOTDIR" },
3075         {       21,     "ERR_ISDIR" },
3076         {       22,     "ERR_INVAL" },
3077         {       27,     "ERR_FBIG" },
3078         {       28,     "ERR_NOSPC" },
3079         {       30,     "ERR_ROFS" },
3080         {       31,     "ERR_MLINK" },
3081         {       63,     "ERR_NAMETOOLONG" },
3082         {       66,     "ERR_NOTEMPTY" },
3083         {       69,     "ERR_DQUOT" },
3084         {       70,     "ERR_STALE" },
3085         {       71,     "ERR_REMOTE" },
3086         {       10001,  "ERR_BADHANDLE" },
3087         {       10002,  "ERR_NOT_SYNC" },
3088         {       10003,  "ERR_BAD_COOKIE" },
3089         {       10004,  "ERR_NOTSUPP" },
3090         {       10005,  "ERR_TOOSMALL" },
3091         {       10006,  "ERR_SERVERFAULT" },
3092         {       10007,  "ERR_BADTYPE" },
3093         {       10008,  "ERR_JUKEBOX" },
3094         {       0,      NULL }
3095 };
3096
3097
3098 /* RFC 1813, Page 16 */
3099 static int
3100 dissect_nfsstat3(tvbuff_t *tvb, int offset,
3101         proto_tree *tree,guint32 *status)
3102 {
3103         guint32 nfsstat3;
3104
3105         nfsstat3 = tvb_get_ntohl(tvb, offset+0);
3106
3107         if (tree) {
3108                 proto_tree_add_uint(tree, hf_nfs_nfsstat3, tvb,
3109                         offset, 4, nfsstat3);
3110         }
3111
3112         offset += 4;
3113         *status = nfsstat3;
3114         return offset;
3115 }
3116
3117
3118 static const value_string names_nfs_ftype3[] =
3119 {
3120         {       NF3REG, "Regular File" },
3121         {       NF3DIR, "Directory" },
3122         {       NF3BLK, "Block Special Device" },
3123         {       NF3CHR, "Character Special Device" },
3124         {       NF3LNK, "Symbolic Link" },
3125         {       NF3SOCK,"Socket" },
3126         {       NF3FIFO,"Named Pipe" },
3127         {       0,      NULL }
3128 };
3129
3130
3131 /* RFC 1813, Page 20 */
3132 static int
3133 dissect_ftype3(tvbuff_t *tvb, int offset, proto_tree *tree,
3134         int hf, guint32* ftype3)
3135 {
3136         guint32 type;
3137
3138         type = tvb_get_ntohl(tvb, offset+0);
3139
3140         if (tree) {
3141                 proto_tree_add_uint(tree, hf, tvb, offset, 4, type);
3142         }
3143
3144         offset += 4;
3145         *ftype3 = type;
3146         return offset;
3147 }
3148
3149
3150 /* RFC 1813, Page 20 */
3151 static int
3152 dissect_specdata3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3153 {
3154         guint32 specdata1;
3155         guint32 specdata2;
3156
3157         proto_item* specdata3_item;
3158         proto_tree* specdata3_tree = NULL;
3159
3160         specdata1 = tvb_get_ntohl(tvb, offset+0);
3161         specdata2 = tvb_get_ntohl(tvb, offset+4);
3162
3163         if (tree) {
3164                 specdata3_item = proto_tree_add_text(tree, tvb, offset, 8,
3165                         "%s: %u,%u", name, specdata1, specdata2);
3166                 if (specdata3_item)
3167                         specdata3_tree = proto_item_add_subtree(specdata3_item,
3168                                         ett_nfs_specdata3);
3169         }
3170
3171         if (specdata3_tree) {
3172                 proto_tree_add_text(specdata3_tree, tvb,offset+0,4,
3173                                         "specdata1: %u", specdata1);
3174                 proto_tree_add_text(specdata3_tree, tvb,offset+4,4,
3175                                         "specdata2: %u", specdata2);
3176         }
3177
3178         offset += 8;
3179         return offset;
3180 }
3181
3182
3183 /* RFC 1813, Page 21 */
3184 int
3185 dissect_nfs_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
3186         proto_tree *tree, char *name, guint32 *hash)
3187 {
3188         guint fh3_len;
3189         guint fh3_len_full;
3190         guint fh3_fill;
3191         proto_item* fitem = NULL;
3192         proto_tree* ftree = NULL;
3193         int fh_offset,fh_length;
3194
3195         fh3_len = tvb_get_ntohl(tvb, offset+0);
3196         fh3_len_full = rpc_roundup(fh3_len);
3197         fh3_fill = fh3_len_full - fh3_len;
3198
3199         if (tree) {
3200                 fitem = proto_tree_add_text(tree, tvb, offset, 4+fh3_len_full,
3201                         "%s", name);
3202                 if (fitem)
3203                         ftree = proto_item_add_subtree(fitem, ett_nfs_fh3);
3204         }
3205
3206         /* are we snooping fh to filenames ?*/
3207         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
3208                 rpc_call_info_value *civ=pinfo->private_data;
3209
3210                 /* NFS v3 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
3211                 if( (civ->prog==100003)
3212                   &&(civ->vers==3)
3213                   &&(!civ->request)
3214                   &&((civ->proc==3)||(civ->proc==8)||(civ->proc==9))
3215                 ) {
3216                         fh_length=tvb_get_ntohl(tvb, offset);
3217                         fh_offset=offset+4;
3218                         nfs_name_snoop_add_fh(civ->xid, tvb,
3219                                 fh_offset, fh_length);
3220                 }
3221
3222                 /* MOUNT v3 MNT replies might give us a filehandle */
3223                 if( (civ->prog==100005)
3224                   &&(civ->vers==3)
3225                   &&(!civ->request)
3226                   &&(civ->proc==1)
3227                 ) {
3228                         fh_length=tvb_get_ntohl(tvb, offset);
3229                         fh_offset=offset+4;
3230                         nfs_name_snoop_add_fh(civ->xid, tvb,
3231                                 fh_offset, fh_length);
3232                 }
3233         }
3234
3235         proto_tree_add_uint(ftree, hf_nfs_fh_length, tvb, offset+0, 4,
3236                         fh3_len);
3237
3238         /* Handle WebNFS requests where filehandle may be 0 length */
3239         if (fh3_len > 0)
3240         {
3241                 dissect_fhandle_data(tvb, offset+4, pinfo, ftree, fh3_len, FALSE, hash);
3242
3243                 offset += fh3_len_full;
3244         }
3245
3246         offset += 4;
3247
3248         return offset;
3249 }
3250
3251
3252 /* RFC 1813, Page 21 */
3253 static int
3254 dissect_nfstime3(tvbuff_t *tvb, int offset,
3255         proto_tree *tree, int hf_time, int hf_time_sec, int hf_time_nsec)
3256 {
3257         guint32 seconds;
3258         guint32 nseconds;
3259         nstime_t ts;
3260
3261         proto_item* time_item;
3262         proto_tree* time_tree = NULL;
3263
3264         seconds = tvb_get_ntohl(tvb, offset+0);
3265         nseconds = tvb_get_ntohl(tvb, offset+4);
3266         ts.secs = seconds;
3267         ts.nsecs = nseconds;
3268
3269         if (tree) {
3270                 time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
3271                                 &ts);
3272                 if (time_item)
3273                         time_tree = proto_item_add_subtree(time_item, ett_nfs_nfstime3);
3274         }
3275
3276         if (time_tree) {
3277                 proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
3278                                         seconds);
3279                 proto_tree_add_uint(time_tree, hf_time_nsec, tvb, offset+4, 4,
3280                                         nseconds);
3281         }
3282         offset += 8;
3283         return offset;
3284 }
3285
3286
3287 /* RFC 1813, Page 22 */
3288 int
3289 dissect_nfs_fattr3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3290 {
3291         proto_item* fattr3_item = NULL;
3292         proto_tree* fattr3_tree = NULL;
3293         int old_offset = offset;
3294         guint32 type;
3295
3296         if (tree) {
3297                 fattr3_item = proto_tree_add_text(tree, tvb, offset, -1,
3298                         "%s", name);
3299                 fattr3_tree = proto_item_add_subtree(fattr3_item, ett_nfs_fattr3);
3300         }
3301
3302         offset = dissect_ftype3(tvb,offset,fattr3_tree,hf_nfs_fattr3_type,&type);
3303         offset = dissect_mode3(tvb,offset,fattr3_tree,"mode");
3304         offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_nlink,
3305                 offset);
3306         offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_uid,
3307                 offset);
3308         offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_gid,
3309                 offset);
3310         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_size,
3311                 offset);
3312         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_used,
3313                 offset);
3314         offset = dissect_specdata3(tvb,offset,fattr3_tree,"rdev");
3315         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_fsid,
3316                 offset);
3317         offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_fileid,
3318                 offset);
3319         offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_atime,hf_nfs_atime_sec,hf_nfs_atime_nsec);
3320         offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_mtime,hf_nfs_mtime_sec,hf_nfs_mtime_nsec);
3321         offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_ctime,hf_nfs_ctime_sec,hf_nfs_ctime_nsec);
3322
3323         /* now we know, that fattr3 is shorter */
3324         if (fattr3_item) {
3325                 proto_item_set_len(fattr3_item, offset - old_offset);
3326         }
3327
3328         return offset;
3329 }
3330
3331
3332 static const value_string value_follows[] =
3333         {
3334                 { 0, "no value" },
3335                 { 1, "value follows"},
3336                 { 0, NULL }
3337         };
3338
3339
3340 /* RFC 1813, Page 23 */
3341 int
3342 dissect_nfs_post_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, 
3343                 char* name)
3344 {
3345         proto_item* post_op_attr_item = NULL;
3346         proto_tree* post_op_attr_tree = NULL;
3347         int old_offset = offset;
3348         guint32 attributes_follow;
3349
3350         if (tree) {
3351                 post_op_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
3352                         "%s", name);
3353                 post_op_attr_tree = proto_item_add_subtree(post_op_attr_item,
3354                         ett_nfs_post_op_attr);
3355         }
3356
3357         attributes_follow = tvb_get_ntohl(tvb, offset+0);
3358         proto_tree_add_text(post_op_attr_tree, tvb, offset, 4,
3359                 "attributes_follow: %s (%u)",
3360                 val_to_str(attributes_follow,value_follows,"Unknown"), attributes_follow);
3361         offset += 4;
3362         switch (attributes_follow) {
3363                 case TRUE:
3364                         offset = dissect_nfs_fattr3(tvb, offset, post_op_attr_tree,
3365                                         "attributes");
3366                 break;
3367                 case FALSE:
3368                         /* void */
3369                 break;
3370         }
3371
3372         /* now we know, that post_op_attr_tree is shorter */
3373         if (post_op_attr_item) {
3374                 proto_item_set_len(post_op_attr_item, offset - old_offset);
3375         }
3376
3377         return offset;
3378 }
3379
3380
3381 /* RFC 1813, Page 24 */
3382 static int
3383 dissect_wcc_attr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3384 {
3385         proto_item* wcc_attr_item = NULL;
3386         proto_tree* wcc_attr_tree = NULL;
3387         int old_offset = offset;
3388
3389         if (tree) {
3390                 wcc_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
3391                         "%s", name);
3392                 wcc_attr_tree = proto_item_add_subtree(wcc_attr_item,
3393                         ett_nfs_wcc_attr);
3394         }
3395
3396         offset = dissect_rpc_uint64(tvb, wcc_attr_tree, hf_nfs_wcc_attr_size,
3397                 offset);
3398         offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_nsec);
3399         offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
3400         /* now we know, that wcc_attr_tree is shorter */
3401         if (wcc_attr_item) {
3402                 proto_item_set_len(wcc_attr_item, offset - old_offset);
3403         }
3404
3405         return offset;
3406 }
3407
3408
3409 /* RFC 1813, Page 24 */
3410 static int
3411 dissect_pre_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3412 {
3413         proto_item* pre_op_attr_item = NULL;
3414         proto_tree* pre_op_attr_tree = NULL;
3415         int old_offset = offset;
3416         guint32 attributes_follow;
3417
3418         if (tree) {
3419                 pre_op_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
3420                         "%s", name);
3421                 pre_op_attr_tree = proto_item_add_subtree(pre_op_attr_item,
3422                         ett_nfs_pre_op_attr);
3423         }
3424
3425         attributes_follow = tvb_get_ntohl(tvb, offset+0);
3426         proto_tree_add_text(pre_op_attr_tree, tvb, offset, 4,
3427                 "attributes_follow: %s (%u)",
3428                 val_to_str(attributes_follow,value_follows,"Unknown"), attributes_follow);
3429         offset += 4;
3430         switch (attributes_follow) {
3431                 case TRUE:
3432                         offset = dissect_wcc_attr(tvb, offset, pre_op_attr_tree,
3433                                         "attributes");
3434                 break;
3435                 case FALSE:
3436                         /* void */
3437                 break;
3438         }
3439
3440         /* now we know, that pre_op_attr_tree is shorter */
3441         if (pre_op_attr_item) {
3442                 proto_item_set_len(pre_op_attr_item, offset - old_offset);
3443         }
3444
3445         return offset;
3446 }
3447
3448
3449 /* RFC 1813, Page 24 */
3450 static int
3451 dissect_wcc_data(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3452 {
3453         proto_item* wcc_data_item = NULL;
3454         proto_tree* wcc_data_tree = NULL;
3455         int old_offset = offset;
3456
3457         if (tree) {
3458                 wcc_data_item = proto_tree_add_text(tree, tvb, offset, -1,
3459                         "%s", name);
3460                 wcc_data_tree = proto_item_add_subtree(wcc_data_item,
3461                         ett_nfs_wcc_data);
3462         }
3463
3464         offset = dissect_pre_op_attr (tvb, offset, wcc_data_tree, "before");
3465         offset = dissect_nfs_post_op_attr(tvb, offset, wcc_data_tree, "after" );
3466
3467         /* now we know, that wcc_data is shorter */
3468         if (wcc_data_item) {
3469                 proto_item_set_len(wcc_data_item, offset - old_offset);
3470         }
3471
3472         return offset;
3473 }
3474
3475
3476 /* RFC 1813, Page 25 */
3477 static int
3478 dissect_post_op_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
3479         proto_tree *tree, char* name)
3480 {
3481         proto_item* post_op_fh3_item = NULL;
3482         proto_tree* post_op_fh3_tree = NULL;
3483         int old_offset = offset;
3484         guint32 handle_follows;
3485
3486         if (tree) {
3487                 post_op_fh3_item = proto_tree_add_text(tree, tvb, offset, -1,
3488                         "%s", name);
3489                 post_op_fh3_tree = proto_item_add_subtree(post_op_fh3_item,
3490                         ett_nfs_post_op_fh3);
3491         }
3492
3493         handle_follows = tvb_get_ntohl(tvb, offset+0);
3494         proto_tree_add_text(post_op_fh3_tree, tvb, offset, 4,
3495                 "handle_follows: %s (%u)",
3496                 val_to_str(handle_follows,value_follows,"Unknown"), handle_follows);
3497         offset += 4;
3498         switch (handle_follows) {
3499                 case TRUE:
3500                         offset = dissect_nfs_fh3(tvb, offset, pinfo, post_op_fh3_tree,
3501                                         "handle", NULL);
3502                 break;
3503                 case FALSE:
3504                         /* void */
3505                 break;
3506         }
3507
3508         /* now we know, that post_op_fh3_tree is shorter */
3509         if (post_op_fh3_item) {
3510                 proto_item_set_len(post_op_fh3_item, offset - old_offset);
3511         }
3512
3513         return offset;
3514 }
3515
3516
3517 /* RFC 1813, Page 25 */
3518 static int
3519 dissect_set_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3520 {
3521         proto_item* set_mode3_item = NULL;
3522         proto_tree* set_mode3_tree = NULL;
3523         int old_offset = offset;
3524         guint32 set_it;
3525         char* set_it_name;
3526
3527         set_it = tvb_get_ntohl(tvb, offset+0);
3528         set_it_name = val_to_str(set_it,value_follows,"Unknown");
3529
3530         if (tree) {
3531                 set_mode3_item = proto_tree_add_text(tree, tvb, offset, -1,
3532                         "%s: %s", name, set_it_name);
3533                 set_mode3_tree = proto_item_add_subtree(set_mode3_item,
3534                         ett_nfs_set_mode3);
3535         }
3536
3537         if (set_mode3_tree)
3538                 proto_tree_add_text(set_mode3_tree, tvb, offset, 4,
3539                         "set_it: %s (%u)", set_it_name, set_it);
3540
3541         offset += 4;
3542
3543         switch (set_it) {
3544                 case 1:
3545                         offset = dissect_mode3(tvb, offset, set_mode3_tree,
3546                                         "mode");
3547                 break;
3548                 default:
3549                         /* void */
3550                 break;
3551         }
3552
3553         /* now we know, that set_mode3 is shorter */
3554         if (set_mode3_item) {
3555                 proto_item_set_len(set_mode3_item, offset - old_offset);
3556         }
3557
3558         return offset;
3559 }
3560
3561
3562 /* RFC 1813, Page 26 */
3563 static int
3564 dissect_set_uid3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3565 {
3566         proto_item* set_uid3_item = NULL;
3567         proto_tree* set_uid3_tree = NULL;
3568         int old_offset = offset;
3569         guint32 set_it;
3570         char* set_it_name;
3571
3572         set_it = tvb_get_ntohl(tvb, offset+0);
3573         set_it_name = val_to_str(set_it,value_follows,"Unknown");
3574
3575         if (tree) {
3576                 set_uid3_item = proto_tree_add_text(tree, tvb, offset, -1,
3577                         "%s: %s", name, set_it_name);
3578                 set_uid3_tree = proto_item_add_subtree(set_uid3_item,
3579                         ett_nfs_set_uid3);
3580         }
3581
3582         if (set_uid3_tree)
3583                 proto_tree_add_text(set_uid3_tree, tvb, offset, 4,
3584                         "set_it: %s (%u)", set_it_name, set_it);
3585
3586         offset += 4;
3587
3588         switch (set_it) {
3589                 case 1:
3590                         offset = dissect_rpc_uint32(tvb, set_uid3_tree,
3591                                                                  hf_nfs_uid3, offset);
3592                 break;
3593                 default:
3594                         /* void */
3595                 break;
3596         }
3597
3598         /* now we know, that set_uid3 is shorter */
3599         if (set_uid3_item) {
3600                 proto_item_set_len(set_uid3_item, offset - old_offset);
3601         }
3602
3603         return offset;
3604 }
3605
3606
3607 /* RFC 1813, Page 26 */
3608 static int
3609 dissect_set_gid3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3610 {
3611         proto_item* set_gid3_item = NULL;
3612         proto_tree* set_gid3_tree = NULL;
3613         int old_offset = offset;
3614         guint32 set_it;
3615         char* set_it_name;
3616
3617         set_it = tvb_get_ntohl(tvb, offset+0);
3618         set_it_name = val_to_str(set_it,value_follows,"Unknown");
3619
3620         if (tree) {
3621                 set_gid3_item = proto_tree_add_text(tree, tvb, offset, -1,
3622                         "%s: %s", name, set_it_name);
3623                 set_gid3_tree = proto_item_add_subtree(set_gid3_item,
3624                         ett_nfs_set_gid3);
3625         }
3626
3627         if (set_gid3_tree)
3628                 proto_tree_add_text(set_gid3_tree, tvb, offset, 4,
3629                         "set_it: %s (%u)", set_it_name, set_it);
3630
3631         offset += 4;
3632
3633         switch (set_it) {
3634                 case 1:
3635                         offset = dissect_rpc_uint32(tvb, set_gid3_tree,
3636                                 hf_nfs_gid3, offset);
3637                 break;
3638                 default:
3639                         /* void */
3640                 break;
3641         }
3642
3643         /* now we know, that set_gid3 is shorter */
3644         if (set_gid3_item) {
3645                 proto_item_set_len(set_gid3_item, offset - old_offset);
3646         }
3647
3648         return offset;
3649 }
3650
3651
3652 /* RFC 1813, Page 26 */
3653 static int
3654 dissect_set_size3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3655 {
3656         proto_item* set_size3_item = NULL;
3657         proto_tree* set_size3_tree = NULL;
3658         int old_offset = offset;
3659         guint32 set_it;
3660         char* set_it_name;
3661
3662         set_it = tvb_get_ntohl(tvb, offset+0);
3663         set_it_name = val_to_str(set_it,value_follows,"Unknown");
3664
3665         if (tree) {
3666                 set_size3_item = proto_tree_add_text(tree, tvb, offset, -1,
3667                         "%s: %s", name, set_it_name);
3668                 set_size3_tree = proto_item_add_subtree(set_size3_item,
3669                         ett_nfs_set_size3);
3670         }
3671
3672         if (set_size3_tree)
3673                 proto_tree_add_text(set_size3_tree, tvb, offset, 4,
3674                         "set_it: %s (%u)", set_it_name, set_it);
3675
3676         offset += 4;
3677
3678         switch (set_it) {
3679                 case 1:
3680                         offset = dissect_rpc_uint64(tvb, set_size3_tree,
3681                                 hf_nfs_set_size3_size, offset);
3682                 break;
3683                 default:
3684                         /* void */
3685                 break;
3686         }
3687
3688         /* now we know, that set_size3 is shorter */
3689         if (set_size3_item) {
3690                 proto_item_set_len(set_size3_item, offset - old_offset);
3691         }
3692
3693         return offset;
3694 }
3695
3696
3697 /* RFC 1813, Page 25 */
3698 #define DONT_CHANGE 0
3699 #define SET_TO_SERVER_TIME 1
3700 #define SET_TO_CLIENT_TIME 2
3701
3702 static const value_string time_how[] =
3703         {
3704                 { DONT_CHANGE,  "don't change" },
3705                 { SET_TO_SERVER_TIME, "set to server time" },
3706                 { SET_TO_CLIENT_TIME, "set to client time" },
3707                 { 0, NULL }
3708         };
3709
3710
3711 /* RFC 1813, Page 26 */
3712 static int
3713 dissect_set_atime(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3714 {
3715         proto_item* set_atime_item = NULL;
3716         proto_tree* set_atime_tree = NULL;
3717         int old_offset = offset;
3718         guint32 set_it;
3719         char* set_it_name;
3720
3721         set_it = tvb_get_ntohl(tvb, offset+0);
3722         set_it_name = val_to_str(set_it,time_how,"Unknown");
3723
3724         if (tree) {
3725                 set_atime_item = proto_tree_add_text(tree, tvb, offset, -1,
3726                         "%s: %s", name, set_it_name);
3727                 set_atime_tree = proto_item_add_subtree(set_atime_item,
3728                         ett_nfs_set_atime);
3729         }
3730
3731         if (set_atime_tree)
3732                 proto_tree_add_text(set_atime_tree, tvb, offset, 4,
3733                         "set_it: %s (%u)", set_it_name, set_it);
3734
3735         offset += 4;
3736
3737         switch (set_it) {
3738                 case SET_TO_CLIENT_TIME:
3739                         if (set_atime_item) {
3740                                 offset = dissect_nfstime3(tvb, offset, set_atime_tree,
3741                                         hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
3742                         }
3743                 break;
3744                 default:
3745                         /* void */
3746                 break;
3747         }
3748
3749         /* now we know, that set_atime is shorter */
3750         if (set_atime_item) {
3751                 proto_item_set_len(set_atime_item, offset - old_offset);
3752         }
3753
3754         return offset;
3755 }
3756
3757
3758 /* RFC 1813, Page 26 */
3759 static int
3760 dissect_set_mtime(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3761 {
3762         proto_item* set_mtime_item = NULL;
3763         proto_tree* set_mtime_tree = NULL;
3764         int old_offset = offset;
3765         guint32 set_it;
3766         char* set_it_name;
3767
3768         set_it = tvb_get_ntohl(tvb, offset+0);
3769         set_it_name = val_to_str(set_it,time_how,"Unknown");
3770
3771         if (tree) {
3772                 set_mtime_item = proto_tree_add_text(tree, tvb, offset, -1,
3773                         "%s: %s", name, set_it_name);
3774                 set_mtime_tree = proto_item_add_subtree(set_mtime_item,
3775                         ett_nfs_set_mtime);
3776         }
3777
3778         if (set_mtime_tree)
3779                 proto_tree_add_text(set_mtime_tree, tvb, offset, 4,
3780                                 "set_it: %s (%u)", set_it_name, set_it);
3781
3782         offset += 4;
3783
3784         switch (set_it) {
3785                 case SET_TO_CLIENT_TIME:
3786                         if (set_mtime_item) {
3787                                 offset = dissect_nfstime3(tvb, offset, set_mtime_tree,
3788                                         hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
3789                         }
3790                 break;
3791                 default:
3792                         /* void */
3793                 break;
3794         }
3795
3796         /* now we know, that set_mtime is shorter */
3797         if (set_mtime_item) {
3798                 proto_item_set_len(set_mtime_item, offset - old_offset);
3799         }
3800
3801         return offset;
3802 }
3803
3804
3805 /* RFC 1813, Page 25..27 */
3806 static int
3807 dissect_sattr3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
3808 {
3809         proto_item* sattr3_item = NULL;
3810         proto_tree* sattr3_tree = NULL;
3811         int old_offset = offset;
3812
3813         if (tree) {
3814                 sattr3_item = proto_tree_add_text(tree, tvb, offset, -1,
3815                         "%s", name);
3816                 sattr3_tree = proto_item_add_subtree(sattr3_item, ett_nfs_sattr3);
3817         }
3818
3819         offset = dissect_set_mode3(tvb, offset, sattr3_tree, "mode");
3820         offset = dissect_set_uid3 (tvb, offset, sattr3_tree, "uid");
3821         offset = dissect_set_gid3 (tvb, offset, sattr3_tree, "gid");
3822         offset = dissect_set_size3(tvb, offset, sattr3_tree, "size");
3823         offset = dissect_set_atime(tvb, offset, sattr3_tree, "atime");
3824         offset = dissect_set_mtime(tvb, offset, sattr3_tree, "mtime");
3825
3826         /* now we know, that sattr3 is shorter */
3827         if (sattr3_item) {
3828                 proto_item_set_len(sattr3_item, offset - old_offset);
3829         }
3830
3831         return offset;
3832 }
3833
3834
3835 /* RFC 1813, Page 27 */
3836 static int
3837 dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo,
3838         proto_tree *tree, char* label, guint32 *hash, char **name)
3839 {
3840         proto_item* diropargs3_item = NULL;
3841         proto_tree* diropargs3_tree = NULL;
3842         int old_offset = offset;
3843         int parent_offset, parent_len;
3844         int name_offset, name_len;
3845
3846         if (tree) {
3847                 diropargs3_item = proto_tree_add_text(tree, tvb, offset, -1,
3848                         "%s", label);
3849                 diropargs3_tree = proto_item_add_subtree(diropargs3_item,
3850                         ett_nfs_diropargs3);
3851         }
3852
3853         parent_offset=offset+4;
3854         parent_len=tvb_get_ntohl(tvb, offset);
3855         offset = dissect_nfs_fh3(tvb, offset, pinfo, diropargs3_tree, "dir", hash);
3856         name_offset=offset+4;
3857         name_len=tvb_get_ntohl(tvb, offset);
3858         offset = dissect_filename3(tvb, offset, diropargs3_tree,
3859                 hf_nfs_name, name);
3860
3861         /* are we snooping fh to filenames ?*/
3862         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
3863                 /* v3 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
3864                 rpc_call_info_value *civ=pinfo->private_data;
3865
3866                 if( (civ->prog==100003)
3867                   &&(civ->vers==3)
3868                   &&(civ->request)
3869                   &&((civ->proc==3)||(civ->proc==8)||(civ->proc==9))
3870                 ) {
3871                         nfs_name_snoop_add_name(civ->xid, tvb,
3872                                 name_offset, name_len,
3873                                 parent_offset, parent_len, NULL);
3874                 }
3875         }
3876
3877
3878         /* now we know, that diropargs3 is shorter */
3879         if (diropargs3_item) {
3880                 proto_item_set_len(diropargs3_item, offset - old_offset);
3881         }
3882
3883         return offset;
3884 }
3885
3886 static int
3887 dissect_nfs3_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3888         proto_tree *tree)
3889 {
3890         guint32 hash;
3891         char *name=NULL;
3892
3893         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
3894
3895         if (check_col(pinfo->cinfo, COL_INFO)) {
3896                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
3897         }
3898         proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
3899         g_free(name);
3900
3901         return offset;
3902 }
3903
3904 static int
3905 dissect_nfs3_null_call(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
3906         proto_tree *tree)
3907 {
3908         proto_item_append_text(tree, ", NULL Call");
3909
3910         return offset;
3911 }
3912
3913 static int
3914 dissect_nfs3_null_reply(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
3915         proto_tree *tree)
3916 {
3917         proto_item_append_text(tree, ", NULL Reply");
3918
3919         return offset;
3920 }
3921
3922 static int
3923 dissect_nfs3_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3924         proto_tree *tree)
3925 {
3926         guint32 hash;
3927         char *name=NULL;
3928
3929         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
3930
3931         if (check_col(pinfo->cinfo, COL_INFO)) {
3932                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
3933         }
3934         proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
3935         g_free(name);
3936
3937         return offset;
3938 }
3939
3940
3941 /* RFC 1813, Page 40 */
3942 int
3943 dissect_access(tvbuff_t *tvb, int offset, proto_tree *tree,
3944         char* name)
3945 {
3946         guint32 access;
3947         proto_item* access_item = NULL;
3948         proto_tree* access_tree = NULL;
3949
3950         access = tvb_get_ntohl(tvb, offset+0);
3951
3952         if (tree) {
3953                 access_item = proto_tree_add_text(tree, tvb, offset, 4,
3954                         "%s: 0x%02x", name, access);
3955                 if (access_item)
3956                         access_tree = proto_item_add_subtree(access_item, ett_nfs_access);
3957         }
3958
3959         if (access_tree) {
3960                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s READ",
3961                 decode_boolean_bitfield(access,  0x001, 6, "allow", "not allow"));
3962                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s LOOKUP",
3963                 decode_boolean_bitfield(access,  0x002, 6, "allow", "not allow"));
3964                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s MODIFY",
3965                 decode_boolean_bitfield(access,  0x004, 6, "allow", "not allow"));
3966                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s EXTEND",
3967                 decode_boolean_bitfield(access,  0x008, 6, "allow", "not allow"));
3968                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s DELETE",
3969                 decode_boolean_bitfield(access,  0x010, 6, "allow", "not allow"));
3970                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s EXECUTE",
3971                 decode_boolean_bitfield(access,  0x020, 6, "allow", "not allow"));
3972         }
3973
3974         offset += 4;
3975         return offset;
3976 }
3977
3978
3979 /* RFC 1813, Page 32,33 */
3980 static int
3981 dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
3982         proto_tree* tree)
3983 {
3984         guint32 hash;
3985
3986         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
3987
3988         if (check_col(pinfo->cinfo, COL_INFO)) {
3989                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
3990         }
3991         proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
3992
3993         return offset;
3994 }
3995
3996
3997 /* RFC 1813, Page 32,33 */
3998 static int
3999 dissect_nfs3_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4000         proto_tree* tree)
4001 {
4002         guint32 status;
4003         char *err;
4004
4005         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4006         switch (status) {
4007                 case 0:
4008                         offset = dissect_nfs_fattr3(tvb, offset, tree, "obj_attributes");
4009                         proto_item_append_text(tree, ", GETATTR Reply");
4010                 break;
4011                 default:
4012                         /* void */
4013
4014                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4015                         if (check_col(pinfo->cinfo, COL_INFO)) {
4016                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4017                         }
4018                         proto_item_append_text(tree, ", GETATTR Reply  Error:%s", err);
4019                 break;
4020         }
4021
4022         return offset;
4023 }
4024
4025
4026 /* RFC 1813, Page 33 */
4027 static int
4028 dissect_sattrguard3(tvbuff_t *tvb, int offset, proto_tree* tree, char *name)
4029 {
4030         proto_item* sattrguard3_item = NULL;
4031         proto_tree* sattrguard3_tree = NULL;
4032         int old_offset = offset;
4033         guint32 check;
4034         char* check_name;
4035
4036         check = tvb_get_ntohl(tvb, offset+0);
4037         check_name = val_to_str(check,value_follows,"Unknown");
4038
4039         if (tree) {
4040                 sattrguard3_item = proto_tree_add_text(tree, tvb, offset, -1,
4041                         "%s: %s", name, check_name);
4042                 sattrguard3_tree = proto_item_add_subtree(sattrguard3_item,
4043                         ett_nfs_sattrguard3);
4044         }
4045
4046         if (sattrguard3_tree)
4047                 proto_tree_add_text(sattrguard3_tree, tvb, offset, 4,
4048                         "check: %s (%u)", check_name, check);
4049
4050         offset += 4;
4051
4052         switch (check) {
4053                 case TRUE:
4054                         offset = dissect_nfstime3(tvb, offset, sattrguard3_tree,
4055                                         hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
4056                 break;
4057                 case FALSE:
4058                         /* void */
4059                 break;
4060         }
4061
4062         /* now we know, that sattrguard3 is shorter */
4063         if (sattrguard3_item) {
4064                 proto_item_set_len(sattrguard3_item, offset - old_offset);
4065         }
4066
4067         return offset;
4068 }
4069
4070
4071 /* RFC 1813, Page 33..36 */
4072 static int
4073 dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4074         proto_tree* tree)
4075 {
4076         guint32 hash;
4077
4078         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "object", &hash);
4079         offset = dissect_sattr3     (tvb, offset,        tree, "new_attributes");
4080         offset = dissect_sattrguard3(tvb, offset,        tree, "guard");
4081
4082         if (check_col(pinfo->cinfo, COL_INFO)) {
4083                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4084         }
4085         proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
4086
4087         return offset;
4088 }
4089
4090
4091 /* RFC 1813, Page 33..36 */
4092 static int
4093 dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4094         proto_tree* tree)
4095 {
4096         guint32 status;
4097         char *err;
4098
4099         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4100         switch (status) {
4101                 case 0:
4102                         offset = dissect_wcc_data(tvb, offset, tree, "obj_wcc");
4103                         proto_item_append_text(tree, ", SETATTR Reply");
4104                 break;
4105                 default:
4106                         offset = dissect_wcc_data(tvb, offset, tree, "obj_wcc");
4107
4108                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4109                         if (check_col(pinfo->cinfo, COL_INFO)) {
4110                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4111                         }
4112                         proto_item_append_text(tree, ", SETATTR Reply  Error:%s", err);
4113                 break;
4114         }
4115
4116         return offset;
4117 }
4118
4119
4120 /* RFC 1813, Page 37..39 */
4121 static int
4122 dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4123         proto_tree* tree)
4124 {
4125         guint32 hash;
4126         char *name=NULL;
4127
4128         offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what", &hash, &name);
4129
4130         if (check_col(pinfo->cinfo, COL_INFO)) {
4131                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
4132         }
4133         proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
4134         g_free(name);
4135
4136         return offset;
4137 }
4138
4139
4140 /* RFC 1813, Page 37..39 */
4141 static int
4142 dissect_nfs3_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4143         proto_tree* tree)
4144 {
4145         guint32 status;
4146         char *err;
4147         guint32 hash;
4148
4149         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4150         switch (status) {
4151                 case 0:
4152                         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
4153                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4154                                 "obj_attributes");
4155                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4156                                 "dir_attributes");
4157
4158                         if (check_col(pinfo->cinfo, COL_INFO)) {
4159                                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4160                         }
4161                         proto_item_append_text(tree, ", LOOKUP Reply FH:0x%08x", hash);
4162                 break;
4163                 default:
4164                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4165                                 "dir_attributes");
4166
4167                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4168                         if (check_col(pinfo->cinfo, COL_INFO)) {
4169                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4170                         }
4171                         proto_item_append_text(tree, ", LOOKUP Reply  Error:%s", err);
4172                 break;
4173         }
4174
4175         return offset;
4176 }
4177
4178
4179 /* RFC 1813, Page 40..43 */
4180 static int
4181 dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4182         proto_tree* tree)
4183 {
4184         guint32 hash;
4185
4186         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
4187         offset = dissect_access (tvb, offset,        tree, "access");
4188
4189         if (check_col(pinfo->cinfo, COL_INFO)) {
4190                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4191         }
4192         proto_item_append_text(tree, ", ACCESS Call FH:0x%08x", hash);
4193
4194         return offset;
4195 }
4196
4197
4198 /* RFC 1813, Page 40..43 */
4199 static int
4200 dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4201         proto_tree* tree)
4202 {
4203         guint32 status;
4204         char *err;
4205
4206         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4207         switch (status) {
4208                 case 0:
4209                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4210                                 "obj_attributes");
4211                         offset = dissect_access(tvb, offset, tree, "access");
4212
4213                         proto_item_append_text(tree, ", ACCESS Reply");
4214                 break;
4215                 default:
4216                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4217                                 "obj_attributes");
4218
4219                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4220                         if (check_col(pinfo->cinfo, COL_INFO)) {
4221                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4222                         }
4223                         proto_item_append_text(tree, ", ACCESS Reply  Error:%s", err);
4224                 break;
4225         }
4226
4227         return offset;
4228 }
4229
4230
4231 /* RFC 1813, Page 44,45 */
4232 static int
4233 dissect_nfs3_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4234         proto_tree* tree)
4235 {
4236         guint32 hash;
4237
4238         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
4239
4240         if (check_col(pinfo->cinfo, COL_INFO)) {
4241                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4242         }
4243         proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
4244
4245         return offset;
4246 }
4247 static int
4248 dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4249         proto_tree* tree)
4250 {
4251         guint32 status;
4252         char *err;
4253         char *name=NULL;
4254
4255         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4256         switch (status) {
4257                 case 0:
4258                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4259                                 "symlink_attributes");
4260                         offset = dissect_nfspath3(tvb, offset, tree,
4261                                 hf_nfs_readlink_data, &name);
4262
4263                         if (check_col(pinfo->cinfo, COL_INFO)) {
4264                                 col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
4265                         }
4266                         proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
4267                         g_free(name);
4268                 break;
4269                 default:
4270                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4271                                 "symlink_attributes");
4272
4273                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4274                         if (check_col(pinfo->cinfo, COL_INFO)) {
4275                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4276                         }
4277                         proto_item_append_text(tree, ", READLINK Reply  Error:%s", err);
4278                 break;
4279         }
4280
4281         return offset;
4282 }
4283
4284
4285 /* RFC 1813, Page 46..48 */
4286 static int
4287 dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4288         proto_tree* tree)
4289 {
4290         unsigned char *off;
4291         guint32 len;
4292         guint32 hash;
4293
4294         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
4295
4296         off=u64toa(tvb_get_ptr(tvb, offset, 8));
4297         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
4298
4299         len=tvb_get_ntohl(tvb, offset);
4300         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
4301
4302         
4303         if (check_col(pinfo->cinfo, COL_INFO)) {
4304                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%s Len:%d", hash, off, len);
4305         }
4306         proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%s Len:%d", hash, off, len);
4307
4308         return offset;
4309 }
4310
4311
4312 /* RFC 1813, Page 46..48 */
4313 static int
4314 dissect_nfs3_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4315         proto_tree* tree)
4316 {
4317         guint32 status;
4318         guint32 len;
4319         char *err;
4320
4321         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4322         switch (status) {
4323                 case 0:
4324                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4325                                 "file_attributes");
4326                         len=tvb_get_ntohl(tvb, offset);
4327                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
4328                                 offset);
4329                         offset = dissect_rpc_bool(tvb, tree, hf_nfs_read_eof,
4330                                 offset);
4331                         if (check_col(pinfo->cinfo, COL_INFO)) {
4332                                 col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d", len);
4333                         }
4334                         proto_item_append_text(tree, ", READ Reply Len:%d", len);
4335                         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
4336                 break;
4337                 default:
4338                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4339                                 "file_attributes");
4340
4341                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4342                         if (check_col(pinfo->cinfo, COL_INFO)) {
4343                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4344                         }
4345                         proto_item_append_text(tree, ", READ Reply  Error:%s", err);
4346                 break;
4347         }
4348
4349         return offset;
4350 }
4351
4352
4353 /* RFC 1813, Page 49 */
4354 static const value_string names_stable_how[] = {
4355         {       UNSTABLE,  "UNSTABLE"  },
4356         {       DATA_SYNC, "DATA_SYNC" },
4357         {       FILE_SYNC, "FILE_SYNC" },
4358         { 0, NULL }
4359 };
4360
4361
4362 /* RFC 1813, Page 49 */
4363 static int
4364 dissect_stable_how(tvbuff_t *tvb, int offset, proto_tree* tree, int hfindex)
4365 {
4366         guint32 stable_how;
4367
4368         stable_how = tvb_get_ntohl(tvb,offset+0);
4369         if (tree) {
4370                 proto_tree_add_uint(tree, hfindex, tvb,
4371                         offset, 4, stable_how);
4372         }
4373         offset += 4;
4374
4375         return offset;
4376 }
4377
4378
4379 /* RFC 1813, Page 49..54 */
4380 static int
4381 dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4382         proto_tree* tree)
4383 {
4384         unsigned char *off;
4385         guint32 len;
4386         guint32 stable;
4387         guint32 hash;
4388
4389         offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file", &hash);
4390
4391         off=u64toa(tvb_get_ptr(tvb, offset, 8));
4392         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
4393
4394         len=tvb_get_ntohl(tvb, offset);
4395         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
4396
4397         stable=tvb_get_ntohl(tvb, offset);
4398         offset = dissect_stable_how(tvb, offset, tree, hf_nfs_write_stable);
4399
4400         if (check_col(pinfo->cinfo, COL_INFO)) {
4401                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%s Len:%d %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
4402         }
4403         proto_item_append_text(tree, ", WRITE Call FH:0x%08x Offset:%s Len:%d %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
4404
4405         offset = dissect_nfsdata   (tvb, offset, tree, hf_nfs_data);
4406
4407         return offset;
4408 }
4409
4410
4411 /* RFC 1813, Page 49..54 */
4412 static int
4413 dissect_nfs3_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4414         proto_tree* tree)
4415 {
4416         guint32 status;
4417         guint32 len;
4418         guint32 stable;
4419         char *err;
4420
4421         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4422         switch (status) {
4423                 case 0:
4424                         offset = dissect_wcc_data  (tvb, offset, tree, "file_wcc");
4425                         len=tvb_get_ntohl(tvb, offset);
4426                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
4427                                 offset);
4428                         stable=tvb_get_ntohl(tvb, offset);
4429                         offset = dissect_stable_how(tvb, offset, tree,
4430                                 hf_nfs_write_committed);
4431                         offset = dissect_writeverf3(tvb, offset, tree);
4432
4433                         if (check_col(pinfo->cinfo, COL_INFO)) {
4434                                 col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
4435                         }
4436                         proto_item_append_text(tree, ", WRITE Reply Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
4437                 break;
4438                 default:
4439                         offset = dissect_wcc_data(tvb, offset, tree, "file_wcc");
4440
4441                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4442                         if (check_col(pinfo->cinfo, COL_INFO)) {
4443                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4444                         }
4445                         proto_item_append_text(tree, ", WRITE Reply  Error:%s", err);
4446                 break;
4447         }
4448
4449         return offset;
4450 }
4451
4452
4453 /* RFC 1813, Page 54 */
4454 static const value_string names_createmode3[] = {
4455         {       UNCHECKED, "UNCHECKED" },
4456         {       GUARDED,   "GUARDED" },
4457         {       EXCLUSIVE, "EXCLUSIVE" },
4458         { 0, NULL }
4459 };
4460
4461
4462 /* RFC 1813, Page 54 */
4463 static int
4464 dissect_createmode3(tvbuff_t *tvb, int offset, proto_tree* tree, guint32* mode)
4465 {
4466         guint32 mode_value;
4467
4468         mode_value = tvb_get_ntohl(tvb, offset + 0);
4469         if (tree) {
4470                 proto_tree_add_uint(tree, hf_nfs_createmode3, tvb,
4471                 offset+0, 4, mode_value);
4472         }
4473         offset += 4;
4474
4475         *mode = mode_value;
4476         return offset;
4477 }
4478
4479
4480 /* RFC 1813, Page 54..58 */
4481 static int
4482 dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4483         proto_tree* tree)
4484 {
4485         guint32 mode;
4486         guint32 hash;
4487         char *name=NULL;
4488
4489         offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where", &hash, &name);
4490         offset = dissect_createmode3(tvb, offset, tree, &mode);
4491         switch (mode) {
4492                 case UNCHECKED:
4493                 case GUARDED:
4494                         offset = dissect_sattr3(tvb, offset, tree, "obj_attributes");
4495                 break;
4496                 case EXCLUSIVE:
4497                         offset = dissect_createverf3(tvb, offset, tree);
4498                 break;
4499         }
4500
4501         if (check_col(pinfo->cinfo, COL_INFO)) {
4502                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
4503         }
4504         proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
4505         g_free(name);
4506
4507         return offset;
4508 }
4509
4510
4511 /* RFC 1813, Page 54..58 */
4512 static int
4513 dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4514         proto_tree* tree)
4515 {
4516         guint32 status;
4517         char *err;
4518
4519         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4520         switch (status) {
4521                 case 0:
4522                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
4523                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4524                                 "obj_attributes");
4525                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4526                         proto_item_append_text(tree, ", CREATE Reply");
4527                 break;
4528                 default:
4529                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4530
4531                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4532                         if (check_col(pinfo->cinfo, COL_INFO)) {
4533                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4534                         }
4535                         proto_item_append_text(tree, ", CREATE Reply  Error:%s", err);
4536                 break;
4537         }
4538
4539         return offset;
4540 }
4541
4542
4543 /* RFC 1813, Page 58..60 */
4544 static int
4545 dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4546         proto_tree* tree)
4547 {
4548         guint32 hash;
4549         char *name=NULL;
4550
4551         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
4552         offset = dissect_sattr3    (tvb, offset, tree, "attributes");
4553
4554         if (check_col(pinfo->cinfo, COL_INFO)) {
4555                 col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
4556         }
4557         proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
4558         g_free(name);
4559
4560         return offset;
4561 }
4562
4563 static int
4564 dissect_nfs3_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4565         proto_tree* tree)
4566 {
4567         guint32 status;
4568         char *err;
4569
4570         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4571         switch (status) {
4572                 case 0:
4573                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
4574                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4575                                 "obj_attributes");
4576                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4577                         proto_item_append_text(tree, ", MKDIR Reply");
4578                 break;
4579                 default:
4580                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4581
4582                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4583                         if (check_col(pinfo->cinfo, COL_INFO)) {
4584                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4585                         }
4586                         proto_item_append_text(tree, ", MKDIR Reply  Error:%s", err);
4587                 break;
4588         }
4589
4590         return offset;
4591 }
4592
4593
4594 /* RFC 1813, Page 61..63 */
4595 static int
4596 dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4597         proto_tree* tree)
4598 {
4599         guint32 from_hash;
4600         char *from_name=NULL;
4601         char *to_name=NULL;
4602
4603         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &from_hash, &from_name);
4604         offset = dissect_sattr3    (tvb, offset,        tree, "symlink_attributes");
4605         offset = dissect_nfspath3  (tvb, offset,        tree, hf_nfs_symlink_to, &to_name);
4606
4607         if (check_col(pinfo->cinfo, COL_INFO)) {
4608                 col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
4609         }
4610         proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
4611         g_free(from_name);
4612         g_free(to_name);
4613
4614         return offset;
4615 }
4616 static int
4617 dissect_nfs3_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4618         proto_tree* tree)
4619 {
4620         guint32 status;
4621         char *err;
4622
4623         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4624         switch (status) {
4625                 case 0:
4626                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
4627                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4628                                 "obj_attributes");
4629                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4630                         proto_item_append_text(tree, ", SYMLINK Reply");
4631                 break;
4632                 default:
4633                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4634
4635                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4636                         if (check_col(pinfo->cinfo, COL_INFO)) {
4637                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4638                         }
4639                         proto_item_append_text(tree, ", SYMLINK Reply  Error:%s", err);
4640                 break;
4641         }
4642
4643         return offset;
4644 }
4645
4646
4647 /* RFC 1813, Page 63..66 */
4648 static int
4649 dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4650         proto_tree* tree)
4651 {
4652         guint32 type;
4653         guint32 hash;
4654         char *name=NULL;
4655         char *type_str;
4656
4657         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
4658         offset = dissect_ftype3(tvb, offset, tree, hf_nfs_ftype3, &type);
4659         switch (type) {
4660                 case NF3CHR:
4661                 case NF3BLK:
4662                         offset = dissect_sattr3(tvb, offset, tree, "dev_attributes");
4663                         offset = dissect_specdata3(tvb, offset, tree, "spec");
4664                 break;
4665                 case NF3SOCK:
4666                 case NF3FIFO:
4667                         offset = dissect_sattr3(tvb, offset, tree, "pipe_attributes");
4668                 break;
4669                 default:
4670                         /* nothing to do */
4671                 break;
4672         }
4673
4674         type_str=val_to_str(type, names_nfs_ftype3, "Unknown type:%u");
4675         if (check_col(pinfo->cinfo, COL_INFO)) {
4676                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x/%s %s", hash, name, type_str);
4677         }
4678         proto_item_append_text(tree, ", MKNOD Call FH:0x%08x/%s %s", hash, name, type_str);
4679         g_free(name);
4680
4681         return offset;
4682 }
4683 static int
4684 dissect_nfs3_mknod_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4685         proto_tree* tree)
4686 {
4687         guint32 status;
4688         char *err;
4689
4690         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4691         switch (status) {
4692                 case 0:
4693                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
4694                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4695                                 "obj_attributes");
4696                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4697                         proto_item_append_text(tree, ", MKNOD Reply");
4698                 break;
4699                 default:
4700                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4701
4702                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4703                         if (check_col(pinfo->cinfo, COL_INFO)) {
4704                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4705                         }
4706                         proto_item_append_text(tree, ", MKNOD Reply  Error:%s", err);
4707                 break;
4708         }
4709
4710         return offset;
4711 }
4712
4713
4714 /* RFC 1813, Page 67..69 */
4715 static int
4716 dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4717         proto_tree* tree)
4718 {
4719         guint32 status;
4720         char *err;
4721
4722         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4723         switch (status) {
4724                 case 0:
4725                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4726                         proto_item_append_text(tree, ", REMOVE Reply");
4727                 break;
4728                 default:
4729                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4730                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4731                         if (check_col(pinfo->cinfo, COL_INFO)) {
4732                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4733                         }
4734                         proto_item_append_text(tree, ", REMOVE Reply  Error:%s", err);
4735                 break;
4736         }
4737
4738         return offset;
4739 }
4740 static int
4741 dissect_nfs3_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4742         proto_tree* tree)
4743 {
4744         guint32 status;
4745         char *err;
4746
4747         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4748         switch (status) {
4749                 case 0:
4750                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4751                         proto_item_append_text(tree, ", RMDIR Reply");
4752                 break;
4753                 default:
4754                         offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
4755                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4756                         if (check_col(pinfo->cinfo, COL_INFO)) {
4757                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4758                         }
4759                         proto_item_append_text(tree, ", RMDIR Reply  Error:%s", err);
4760                 break;
4761         }
4762
4763         return offset;
4764 }
4765
4766
4767 /* RFC 1813, Page 71..74 */
4768 static int
4769 dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4770         proto_tree* tree)
4771 {
4772         guint32 from_hash;
4773         char *from_name=NULL;
4774         guint32 to_hash;
4775         char *to_name=NULL;
4776
4777         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
4778         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
4779
4780         if (check_col(pinfo->cinfo, COL_INFO)) {
4781                 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);
4782         }
4783         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);
4784
4785         g_free(from_name);
4786         g_free(to_name);
4787         return offset;
4788 }
4789
4790
4791 /* RFC 1813, Page 71..74 */
4792 static int
4793 dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4794         proto_tree* tree)
4795 {
4796         guint32 status;
4797         char *err;
4798
4799         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4800         switch (status) {
4801                 case 0:
4802                         offset = dissect_wcc_data(tvb, offset, tree, "fromdir_wcc");
4803                         offset = dissect_wcc_data(tvb, offset, tree, "todir_wcc");
4804                         proto_item_append_text(tree, ", RENAME Reply");
4805                 break;
4806                 default:
4807                         offset = dissect_wcc_data(tvb, offset, tree, "fromdir_wcc");
4808                         offset = dissect_wcc_data(tvb, offset, tree, "todir_wcc");
4809
4810                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4811                         if (check_col(pinfo->cinfo, COL_INFO)) {
4812                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4813                         }
4814                         proto_item_append_text(tree, ", RENAME Reply  Error:%s", err);
4815                 break;
4816         }
4817
4818         return offset;
4819 }
4820
4821
4822 /* RFC 1813, Page 74..76 */
4823 static int
4824 dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4825         proto_tree* tree)
4826 {
4827         guint32 from_hash;
4828         guint32 to_hash;
4829         char *to_name=NULL;
4830
4831         offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file", &from_hash);
4832         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link", &to_hash, &to_name);
4833
4834         if (check_col(pinfo->cinfo, COL_INFO)) {
4835                 col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
4836         }
4837         proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
4838
4839         g_free(to_name);
4840         return offset;
4841 }
4842
4843
4844 /* RFC 1813, Page 74..76 */
4845 static int
4846 dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4847         proto_tree* tree)
4848 {
4849         guint32 status;
4850         char *err;
4851
4852         offset = dissect_nfsstat3(tvb, offset, tree, &status);
4853         switch (status) {
4854                 case 0:
4855                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4856                                 "file_attributes");
4857                         offset = dissect_wcc_data(tvb, offset, tree, "linkdir_wcc");
4858                         proto_item_append_text(tree, ", LINK Reply");
4859                 break;
4860                 default:
4861                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4862                                 "file_attributes");
4863                         offset = dissect_wcc_data(tvb, offset, tree, "linkdir_wcc");
4864
4865                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4866                         if (check_col(pinfo->cinfo, COL_INFO)) {
4867                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4868                         }
4869                         proto_item_append_text(tree, ", LINK Reply  Error:%s", err);
4870                 break;
4871         }
4872
4873         return offset;
4874 }
4875
4876
4877 /* RFC 1813, Page 76..80 */
4878 static int
4879 dissect_nfs3_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4880         proto_tree* tree)
4881 {
4882         guint32 hash;
4883
4884         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir", &hash);
4885         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
4886         offset = dissect_cookieverf3(tvb, offset, tree);
4887         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
4888
4889         if (check_col(pinfo->cinfo, COL_INFO)) {
4890                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4891         }
4892         proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
4893
4894         return offset;
4895 }
4896
4897
4898 /* RFC 1813, Page 76..80 */
4899 static int
4900 dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
4901         proto_tree* tree)
4902 {
4903         proto_item* entry_item = NULL;
4904         proto_tree* entry_tree = NULL;
4905         int old_offset = offset;
4906         char *name=NULL;
4907
4908         if (tree) {
4909                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
4910                         offset+0, -1, FALSE);
4911                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
4912         }
4913
4914         offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdir_entry3_fileid,
4915                 offset);
4916
4917         offset = dissect_filename3(tvb, offset, entry_tree,
4918                 hf_nfs_readdir_entry3_name, &name);
4919         if (entry_item)
4920                 proto_item_set_text(entry_item, "Entry: name %s", name);
4921
4922         if (check_col(pinfo->cinfo, COL_INFO)) {
4923                 col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
4924         }
4925         g_free(name);
4926
4927         offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdir_entry3_cookie,
4928                 offset);
4929
4930         /* now we know, that a readdir entry is shorter */
4931         if (entry_item) {
4932                 proto_item_set_len(entry_item, offset - old_offset);
4933         }
4934
4935         return offset;
4936 }
4937
4938
4939 /* RFC 1813, Page 76..80 */
4940 static int
4941 dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4942         proto_tree* tree)
4943 {
4944         guint32 status;
4945         guint32 eof_value;
4946         char *err;
4947
4948         offset = dissect_stat(tvb, offset, tree, &status);
4949         switch (status) {
4950                 case 0:
4951                         proto_item_append_text(tree, ", READDIR Reply");
4952
4953                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4954                                 "dir_attributes");
4955                         offset = dissect_cookieverf3(tvb, offset, tree);
4956                         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
4957                                 dissect_entry3);
4958                         eof_value = tvb_get_ntohl(tvb, offset+0);
4959                         if (tree)
4960                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
4961                                         offset+ 0, 4, eof_value);
4962                         offset += 4;
4963                 break;
4964                 default:
4965                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
4966                                 "dir_attributes");
4967
4968                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
4969                         if (check_col(pinfo->cinfo, COL_INFO)) {
4970                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
4971                         }
4972                         proto_item_append_text(tree, ", READDIR Reply  Error:%s", err);
4973                 break;
4974         }
4975
4976         return offset;
4977 }
4978
4979
4980 /* RFC 1813, Page 80..83 */
4981 static int
4982 dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
4983         proto_tree* tree)
4984 {
4985         guint32 hash;
4986
4987         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir", &hash);
4988         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
4989         offset = dissect_cookieverf3(tvb, offset, tree);
4990         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_dircount,
4991                 offset);
4992         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_maxcount,
4993                 offset);
4994
4995         if (check_col(pinfo->cinfo, COL_INFO)) {
4996                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
4997         }
4998         proto_item_append_text(tree, ", READDIRPLUS Call FH:0x%08x", hash);
4999
5000         return offset;
5001 }
5002
5003
5004 /* RFC 1813, Page 80..83 */
5005 static int
5006 dissect_entryplus3(tvbuff_t *tvb, int offset, packet_info *pinfo,
5007         proto_tree* tree)
5008 {
5009         proto_item* entry_item = NULL;
5010         proto_tree* entry_tree = NULL;
5011         int old_offset = offset;
5012         char *name=NULL;
5013
5014         if (tree) {
5015                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
5016                         offset+0, -1, FALSE);
5017                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
5018         }
5019
5020         offset = dissect_rpc_uint64(tvb, entry_tree,
5021                 hf_nfs_readdirplus_entry_fileid, offset);
5022
5023         offset = dissect_filename3(tvb, offset, entry_tree,
5024                 hf_nfs_readdirplus_entry_name, &name);
5025         if (entry_item)
5026                 proto_item_set_text(entry_item, "Entry: name %s", name);
5027
5028         if (check_col(pinfo->cinfo, COL_INFO)) {
5029                 col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
5030         }
5031         g_free(name);
5032
5033         offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdirplus_entry_cookie,
5034                 offset);
5035
5036         offset = dissect_nfs_post_op_attr(tvb, offset, entry_tree,
5037                 "name_attributes");
5038         offset = dissect_post_op_fh3(tvb, offset, pinfo, entry_tree, "name_handle");
5039
5040         /* now we know, that a readdirplus entry is shorter */
5041         if (entry_item) {
5042                 proto_item_set_len(entry_item, offset - old_offset);
5043         }
5044
5045         return offset;
5046 }
5047
5048
5049 /* RFC 1813, Page 80..83 */
5050 static int
5051 dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
5052         proto_tree* tree)
5053 {
5054         guint32 status;
5055         guint32 eof_value;
5056         char *err;
5057
5058         offset = dissect_stat(tvb, offset, tree, &status);
5059         switch (status) {
5060                 case 0:
5061                         proto_item_append_text(tree, ", READDIRPLUS Reply");
5062
5063                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5064                                 "dir_attributes");
5065                         offset = dissect_cookieverf3(tvb, offset, tree);
5066                         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
5067                                 dissect_entryplus3);
5068                         eof_value = tvb_get_ntohl(tvb, offset+0);
5069                         if (tree)
5070                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
5071                                         offset+ 0, 4, eof_value);
5072                         offset += 4;
5073                 break;
5074                 default:
5075                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5076                                 "dir_attributes");
5077
5078                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
5079                         if (check_col(pinfo->cinfo, COL_INFO)) {
5080                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5081                         }
5082                         proto_item_append_text(tree, ", READDIRPLUS Reply  Error:%s", err);
5083                 break;
5084         }
5085
5086         return offset;
5087 }
5088
5089
5090 /* RFC 1813, Page 84..86 */
5091 static int
5092 dissect_nfs3_fsstat_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5093         proto_tree* tree)
5094 {
5095         guint32 hash;
5096
5097         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
5098
5099         if (check_col(pinfo->cinfo, COL_INFO)) {
5100                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5101         }
5102         proto_item_append_text(tree, ", FSSTAT Call DH:0x%08x", hash);
5103         return offset;
5104 }
5105
5106
5107 static int
5108 dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5109         proto_tree* tree)
5110 {
5111         guint32 status;
5112         guint32 invarsec;
5113         char *err;
5114
5115         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5116         switch (status) {
5117                 case 0:
5118                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5119                                 "obj_attributes");
5120                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_tbytes,
5121                                 offset);
5122                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_fbytes,
5123                                 offset);
5124                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_abytes,
5125                                 offset);
5126                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_tfiles,
5127                                 offset);
5128                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_ffiles,
5129                                 offset);
5130                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_afiles,
5131                                 offset);
5132                         invarsec = tvb_get_ntohl(tvb, offset + 0);
5133                         if (tree)
5134                                 proto_tree_add_uint(tree, hf_nfs_fsstat_invarsec, tvb,
5135                                 offset+0, 4, invarsec);
5136                         offset += 4;
5137
5138                         proto_item_append_text(tree, ", FSSTAT Reply");
5139                 break;
5140                 default:
5141                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5142                                 "obj_attributes");
5143
5144                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
5145                         if (check_col(pinfo->cinfo, COL_INFO)) {
5146                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5147                         }
5148                         proto_item_append_text(tree, ", FSSTAT Reply  Error:%s", err);
5149                 break;
5150         }
5151
5152         return offset;
5153 }
5154
5155
5156 #define FSF3_LINK        0x0001
5157 #define FSF3_SYMLINK     0x0002
5158 #define FSF3_HOMOGENEOUS 0x0008
5159 #define FSF3_CANSETTIME  0x0010
5160
5161
5162 /* RFC 1813, Page 86..90 */
5163 static int
5164 dissect_nfs3_fsinfo_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5165         proto_tree* tree)
5166 {
5167         guint32 hash;
5168
5169         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
5170
5171         if (check_col(pinfo->cinfo, COL_INFO)) {
5172                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5173         }
5174         proto_item_append_text(tree, ", FSINFO Call DH:0x%08x", hash);
5175         return offset;
5176 }
5177 static int
5178 dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5179         proto_tree* tree)
5180 {
5181         guint32 status;
5182         guint32 rtmax;
5183         guint32 rtpref;
5184         guint32 rtmult;
5185         guint32 wtmax;
5186         guint32 wtpref;
5187         guint32 wtmult;
5188         guint32 dtpref;
5189         guint32 properties;
5190         proto_item*     properties_item = NULL;
5191         proto_tree*     properties_tree = NULL;
5192         char *err;
5193
5194         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5195         switch (status) {
5196                 case 0:
5197                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5198                                 "obj_attributes");
5199                         rtmax = tvb_get_ntohl(tvb, offset+0);
5200                         if (tree)
5201                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmax, tvb,
5202                                 offset+0, 4, rtmax);
5203                         offset += 4;
5204                         rtpref = tvb_get_ntohl(tvb, offset+0);
5205                         if (tree)
5206                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtpref, tvb,
5207                                 offset+0, 4, rtpref);
5208                         offset += 4;
5209                         rtmult = tvb_get_ntohl(tvb, offset+0);
5210                         if (tree)
5211                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmult, tvb,
5212                                 offset+0, 4, rtmult);
5213                         offset += 4;
5214                         wtmax = tvb_get_ntohl(tvb, offset+0);
5215                         if (tree)
5216                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmax, tvb,
5217                                 offset+0, 4, wtmax);
5218                         offset += 4;
5219                         wtpref = tvb_get_ntohl(tvb, offset+0);
5220                         if (tree)
5221                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtpref, tvb,
5222                                 offset+0, 4, wtpref);
5223                         offset += 4;
5224                         wtmult = tvb_get_ntohl(tvb, offset+0);
5225                         if (tree)
5226                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmult, tvb,
5227                                 offset+0, 4, wtmult);
5228                         offset += 4;
5229                         dtpref = tvb_get_ntohl(tvb, offset+0);
5230                         if (tree)
5231                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_dtpref, tvb,
5232                                 offset+0, 4, dtpref);
5233                         offset += 4;
5234
5235                         offset = dissect_rpc_uint64(tvb, tree,
5236                                 hf_nfs_fsinfo_maxfilesize, offset);
5237                         offset = dissect_nfstime3(tvb, offset, tree, hf_nfs_dtime, hf_nfs_dtime_sec, hf_nfs_dtime_nsec);
5238                         properties = tvb_get_ntohl(tvb, offset+0);
5239                         if (tree) {
5240                                 properties_item = proto_tree_add_uint(tree,
5241                                 hf_nfs_fsinfo_properties,
5242                                 tvb, offset+0, 4, properties);
5243                                 if (properties_item)
5244                                         properties_tree = proto_item_add_subtree(properties_item,
5245                                                 ett_nfs_fsinfo_properties);
5246                                 if (properties_tree) {
5247                                         proto_tree_add_text(properties_tree, tvb,
5248                                         offset, 4, "%s",
5249                                         decode_boolean_bitfield(properties,
5250                                         FSF3_CANSETTIME,5,
5251                                         "SETATTR can set time on server",
5252                                         "SETATTR can't set time on server"));
5253
5254                                         proto_tree_add_text(properties_tree, tvb,
5255                                         offset, 4, "%s",
5256                                         decode_boolean_bitfield(properties,
5257                                         FSF3_HOMOGENEOUS,5,
5258                                         "PATHCONF is valid for all files",
5259                                         "PATHCONF should be get for every single file"));
5260
5261                                         proto_tree_add_text(properties_tree, tvb,
5262                                         offset, 4, "%s",
5263                                         decode_boolean_bitfield(properties,
5264                                         FSF3_SYMLINK,5,
5265                                         "File System supports symbolic links",
5266                                         "File System does not symbolic hard links"));
5267
5268                                         proto_tree_add_text(properties_tree, tvb,
5269                                         offset, 4, "%s",
5270                                         decode_boolean_bitfield(properties,
5271                                         FSF3_LINK,5,
5272                                         "File System supports hard links",
5273                                         "File System does not support hard links"));
5274                                 }
5275                         }
5276                         offset += 4;
5277
5278                         proto_item_append_text(tree, ", FSINFO Reply");
5279                 break;
5280                 default:
5281                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5282                                 "obj_attributes");
5283
5284                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
5285                         if (check_col(pinfo->cinfo, COL_INFO)) {
5286                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5287                         }
5288                         proto_item_append_text(tree, ", FSINFO Reply  Error:%s", err);
5289                 break;
5290         }
5291
5292         return offset;
5293 }
5294
5295
5296 /* RFC 1813, Page 90..92 */
5297 static int
5298 dissect_nfs3_pathconf_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5299         proto_tree* tree)
5300 {
5301         guint32 hash;
5302
5303         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
5304
5305         if (check_col(pinfo->cinfo, COL_INFO)) {
5306                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5307         }
5308         proto_item_append_text(tree, ", PATHCONF Call DH:0x%08x", hash);
5309         return offset;
5310 }
5311 static int
5312 dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5313         proto_tree* tree)
5314 {
5315         guint32 status;
5316         guint32 linkmax;
5317         guint32 name_max;
5318         char *err;
5319
5320         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5321         switch (status) {
5322                 case 0:
5323                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5324                                 "obj_attributes");
5325                         linkmax = tvb_get_ntohl(tvb, offset + 0);
5326                         if (tree)
5327                                 proto_tree_add_uint(tree, hf_nfs_pathconf_linkmax, tvb,
5328                                 offset+0, 4, linkmax);
5329                         offset += 4;
5330                         name_max = tvb_get_ntohl(tvb, offset + 0);
5331                         if (tree)
5332                                 proto_tree_add_uint(tree, hf_nfs_pathconf_name_max, tvb,
5333                                 offset+0, 4, name_max);
5334                         offset += 4;
5335                         offset = dissect_rpc_bool(tvb, tree,
5336                                 hf_nfs_pathconf_no_trunc, offset);
5337                         offset = dissect_rpc_bool(tvb, tree,
5338                                 hf_nfs_pathconf_chown_restricted, offset);
5339                         offset = dissect_rpc_bool(tvb, tree,
5340                                 hf_nfs_pathconf_case_insensitive, offset);
5341                         offset = dissect_rpc_bool(tvb, tree,
5342                                 hf_nfs_pathconf_case_preserving, offset);
5343
5344                         proto_item_append_text(tree, ", PATHCONF Reply");
5345                 break;
5346                 default:
5347                         offset = dissect_nfs_post_op_attr(tvb, offset, tree,
5348                                 "obj_attributes");
5349
5350                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
5351                         if (check_col(pinfo->cinfo, COL_INFO)) {
5352                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5353                         }
5354                         proto_item_append_text(tree, ", PATHCONF Reply  Error:%s", err);
5355                 break;
5356         }
5357
5358         return offset;
5359 }
5360
5361
5362 /* RFC 1813, Page 92..95 */
5363 static int
5364 dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
5365         proto_tree* tree)
5366 {
5367         guint32 hash;
5368
5369         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
5370         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
5371         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
5372
5373         if (check_col(pinfo->cinfo, COL_INFO)) {
5374                 col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
5375         }
5376         proto_item_append_text(tree, ", COMMIT Call FH:0x%08x", hash);
5377
5378         return offset;
5379 }
5380
5381
5382 /* RFC 1813, Page 92..95 */
5383 static int
5384 dissect_nfs3_commit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5385         proto_tree* tree)
5386 {
5387         guint32 status;
5388         char *err;
5389
5390         offset = dissect_nfsstat3(tvb, offset, tree, &status);
5391         switch (status) {
5392                 case 0:
5393                         offset = dissect_wcc_data  (tvb, offset, tree, "file_wcc");
5394                         offset = dissect_writeverf3(tvb, offset, tree);
5395
5396                         proto_item_append_text(tree, ", COMMIT Reply");
5397                 break;
5398                 default:
5399                         offset = dissect_wcc_data(tvb, offset, tree, "file_wcc");
5400
5401                         err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
5402                         if (check_col(pinfo->cinfo, COL_INFO)) {
5403                                 col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
5404                         }
5405                         proto_item_append_text(tree, ", COMMIT Reply  Error:%s", err);
5406                 break;
5407         }
5408
5409         return offset;
5410 }
5411
5412 /**********************************************************/
5413 /* NFS Version 4, RFC 3010 with nfs4_prot.x 1.103 changes */
5414 /**********************************************************/
5415
5416 static int
5417 dissect_nfs_utf8string(tvbuff_t *tvb, int offset,
5418         proto_tree *tree, int hf, char **string_ret)
5419 {
5420         /* TODO: this dissector is subject to change; do not remove */
5421         return dissect_rpc_string(tvb, tree, hf, offset, string_ret);
5422 }
5423
5424 static int
5425 dissect_nfs_specdata4(tvbuff_t *tvb, int offset, proto_tree *tree)
5426 {
5427         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_specdata1, offset);
5428         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_specdata2, offset);
5429
5430         return offset;
5431 }
5432
5433 static const value_string names_ftype4[] = {
5434         {       NF4REG, "NF4REG"        },
5435         {       NF4DIR, "NF4DIR"        },
5436         {       NF4BLK, "NF4BLK"  },
5437         {       NF4CHR, "NF4CHR"  },
5438         {       NF4LNK,  "NF4LNK"  },
5439         {       NF4SOCK,        "NF4SOCK"  },
5440         {       NF4FIFO,        "NF4FIFO"  },
5441         {       NF4ATTRDIR,     "NF4ATTRDIR"    },
5442         {       NF4NAMEDATTR,   "NF4NAMEDATTR"  },
5443         { 0, NULL }
5444 };
5445
5446 static int
5447 dissect_nfs_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
5448 {
5449         proto_tree *newftree = NULL;
5450         proto_item *fitem = NULL;
5451
5452         fitem = proto_tree_add_text(tree, tvb, offset, 4, "Owner");
5453
5454         if (fitem)
5455         {
5456                 newftree = proto_item_add_subtree(fitem, ett_nfs_lock_owner4);
5457
5458                 if (newftree)
5459                 {
5460                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
5461                         offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
5462                 }
5463         }
5464
5465         return offset;
5466 }
5467
5468 static int
5469 dissect_nfs_pathname4(tvbuff_t *tvb, int offset, proto_tree *tree)
5470 {
5471         guint32 comp_count, i;
5472         proto_item *fitem = NULL;
5473         proto_tree *newftree = NULL;
5474
5475         comp_count=tvb_get_ntohl(tvb, offset);
5476         fitem = proto_tree_add_text(tree, tvb, offset, 4,
5477                 "pathname components (%u)", comp_count);
5478         offset += 4;
5479
5480         if (fitem)
5481         {
5482                 newftree = proto_item_add_subtree(fitem, ett_nfs_pathname4);
5483
5484                 if (newftree)
5485                 {
5486                         for (i = 0; i < comp_count; i++)
5487                                 offset = dissect_nfs_utf8string(tvb, offset, newftree,
5488                                         hf_nfs_component4, NULL);
5489                 }
5490         }
5491
5492         return offset;
5493 }
5494
5495 static int
5496 dissect_nfs_nfstime4(tvbuff_t *tvb, int offset, proto_tree *tree)
5497 {
5498         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_nfstime4_seconds, offset);
5499         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_nfstime4_nseconds, offset);
5500
5501         return offset;
5502 }
5503
5504 static const value_string names_time_how4[] = {
5505 #define SET_TO_SERVER_TIME4 0
5506         {       SET_TO_SERVER_TIME4,    "SET_TO_SERVER_TIME4"   },
5507 #define SET_TO_CLIENT_TIME4 1
5508         {       SET_TO_CLIENT_TIME4,    "SET_TO_CLIENT_TIME4"   },
5509         {       0,      NULL    },
5510 };
5511
5512 static int
5513 dissect_nfs_settime4(tvbuff_t *tvb, int offset,
5514         proto_tree *tree, char *name _U_)
5515 {
5516         guint32 set_it;
5517
5518         set_it = tvb_get_ntohl(tvb, offset);
5519         proto_tree_add_uint(tree, hf_nfs_time_how4, tvb, offset+0,
5520                 4, set_it);
5521         offset += 4;
5522
5523         if (set_it == SET_TO_CLIENT_TIME4)
5524                 offset = dissect_nfs_nfstime4(tvb, offset, tree);
5525
5526         return offset;
5527 }
5528
5529 static int
5530 dissect_nfs_fsid4(tvbuff_t *tvb, int offset, proto_tree *tree, char *name)
5531 {
5532         proto_tree *newftree = NULL;
5533         proto_item *fitem = NULL;
5534
5535         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
5536
5537         if (fitem == NULL) return offset;
5538
5539         newftree = proto_item_add_subtree(fitem, ett_nfs_fsid4);
5540
5541         if (newftree == NULL) return offset;
5542
5543         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_fsid4_major,
5544                 offset);
5545         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_fsid4_minor,
5546                 offset);
5547
5548         return offset;
5549 }
5550
5551 static const value_string names_acetype4[] = {
5552 #define ACE4_ACCESS_ALLOWED_ACE_TYPE    0x00000000
5553         {       ACE4_ACCESS_ALLOWED_ACE_TYPE, "ACE4_ACCESS_ALLOWED_ACE_TYPE"  },
5554 #define ACE4_ACCESS_DENIED_ACE_TYPE             0x00000001
5555         {       ACE4_ACCESS_DENIED_ACE_TYPE, "ACE4_ACCESS_DENIED_ACE_TYPE" },
5556 #define ACE4_SYSTEM_AUDIT_ACE_TYPE              0x00000002
5557         {       ACE4_SYSTEM_AUDIT_ACE_TYPE, "ACE4_SYSTEM_AUDIT_ACE_TYPE" },
5558 #define ACE4_SYSTEM_ALARM_ACE_TYPE              0x00000003
5559         {       ACE4_SYSTEM_ALARM_ACE_TYPE, "ACE4_SYSTEM_ALARM_ACE_TYPE"        },
5560         { 0, NULL }
5561 };
5562
5563 /* ACE mask values */
5564 #define ACE4_READ_DATA                          0x00000001
5565 #define ACE4_LIST_DIRECTORY             0x00000001
5566 #define ACE4_WRITE_DATA                         0x00000002
5567 #define ACE4_ADD_FILE                           0x00000002
5568 #define ACE4_APPEND_DATA                        0x00000004
5569 #define ACE4_ADD_SUBDIRECTORY           0x00000004
5570 #define ACE4_READ_NAMED_ATTRS           0x00000008
5571 #define ACE4_WRITE_NAMED_ATTRS  0x00000010
5572 #define ACE4_EXECUTE                                    0x00000020
5573 #define ACE4_DELETE_CHILD                       0x00000040
5574 #define ACE4_READ_ATTRIBUTES            0x00000080
5575 #define ACE4_WRITE_ATTRIBUTES           0x00000100
5576 #define ACE4_DELETE                                     0x00010000
5577 #define ACE4_READ_ACL                           0x00020000
5578 #define ACE4_WRITE_ACL                          0x00040000
5579 #define ACE4_WRITE_OWNER                        0x00080000
5580 #define ACE4_SYNCHRONIZE                        0x00100000
5581
5582 static int
5583 dissect_nfs_acemask4(tvbuff_t *tvb, int offset, proto_tree *tree)
5584 {
5585         guint32 acemask;
5586         proto_item *acemask_item = NULL;
5587         proto_tree *acemask_tree = NULL;
5588
5589         acemask = tvb_get_ntohl(tvb, offset);
5590
5591         acemask_item = proto_tree_add_text(tree, tvb, offset, 4,
5592                 "acemask: 0x%08x", acemask);
5593
5594         if (acemask_item)
5595                 acemask_tree = proto_item_add_subtree(acemask_item, ett_nfs_acemask4);
5596
5597         if (acemask_tree)
5598         {
5599                 if (acemask & ACE4_READ_DATA)
5600                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5601                                 "ACE4_READ_DATA/ACE4_LIST_DIRECTORY (0x%08x)",
5602                                 ACE4_READ_DATA);
5603
5604                 if (acemask & ACE4_WRITE_DATA)
5605                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5606                                 "ACE4_WRITE_DATA/ACE4_ADD_FILE (0x%08x)",
5607                                 ACE4_WRITE_DATA);
5608
5609                 if (acemask & ACE4_APPEND_DATA)
5610                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5611                                 "ACE4_ADD_FILE/ACE4_ADD_SUBDIRECTORY (0x%08x)",
5612                                 ACE4_APPEND_DATA);
5613
5614                 if (acemask & ACE4_READ_NAMED_ATTRS)
5615                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5616                                 "ACE4_READ_NAMED_ATTRS (0x%08x)",
5617                                 ACE4_READ_NAMED_ATTRS);
5618
5619                 if (acemask & ACE4_WRITE_NAMED_ATTRS)
5620                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5621                                 "ACE4_WRITE_NAMED_ATTRS (0x%08x)",
5622                                 ACE4_WRITE_NAMED_ATTRS);
5623
5624                 if (acemask & ACE4_EXECUTE)
5625                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5626                                 "ACE4_EXECUTE (0x%08x)",
5627                                 ACE4_EXECUTE);
5628
5629                 if (acemask & ACE4_DELETE_CHILD)
5630                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5631                                 "ACE4_DELETE_CHILD (0x%08x)",
5632                                 ACE4_DELETE_CHILD);
5633
5634                 if (acemask & ACE4_READ_ATTRIBUTES)
5635                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5636                                 "ACE4_READ_ATTRIBUTES (0x%08x)",
5637                                 ACE4_READ_ATTRIBUTES);
5638
5639                 if (acemask & ACE4_WRITE_ATTRIBUTES)
5640                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5641                                 "ACE4_WRITE_ATTRIBUTES (0x%08x)",
5642                                 ACE4_WRITE_ATTRIBUTES);
5643
5644                 if (acemask & ACE4_DELETE)
5645                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5646                                 "ACE4_DELETE (0x%08x)",
5647                                 ACE4_DELETE);
5648
5649                 if (acemask & ACE4_READ_ACL)
5650                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5651                                 "ACE4_READ_ACL (0x%08x)",
5652                                 ACE4_READ_ACL);
5653
5654                 if (acemask & ACE4_WRITE_ACL)
5655                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5656                                 "ACE4_WRITE_ACL (0x%08x)",
5657                                 ACE4_WRITE_ACL);
5658
5659                 if (acemask & ACE4_WRITE_OWNER)
5660                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5661                                 "ACE4_WRITE_OWNER (0x%08x)",
5662                                 ACE4_WRITE_OWNER);
5663
5664                 if (acemask & ACE4_SYNCHRONIZE)
5665                         proto_tree_add_text(acemask_tree, tvb, offset, 4,
5666                                 "ACE4_SYNCHRONIZE (0x%08x)",
5667                                 ACE4_SYNCHRONIZE);
5668         }
5669
5670         offset += 4;
5671
5672         return offset;
5673 }
5674
5675 /* ACE flag values */
5676 #define ACE4_FILE_INHERIT_ACE                                   0x00000001
5677 #define ACE4_DIRECTORY_INHERIT_ACE                      0x00000002
5678 #define ACE4_NO_PROPAGATE_INHERIT_ACE           0x00000004
5679 #define ACE4_INHERIT_ONLY_ACE                                   0x00000008
5680 #define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
5681 #define ACE4_FAILED_ACCESS_ACE_FLAG                     0x00000020
5682 #define ACE4_IDENTIFIER_GROUP                                   0x00000040
5683
5684
5685 static int
5686 dissect_nfs_ace4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5687         proto_tree *tree)
5688 {
5689         proto_item* ace_item = NULL;
5690         proto_tree* ace_tree = NULL;
5691         proto_item *aceflag_item = NULL;
5692         proto_tree *aceflag_tree = NULL;
5693         guint32 aceflag4;
5694
5695         if (tree) {
5696                 ace_item = proto_tree_add_text(tree, tvb, offset, 4,
5697                         "ACE");
5698
5699                 if (ace_item)
5700                         ace_tree = proto_item_add_subtree(ace_item, ett_nfs_ace4);
5701         }
5702
5703         if (ace_tree) {
5704                 offset = dissect_rpc_uint32(tvb, ace_tree, hf_nfs_acetype4, offset);
5705
5706                 aceflag4 = tvb_get_ntohl(tvb, offset);
5707
5708                 aceflag_item = proto_tree_add_text(ace_tree, tvb, offset, 4,
5709                         "aceflag: 0x%08x", aceflag4);
5710
5711                 if (aceflag_item)
5712                 {
5713                         aceflag_tree = proto_item_add_subtree(aceflag_item, ett_nfs_aceflag4);
5714
5715                         if (aceflag_tree)
5716                         {
5717                                 if (aceflag4 & ACE4_FILE_INHERIT_ACE)
5718                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
5719                                                 "ACE4_FILE_INHERIT_ACE (0x%08x)", ACE4_FILE_INHERIT_ACE);
5720
5721                                 if (aceflag4 & ACE4_DIRECTORY_INHERIT_ACE)
5722                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
5723                                                 "ACE4_DIRECTORY_INHERIT_ACE (0x%08x)",
5724                                                  ACE4_DIRECTORY_INHERIT_ACE);
5725
5726                                 if (aceflag4 & ACE4_INHERIT_ONLY_ACE)
5727                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
5728                                                 "ACE4_INHERIT_ONLY_ACE (0x%08x)",
5729                                                 ACE4_INHERIT_ONLY_ACE);
5730
5731                                 if (aceflag4 & ACE4_SUCCESSFUL_ACCESS_ACE_FLAG)
5732                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
5733                                                 "ACE4_SUCCESSFUL_ACCESS_ACE_FLAG (0x%08x)",
5734                                                 ACE4_SUCCESSFUL_ACCESS_ACE_FLAG);
5735
5736                                 if (aceflag4 & ACE4_FAILED_ACCESS_ACE_FLAG)
5737                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
5738                                                 "ACE4_FAILED_ACCESS_ACE_FLAG (0x%08x)",
5739                                                 ACE4_FAILED_ACCESS_ACE_FLAG);
5740
5741                                 if (aceflag4 & ACE4_IDENTIFIER_GROUP)
5742                                         proto_tree_add_text(aceflag_tree, tvb, offset, 4,
5743                                                 "ACE4_IDENTIFIER_GROUP (0x%08x)",
5744                                                 ACE4_IDENTIFIER_GROUP);
5745                         }
5746                 }
5747
5748                 offset += 4;
5749
5750                 offset = dissect_nfs_acemask4(tvb, offset, ace_tree);
5751
5752                 offset = dissect_nfs_utf8string(tvb, offset, ace_tree, hf_nfs_who, NULL);
5753         }
5754
5755         return offset;
5756 }
5757
5758 static int
5759 dissect_nfs_fattr4_acl(tvbuff_t *tvb, int offset, packet_info *pinfo,
5760         proto_tree *tree)
5761 {
5762         return dissect_rpc_array(tvb, pinfo, tree, offset, dissect_nfs_ace4,
5763                 hf_nfs_acl4);
5764 }
5765
5766 static int
5767 dissect_nfs_fh4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5768         proto_tree *tree, char *name)
5769 {
5770         return dissect_nfs_fh3(tvb, offset, pinfo, tree, name, NULL);
5771 }
5772
5773 static int
5774 dissect_nfs_fs_location4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5775         proto_tree *tree)
5776 {
5777         proto_tree *newftree = NULL;
5778         proto_item *fitem = NULL;
5779
5780         fitem = proto_tree_add_text(tree, tvb, offset, 0, "rootpath");
5781
5782         if (fitem == NULL) return offset;
5783
5784         newftree = proto_item_add_subtree(fitem, ett_nfs_fs_location4);
5785
5786         if (newftree == NULL) return offset;
5787
5788         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_server, NULL);
5789
5790         return offset;
5791 }
5792
5793 static int
5794 dissect_nfs_fs_locations4(tvbuff_t *tvb, packet_info *pinfo, int offset,
5795         proto_tree *tree, char *name)
5796 {
5797         proto_tree *newftree = NULL;
5798         proto_item *fitem = NULL;
5799
5800         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
5801
5802         if (fitem == NULL) return offset;
5803
5804         newftree = proto_item_add_subtree(fitem, ett_nfs_fs_locations4);
5805
5806         if (newftree == NULL) return offset;
5807
5808         offset = dissect_nfs_pathname4(tvb, offset, newftree);
5809
5810         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
5811                 dissect_nfs_fs_location4);
5812
5813         return offset;
5814 }
5815
5816 static int
5817 dissect_nfs_mode4(tvbuff_t *tvb, int offset,
5818         proto_tree *tree, char *name)
5819 {
5820         return dissect_mode(tvb, offset, tree, name);
5821 }
5822
5823 static const value_string nfs4_fattr4_fh_expire_type_names[] = {
5824 #define FH4_PERSISTENT 0x00000000
5825         {       FH4_PERSISTENT, "FH4_PERSISTENT"        },
5826 #define FH4_NOEXPIRE_WITH_OPEN 0x00000001
5827         {       FH4_NOEXPIRE_WITH_OPEN, "FH4_NOEXPIRE_WITH_OPEN"        },
5828 #define FH4_VOLATILE_ANY 0x00000002
5829         {       FH4_VOLATILE_ANY,       "FH4_VOLATILE_ANY"      },
5830 #define FH4_VOL_MIGRATION 0x00000004
5831         {       FH4_VOL_MIGRATION,      "FH4_VOL_MIGRATION"     },
5832 #define FH4_VOL_RENAME 0x00000008
5833         {       FH4_VOL_RENAME, "FH4_VOL_RENAME"        },
5834         {       0,      NULL    }
5835 };
5836
5837
5838 static int
5839 dissect_nfs_fattr4_fh_expire_type(tvbuff_t *tvb, int offset, proto_tree *tree)
5840 {
5841         guint32 expire_type;
5842         proto_item *expire_type_item = NULL;
5843         proto_tree *expire_type_tree = NULL;
5844
5845         expire_type = tvb_get_ntohl(tvb, offset + 0);
5846
5847         if (tree)
5848         {
5849                 expire_type_item = proto_tree_add_text(tree, tvb, offset, 4,
5850                         "fattr4_fh_expire_type: 0x%08x", expire_type);
5851                 if (expire_type_item)
5852                         expire_type_tree = proto_item_add_subtree(expire_type_item,
5853                                 ett_nfs_fattr4_fh_expire_type);
5854         }
5855
5856         if (expire_type_tree)
5857         {
5858                 if (expire_type == FH4_PERSISTENT)
5859                 {
5860                         proto_tree_add_text(expire_type_tree, tvb, offset, 4, "%s",
5861                                 decode_enumerated_bitfield(expire_type, FH4_PERSISTENT, 8,
5862                                 nfs4_fattr4_fh_expire_type_names, "%s"));
5863                 }
5864                 else
5865                 {
5866                         if (expire_type & FH4_NOEXPIRE_WITH_OPEN)
5867                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
5868                                                 "FH4_NOEXPIRE_WITH_OPEN (0x%08x)", FH4_NOEXPIRE_WITH_OPEN);
5869
5870                         if (expire_type & FH4_VOLATILE_ANY)
5871                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
5872                                                 "FH4_VOLATILE_ANY (0x%08x)", FH4_VOLATILE_ANY);
5873
5874                         if (expire_type & FH4_VOL_MIGRATION)
5875                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
5876                                                 "FH4_VOL_MIGRATION (0x%08x)", FH4_VOL_MIGRATION);
5877
5878                         if (expire_type & FH4_VOL_RENAME)
5879                                 proto_tree_add_text(expire_type_tree, tvb, offset, 4,
5880                                                 "FH4_VOL_RENAME (0x%08x)", FH4_VOL_RENAME);
5881                 }
5882         }
5883
5884         offset += 4;
5885
5886         return offset;
5887 }
5888
5889 static const value_string names_fattr4[] = {
5890 #define FATTR4_SUPPORTED_ATTRS     0
5891         {       FATTR4_SUPPORTED_ATTRS, "FATTR4_SUPPORTED_ATTRS"        },
5892 #define FATTR4_TYPE                1
5893         {       FATTR4_TYPE,    "FATTR4_TYPE"   },
5894 #define FATTR4_FH_EXPIRE_TYPE      2
5895         {       FATTR4_FH_EXPIRE_TYPE,  "FATTR4_FH_EXPIRE_TYPE" },
5896 #define FATTR4_CHANGE              3
5897         {       FATTR4_CHANGE,  "FATTR4_CHANGE" },
5898 #define FATTR4_SIZE                4
5899         {       FATTR4_SIZE,    "FATTR4_SIZE"   },
5900 #define FATTR4_LINK_SUPPORT        5
5901         {       FATTR4_LINK_SUPPORT,    "FATTR4_LINK_SUPPORT"   },
5902 #define FATTR4_SYMLINK_SUPPORT     6
5903         {       FATTR4_SYMLINK_SUPPORT, "FATTR4_SYMLINK_SUPPORT"        },
5904 #define FATTR4_NAMED_ATTR          7
5905         {       FATTR4_NAMED_ATTR,      "FATTR4_NAMED_ATTR"     },
5906 #define FATTR4_FSID                8
5907         {       FATTR4_FSID,    "FATTR4_FSID"   },
5908 #define FATTR4_UNIQUE_HANDLES      9
5909         {       FATTR4_UNIQUE_HANDLES,  "FATTR4_UNIQUE_HANDLES" },
5910 #define FATTR4_LEASE_TIME          10
5911         {       FATTR4_LEASE_TIME,      "FATTR4_LEASE_TIME"     },
5912 #define FATTR4_RDATTR_ERROR        11
5913         {       FATTR4_RDATTR_ERROR,    "FATTR4_RDATTR_ERROR"   },
5914 #define FATTR4_ACL                 12
5915         {       FATTR4_ACL,     "FATTR4_ACL"    },
5916 #define FATTR4_ACLSUPPORT          13
5917         {       FATTR4_ACLSUPPORT,      "FATTR4_ACLSUPPORT"     },
5918 #define FATTR4_ARCHIVE             14
5919         {       FATTR4_ARCHIVE, "FATTR4_ARCHIVE"        },
5920 #define FATTR4_CANSETTIME          15
5921         {       FATTR4_CANSETTIME, "FATTR4_CANSETTIME"  },
5922 #define FATTR4_CASE_INSENSITIVE    16
5923         {       FATTR4_CASE_INSENSITIVE, "FATTR4_CASE_INSENSITIVE"      },
5924 #define FATTR4_CASE_PRESERVING     17
5925         {       FATTR4_CASE_PRESERVING, "FATTR4_CASE_PRESERVING"        },
5926 #define FATTR4_CHOWN_RESTRICTED    18
5927         {       FATTR4_CHOWN_RESTRICTED, "FATTR4_CHOWN_RESTRICTED"      },
5928 #define FATTR4_FILEHANDLE          19
5929         {       FATTR4_FILEHANDLE, "FATTR4_FILEHANDLE"  },
5930 #define FATTR4_FILEID              20
5931         {       FATTR4_FILEID, "FATTR4_FILEID"  },
5932 #define FATTR4_FILES_AVAIL         21
5933         {       FATTR4_FILES_AVAIL, "FATTR4_FILES_AVAIL"        },
5934 #define FATTR4_FILES_FREE          22
5935         {       FATTR4_FILES_FREE, "FATTR4_FILES_FREE"  },
5936 #define FATTR4_FILES_TOTAL         23
5937         {       FATTR4_FILES_TOTAL, "FATTR4_FILES_TOTAL"        },
5938 #define FATTR4_FS_LOCATIONS        24
5939         {       FATTR4_FS_LOCATIONS, "FATTR4_FS_LOCATIONS"      },
5940 #define FATTR4_HIDDEN              25
5941         {       FATTR4_HIDDEN, "FATTR4_HIDDEN"  },
5942 #define FATTR4_HOMOGENEOUS         26
5943         {       FATTR4_HOMOGENEOUS, "FATTR4_HOMOGENEOUS"        },
5944 #define FATTR4_MAXFILESIZE         27
5945         {       FATTR4_MAXFILESIZE, "FATTR4_MAXFILESIZE"        },
5946 #define FATTR4_MAXLINK             28
5947         {       FATTR4_MAXLINK, "FATTR4_MAXLINK"        },
5948 #define FATTR4_MAXNAME             29
5949         {       FATTR4_MAXNAME, "FATTR4_MAXNAME"        },
5950 #define FATTR4_MAXREAD             30
5951         {       FATTR4_MAXREAD, "FATTR4_MAXREAD"        },
5952 #define FATTR4_MAXWRITE            31
5953         {       FATTR4_MAXWRITE, "FATTR4_MAXWRITE"      },
5954 #define FATTR4_MIMETYPE            32
5955         {       FATTR4_MIMETYPE, "FATTR4_MIMETYPE"      },
5956 #define FATTR4_MODE                33
5957         {       FATTR4_MODE, "FATTR4_MODE"      },
5958 #define FATTR4_NO_TRUNC            34
5959         {       FATTR4_NO_TRUNC, "FATTR4_NO_TRUNC"      },
5960 #define FATTR4_NUMLINKS            35
5961         {       FATTR4_NUMLINKS, "FATTR4_NUMLINKS"      },
5962 #define FATTR4_OWNER               36
5963         {       FATTR4_OWNER, "FATTR4_OWNER"    },
5964 #define FATTR4_OWNER_GROUP         37
5965         {       FATTR4_OWNER_GROUP, "FATTR4_OWNER_GROUP"        },
5966 #define FATTR4_QUOTA_AVAIL_HARD    38
5967         {       FATTR4_QUOTA_AVAIL_HARD, "FATTR4_QUOTA_AVAIL_HARD"      },
5968 #define FATTR4_QUOTA_AVAIL_SOFT    39
5969         {       FATTR4_QUOTA_AVAIL_SOFT, "FATTR4_QUOTA_AVAIL_SOFT"      },
5970 #define FATTR4_QUOTA_USED          40
5971         {       FATTR4_QUOTA_USED, "FATTR4_QUOTA_USED"  },
5972 #define FATTR4_RAWDEV              41
5973         {       FATTR4_RAWDEV, "FATTR4_RAWDEV"  },
5974 #define FATTR4_SPACE_AVAIL         42
5975         {       FATTR4_SPACE_AVAIL, "FATTR4_SPACE_AVAIL"        },
5976 #define FATTR4_SPACE_FREE          43
5977         {       FATTR4_SPACE_FREE, "FATTR4_SPACE_FREE"  },
5978 #define FATTR4_SPACE_TOTAL         44
5979         {       FATTR4_SPACE_TOTAL, "FATTR4_SPACE_TOTAL"        },
5980 #define FATTR4_SPACE_USED          45
5981         {       FATTR4_SPACE_USED, "FATTR4_SPACE_USED"  },
5982 #define FATTR4_SYSTEM              46
5983         {       FATTR4_SYSTEM, "FATTR4_SYSTEM"  },
5984 #define FATTR4_TIME_ACCESS         47
5985         {       FATTR4_TIME_ACCESS, "FATTR4_TIME_ACCESS"        },
5986 #define FATTR4_TIME_ACCESS_SET     48
5987         {       FATTR4_TIME_ACCESS_SET, "FATTR4_TIME_ACCESS_SET"        },
5988 #define FATTR4_TIME_BACKUP         49
5989         {       FATTR4_TIME_BACKUP, "FATTR4_TIME_BACKUP"        },
5990 #define FATTR4_TIME_CREATE         50
5991         {       FATTR4_TIME_CREATE, "FATTR4_TIME_CREATE"        },
5992 #define FATTR4_TIME_DELTA          51
5993         {       FATTR4_TIME_DELTA, "FATTR4_TIME_DELTA"  },
5994 #define FATTR4_TIME_METADATA       52
5995         {       FATTR4_TIME_METADATA, "FATTR4_TIME_METADATA"    },
5996 #define FATTR4_TIME_MODIFY         53
5997         {       FATTR4_TIME_MODIFY, "FATTR4_TIME_MODIFY"        },
5998 #define FATTR4_TIME_MODIFY_SET     54
5999         {       FATTR4_TIME_MODIFY_SET, "FATTR4_TIME_MODIFY_SET"        },
6000 #define FATTR4_MOUNTED_ON_FILEID   55
6001         {       FATTR4_MOUNTED_ON_FILEID, "FATTR4_MOUNTED_ON_FILEID"    },
6002         {       0,      NULL    }
6003 };
6004
6005 #define FATTR4_BITMAP_ONLY 0
6006 #define FATTR4_FULL_DISSECT 1
6007
6008 static int
6009 dissect_nfs_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo,
6010         proto_tree *tree, int type)
6011 {
6012         guint32 bitmap_len;
6013         proto_item *fitem = NULL;
6014         proto_tree *newftree = NULL;
6015         proto_item *attr_fitem = NULL;
6016         proto_tree *attr_newftree = NULL;
6017         guint32 i;
6018         gint j;
6019         guint32 fattr;
6020         guint32 *bitmap;
6021         guint32 sl;
6022         int attr_vals_offset;
6023
6024         bitmap_len = tvb_get_ntohl(tvb, offset);
6025         tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_len * 4);
6026         fitem = proto_tree_add_text(tree, tvb, offset, 4 + bitmap_len * 4,
6027                 "%s", "attrmask");
6028         offset += 4;
6029
6030         if (fitem == NULL) return offset;
6031
6032         newftree = proto_item_add_subtree(fitem, ett_nfs_bitmap4);
6033
6034         if (newftree == NULL) return offset;
6035
6036         attr_vals_offset = offset + 4 + bitmap_len * 4;
6037
6038         bitmap = g_malloc(bitmap_len * sizeof(guint32));
6039         if (bitmap == NULL) return offset;
6040
6041         for (i = 0; i < bitmap_len; i++)
6042         {
6043                 bitmap[i] = tvb_get_ntohl(tvb, offset);
6044
6045                 sl = 0x00000001;
6046
6047                 for (j = 0; j < 32; j++)
6048                 {
6049                         fattr = 32 * i + j;
6050
6051                         if (bitmap[i] & sl)
6052                         {
6053                                 /* switch label if attribute is recommended vs. mandatory */
6054                                 attr_fitem = proto_tree_add_uint(newftree,
6055                                         (fattr < FATTR4_ACL)? hf_nfs_mand_attr: hf_nfs_recc_attr,
6056                                         tvb, offset, 4, fattr);
6057
6058                                 if (attr_fitem == NULL) break;
6059
6060                                 attr_newftree = proto_item_add_subtree(attr_fitem, ett_nfs_bitmap4);
6061
6062                                 if (attr_newftree == NULL) break;
6063
6064                                 if (type == FATTR4_FULL_DISSECT)
6065                                 {
6066                                         /* do a full decode of the arguments for the set flag */
6067                                         switch(fattr)
6068                                         {
6069                                         case FATTR4_SUPPORTED_ATTRS:
6070                                                 attr_vals_offset = dissect_nfs_attributes(tvb,
6071                                                         attr_vals_offset, pinfo, attr_newftree,
6072                                                         FATTR4_BITMAP_ONLY);
6073                                                 break;
6074
6075                                         case FATTR4_TYPE:
6076                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
6077                                                         attr_newftree, hf_nfs_ftype4, attr_vals_offset);
6078                                                 break;
6079
6080                                         case FATTR4_FH_EXPIRE_TYPE:
6081                                                 attr_vals_offset = dissect_nfs_fattr4_fh_expire_type(tvb,
6082                                                         attr_vals_offset, attr_newftree);
6083                                                 break;
6084
6085                                         case FATTR4_CHANGE:
6086                                                 attr_vals_offset = dissect_rpc_uint64(tvb, attr_newftree,
6087                                                         hf_nfs_changeid4, attr_vals_offset);
6088                                                 break;
6089
6090                                         case FATTR4_SIZE:
6091                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6092                                                         attr_newftree, hf_nfs_fattr4_size, attr_vals_offset);
6093                                                 break;
6094
6095                                         case FATTR4_LINK_SUPPORT:
6096                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6097                                                         attr_newftree, hf_nfs_fattr4_link_support,
6098                                                         attr_vals_offset);
6099                                                 break;
6100
6101                                         case FATTR4_SYMLINK_SUPPORT:
6102                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6103                                                         attr_newftree, hf_nfs_fattr4_symlink_support,
6104                                                         attr_vals_offset);
6105                                                 break;
6106
6107                                         case FATTR4_NAMED_ATTR:
6108                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6109                                                         attr_newftree, hf_nfs_fattr4_named_attr, attr_vals_offset);
6110                                                 break;
6111
6112                                         case FATTR4_FSID:
6113                                                 attr_vals_offset = dissect_nfs_fsid4(tvb, attr_vals_offset,
6114                                                         attr_newftree, "fattr4_fsid");
6115                                                 break;
6116
6117                                         case FATTR4_UNIQUE_HANDLES:
6118                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6119                                                         attr_newftree, hf_nfs_fattr4_unique_handles,
6120                                                         attr_vals_offset);
6121                                                 break;
6122
6123                                         case FATTR4_LEASE_TIME:
6124                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
6125                                                         attr_newftree, hf_nfs_fattr4_lease_time,
6126                                                         attr_vals_offset);
6127                                                 break;
6128
6129                                         case FATTR4_RDATTR_ERROR:
6130                                                 attr_vals_offset = dissect_nfs_nfsstat4(tvb,
6131                                                         attr_vals_offset, attr_newftree, NULL);
6132                                                 break;
6133
6134                                         case FATTR4_ACL:
6135                                                 attr_vals_offset = dissect_nfs_fattr4_acl(tvb,
6136                                                         attr_vals_offset, pinfo, attr_newftree);
6137                                                 break;
6138
6139                                         case FATTR4_ACLSUPPORT:
6140                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
6141                                                         attr_newftree, hf_nfs_fattr4_aclsupport,
6142                                                         attr_vals_offset);
6143                                                 break;
6144
6145                                         case FATTR4_ARCHIVE:
6146                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6147                                                         attr_newftree, hf_nfs_fattr4_archive,
6148                                                         attr_vals_offset);
6149                                                 break;
6150
6151                                         case FATTR4_CANSETTIME:
6152                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6153                                                         attr_newftree, hf_nfs_fattr4_cansettime, attr_vals_offset);
6154                                                 break;
6155
6156                                         case FATTR4_CASE_INSENSITIVE:
6157                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6158                                                         attr_newftree, hf_nfs_fattr4_case_insensitive,
6159                                                         attr_vals_offset);
6160                                                 break;
6161
6162                                         case FATTR4_CASE_PRESERVING:
6163                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6164                                                         attr_newftree, hf_nfs_fattr4_case_preserving,
6165                                                         attr_vals_offset);
6166                                                 break;
6167
6168                                         case FATTR4_CHOWN_RESTRICTED:
6169                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6170                                                         attr_newftree, hf_nfs_fattr4_chown_restricted,
6171                                                         attr_vals_offset);
6172                                                 break;
6173
6174                                         case FATTR4_FILEID:
6175                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6176                                                         attr_newftree, hf_nfs_fattr4_fileid, attr_vals_offset);
6177                                                 break;
6178
6179                                         case FATTR4_FILES_AVAIL:
6180                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6181                                                         attr_newftree, hf_nfs_fattr4_files_avail,
6182                                                         attr_vals_offset);
6183                                                 break;
6184
6185                                         case FATTR4_FILEHANDLE:
6186                                                 attr_vals_offset = dissect_nfs_fh4(tvb, attr_vals_offset,
6187                                                         pinfo, attr_newftree, "fattr4_filehandle");
6188                                                 break;
6189
6190                                         case FATTR4_FILES_FREE:
6191                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6192                                                         attr_newftree, hf_nfs_fattr4_files_free, attr_vals_offset);
6193                                                 break;
6194
6195                                         case FATTR4_FILES_TOTAL:
6196                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6197                                                         attr_newftree, hf_nfs_fattr4_files_total,
6198                                                         attr_vals_offset);
6199                                                 break;
6200
6201                                         case FATTR4_FS_LOCATIONS:
6202                                                 attr_vals_offset = dissect_nfs_fs_locations4(tvb, pinfo,
6203                                                         attr_vals_offset, attr_newftree,
6204                                                         "fattr4_fs_locations");
6205                                                 break;
6206
6207                                         case FATTR4_HIDDEN:
6208                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6209                                                         attr_newftree, hf_nfs_fattr4_hidden, attr_vals_offset);
6210                                                 break;
6211
6212                                         case FATTR4_HOMOGENEOUS:
6213                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6214                                                         attr_newftree, hf_nfs_fattr4_homogeneous,
6215                                                         attr_vals_offset);
6216                                                 break;
6217
6218                                         case FATTR4_MAXFILESIZE:
6219                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6220                                                         attr_newftree, hf_nfs_fattr4_maxfilesize,
6221                                                         attr_vals_offset);
6222                                                 break;
6223
6224                                         case FATTR4_MAXLINK:
6225                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
6226                                                         attr_newftree, hf_nfs_fattr4_maxlink, attr_vals_offset);
6227                                                 break;
6228
6229                                         case FATTR4_MAXNAME:
6230                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
6231                                                         attr_newftree, hf_nfs_fattr4_maxname, attr_vals_offset);
6232                                                 break;
6233
6234                                         case FATTR4_MAXREAD:
6235                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6236                                                         attr_newftree, hf_nfs_fattr4_maxread, attr_vals_offset);
6237                                                 break;
6238
6239                                         case FATTR4_MAXWRITE:
6240                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6241                                                         attr_newftree, hf_nfs_fattr4_maxwrite, attr_vals_offset);
6242                                                 break;
6243
6244                                         case FATTR4_MIMETYPE:
6245                                                 attr_vals_offset = dissect_nfs_utf8string(tvb,
6246                                                         attr_vals_offset, attr_newftree,
6247                                                         hf_nfs_fattr4_mimetype, NULL);
6248                                                 break;
6249
6250                                         case FATTR4_MODE:
6251                                                 attr_vals_offset = dissect_nfs_mode4(tvb,
6252                                                         attr_vals_offset, attr_newftree, "fattr4_mode");
6253                                                 break;
6254
6255                                         case FATTR4_NO_TRUNC:
6256                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6257                                                         attr_newftree, hf_nfs_fattr4_no_trunc, attr_vals_offset);
6258                                                 break;
6259
6260                                         case FATTR4_NUMLINKS:
6261                                                 attr_vals_offset = dissect_rpc_uint32(tvb,
6262                                                         attr_newftree, hf_nfs_fattr4_numlinks, attr_vals_offset);
6263                                                 break;
6264
6265                                         case FATTR4_OWNER:
6266                                                 attr_vals_offset = dissect_nfs_utf8string(tvb,
6267                                                         attr_vals_offset, attr_newftree,
6268                                                         hf_nfs_fattr4_owner,
6269                                                         NULL);
6270                                                 break;
6271
6272                                         case FATTR4_OWNER_GROUP:
6273                                                 attr_vals_offset = dissect_nfs_utf8string(tvb,
6274                                                         attr_vals_offset, attr_newftree,
6275                                                         hf_nfs_fattr4_owner_group, NULL);
6276                                                 break;
6277
6278                                         case FATTR4_QUOTA_AVAIL_HARD:
6279                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6280                                                         attr_newftree, hf_nfs_fattr4_quota_hard, attr_vals_offset);
6281                                                 break;
6282
6283                                         case FATTR4_QUOTA_AVAIL_SOFT:
6284                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6285                                                         attr_newftree, hf_nfs_fattr4_quota_soft, attr_vals_offset);
6286                                                 break;
6287
6288                                         case FATTR4_QUOTA_USED:
6289                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6290                                                         attr_newftree, hf_nfs_fattr4_quota_used, attr_vals_offset);
6291                                                 break;
6292
6293                                         case FATTR4_RAWDEV:
6294                                                 attr_vals_offset = dissect_nfs_specdata4(tvb,
6295                                                         attr_vals_offset, attr_newftree);
6296                                                 break;
6297
6298                                         case FATTR4_SPACE_AVAIL:
6299                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6300                                                         attr_newftree, hf_nfs_fattr4_space_avail,
6301                                                         attr_vals_offset);
6302                                                 break;
6303
6304                                         case FATTR4_SPACE_FREE:
6305                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6306                                                         attr_newftree, hf_nfs_fattr4_space_free, attr_vals_offset);
6307                                                 break;
6308
6309                                         case FATTR4_SPACE_TOTAL:
6310                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6311                                                         attr_newftree, hf_nfs_fattr4_space_total,
6312                                                         attr_vals_offset);
6313                                                 break;
6314
6315                                         case FATTR4_SPACE_USED:
6316                                                 attr_vals_offset = dissect_rpc_uint64(tvb,
6317                                                         attr_newftree, hf_nfs_fattr4_space_used, attr_vals_offset);
6318                                                 break;
6319
6320                                         case FATTR4_SYSTEM:
6321                                                 attr_vals_offset = dissect_rpc_bool(tvb,
6322                                                         attr_newftree, hf_nfs_fattr4_system, attr_vals_offset);
6323                                                 break;
6324
6325                                         case FATTR4_TIME_ACCESS:
6326                                         case FATTR4_TIME_BACKUP:
6327                                         case FATTR4_TIME_CREATE:
6328                                         case FATTR4_TIME_DELTA:
6329                                         case FATTR4_TIME_METADATA:
6330                                         case FATTR4_TIME_MODIFY:
6331                                                 attr_vals_offset = dissect_nfs_nfstime4(tvb, attr_vals_offset,
6332                                                         attr_newftree);
6333                                                 break;
6334
6335                                         case FATTR4_TIME_ACCESS_SET:
6336                                         case FATTR4_TIME_MODIFY_SET:
6337                                                 attr_vals_offset = dissect_nfs_settime4(tvb,
6338                                                         attr_vals_offset, attr_newftree, "settime4");
6339                                                 break;
6340
6341                                         default:
6342                                                 break;
6343                                         }
6344                                 }
6345                         }
6346
6347                         sl <<= 1;
6348                 }
6349
6350                 offset += 4;
6351         }
6352
6353         g_free(bitmap);
6354
6355         return offset;
6356 }
6357
6358 static int
6359 dissect_nfs_fattr4(tvbuff_t *tvb, int offset, packet_info *pinfo,
6360         proto_tree *tree)
6361 {
6362         proto_tree *newftree = NULL;
6363         proto_item *fitem = NULL;
6364
6365         fitem = proto_tree_add_text(tree, tvb, offset, 4, "obj_attributes");
6366
6367         if (fitem == NULL) return offset;
6368
6369         newftree = proto_item_add_subtree(fitem, ett_nfs_fattr4);
6370
6371         if (newftree == NULL) return offset;
6372
6373         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
6374                 FATTR4_FULL_DISSECT);
6375
6376         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_attrlist4);
6377
6378         return offset;
6379 }
6380
6381 static const value_string names_open4_share_access[] = {
6382 #define OPEN4_SHARE_ACCESS_READ 0x00000001
6383         { OPEN4_SHARE_ACCESS_READ, "OPEN4_SHARE_ACCESS_READ" },
6384 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002
6385         { OPEN4_SHARE_ACCESS_WRITE, "OPEN4_SHARE_ACCESS_WRITE" },
6386 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003
6387         { OPEN4_SHARE_ACCESS_BOTH, "OPEN4_SHARE_ACCESS_BOTH" },
6388         { 0, NULL }
6389 };
6390
6391 static int
6392 dissect_nfs_open4_share_access(tvbuff_t *tvb, int offset,
6393         proto_tree *tree)
6394 {
6395         guint share_access;
6396
6397         share_access = tvb_get_ntohl(tvb, offset);
6398         proto_tree_add_uint(tree, hf_nfs_open4_share_access, tvb, offset, 4,
6399                 share_access);
6400         offset += 4;
6401
6402         return offset;
6403 }
6404
6405 static const value_string names_open4_share_deny[] = {
6406 #define OPEN4_SHARE_DENY_NONE 0x00000000
6407         { OPEN4_SHARE_DENY_NONE, "OPEN4_SHARE_DENY_NONE" },
6408 #define OPEN4_SHARE_DENY_READ 0x00000001
6409         { OPEN4_SHARE_DENY_READ, "OPEN4_SHARE_DENY_READ" },
6410 #define OPEN4_SHARE_DENY_WRITE 0x00000002
6411         { OPEN4_SHARE_DENY_WRITE, "OPEN4_SHARE_DENY_WRITE" },
6412 #define OPEN4_SHARE_DENY_BOTH 0x00000003
6413         { OPEN4_SHARE_DENY_BOTH, "OPEN4_SHARE_DENY_BOTH" },
6414         { 0, NULL }
6415 };
6416
6417 static int
6418 dissect_nfs_open4_share_deny(tvbuff_t *tvb, int offset,
6419         proto_tree *tree)
6420 {
6421         guint deny_access;
6422
6423         deny_access = tvb_get_ntohl(tvb, offset);
6424         proto_tree_add_uint(tree, hf_nfs_open4_share_deny, tvb, offset, 4,
6425                 deny_access);
6426         offset += 4;
6427
6428         return offset;
6429 }
6430
6431 static int
6432 dissect_nfs_open_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
6433 {
6434         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_clientid4, offset);
6435         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_open_owner4);
6436
6437         return offset;
6438 }
6439
6440 static int
6441 dissect_nfs_open_claim_delegate_cur4(tvbuff_t *tvb, int offset,
6442         proto_tree *tree)
6443 {
6444         offset = dissect_rpc_uint64(tvb, tree,
6445                 hf_nfs_stateid4_delegate_stateid, offset);
6446         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_component4, NULL);
6447
6448         return offset;
6449 }
6450
6451 #define CLAIM_NULL                              0
6452 #define CLAIM_PREVIOUS                  1
6453 #define CLAIM_DELEGATE_CUR              2
6454 #define CLAIM_DELEGATE_PREV     3
6455
6456 static const value_string names_claim_type4[] = {
6457         {       CLAIM_NULL,             "CLAIM_NULL"  },
6458         {       CLAIM_PREVIOUS,         "CLAIM_PREVIOUS" },
6459         {       CLAIM_DELEGATE_CUR,     "CLAIM_DELEGATE_CUR" },
6460         {       CLAIM_DELEGATE_PREV,    "CLAIM_DELEGATE_PREV" },
6461         {       0, NULL }
6462 };
6463
6464 static int
6465 dissect_nfs_open_claim4(tvbuff_t *tvb, int offset,
6466         proto_tree *tree)
6467 {
6468         guint open_claim_type4;
6469         proto_item *fitem = NULL;
6470         proto_tree *newftree = NULL;
6471
6472         open_claim_type4 = tvb_get_ntohl(tvb, offset);
6473         fitem = proto_tree_add_uint(tree, hf_nfs_open_claim_type4, tvb,
6474                 offset+0, 4, open_claim_type4);
6475         offset += 4;
6476
6477         if (fitem) {
6478                 newftree = proto_item_add_subtree(fitem, ett_nfs_open_claim4);
6479
6480                 if (newftree) {
6481
6482                         switch(open_claim_type4)
6483                         {
6484                         case CLAIM_NULL:
6485                                 offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
6486                                 break;
6487
6488                         case CLAIM_PREVIOUS:
6489                                 offset = dissect_rpc_uint32(tvb, newftree,
6490                                         hf_nfs_delegate_type, offset);
6491                                 break;
6492
6493                         case CLAIM_DELEGATE_CUR:
6494                                 offset = dissect_nfs_open_claim_delegate_cur4(tvb, offset,
6495                                         newftree);
6496                                 break;
6497
6498                         case CLAIM_DELEGATE_PREV:
6499                                 offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
6500                                 break;
6501
6502                         default:
6503                                 break;
6504                         }
6505                 }
6506         }
6507
6508         return offset;
6509 }
6510
6511 static int
6512 dissect_nfs_createhow4(tvbuff_t *tvb, int offset, packet_info *pinfo,
6513         proto_tree *tree)
6514 {
6515         guint mode;
6516
6517         /* This is intentional; we're using the same flags as NFSv3 */
6518         mode = tvb_get_ntohl(tvb, offset);
6519         proto_tree_add_uint(tree, hf_nfs_createmode3, tvb, offset, 4, mode);
6520         offset += 4;
6521
6522         switch(mode)
6523         {
6524         case UNCHECKED:         /* UNCHECKED4 */
6525         case GUARDED:           /* GUARDED4 */
6526                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree);
6527                 break;
6528
6529         case EXCLUSIVE:         /* EXCLUSIVE4 */
6530                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_verifier4, offset);
6531                 break;
6532
6533         default:
6534                 break;
6535         }
6536
6537         return offset;
6538 }
6539
6540 #define OPEN4_NOCREATE                          0
6541 #define OPEN4_CREATE                                    1
6542 static const value_string names_opentype4[] = {
6543         {       OPEN4_NOCREATE,  "OPEN4_NOCREATE"  },
6544         {       OPEN4_CREATE, "OPEN4_CREATE" },
6545         { 0, NULL }
6546 };
6547
6548 static int
6549 dissect_nfs_openflag4(tvbuff_t *tvb, int offset, packet_info *pinfo,
6550         proto_tree *tree)
6551 {
6552         guint opentype4;
6553         proto_item *fitem = NULL;
6554         proto_tree *newftree = NULL;
6555
6556         opentype4 = tvb_get_ntohl(tvb, offset);
6557         fitem = proto_tree_add_uint(tree, hf_nfs_opentype4, tvb,
6558                 offset+0, 4, opentype4);
6559         offset += 4;
6560
6561         if (fitem) {
6562                 newftree = proto_item_add_subtree(fitem, ett_nfs_opentype4);
6563
6564                 if (newftree) {
6565
6566                         switch(opentype4)
6567                         {
6568                         case OPEN4_CREATE:
6569                                 offset = dissect_nfs_createhow4(tvb, offset, pinfo, newftree);
6570                                 break;
6571
6572                         default:
6573                                 break;
6574                         }
6575                 }
6576         }
6577
6578         return offset;
6579 }
6580
6581 static int
6582 dissect_nfs_clientaddr4(tvbuff_t *tvb, int offset, proto_tree *tree)
6583 {
6584         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_r_netid);
6585         offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_r_addr);
6586
6587         return offset;
6588 }
6589
6590
6591 static int
6592 dissect_nfs_cb_client4(tvbuff_t *tvb, int offset, proto_tree *tree)
6593 {
6594         proto_tree *cb_location = NULL;
6595         proto_item *fitem = NULL;
6596
6597         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_cb_program, offset);
6598
6599         fitem = proto_tree_add_text(tree, tvb, offset, 0, "cb_location");
6600
6601         if (fitem)
6602         {
6603                 cb_location = proto_item_add_subtree(fitem, ett_nfs_clientaddr4);
6604
6605                 offset = dissect_nfs_clientaddr4(tvb, offset, cb_location);
6606         }
6607
6608         return offset;
6609 }
6610
6611 static const value_string names_stable_how4[] = {
6612 #define UNSTABLE4 0
6613         {       UNSTABLE4,      "UNSTABLE4"     },
6614 #define DATA_SYNC4 1
6615         {       DATA_SYNC4,     "DATA_SYNC4"    },
6616 #define FILE_SYNC4 2
6617         {       FILE_SYNC4,     "FILE_SYNC4"    },
6618         {       0,      NULL    }
6619 };
6620
6621 static int
6622 dissect_nfs_stable_how4(tvbuff_t *tvb, int offset,
6623         proto_tree *tree, char *name)
6624 {
6625         guint stable_how4;
6626
6627         stable_how4 = tvb_get_ntohl(tvb, offset);
6628         proto_tree_add_uint_format(tree, hf_nfs_stable_how4, tvb,
6629                         offset+0, 4, stable_how4, "%s: %s (%u)", name,
6630                         val_to_str(stable_how4, names_stable_how4, "%u"), stable_how4);
6631         offset += 4;
6632
6633         return offset;
6634 }
6635
6636 static const value_string names_nfsv4_operation[] = {
6637         {       NFS4_OP_ACCESS,                                 "ACCESS"        },
6638         {       NFS4_OP_CLOSE,                                          "CLOSE" },
6639         {       NFS4_OP_COMMIT,                                 "COMMIT"        },
6640         {       NFS4_OP_CREATE,                                 "CREATE"        },
6641         {       NFS4_OP_DELEGPURGE,                             "DELEGPURGE"    },
6642         {       NFS4_OP_DELEGRETURN,                            "DELEGRETURN"   },
6643         {       NFS4_OP_GETATTR,                                        "GETATTR"       },
6644         {       NFS4_OP_GETFH,                                          "GETFH" },
6645         {       NFS4_OP_LINK,                                           "LINK"  },
6646         {       NFS4_OP_LOCK,                                           "LOCK"  },
6647         {       NFS4_OP_LOCKT,                                          "LOCKT" },
6648         {       NFS4_OP_LOCKU,                                          "LOCKU" },
6649         {       NFS4_OP_LOOKUP,                                 "LOOKUP"        },
6650         {       NFS4_OP_LOOKUPP,                                        "LOOKUPP" },
6651         {       NFS4_OP_NVERIFY,                                        "NVERIFY"       },
6652         {       NFS4_OP_OPEN,                                           "OPEN"  },
6653         {       NFS4_OP_OPENATTR,                                       "OPENATTR"      },
6654         {       NFS4_OP_OPEN_CONFIRM,                   "OPEN_CONFIRM"  },
6655         {       NFS4_OP_OPEN_DOWNGRADE,                 "OPEN_DOWNGRADE"        },
6656         {       NFS4_OP_PUTFH,                                          "PUTFH" },
6657         {       NFS4_OP_PUTPUBFH,                                       "PUTPUBFH"      },
6658         {       NFS4_OP_PUTROOTFH,                              "PUTROOTFH"     },
6659         {       NFS4_OP_READ,                                           "READ"  },
6660         {       NFS4_OP_READDIR,                                        "READDIR"       },
6661         {       NFS4_OP_READLINK,                                       "READLINK"      },
6662         {       NFS4_OP_REMOVE,                                 "REMOVE"        },
6663         {       NFS4_OP_RENAME,                                 "RENAME"        },
6664         {       NFS4_OP_RENEW,                                          "RENEW" },
6665         {       NFS4_OP_RESTOREFH,                              "RESTOREFH"     },
6666         {       NFS4_OP_SAVEFH,                                 "SAVEFH"        },
6667         {       NFS4_OP_SECINFO,                                        "SECINFO"       },
6668         {       NFS4_OP_SETATTR,                                        "SETATTR"       },
6669         {       NFS4_OP_SETCLIENTID,                            "SETCLIENTID"   },
6670         {       NFS4_OP_SETCLIENTID_CONFIRM,    "SETCLIENTID_CONFIRM"   },
6671         {       NFS4_OP_VERIFY,                                 "VERIFY"        },
6672         {       NFS4_OP_WRITE,                                          "WRITE" },
6673         {       NFS4_OP_RELEASE_LOCKOWNER,              "RELEASE_LOCKOWNER"     },
6674         {       NFS4_OP_ILLEGAL,                                        "ILLEGAL"       },
6675         { 0, NULL }
6676 };
6677
6678 gint *nfsv4_operation_ett[] =
6679 {
6680          &ett_nfs_access4 ,
6681          &ett_nfs_close4 ,
6682          &ett_nfs_commit4 ,
6683          &ett_nfs_create4 ,
6684          &ett_nfs_delegpurge4 ,
6685          &ett_nfs_delegreturn4 ,
6686          &ett_nfs_getattr4 ,
6687          &ett_nfs_getfh4 ,
6688          &ett_nfs_link4 ,
6689          &ett_nfs_lock4 ,
6690          &ett_nfs_lockt4 ,
6691          &ett_nfs_locku4 ,
6692          &ett_nfs_lookup4 ,
6693          &ett_nfs_lookupp4 ,
6694          &ett_nfs_nverify4 ,
6695          &ett_nfs_open4 ,
6696          &ett_nfs_openattr4 ,
6697          &ett_nfs_open_confirm4 ,
6698          &ett_nfs_open_downgrade4 ,
6699          &ett_nfs_putfh4 ,
6700          &ett_nfs_putpubfh4 ,
6701          &ett_nfs_putrootfh4 ,
6702          &ett_nfs_read4 ,
6703          &ett_nfs_readdir4 ,
6704          &ett_nfs_readlink4 ,
6705          &ett_nfs_remove4 ,
6706          &ett_nfs_rename4 ,
6707          &ett_nfs_renew4 ,
6708          &ett_nfs_restorefh4 ,
6709          &ett_nfs_savefh4 ,
6710          &ett_nfs_secinfo4 ,
6711          &ett_nfs_setattr4 ,
6712          &ett_nfs_setclientid4 ,
6713          &ett_nfs_setclientid_confirm4 ,
6714          &ett_nfs_verify4 ,
6715          &ett_nfs_write4,
6716     &ett_nfs_release_lockowner4,
6717 };
6718
6719 static int
6720 dissect_nfs_entry4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
6721         proto_tree *tree)
6722 {
6723         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie4, offset);
6724         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_component4, NULL);
6725         offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree);
6726
6727         return offset;
6728 }
6729
6730 static int
6731 dissect_nfs_dirlist4(tvbuff_t *tvb, int offset, packet_info *pinfo,
6732         proto_tree *tree)
6733 {
6734         proto_tree *newftree = NULL;
6735
6736         newftree = proto_item_add_subtree(tree, ett_nfs_dirlist4);
6737         if (newftree==NULL) return offset;
6738
6739         offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_nfs_entry4);
6740         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_dirlist4_eof, offset);
6741
6742         return offset;
6743 }
6744
6745 static int
6746 dissect_nfs_change_info4(tvbuff_t *tvb, int offset,
6747         proto_tree *tree, char *name)
6748 {
6749         proto_tree *newftree = NULL;
6750         proto_tree *fitem = NULL;
6751
6752         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
6753
6754         if (fitem) {
6755                 newftree = proto_item_add_subtree(fitem, ett_nfs_change_info4);
6756
6757                 if (newftree) {
6758                         offset = dissect_rpc_bool(tvb, newftree,
6759                                 hf_nfs_change_info4_atomic, offset);
6760                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_changeid4_before,
6761                                 offset);
6762                         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_changeid4_after,
6763                                 offset);
6764                 }
6765         }
6766
6767         return offset;
6768 }
6769
6770 static const value_string names_nfs_lock_type4[] =
6771 {
6772 #define READ_LT 1
6773         {       READ_LT,                "READ_LT"                               },
6774 #define WRITE_LT 2
6775         {       WRITE_LT,               "WRITE_LT"                              },
6776 #define READW_LT 3
6777         {       READW_LT,       "READW_LT"      },
6778 #define WRITEW_LT 4
6779         {       WRITEW_LT,      "WRITEW_LT"     },
6780 #define RELEASE_STATE 5
6781         {       RELEASE_STATE,  "RELEASE_STATE" },
6782         {       0,      NULL    }
6783 };
6784
6785 static int
6786 dissect_nfs_lock4denied(tvbuff_t *tvb, int offset, proto_tree *tree)
6787 {
6788         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset4, offset);
6789         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_length4, offset);
6790         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_type4, offset);
6791         offset = dissect_nfs_lock_owner4(tvb, offset, tree);
6792
6793         return offset;
6794 }
6795
6796
6797 static const value_string names_open4_result_flags[] = {
6798 #define OPEN4_RESULT_MLOCK 0x00000001
6799         { OPEN4_RESULT_MLOCK, "OPEN4_RESULT_MLOCK" },
6800 #define OPEN4_RESULT_CONFIRM 0x00000002
6801         { OPEN4_RESULT_CONFIRM, "OPEN4_RESULT_CONFIRM" },
6802         { 0, NULL }
6803 };
6804
6805 static int
6806 dissect_nfs_open4_rflags(tvbuff_t *tvb, int offset,
6807         proto_tree *tree, char *name)
6808 {
6809         guint rflags;
6810         proto_item *rflags_item = NULL;
6811         proto_item *rflags_tree = NULL;
6812
6813         rflags = tvb_get_ntohl(tvb, offset);
6814
6815         if (tree)
6816         {
6817                 rflags_item = proto_tree_add_text(tree, tvb, offset, 4,
6818                         "%s: 0x%08x", name, rflags);
6819
6820                 if (rflags_item)
6821                 {
6822                         rflags_tree = proto_item_add_subtree(rflags_item,
6823                                 ett_nfs_open4_result_flags);
6824
6825                         if (rflags_tree)
6826                         {
6827                                 proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
6828                                         decode_enumerated_bitfield(rflags, OPEN4_RESULT_MLOCK, 2,
6829                                         names_open4_result_flags, "%s"));
6830
6831                                 proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
6832                                         decode_enumerated_bitfield(rflags, OPEN4_RESULT_CONFIRM, 2,
6833                                         names_open4_result_flags, "%s"));
6834                         }
6835                 }
6836         }
6837
6838         offset += 4;
6839
6840         return offset;
6841 }
6842
6843 static int
6844 dissect_nfs_stateid4(tvbuff_t *tvb, int offset,
6845                 proto_tree *tree)
6846 {
6847         proto_item *fitem = NULL;
6848         proto_tree *newftree = NULL;
6849         int sublen;
6850         int bytes_left;
6851         gboolean first_line;
6852
6853         fitem = proto_tree_add_text(tree, tvb, offset, 4, "stateid");
6854
6855         if (fitem) {
6856                 newftree = proto_item_add_subtree(fitem, ett_nfs_stateid4);
6857                 if (newftree) {
6858                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
6859                                 offset);
6860
6861                         bytes_left = 12;
6862                         first_line = TRUE;
6863
6864                         while (bytes_left != 0)
6865                         {
6866                                 sublen = 12;
6867                                 if (sublen > bytes_left)
6868                                         sublen = bytes_left;
6869
6870                                 proto_tree_add_text(newftree, tvb, offset, sublen, "%s%s",
6871                                         first_line ? "other: " : "      ",
6872                                         tvb_bytes_to_str(tvb, offset, sublen));
6873
6874                                 bytes_left -= sublen;
6875                                 offset += sublen;
6876                                 first_line = FALSE;
6877                         }
6878                 }
6879         }
6880
6881         return offset;
6882 }
6883
6884 static int
6885 dissect_nfs_open_read_delegation4(tvbuff_t *tvb, int offset,
6886         packet_info *pinfo, proto_tree *tree)
6887 {
6888         offset = dissect_nfs_stateid4(tvb, offset, tree);
6889         offset = dissect_rpc_bool(tvb, tree, hf_nfs_recall4, offset);
6890         offset = dissect_nfs_ace4(tvb, offset, pinfo, tree);
6891
6892         return offset;
6893 }
6894
6895 static int
6896 dissect_nfs_modified_limit4(tvbuff_t *tvb, int offset, proto_tree *tree)
6897 {
6898         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_num_blocks, offset);
6899         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_bytes_per_block, offset);
6900
6901         return offset;
6902 }
6903
6904 #define NFS_LIMIT_SIZE                                          1
6905 #define NFS_LIMIT_BLOCKS                                        2
6906 static const value_string names_limit_by4[] = {
6907         {       NFS_LIMIT_SIZE,  "NFS_LIMIT_SIZE"  },
6908         {       NFS_LIMIT_BLOCKS, "NFS_LIMIT_BLOCKS" },
6909         { 0, NULL }
6910 };
6911
6912 static int
6913 dissect_nfs_space_limit4(tvbuff_t *tvb, int offset,
6914         proto_tree *tree)
6915 {
6916         guint limitby;
6917
6918         limitby = tvb_get_ntohl(tvb, offset);
6919         proto_tree_add_uint(tree, hf_nfs_limit_by4, tvb, offset+0, 4, limitby);
6920         offset += 4;
6921
6922         switch(limitby)
6923         {
6924         case NFS_LIMIT_SIZE:
6925                 offset = dissect_rpc_uint64(tvb, tree, hf_nfs_filesize,
6926                         offset);
6927                 break;
6928
6929         case NFS_LIMIT_BLOCKS:
6930                 offset = dissect_nfs_modified_limit4(tvb, offset, tree);
6931                 break;
6932
6933         default:
6934                 break;
6935         }
6936
6937         return offset;
6938 }
6939
6940 static int
6941 dissect_nfs_open_write_delegation4(tvbuff_t *tvb, int offset,
6942         packet_info *pinfo, proto_tree *tree)
6943 {
6944         offset = dissect_nfs_stateid4(tvb, offset, tree);
6945         offset = dissect_rpc_bool(tvb, tree, hf_nfs_recall, offset);
6946         offset = dissect_nfs_space_limit4(tvb, offset, tree);
6947         offset = dissect_nfs_ace4(tvb, offset, pinfo, tree);
6948
6949         return offset;
6950 }
6951
6952 #define OPEN_DELEGATE_NONE 0
6953 #define OPEN_DELEGATE_READ 1
6954 #define OPEN_DELEGATE_WRITE 2
6955 static const value_string names_open_delegation_type4[] = {
6956         {       OPEN_DELEGATE_NONE,  "OPEN_DELEGATE_NONE"  },
6957         {       OPEN_DELEGATE_READ,     "OPEN_DELEGATE_READ" },
6958         {       OPEN_DELEGATE_WRITE,    "OPEN_DELEGATE_WRITE" },
6959         { 0, NULL }
6960 };
6961
6962 static int
6963 dissect_nfs_open_delegation4(tvbuff_t *tvb, int offset, packet_info *pinfo,
6964         proto_tree *tree)
6965 {
6966         guint delegation_type;
6967         proto_tree *newftree = NULL;
6968         proto_item *fitem = NULL;
6969
6970         delegation_type = tvb_get_ntohl(tvb, offset);
6971         proto_tree_add_uint(tree, hf_nfs_open_delegation_type4, tvb, offset+0,
6972                 4, delegation_type);
6973         offset += 4;
6974
6975         if (fitem) {
6976                 newftree = proto_item_add_subtree(fitem, ett_nfs_open_delegation4);
6977
6978                 switch(delegation_type)
6979                 {
6980                 case OPEN_DELEGATE_NONE:
6981                         break;
6982
6983                 case OPEN_DELEGATE_READ:
6984                         offset = dissect_nfs_open_read_delegation4(tvb, offset, pinfo,
6985                                 newftree);
6986                         break;
6987
6988                 case OPEN_DELEGATE_WRITE:
6989                         offset = dissect_nfs_open_write_delegation4(tvb, offset, pinfo,
6990                                 newftree);
6991                         break;
6992
6993                 default:
6994                         break;
6995                 }
6996         }
6997
6998         return offset;
6999 }
7000
7001 static int
7002 dissect_nfs_rpcsec_gss_info(tvbuff_t *tvb, int offset, proto_tree *tree)
7003 {
7004         offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
7005             hf_nfs_sec_oid4, FALSE, 0, FALSE, NULL, NULL);
7006         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_qop4, offset);
7007         offset = dissect_rpc_uint32(tvb, tree,
7008                 hf_nfs_secinfo_rpcsec_gss_info_service, offset);
7009
7010         return offset;
7011 }
7012
7013 static int
7014 dissect_nfs_open_to_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
7015 {
7016         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_seqid4, offset);
7017         offset = dissect_nfs_stateid4(tvb, offset, tree);
7018         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_seqid4, offset);
7019         offset = dissect_nfs_lock_owner4(tvb, offset, tree);
7020
7021         return offset;
7022 }
7023
7024 static int
7025 dissect_nfs_exist_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
7026 {
7027         offset = dissect_nfs_stateid4(tvb, offset, tree);
7028         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_seqid4, offset);
7029
7030         return offset;
7031 }
7032
7033 static int
7034 dissect_nfs_locker4(tvbuff_t *tvb, int offset, proto_tree *tree)
7035 {
7036         guint new_lock_owner;
7037
7038         new_lock_owner = tvb_get_ntohl(tvb, offset);
7039         offset = dissect_rpc_bool(tvb, tree, hf_nfs_new_lock_owner, offset);
7040
7041         if (new_lock_owner)
7042                 offset = dissect_nfs_open_to_lock_owner4(tvb, offset, tree);
7043         else
7044                 offset = dissect_nfs_exist_lock_owner4(tvb, offset, tree);
7045
7046         return offset;
7047 }
7048
7049 static int
7050 dissect_nfs_client_id4(tvbuff_t *tvb, int offset, proto_tree *tree)
7051 {
7052         offset = dissect_rpc_uint64(tvb, tree, hf_nfs_verifier4, offset);
7053         offset = dissect_rpc_data(tvb, tree, hf_nfs_client_id4_id, offset);
7054
7055         return offset;
7056 }
7057
7058 static int
7059 dissect_nfs_argop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
7060         proto_tree *tree)
7061 {
7062         guint32 ops, ops_counter;
7063         guint opcode;
7064         proto_item *fitem;
7065         proto_tree *ftree = NULL;
7066         proto_tree *newftree = NULL;
7067
7068         ops = tvb_get_ntohl(tvb, offset+0);
7069
7070         fitem = proto_tree_add_text(tree, tvb, offset, 4,
7071                 "Operations (count: %u)", ops);
7072         offset += 4;
7073
7074         if (fitem == NULL) return offset;
7075
7076         ftree = proto_item_add_subtree(fitem, ett_nfs_argop4);
7077
7078         if (ftree == NULL) return offset;
7079
7080         for (ops_counter=0; ops_counter<ops; ops_counter++)
7081         {
7082                 opcode = tvb_get_ntohl(tvb, offset);
7083
7084                 fitem = proto_tree_add_uint(ftree, hf_nfs_argop4, tvb, offset, 4,
7085                         opcode);
7086                 offset += 4;
7087
7088                 /* the opcodes are not contiguous */
7089                 if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_WRITE) &&
7090                         (opcode != NFS4_OP_ILLEGAL))
7091                         break;
7092
7093                 if (fitem == NULL)      break;
7094
7095                 /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
7096                 if (opcode == NFS4_OP_ILLEGAL)
7097                         newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4);
7098                 else
7099                         newftree = proto_item_add_subtree(fitem, 
7100                                 *nfsv4_operation_ett[opcode - 3]);
7101
7102                 if (newftree == NULL)   break;
7103
7104                 switch(opcode)
7105                 {
7106                 case NFS4_OP_ACCESS:
7107                         offset = dissect_access(tvb, offset, newftree, "access");
7108                         break;
7109
7110                 case NFS4_OP_CLOSE:
7111                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
7112                                 offset);
7113                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7114                         break;
7115
7116                 case NFS4_OP_COMMIT:
7117                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4,
7118                                 offset);
7119                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
7120                                 offset);
7121                         break;
7122
7123                 case NFS4_OP_CREATE:
7124                         {
7125                                 guint create_type;
7126
7127                                 create_type = tvb_get_ntohl(tvb, offset);
7128                                 offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_ftype4,
7129                                         offset);
7130
7131                                 switch(create_type)
7132                                 {
7133                                 case NF4LNK:
7134                                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7135                                                 hf_nfs_linktext4, NULL);
7136                                         break;
7137
7138                                 case NF4BLK:
7139                                 case NF4CHR:
7140                                         offset = dissect_nfs_specdata4(tvb, offset, newftree);
7141                                         break;
7142
7143                                 case NF4SOCK:
7144                                 case NF4FIFO:
7145                                 case NF4DIR:
7146                                         break;
7147
7148                                 default:
7149                                         break;
7150                                 }
7151
7152                                 offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
7153
7154                                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
7155                         }
7156                         break;
7157
7158                 case NFS4_OP_DELEGPURGE:
7159                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
7160                         break;
7161
7162                 case NFS4_OP_DELEGRETURN:
7163                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7164                         break;
7165
7166                 case NFS4_OP_GETATTR:
7167                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
7168                                 FATTR4_BITMAP_ONLY);
7169                         break;
7170
7171                 case NFS4_OP_GETFH:
7172                         break;
7173
7174                 case NFS4_OP_LINK:
7175                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7176                                 hf_nfs_component4, NULL);
7177                         break;
7178
7179                 case NFS4_OP_LOCK:
7180                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
7181                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_lock4_reclaim, offset);
7182                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
7183                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
7184                         offset = dissect_nfs_locker4(tvb, offset, newftree);
7185                         break;
7186
7187                 case NFS4_OP_LOCKT:
7188                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
7189                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
7190                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
7191                         offset = dissect_nfs_lock_owner4(tvb, offset, newftree);
7192                         break;
7193
7194                 case NFS4_OP_LOCKU:
7195                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
7196                         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_seqid4, offset);
7197                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7198                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
7199                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
7200                         break;
7201
7202                 case NFS4_OP_LOOKUP:
7203                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7204                                 hf_nfs_component4, NULL);
7205                         break;
7206
7207                 case NFS4_OP_LOOKUPP:
7208                         break;
7209
7210                 case NFS4_OP_NVERIFY:
7211                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
7212                         break;
7213
7214                 case NFS4_OP_OPEN:
7215                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
7216                                 offset);
7217                         offset = dissect_nfs_open4_share_access(tvb, offset, newftree);
7218                         offset = dissect_nfs_open4_share_deny(tvb, offset, newftree);
7219                         offset = dissect_nfs_open_owner4(tvb, offset, newftree);
7220                         offset = dissect_nfs_openflag4(tvb, offset, pinfo, newftree);
7221                         offset = dissect_nfs_open_claim4(tvb, offset, newftree);
7222                         break;
7223
7224                 case NFS4_OP_OPENATTR:
7225                         offset = dissect_rpc_bool(tvb, newftree, hf_nfs_attrdircreate,
7226                                 offset);
7227                         break;
7228
7229                 case NFS4_OP_OPEN_CONFIRM:
7230                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7231                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
7232                                 offset);
7233                         break;
7234
7235                 case NFS4_OP_OPEN_DOWNGRADE:
7236                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7237                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
7238                                 offset);
7239                         offset = dissect_nfs_open4_share_access(tvb, offset, newftree);
7240                         offset = dissect_nfs_open4_share_deny(tvb, offset, newftree);
7241                         break;
7242
7243                 case NFS4_OP_PUTFH:
7244                         offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "filehandle");
7245                         break;
7246
7247                 case NFS4_OP_PUTPUBFH:
7248                 case NFS4_OP_PUTROOTFH:
7249                         break;
7250
7251                 case NFS4_OP_READ:
7252                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7253                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4,
7254                                 offset);
7255                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
7256                                 offset);
7257                         break;
7258
7259                 case NFS4_OP_READDIR:
7260                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookie4,
7261                                 offset);
7262                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookieverf4,
7263                                 offset);
7264                         offset = dissect_rpc_uint32(tvb, newftree,
7265                                 hf_nfs_count4_dircount, offset);
7266                         offset = dissect_rpc_uint32(tvb, newftree,
7267                                 hf_nfs_count4_maxcount, offset);
7268                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
7269                                 FATTR4_BITMAP_ONLY);
7270                         break;
7271
7272                 case NFS4_OP_READLINK:
7273                         break;
7274
7275                 case NFS4_OP_REMOVE:
7276                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7277                                 hf_nfs_component4, NULL);
7278                         break;
7279
7280                 case NFS4_OP_RENAME:
7281                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7282                                 hf_nfs_component4, NULL);
7283                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7284                                 hf_nfs_component4, NULL);
7285                         break;
7286
7287                 case NFS4_OP_RENEW:
7288                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
7289                         break;
7290
7291                 case NFS4_OP_RESTOREFH:
7292                 case NFS4_OP_SAVEFH:
7293                         break;
7294
7295                 case NFS4_OP_SECINFO:
7296                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7297                                 hf_nfs_component4, NULL);
7298                         break;
7299
7300                 case NFS4_OP_SETATTR:
7301                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7302                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
7303                         break;
7304
7305                 case NFS4_OP_SETCLIENTID:
7306                         {
7307                                 proto_tree *client_tree = NULL;
7308                                 proto_tree *callback_tree = NULL;
7309
7310                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "client");
7311                                 if (fitem)
7312                                 {
7313                                         client_tree = proto_item_add_subtree(fitem, ett_nfs_client_id4);
7314
7315                                         if (client_tree)
7316                                                 offset = dissect_nfs_client_id4(tvb, offset, client_tree);
7317                                 }
7318
7319                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "callback");
7320                                 if (fitem)
7321                                 {
7322                                         callback_tree = proto_item_add_subtree(fitem,
7323                                                 ett_nfs_cb_client4);
7324
7325                                         if (callback_tree)
7326                                                 offset = dissect_nfs_cb_client4(tvb, offset, callback_tree);
7327                                 }
7328
7329                                 offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_callback_ident,
7330                                         offset);
7331                         }
7332                         break;
7333
7334                 case NFS4_OP_SETCLIENTID_CONFIRM:
7335                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
7336                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4, offset);
7337                         break;
7338
7339                 case NFS4_OP_VERIFY:
7340                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
7341                         break;
7342
7343                 case NFS4_OP_WRITE:
7344                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7345                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
7346                         offset = dissect_nfs_stable_how4(tvb, offset, newftree, "stable");
7347                         offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
7348                         break;
7349
7350                 case NFS4_OP_RELEASE_LOCKOWNER:
7351                         offset = dissect_nfs_lock_owner4(tvb, offset, newftree);
7352                         break;
7353
7354                 /* In theory, it's possible to get this opcode */
7355                 case NFS4_OP_ILLEGAL:
7356                         break;
7357
7358                 default:
7359                         break;
7360                 }
7361         }
7362
7363         return offset;
7364 }
7365
7366 static int
7367 dissect_nfs4_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
7368         proto_tree* tree)
7369 {
7370         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, NULL);
7371         offset = dissect_rpc_uint32(tvb, tree, hf_nfs_minorversion, offset);
7372         offset = dissect_nfs_argop4(tvb, offset, pinfo, tree);
7373
7374         return offset;
7375 }
7376
7377 static int
7378 dissect_nfs_secinfo4_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
7379         proto_tree *tree)
7380 {
7381         guint flavor;
7382         proto_item *fitem;
7383         proto_tree *secftree;
7384
7385         flavor = tvb_get_ntohl(tvb, offset);
7386         fitem = proto_tree_add_uint(tree, hf_nfs_secinfo_flavor, tvb, offset, 4,
7387                 flavor);
7388         offset += 4;
7389
7390         if (fitem)
7391         {
7392                 switch(flavor)
7393                 {
7394                 case RPCSEC_GSS:
7395                         secftree = proto_item_add_subtree(fitem, ett_nfs_secinfo4_flavor_info);
7396                         if (secftree)
7397                                 offset = dissect_nfs_rpcsec_gss_info(tvb, offset, secftree);
7398                         break;
7399
7400                 default:
7401                         break;
7402                 }
7403         }
7404
7405         return offset;
7406 }
7407
7408 static int
7409 dissect_nfs_resop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
7410         proto_tree *tree)
7411 {
7412         guint32 ops, ops_counter;
7413         guint32 opcode;
7414         proto_item *fitem;
7415         proto_tree *ftree = NULL;
7416         proto_tree *newftree = NULL;
7417         guint32 status;
7418
7419         ops = tvb_get_ntohl(tvb, offset+0);
7420
7421         fitem = proto_tree_add_text(tree, tvb, offset, 4,
7422                 "Operations (count: %u)", ops);
7423         offset += 4;
7424
7425         if (fitem == NULL)      return offset;
7426
7427         ftree = proto_item_add_subtree(fitem, ett_nfs_resop4);
7428
7429         if (ftree == NULL)      return offset;          /* error adding new subtree */
7430
7431         for (ops_counter = 0; ops_counter < ops; ops_counter++)
7432         {
7433                 opcode = tvb_get_ntohl(tvb, offset);
7434
7435                 /* sanity check for bogus packets */
7436                 if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_WRITE) &&
7437                         (opcode != NFS4_OP_ILLEGAL))
7438                         break;
7439
7440                 fitem = proto_tree_add_uint(ftree, hf_nfs_resop4, tvb, offset, 4,
7441                         opcode);
7442                 offset += 4;
7443
7444                 if (fitem == NULL)      break;          /* error adding new item to tree */
7445
7446                 /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
7447                 if (opcode == NFS4_OP_ILLEGAL)
7448                         newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4);
7449                 else
7450                         newftree = proto_item_add_subtree(fitem, 
7451                                 *nfsv4_operation_ett[opcode - 3]);
7452
7453                 if (newftree == NULL)
7454                         break;          /* error adding new subtree to operation item */
7455
7456                 offset = dissect_nfs_nfsstat4(tvb, offset, newftree, &status);
7457
7458                 /*
7459                  * With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT, and
7460                  * NFS4_OP_SETATTR, all other ops do *not* return data with the
7461                  * failed status code. 
7462                  */
7463                 if ((status != NFS4_OK) &&
7464                         ((opcode != NFS4_OP_LOCK) && (opcode != NFS4_OP_LOCKT) &&
7465                         (opcode != NFS4_OP_SETATTR)))
7466                         continue;
7467
7468                 /* These parsing routines are only executed if the status is NFS4_OK */
7469                 switch(opcode)
7470                 {
7471                 case NFS4_OP_ACCESS:
7472                         offset = dissect_access(tvb, offset, newftree, "Supported");
7473                         offset = dissect_access(tvb, offset, newftree, "Access");
7474                         break;
7475
7476                 case NFS4_OP_CLOSE:
7477                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7478                         break;
7479
7480                 case NFS4_OP_COMMIT:
7481                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
7482                                 offset);
7483                         break;
7484
7485                 case NFS4_OP_CREATE:
7486                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
7487                                 "change_info");
7488                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
7489                                 FATTR4_BITMAP_ONLY);
7490                         break;
7491
7492                 case NFS4_OP_GETATTR:
7493                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
7494                         break;
7495
7496                 case NFS4_OP_GETFH:
7497                         offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "Filehandle");
7498                         break;
7499
7500                 case NFS4_OP_LINK:
7501                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
7502                                 "change_info");
7503                         break;
7504
7505                 case NFS4_OP_LOCK:
7506                 case NFS4_OP_LOCKT:
7507                         if (status == NFS4_OK)
7508                         {
7509                                 if (opcode == NFS4_OP_LOCK)
7510                                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7511                         }
7512                         else
7513                         if (status == NFS4ERR_DENIED)
7514                                 offset = dissect_nfs_lock4denied(tvb, offset, newftree);
7515                         break;
7516
7517                 case NFS4_OP_LOCKU:
7518                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7519                         break;
7520
7521                 case NFS4_OP_OPEN:
7522                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7523                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
7524                                 "change_info");
7525                         offset = dissect_nfs_open4_rflags(tvb, offset, newftree,
7526                                 "result_flags");
7527                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
7528                                 FATTR4_BITMAP_ONLY);
7529                         offset = dissect_nfs_open_delegation4(tvb, offset, pinfo, newftree);
7530                         break;
7531
7532                 case NFS4_OP_OPEN_CONFIRM:
7533                 case NFS4_OP_OPEN_DOWNGRADE:
7534                         offset = dissect_nfs_stateid4(tvb, offset, newftree);
7535                         break;
7536
7537                 case NFS4_OP_READ:
7538                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_eof, offset);
7539                         offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
7540                         break;
7541
7542                 case NFS4_OP_READDIR:
7543                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4, offset);
7544                         offset = dissect_nfs_dirlist4(tvb, offset, pinfo, newftree);
7545                         break;
7546
7547                 case NFS4_OP_READLINK:
7548                         offset = dissect_nfs_utf8string(tvb, offset, newftree,
7549                                 hf_nfs_linktext4, NULL);
7550                         break;
7551
7552                 case NFS4_OP_REMOVE:
7553                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
7554                                 "change_info");
7555                         break;
7556
7557                 case NFS4_OP_RENAME:
7558                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
7559                                 "source_cinfo");
7560                         offset = dissect_nfs_change_info4(tvb, offset, newftree,
7561                                 "target_cinfo");
7562                         break;
7563
7564                 case NFS4_OP_SECINFO:
7565                         offset = dissect_rpc_array(tvb, pinfo, newftree, offset,
7566                                 dissect_nfs_secinfo4_res, hf_nfs_secinfo_arr4);
7567                         break;
7568
7569                 case NFS4_OP_SETATTR:
7570                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
7571                                 FATTR4_BITMAP_ONLY);
7572                         break;
7573
7574                 case NFS4_OP_SETCLIENTID:
7575                         if (status == NFS4_OK)
7576                         {
7577                                 offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4,
7578                                         offset);
7579                                 offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
7580                                         offset);
7581                         }
7582                         else
7583                         if (status == NFS4ERR_CLID_INUSE)
7584                                 offset = dissect_nfs_clientaddr4(tvb, offset, newftree);
7585                         break;
7586
7587                 case NFS4_OP_WRITE:
7588                         offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
7589                                 offset);
7590                         offset = dissect_nfs_stable_how4(tvb, offset, newftree,
7591                                 "committed");
7592                         offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
7593                                 offset);
7594                         break;
7595
7596                 default:
7597                         break;
7598                 }
7599         }
7600
7601         return offset;
7602 }
7603
7604 static int
7605 dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
7606         proto_tree* tree)
7607 {
7608         guint32 status;
7609
7610         offset = dissect_nfs_nfsstat4(tvb, offset, tree, &status);
7611         offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, NULL);
7612         offset = dissect_nfs_resop4(tvb, offset, pinfo, tree);
7613
7614         return offset;
7615 }
7616
7617
7618 /* proc number, "proc name", dissect_request, dissect_reply */
7619 /* NULL as function pointer means: type of arguments is "void". */
7620 static const vsff nfs3_proc[] = {
7621         { 0,    "NULL",         /* OK */
7622         dissect_nfs3_null_call,         dissect_nfs3_null_reply },
7623         { 1,    "GETATTR",      /* OK */
7624         dissect_nfs3_getattr_call,      dissect_nfs3_getattr_reply },
7625         { 2,    "SETATTR",      /* OK */
7626         dissect_nfs3_setattr_call,      dissect_nfs3_setattr_reply },
7627         { 3,    "LOOKUP",       /* OK */
7628         dissect_nfs3_lookup_call,       dissect_nfs3_lookup_reply },
7629         { 4,    "ACCESS",       /* OK */
7630         dissect_nfs3_access_call,       dissect_nfs3_access_reply },
7631         { 5,    "READLINK",     /* OK */
7632         dissect_nfs3_readlink_call,     dissect_nfs3_readlink_reply },
7633         { 6,    "READ",         /* OK */
7634         dissect_nfs3_read_call,         dissect_nfs3_read_reply },
7635         { 7,    "WRITE",        /* OK */
7636         dissect_nfs3_write_call,        dissect_nfs3_write_reply },
7637         { 8,    "CREATE",       /* OK */
7638         dissect_nfs3_create_call,       dissect_nfs3_create_reply },
7639         { 9,    "MKDIR",        /* OK */
7640         dissect_nfs3_mkdir_call,        dissect_nfs3_mkdir_reply },
7641         { 10,   "SYMLINK",      /* OK */
7642         dissect_nfs3_symlink_call,      dissect_nfs3_symlink_reply },
7643         { 11,   "MKNOD",        /* OK */
7644         dissect_nfs3_mknod_call,        dissect_nfs3_mknod_reply },
7645         { 12,   "REMOVE",       /* OK */
7646         dissect_nfs3_remove_call,       dissect_nfs3_remove_reply },
7647         { 13,   "RMDIR",        /* OK */
7648         dissect_nfs3_rmdir_call,        dissect_nfs3_rmdir_reply },
7649         { 14,   "RENAME",       /* OK */
7650         dissect_nfs3_rename_call,       dissect_nfs3_rename_reply },
7651         { 15,   "LINK",         /* OK */
7652         dissect_nfs3_link_call,         dissect_nfs3_link_reply },
7653         { 16,   "READDIR",      /* OK */
7654         dissect_nfs3_readdir_call,      dissect_nfs3_readdir_reply },
7655         { 17,   "READDIRPLUS",  /* OK */
7656         dissect_nfs3_readdirplus_call,  dissect_nfs3_readdirplus_reply },
7657         { 18,   "FSSTAT",       /* OK */
7658         dissect_nfs3_fsstat_call,       dissect_nfs3_fsstat_reply },
7659         { 19,   "FSINFO",       /* OK */
7660         dissect_nfs3_fsinfo_call,       dissect_nfs3_fsinfo_reply },
7661         { 20,   "PATHCONF",     /* OK */
7662         dissect_nfs3_pathconf_call,     dissect_nfs3_pathconf_reply },
7663         { 21,   "COMMIT",       /* OK */
7664         dissect_nfs3_commit_call,       dissect_nfs3_commit_reply },
7665         { 0,NULL,NULL,NULL }
7666 };
7667
7668 static const value_string nfsv3_proc_vals[] = {
7669         { 0,    "NULL" },
7670         { 1,    "GETATTR" },
7671         { 2,    "SETATTR" },
7672         { 3,    "LOOKUP" },
7673         { 4,    "ACCESS" },
7674         { 5,    "READLINK" },
7675         { 6,    "READ" },
7676         { 7,    "WRITE" },
7677         { 8,    "CREATE" },
7678         { 9,    "MKDIR" },
7679         { 10,   "SYMLINK" },
7680         { 11,   "MKNOD" },
7681         { 12,   "REMOVE" },
7682         { 13,   "RMDIR" },
7683         { 14,   "RENAME" },
7684         { 15,   "LINK" },
7685         { 16,   "READDIR" },
7686         { 17,   "READDIRPLUS" },
7687         { 18,   "FSSTAT" },
7688         { 19,   "FSINFO" },
7689         { 20,   "PATHCONF" },
7690         { 21,   "COMMIT" },
7691         { 0,    NULL }
7692 };
7693
7694 /* end of NFS Version 3 */
7695
7696 /* the call to dissect_nfs3_null_call & dissect_nfs3_null_reply is 
7697  * intentional.  The V4 NULLPROC is the same as V3.
7698  */
7699 static const vsff nfs4_proc[] = {
7700         { 0, "NULL",
7701         dissect_nfs3_null_call,         dissect_nfs3_null_reply },
7702         { 1, "COMPOUND",
7703         dissect_nfs4_compound_call, dissect_nfs4_compound_reply },
7704         { 0, NULL, NULL, NULL }
7705 };
7706
7707 static const value_string nfsv4_proc_vals[] = {
7708         { 0, "NULL" },
7709         { 1, "COMPOUND" },
7710         { 0, NULL }
7711 };
7712
7713 static struct true_false_string yesno = { "Yes", "No" };
7714
7715
7716 void
7717 proto_register_nfs(void)
7718 {
7719         static hf_register_info hf[] = {
7720                 { &hf_nfs_procedure_v2, {
7721                         "V2 Procedure", "nfs.procedure_v2", FT_UINT32, BASE_DEC,
7722                         VALS(nfsv2_proc_vals), 0, "V2 Procedure", HFILL }},
7723                 { &hf_nfs_procedure_v3, {
7724                         "V3 Procedure", "nfs.procedure_v3", FT_UINT32, BASE_DEC,
7725                         VALS(nfsv3_proc_vals), 0, "V3 Procedure", HFILL }},
7726                 { &hf_nfs_procedure_v4, {
7727                         "V4 Procedure", "nfs.procedure_v4", FT_UINT32, BASE_DEC,
7728                         VALS(nfsv4_proc_vals), 0, "V4 Procedure", HFILL }},
7729                 { &hf_nfs_fh_length, {
7730                         "length", "nfs.fh.length", FT_UINT32, BASE_DEC,
7731                         NULL, 0, "file handle length", HFILL }},
7732                 { &hf_nfs_fh_hash, {
7733                         "hash", "nfs.fh.hash", FT_UINT32, BASE_HEX,
7734                         NULL, 0, "file handle hash", HFILL }},
7735                 { &hf_nfs_fh_mount_fileid, {
7736                         "fileid", "nfs.fh.mount.fileid", FT_UINT32, BASE_DEC,
7737                         NULL, 0, "mount point fileid", HFILL }},
7738                 { &hf_nfs_fh_mount_generation, {
7739                         "generation", "nfs.fh.mount.generation", FT_UINT32, BASE_HEX,
7740                         NULL, 0, "mount point generation", HFILL }},
7741                 { &hf_nfs_fh_flags, {
7742                         "flags", "nfs.fh.flags", FT_UINT16, BASE_HEX,
7743                         NULL, 0, "file handle flags", HFILL }},
7744                 { &hf_nfs_fh_snapid, {
7745                         "snapid", "nfs.fh.snapid", FT_UINT8, BASE_DEC,
7746                         NULL, 0, "snapshot ID", HFILL }},
7747                 { &hf_nfs_fh_unused, {
7748                         "unused", "nfs.fh.unused", FT_UINT8, BASE_DEC,
7749                         NULL, 0, "unused", HFILL }},
7750                 { &hf_nfs_fh_fileid, {
7751                         "fileid", "nfs.fh.fileid", FT_UINT32, BASE_DEC,
7752                         NULL, 0, "file ID", HFILL }},
7753                 { &hf_nfs_fh_generation, {
7754                         "generation", "nfs.fh.generation", FT_UINT32, BASE_HEX,
7755                         NULL, 0, "inode generation", HFILL }},
7756                 { &hf_nfs_fh_fsid, {
7757                         "fsid", "nfs.fh.fsid", FT_UINT32, BASE_HEX,
7758                         NULL, 0, "file system ID", HFILL }},
7759                 { &hf_nfs_fh_export_fileid, {
7760                         "fileid", "nfs.fh.export.fileid", FT_UINT32, BASE_DEC,
7761                         NULL, 0, "export point fileid", HFILL }},
7762                 { &hf_nfs_fh_export_generation, {
7763                         "generation", "nfs.fh.export.generation", FT_UINT32, BASE_HEX,
7764                         NULL, 0, "export point generation", HFILL }},
7765                 { &hf_nfs_fh_export_snapid, {
7766                         "snapid", "nfs.fh.export.snapid", FT_UINT8, BASE_DEC,
7767                         NULL, 0, "export point snapid", HFILL }},
7768                 { &hf_nfs_fh_fsid_major, {
7769                         "major", "nfs.fh.fsid.major", FT_UINT32, BASE_DEC,
7770                         NULL, 0, "major file system ID", HFILL }},
7771                 { &hf_nfs_fh_fsid_minor, {
7772                         "minor", "nfs.fh.fsid.minor", FT_UINT32, BASE_DEC,
7773                         NULL, 0, "minor file system ID", HFILL }},
7774                 { &hf_nfs_fh_fsid_inode, {
7775                         "inode", "nfs.fh.fsid.inode", FT_UINT32, BASE_DEC,
7776                         NULL, 0, "file system inode", HFILL }},
7777                 { &hf_nfs_fh_xfsid_major, {
7778                         "exported major", "nfs.fh.xfsid.major", FT_UINT32, BASE_DEC,
7779                         NULL, 0, "exported major file system ID", HFILL }},
7780                 { &hf_nfs_fh_xfsid_minor, {
7781                         "exported minor", "nfs.fh.xfsid.minor", FT_UINT32, BASE_DEC,
7782                         NULL, 0, "exported minor file system ID", HFILL }},
7783                 { &hf_nfs_fh_fstype, {
7784                         "file system type", "nfs.fh.fstype", FT_UINT32, BASE_DEC,
7785                         NULL, 0, "file system type", HFILL }},
7786                 { &hf_nfs_fh_fn, {
7787                         "file number", "nfs.fh.fn", FT_UINT32, BASE_DEC,
7788                         NULL, 0, "file number", HFILL }},
7789                 { &hf_nfs_fh_fn_len, {
7790                         "length", "nfs.fh.fn.len", FT_UINT32, BASE_DEC,
7791                         NULL, 0, "file number length", HFILL }},
7792                 { &hf_nfs_fh_fn_inode, {
7793                         "inode", "nfs.fh.fn.inode", FT_UINT32, BASE_DEC,
7794                         NULL, 0, "file number inode", HFILL }},
7795                 { &hf_nfs_fh_fn_generation, {
7796                         "generation", "nfs.fh.fn.generation", FT_UINT32, BASE_DEC,
7797                         NULL, 0, "file number generation", HFILL }},
7798                 { &hf_nfs_fh_xfn, {
7799                         "exported file number", "nfs.fh.xfn", FT_UINT32, BASE_DEC,
7800                         NULL, 0, "exported file number", HFILL }},
7801                 { &hf_nfs_fh_xfn_len, {
7802                         "length", "nfs.fh.xfn.len", FT_UINT32, BASE_DEC,
7803                         NULL, 0, "exported file number length", HFILL }},
7804                 { &hf_nfs_fh_xfn_inode, {
7805                         "exported inode", "nfs.fh.xfn.inode", FT_UINT32, BASE_DEC,
7806                         NULL, 0, "exported file number inode", HFILL }},
7807                 { &hf_nfs_fh_xfn_generation, {
7808                         "generation", "nfs.fh.xfn.generation", FT_UINT32, BASE_DEC,
7809                         NULL, 0, "exported file number generation", HFILL }},
7810                 { &hf_nfs_fh_dentry, {
7811                         "dentry", "nfs.fh.dentry", FT_UINT32, BASE_HEX,
7812                         NULL, 0, "dentry (cookie)", HFILL }},
7813                 { &hf_nfs_fh_dev, {
7814                         "device", "nfs.fh.dev", FT_UINT32, BASE_DEC,
7815                         NULL, 0, "device", HFILL }},
7816                 { &hf_nfs_fh_xdev, {
7817                         "exported device", "nfs.fh.xdev", FT_UINT32, BASE_DEC,
7818                         NULL, 0, "exported device", HFILL }},
7819                 { &hf_nfs_fh_dirinode, {
7820                         "directory inode", "nfs.fh.dirinode", FT_UINT32, BASE_DEC,
7821                         NULL, 0, "directory inode", HFILL }},
7822                 { &hf_nfs_fh_pinode, {
7823                         "pseudo inode", "nfs.fh.pinode", FT_UINT32, BASE_HEX,
7824                         NULL, 0, "pseudo inode", HFILL }},
7825                 { &hf_nfs_fh_hp_len, {
7826                         "length", "nfs.fh.hp.len", FT_UINT32, BASE_DEC,
7827                         NULL, 0, "hash path length", HFILL }},
7828                 { &hf_nfs_fh_version, {
7829                         "version", "nfs.fh.version", FT_UINT8, BASE_DEC,
7830                         NULL, 0, "file handle layout version", HFILL }},
7831                 { &hf_nfs_fh_auth_type, {
7832                         "auth_type", "nfs.fh.auth_type", FT_UINT8, BASE_DEC,
7833                         VALS(auth_type_names), 0, "authentication type", HFILL }},
7834                 { &hf_nfs_fh_fsid_type, {
7835                         "fsid_type", "nfs.fh.fsid_type", FT_UINT8, BASE_DEC,
7836                         VALS(fsid_type_names), 0, "file system ID type", HFILL }},
7837                 { &hf_nfs_fh_fileid_type, {
7838                         "fileid_type", "nfs.fh.fileid_type", FT_UINT8, BASE_DEC,
7839                         VALS(fileid_type_names), 0, "file ID type", HFILL }},
7840                 { &hf_nfs_stat, {
7841                         "Status", "nfs.status2", FT_UINT32, BASE_DEC,
7842                         VALS(names_nfs_stat), 0, "Reply status", HFILL }},
7843                 { &hf_nfs_full_name, {
7844                         "Full Name", "nfs.full_name", FT_STRING, BASE_DEC,
7845                         NULL, 0, "Full Name", HFILL }},
7846                 { &hf_nfs_name, {
7847                         "Name", "nfs.name", FT_STRING, BASE_DEC,
7848                         NULL, 0, "Name", HFILL }},
7849                 { &hf_nfs_readlink_data, {
7850                         "Data", "nfs.readlink.data", FT_STRING, BASE_DEC,
7851                         NULL, 0, "Symbolic Link Data", HFILL }},
7852                 { &hf_nfs_read_offset, {
7853                         "Offset", "nfs.read.offset", FT_UINT32, BASE_DEC,
7854                         NULL, 0, "Read Offset", HFILL }},
7855                 { &hf_nfs_read_count, {
7856                         "Count", "nfs.read.count", FT_UINT32, BASE_DEC,
7857                         NULL, 0, "Read Count", HFILL }},
7858                 { &hf_nfs_read_totalcount, {
7859                         "Total Count", "nfs.read.totalcount", FT_UINT32, BASE_DEC,
7860                         NULL, 0, "Total Count (obsolete)", HFILL }},
7861                 { &hf_nfs_data, {
7862                         "Data", "nfs.data", FT_BYTES, BASE_DEC,
7863                         NULL, 0, "Data", HFILL }},
7864                 { &hf_nfs_write_beginoffset, {
7865                         "Begin Offset", "nfs.write.beginoffset", FT_UINT32, BASE_DEC,
7866                         NULL, 0, "Begin offset (obsolete)", HFILL }},
7867                 { &hf_nfs_write_offset, {
7868                         "Offset", "nfs.write.offset", FT_UINT32, BASE_DEC,
7869                         NULL, 0, "Offset", HFILL }},
7870                 { &hf_nfs_write_totalcount, {
7871                         "Total Count", "nfs.write.totalcount", FT_UINT32, BASE_DEC,
7872                         NULL, 0, "Total Count (obsolete)", HFILL }},
7873                 { &hf_nfs_symlink_to, {
7874                         "To", "nfs.symlink.to", FT_STRING, BASE_DEC,
7875                         NULL, 0, "Symbolic link destination name", HFILL }},
7876                 { &hf_nfs_readdir_cookie, {
7877                         "Cookie", "nfs.readdir.cookie", FT_UINT32, BASE_DEC,
7878                         NULL, 0, "Directory Cookie", HFILL }},
7879                 { &hf_nfs_readdir_count, {
7880                         "Count", "nfs.readdir.count", FT_UINT32, BASE_DEC,
7881                         NULL, 0, "Directory Count", HFILL }},
7882
7883                 { &hf_nfs_readdir_entry, {
7884                         "Entry", "nfs.readdir.entry", FT_NONE, 0,
7885                         NULL, 0, "Directory Entry", HFILL }},
7886
7887                 { &hf_nfs_readdir_entry_fileid, {
7888                         "File ID", "nfs.readdir.entry.fileid", FT_UINT32, BASE_DEC,
7889                         NULL, 0, "File ID", HFILL }},
7890
7891                 { &hf_nfs_readdir_entry_name, {
7892                         "Name", "nfs.readdir.entry.name", FT_STRING, BASE_DEC,
7893                         NULL, 0, "Name", HFILL }},
7894
7895                 { &hf_nfs_readdir_entry_cookie, {
7896                         "Cookie", "nfs.readdir.entry.cookie", FT_UINT32, BASE_DEC,
7897                         NULL, 0, "Directory Cookie", HFILL }},
7898
7899                 { &hf_nfs_readdir_entry3_fileid, {
7900                         "File ID", "nfs.readdir.entry3.fileid", FT_UINT64, BASE_DEC,
7901                         NULL, 0, "File ID", HFILL }},
7902
7903                 { &hf_nfs_readdir_entry3_name, {
7904                         "Name", "nfs.readdir.entry3.name", FT_STRING, BASE_DEC,
7905                         NULL, 0, "Name", HFILL }},
7906
7907                 { &hf_nfs_readdir_entry3_cookie, {
7908                         "Cookie", "nfs.readdir.entry3.cookie", FT_UINT64, BASE_DEC,
7909                         NULL, 0, "Directory Cookie", HFILL }},
7910
7911                 { &hf_nfs_readdirplus_entry_fileid, {
7912                         "File ID", "nfs.readdirplus.entry.fileid", FT_UINT64, BASE_DEC,
7913                         NULL, 0, "Name", HFILL }},
7914
7915                 { &hf_nfs_readdirplus_entry_name, {
7916                         "Name", "nfs.readdirplus.entry.name", FT_STRING, BASE_DEC,
7917                         NULL, 0, "Name", HFILL }},
7918
7919                 { &hf_nfs_readdirplus_entry_cookie, {
7920                         "Cookie", "nfs.readdirplus.entry.cookie", FT_UINT64, BASE_DEC,
7921                         NULL, 0, "Directory Cookie", HFILL }},
7922
7923                 { &hf_nfs_readdir_eof, {
7924                         "EOF", "nfs.readdir.eof", FT_UINT32, BASE_DEC,
7925                         NULL, 0, "EOF", HFILL }},
7926
7927                 { &hf_nfs_statfs_tsize, {
7928                         "Transfer Size", "nfs.statfs.tsize", FT_UINT32, BASE_DEC,
7929                         NULL, 0, "Transfer Size", HFILL }},
7930                 { &hf_nfs_statfs_bsize, {
7931                         "Block Size", "nfs.statfs.bsize", FT_UINT32, BASE_DEC,
7932                         NULL, 0, "Block Size", HFILL }},
7933                 { &hf_nfs_statfs_blocks, {
7934                         "Total Blocks", "nfs.statfs.blocks", FT_UINT32, BASE_DEC,
7935                         NULL, 0, "Total Blocks", HFILL }},
7936                 { &hf_nfs_statfs_bfree, {
7937                         "Free Blocks", "nfs.statfs.bfree", FT_UINT32, BASE_DEC,
7938                         NULL, 0, "Free Blocks", HFILL }},
7939                 { &hf_nfs_statfs_bavail, {
7940                         "Available Blocks", "nfs.statfs.bavail", FT_UINT32, BASE_DEC,
7941                         NULL, 0, "Available Blocks", HFILL }},
7942                 { &hf_nfs_ftype3, {
7943                         "Type", "nfs.type", FT_UINT32, BASE_DEC,
7944                         VALS(names_nfs_ftype3), 0, "File Type", HFILL }},
7945                 { &hf_nfs_nfsstat3, {
7946                         "Status", "nfs.status", FT_UINT32, BASE_DEC,
7947                         VALS(names_nfs_nfsstat3), 0, "Reply status", HFILL }},
7948                 { &hf_nfs_read_eof, {
7949                         "EOF", "nfs.read.eof", FT_BOOLEAN, BASE_NONE,
7950                         &yesno, 0, "EOF", HFILL }},
7951                 { &hf_nfs_write_stable, {
7952                         "Stable", "nfs.write.stable", FT_UINT32, BASE_DEC,
7953                         VALS(names_stable_how), 0, "Stable", HFILL }},
7954                 { &hf_nfs_write_committed, {
7955                         "Committed", "nfs.write.committed", FT_UINT32, BASE_DEC,
7956                         VALS(names_stable_how), 0, "Committed", HFILL }},
7957                 { &hf_nfs_createmode3, {
7958                         "Create Mode", "nfs.createmode", FT_UINT32, BASE_DEC,
7959                         VALS(names_createmode3), 0, "Create Mode", HFILL }},
7960                 { &hf_nfs_fsstat_invarsec, {
7961                         "invarsec", "nfs.fsstat.invarsec", FT_UINT32, BASE_DEC,
7962                         NULL, 0, "probable number of seconds of file system invariance", HFILL }},
7963                 { &hf_nfs_fsinfo_rtmax, {
7964                         "rtmax", "nfs.fsinfo.rtmax", FT_UINT32, BASE_DEC,
7965                         NULL, 0, "maximum READ request", HFILL }},
7966                 { &hf_nfs_fsinfo_rtpref, {
7967                         "rtpref", "nfs.fsinfo.rtpref", FT_UINT32, BASE_DEC,
7968                         NULL, 0, "Preferred READ request size", HFILL }},
7969                 { &hf_nfs_fsinfo_rtmult, {
7970                         "rtmult", "nfs.fsinfo.rtmult", FT_UINT32, BASE_DEC,
7971                         NULL, 0, "Suggested READ multiple", HFILL }},
7972                 { &hf_nfs_fsinfo_wtmax, {
7973                         "wtmax", "nfs.fsinfo.wtmax", FT_UINT32, BASE_DEC,
7974                         NULL, 0, "Maximum WRITE request size", HFILL }},
7975                 { &hf_nfs_fsinfo_wtpref, {
7976                         "wtpref", "nfs.fsinfo.wtpref", FT_UINT32, BASE_DEC,
7977                         NULL, 0, "Preferred WRITE request size", HFILL }},
7978                 { &hf_nfs_fsinfo_wtmult, {
7979                         "wtmult", "nfs.fsinfo.wtmult", FT_UINT32, BASE_DEC,
7980                         NULL, 0, "Suggested WRITE multiple", HFILL }},
7981                 { &hf_nfs_fsinfo_dtpref, {
7982                         "dtpref", "nfs.fsinfo.dtpref", FT_UINT32, BASE_DEC,
7983                         NULL, 0, "Preferred READDIR request", HFILL }},
7984                 { &hf_nfs_fsinfo_maxfilesize, {
7985                         "maxfilesize", "nfs.fsinfo.maxfilesize", FT_UINT64, BASE_DEC,
7986                         NULL, 0, "Maximum file size", HFILL }},
7987                 { &hf_nfs_fsinfo_properties, {
7988                         "Properties", "nfs.fsinfo.propeties", FT_UINT32, BASE_HEX,
7989                         NULL, 0, "File System Properties", HFILL }},
7990                 { &hf_nfs_pathconf_linkmax, {
7991                         "linkmax", "nfs.pathconf.linkmax", FT_UINT32, BASE_DEC,
7992                         NULL, 0, "Maximum number of hard links", HFILL }},
7993                 { &hf_nfs_pathconf_name_max, {
7994                         "name_max", "nfs.pathconf.name_max", FT_UINT32, BASE_DEC,
7995                         NULL, 0, "Maximum file name length", HFILL }},
7996                 { &hf_nfs_pathconf_no_trunc, {
7997                         "no_trunc", "nfs.pathconf.no_trunc", FT_BOOLEAN, BASE_NONE,
7998                         &yesno, 0, "No long file name truncation", HFILL }},
7999                 { &hf_nfs_pathconf_chown_restricted, {
8000                         "chown_restricted", "nfs.pathconf.chown_restricted", FT_BOOLEAN,
8001                         BASE_NONE, &yesno, 0, "chown is restricted to root", HFILL }},
8002                 { &hf_nfs_pathconf_case_insensitive, {
8003                         "case_insensitive", "nfs.pathconf.case_insensitive", FT_BOOLEAN,
8004                         BASE_NONE, &yesno, 0, "file names are treated case insensitive", HFILL }},
8005                 { &hf_nfs_pathconf_case_preserving, {
8006                         "case_preserving", "nfs.pathconf.case_preserving", FT_BOOLEAN,
8007                         BASE_NONE, &yesno, 0, "file name cases are preserved", HFILL }},
8008
8009                 { &hf_nfs_fattr_type, {
8010                         "type", "nfs.fattr.type", FT_UINT32, BASE_DEC,
8011                         NULL, 0, "nfs.fattr.type", HFILL }},
8012
8013                 { &hf_nfs_fattr_nlink, {
8014                         "nlink", "nfs.fattr.nlink", FT_UINT32, BASE_DEC,
8015                         NULL, 0, "nfs.fattr.nlink", HFILL }},
8016
8017                 { &hf_nfs_fattr_uid, {
8018                         "uid", "nfs.fattr.uid", FT_UINT32, BASE_DEC,
8019                         NULL, 0, "nfs.fattr.uid", HFILL }},
8020
8021                 { &hf_nfs_fattr_gid, {
8022                         "gid", "nfs.fattr.gid", FT_UINT32, BASE_DEC,
8023                         NULL, 0, "nfs.fattr.gid", HFILL }},
8024
8025                 { &hf_nfs_fattr_size, {
8026                         "size", "nfs.fattr.size", FT_UINT32, BASE_DEC,
8027                         NULL, 0, "nfs.fattr.size", HFILL }},
8028
8029                 { &hf_nfs_fattr_blocksize, {
8030                         "blocksize", "nfs.fattr.blocksize", FT_UINT32, BASE_DEC,
8031                         NULL, 0, "nfs.fattr.blocksize", HFILL }},
8032
8033                 { &hf_nfs_fattr_rdev, {
8034                         "rdev", "nfs.fattr.rdev", FT_UINT32, BASE_DEC,
8035                         NULL, 0, "nfs.fattr.rdev", HFILL }},
8036
8037                 { &hf_nfs_fattr_blocks, {
8038                         "blocks", "nfs.fattr.blocks", FT_UINT32, BASE_DEC,
8039                         NULL, 0, "nfs.fattr.blocks", HFILL }},
8040
8041                 { &hf_nfs_fattr_fsid, {
8042                         "fsid", "nfs.fattr.fsid", FT_UINT32, BASE_HEX,
8043                         NULL, 0, "nfs.fattr.fsid", HFILL }},
8044
8045                 { &hf_nfs_fattr_fileid, {
8046                         "fileid", "nfs.fattr.fileid", FT_UINT32, BASE_DEC,
8047                         NULL, 0, "nfs.fattr.fileid", HFILL }},
8048
8049                 { &hf_nfs_fattr3_type, {
8050                         "Type", "nfs.fattr3.type", FT_UINT32, BASE_DEC,
8051                         VALS(names_nfs_ftype3), 0, "nfs.fattr3.type", HFILL }},
8052
8053                 { &hf_nfs_fattr3_nlink, {
8054                         "nlink", "nfs.fattr3.nlink", FT_UINT32, BASE_DEC,
8055                         NULL, 0, "nfs.fattr3.nlink", HFILL }},
8056
8057                 { &hf_nfs_fattr3_uid, {
8058                         "uid", "nfs.fattr3.uid", FT_UINT32, BASE_DEC,
8059                         NULL, 0, "nfs.fattr3.uid", HFILL }},
8060
8061                 { &hf_nfs_fattr3_gid, {
8062                         "gid", "nfs.fattr3.gid", FT_UINT32, BASE_DEC,
8063                         NULL, 0, "nfs.fattr3.gid", HFILL }},
8064
8065                 { &hf_nfs_fattr3_size, {
8066                         "size", "nfs.fattr3.size", FT_UINT64, BASE_DEC,
8067                         NULL, 0, "nfs.fattr3.size", HFILL }},
8068
8069                 { &hf_nfs_fattr3_used, {
8070                         "used", "nfs.fattr3.used", FT_UINT64, BASE_DEC,
8071                         NULL, 0, "nfs.fattr3.used", HFILL }},
8072
8073                 { &hf_nfs_fattr3_rdev, {
8074                         "rdev", "nfs.fattr3.rdev", FT_UINT32, BASE_DEC,
8075                         NULL, 0, "nfs.fattr3.rdev", HFILL }},
8076
8077                 { &hf_nfs_fattr3_fsid, {
8078                         "fsid", "nfs.fattr3.fsid", FT_UINT64, BASE_HEX,
8079                         NULL, 0, "nfs.fattr3.fsid", HFILL }},
8080
8081                 { &hf_nfs_fattr3_fileid, {
8082                         "fileid", "nfs.fattr3.fileid", FT_UINT64, BASE_DEC,
8083                         NULL, 0, "nfs.fattr3.fileid", HFILL }},
8084
8085                 { &hf_nfs_wcc_attr_size, {
8086                         "size", "nfs.wcc_attr.size", FT_UINT64, BASE_DEC,
8087                         NULL, 0, "nfs.wcc_attr.size", HFILL }},
8088
8089                 { &hf_nfs_set_size3_size, {
8090                         "size", "nfs.set_size3.size", FT_UINT64, BASE_DEC,
8091                         NULL, 0, "nfs.set_size3.size", HFILL }},
8092
8093                 { &hf_nfs_uid3, {
8094                         "uid", "nfs.uid3", FT_UINT32, BASE_DEC,
8095                         NULL, 0, "nfs.uid3", HFILL }},
8096
8097                 { &hf_nfs_gid3, {
8098                         "gid", "nfs.gid3", FT_UINT32, BASE_DEC,
8099                         NULL, 0, "nfs.gid3", HFILL }},
8100
8101                 { &hf_nfs_cookie3, {
8102                         "cookie", "nfs.cookie3", FT_UINT64, BASE_DEC,
8103                         NULL, 0, "nfs.cookie3", HFILL }},
8104
8105                 { &hf_nfs_offset3, {
8106                         "offset", "nfs.offset3", FT_UINT64, BASE_DEC,
8107                         NULL, 0, "nfs.offset3", HFILL }},
8108
8109                 { &hf_nfs_count3, {
8110                         "count", "nfs.count3", FT_UINT32, BASE_DEC,
8111                         NULL, 0, "nfs.count3", HFILL }},
8112
8113                 { &hf_nfs_count3_maxcount, {
8114                         "maxcount", "nfs.count3_maxcount", FT_UINT32, BASE_DEC,
8115                         NULL, 0, "nfs.count3_maxcount", HFILL }},
8116
8117                 { &hf_nfs_count3_dircount, {
8118                         "dircount", "nfs.count3_dircount", FT_UINT32, BASE_DEC,
8119                         NULL, 0, "nfs.count3_dircount", HFILL }},
8120
8121                 { &hf_nfs_fsstat3_resok_tbytes, {
8122                         "Total bytes", "nfs.fsstat3_resok.tbytes", FT_UINT64, BASE_DEC,
8123                         NULL, 0, "Total bytes", HFILL }},
8124
8125                 { &hf_nfs_fsstat3_resok_fbytes, {
8126                         "Free bytes", "nfs.fsstat3_resok.fbytes", FT_UINT64, BASE_DEC,
8127                         NULL, 0, "Free bytes", HFILL }},
8128
8129                 { &hf_nfs_fsstat3_resok_abytes, {
8130                         "Available free bytes", "nfs.fsstat3_resok.abytes", FT_UINT64, BASE_DEC,
8131                         NULL, 0, "Available free bytes", HFILL }},
8132
8133                 { &hf_nfs_fsstat3_resok_tfiles, {
8134                         "Total file slots", "nfs.fsstat3_resok.tfiles", FT_UINT64, BASE_DEC,
8135                         NULL, 0, "Total file slots", HFILL }},
8136
8137                 { &hf_nfs_fsstat3_resok_ffiles, {
8138                         "Free file slots", "nfs.fsstat3_resok.ffiles", FT_UINT64, BASE_DEC,
8139                         NULL, 0, "Free file slots", HFILL }},
8140
8141                 { &hf_nfs_fsstat3_resok_afiles, {
8142                         "Available free file slots", "nfs.fsstat3_resok.afiles", FT_UINT64, BASE_DEC,
8143                         NULL, 0, "Available free file slots", HFILL }},
8144
8145                 /* NFSv4 */
8146
8147                 { &hf_nfs_argop4, {
8148                         "Opcode", "nfs.call.operation", FT_UINT32, BASE_DEC,
8149                         VALS(names_nfsv4_operation), 0, "Opcode", HFILL }},
8150
8151                 { &hf_nfs_resop4,       {
8152                         "Opcode", "nfs.reply.operation", FT_UINT32, BASE_DEC,
8153                         VALS(names_nfsv4_operation), 0, "Opcode", HFILL }},
8154
8155                 { &hf_nfs_linktext4, {
8156                         "Name", "nfs.symlink.linktext", FT_STRING, BASE_DEC,
8157                         NULL, 0, "Symbolic link contents", HFILL }},
8158
8159                 { &hf_nfs_component4, {
8160                         "Filename", "nfs.pathname.component", FT_STRING, BASE_DEC,
8161                         NULL, 0, "Pathname component", HFILL }},
8162
8163                 { &hf_nfs_tag4, {
8164                         "Tag", "nfs.tag", FT_STRING, BASE_DEC,
8165                         NULL, 0, "Tag", HFILL }},
8166
8167                 { &hf_nfs_clientid4, {
8168                         "clientid", "nfs.clientid", FT_UINT64, BASE_HEX,
8169                         NULL, 0, "Client ID", HFILL }},
8170
8171                 { &hf_nfs_ace4, {
8172                         "ace", "nfs.ace", FT_STRING, BASE_DEC,
8173                         NULL, 0, "Access Control Entry", HFILL }},
8174
8175                 { &hf_nfs_recall, {
8176                         "EOF", "nfs.recall", FT_BOOLEAN, BASE_NONE,
8177                         &yesno, 0, "Recall", HFILL }},
8178
8179                 { &hf_nfs_open_claim_type4, {
8180                         "Claim Type", "nfs.open.claim_type", FT_UINT32, BASE_DEC,
8181                         VALS(names_claim_type4), 0, "Claim Type", HFILL }},
8182
8183                 { &hf_nfs_opentype4, {
8184                         "Open Type", "nfs.open.opentype", FT_UINT32, BASE_DEC,
8185                         VALS(names_opentype4), 0, "Open Type", HFILL }},
8186
8187                 { &hf_nfs_limit_by4, {
8188                         "Space Limit", "nfs.open.limit_by", FT_UINT32, BASE_DEC,
8189                         VALS(names_limit_by4), 0, "Limit By", HFILL }},
8190
8191                 { &hf_nfs_open_delegation_type4, {
8192                         "Delegation Type", "nfs.open.delegation_type", FT_UINT32, BASE_DEC,
8193                         VALS(names_open_delegation_type4), 0, "Delegation Type", HFILL }},
8194
8195                 { &hf_nfs_ftype4, {
8196                         "nfs_ftype4", "nfs.nfs_ftype4", FT_UINT32, BASE_DEC,
8197                         VALS(names_ftype4), 0, "nfs.nfs_ftype4", HFILL }},
8198
8199                 { &hf_nfs_change_info4_atomic, {
8200                         "Atomic", "nfs.change_info.atomic", FT_BOOLEAN, BASE_NONE,
8201                         &yesno, 0, "Atomic", HFILL }},
8202
8203                 { &hf_nfs_open4_share_access, {
8204                         "share_access", "nfs.open4.share_access", FT_UINT32, BASE_DEC,
8205                         VALS(names_open4_share_access), 0, "Share Access", HFILL }},
8206
8207                 { &hf_nfs_open4_share_deny, {
8208                         "share_deny", "nfs.open4.share_deny", FT_UINT32, BASE_DEC,
8209                         VALS(names_open4_share_deny), 0, "Share Deny", HFILL }},
8210
8211                 { &hf_nfs_seqid4, {
8212                         "seqid", "nfs.seqid", FT_UINT32, BASE_HEX,
8213                         NULL, 0, "Sequence ID", HFILL }},
8214
8215                 { &hf_nfs_lock_seqid4, {
8216                         "lock_seqid", "nfs.lock_seqid", FT_UINT32, BASE_HEX,
8217                         NULL, 0, "Lock Sequence ID", HFILL }},
8218
8219                 { &hf_nfs_mand_attr, {
8220                         "mand_attr",    "nfs.attr", FT_UINT32, BASE_DEC,
8221                         VALS(names_fattr4), 0, "Mandatory Attribute", HFILL }},
8222
8223                 { &hf_nfs_recc_attr, {
8224                         "recc_attr",    "nfs.attr", FT_UINT32, BASE_DEC,
8225                         VALS(names_fattr4), 0, "Recommended Attribute", HFILL }},
8226
8227                 { &hf_nfs_time_how4,    {
8228                         "set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
8229                         VALS(names_time_how4), 0, "How To Set Time", HFILL }},
8230
8231                 { &hf_nfs_attrlist4, {
8232                         "attr_vals", "nfs.fattr4.attr_vals", FT_BYTES, BASE_DEC,
8233                         NULL, 0, "attr_vals", HFILL }},
8234
8235                 { &hf_nfs_fattr4_link_support, {
8236                         "fattr4_link_support", "nfs.fattr4_link_support", FT_BOOLEAN,
8237                         BASE_NONE, &yesno, 0, "nfs.fattr4_link_support", HFILL }},
8238
8239                 { &hf_nfs_fattr4_symlink_support, {
8240                         "fattr4_symlink_support", "nfs.fattr4_symlink_support", FT_BOOLEAN,
8241                         BASE_NONE, &yesno, 0, "nfs.fattr4_symlink_support", HFILL }},
8242
8243                 { &hf_nfs_fattr4_named_attr, {
8244                         "fattr4_named_attr", "nfs.fattr4_named_attr", FT_BOOLEAN, BASE_NONE,
8245                         &yesno, 0, "nfs.fattr4_named_attr", HFILL }},
8246
8247                 { &hf_nfs_fattr4_unique_handles, {
8248                         "fattr4_unique_handles", "nfs.fattr4_unique_handles", FT_BOOLEAN,
8249                         BASE_NONE, &yesno, 0, "nfs.fattr4_unique_handles", HFILL }},
8250
8251                 { &hf_nfs_fattr4_archive, {
8252                         "fattr4_archive", "nfs.fattr4_archive", FT_BOOLEAN,
8253                         BASE_NONE, &yesno, 0, "nfs.fattr4_archive", HFILL }},
8254
8255                 { &hf_nfs_fattr4_cansettime, {
8256                         "fattr4_cansettime", "nfs.fattr4_cansettime", FT_BOOLEAN,
8257                         BASE_NONE, &yesno, 0, "nfs.fattr4_cansettime", HFILL }},
8258
8259                 { &hf_nfs_fattr4_case_insensitive, {
8260                         "fattr4_case_insensitive", "nfs.fattr4_case_insensitive", FT_BOOLEAN,
8261                         BASE_NONE, &yesno, 0, "nfs.fattr4_case_insensitive", HFILL }},
8262
8263                 { &hf_nfs_fattr4_case_preserving, {
8264                         "fattr4_case_preserving", "nfs.fattr4_case_preserving", FT_BOOLEAN,
8265                         BASE_NONE, &yesno, 0, "nfs.fattr4_case_preserving", HFILL }},
8266
8267                 { &hf_nfs_fattr4_chown_restricted, {
8268                         "fattr4_chown_restricted", "nfs.fattr4_chown_restricted", FT_BOOLEAN,
8269                         BASE_NONE, &yesno, 0, "nfs.fattr4_chown_restricted", HFILL }},
8270
8271                 { &hf_nfs_fattr4_hidden, {
8272                         "fattr4_hidden", "nfs.fattr4_hidden", FT_BOOLEAN,
8273                         BASE_NONE, &yesno, 0, "nfs.fattr4_hidden", HFILL }},
8274
8275                 { &hf_nfs_fattr4_homogeneous, {
8276                         "fattr4_homogeneous", "nfs.fattr4_homogeneous", FT_BOOLEAN,
8277                         BASE_NONE, &yesno, 0, "nfs.fattr4_homogeneous", HFILL }},
8278
8279                 { &hf_nfs_fattr4_mimetype, {
8280                         "fattr4_mimetype", "nfs.fattr4_mimetype", FT_STRING, BASE_DEC,
8281                         NULL, 0, "nfs.fattr4_mimetype", HFILL }},
8282
8283                 { &hf_nfs_fattr4_no_trunc, {
8284                         "fattr4_no_trunc", "nfs.fattr4_no_trunc", FT_BOOLEAN,
8285                         BASE_NONE, &yesno, 0, "nfs.fattr4_no_trunc", HFILL }},
8286
8287                 { &hf_nfs_fattr4_system, {
8288                         "fattr4_system", "nfs.fattr4_system", FT_BOOLEAN,
8289                         BASE_NONE, &yesno, 0, "nfs.fattr4_system", HFILL }},
8290
8291                 { &hf_nfs_who, {
8292                         "who", "nfs.who", FT_STRING, BASE_DEC,
8293                         NULL, 0, "nfs.who", HFILL }},
8294
8295                 { &hf_nfs_server, {
8296                         "server", "nfs.server", FT_STRING, BASE_DEC,
8297                         NULL, 0, "nfs.server", HFILL }},
8298
8299                 { &hf_nfs_fattr4_owner, {
8300                         "fattr4_owner", "nfs.fattr4_owner", FT_STRING, BASE_DEC,
8301                         NULL, 0, "nfs.fattr4_owner", HFILL }},
8302
8303                 { &hf_nfs_fattr4_owner_group, {
8304                         "fattr4_owner_group", "nfs.fattr4_owner_group", FT_STRING, BASE_DEC,
8305                         NULL, 0, "nfs.fattr4_owner_group", HFILL }},
8306
8307                 { &hf_nfs_stable_how4, {
8308                         "stable_how4", "nfs.stable_how4", FT_UINT32, BASE_DEC,
8309                         VALS(names_stable_how4), 0, "nfs.stable_how4", HFILL }},
8310
8311                 { &hf_nfs_dirlist4_eof, {
8312                         "eof", "nfs.dirlist4.eof", FT_BOOLEAN,
8313                         BASE_NONE, &yesno, 0, "nfs.dirlist4.eof", HFILL }},
8314
8315                 { &hf_nfs_stateid4, {
8316                         "stateid", "nfs.stateid4", FT_UINT64, BASE_DEC,
8317                         NULL, 0, "nfs.stateid4", HFILL }},
8318
8319                 { &hf_nfs_offset4, {
8320                         "offset", "nfs.offset4", FT_UINT64, BASE_DEC,
8321                         NULL, 0, "nfs.offset4", HFILL }},
8322
8323                 { &hf_nfs_specdata1, {
8324                         "specdata1", "nfs.specdata1", FT_UINT32, BASE_DEC,
8325                         NULL, 0, "nfs.specdata1", HFILL }},
8326
8327                 { &hf_nfs_specdata2, {
8328                         "specdata2", "nfs.specdata2", FT_UINT32, BASE_DEC,
8329                         NULL, 0, "nfs.specdata2", HFILL }},
8330
8331                 { &hf_nfs_lock_type4, {
8332                         "locktype", "nfs.locktype4", FT_UINT32, BASE_DEC,
8333                         VALS(names_nfs_lock_type4), 0, "nfs.locktype4", HFILL }},
8334
8335                 { &hf_nfs_reclaim4, {
8336                         "reclaim", "nfs.reclaim4", FT_BOOLEAN,
8337                         BASE_NONE, &yesno, 0, "Reclaim", HFILL }},
8338
8339                 { &hf_nfs_length4, {
8340                         "length", "nfs.length4", FT_UINT64, BASE_DEC,
8341                         NULL, 0, "nfs.length4", HFILL }},
8342
8343                 { &hf_nfs_changeid4, {
8344                         "changeid", "nfs.changeid4", FT_UINT64, BASE_DEC,
8345                         NULL, 0, "nfs.changeid4", HFILL }},
8346
8347                 { &hf_nfs_changeid4_before, {
8348                         "changeid", "nfs.changeid4.before", FT_UINT64, BASE_DEC,
8349                         NULL, 0, "nfs.changeid4.before", HFILL }},
8350
8351                 { &hf_nfs_changeid4_after, {
8352                         "changeid", "nfs.changeid4.after", FT_UINT64, BASE_DEC,
8353                         NULL, 0, "nfs.changeid4.after", HFILL }},
8354
8355                 { &hf_nfs_nfstime4_seconds, {
8356                         "seconds", "nfs.nfstime4.seconds", FT_UINT64, BASE_DEC,
8357                         NULL, 0, "nfs.nfstime4.seconds", HFILL }},
8358
8359                 { &hf_nfs_nfstime4_nseconds, {
8360                         "nseconds", "nfs.nfstime4.nseconds", FT_UINT32, BASE_DEC,
8361                         NULL, 0, "nfs.nfstime4.nseconds", HFILL }},
8362
8363                 { &hf_nfs_fsid4_major, {
8364                         "fsid4.major", "nfs.fsid4.major", FT_UINT64, BASE_DEC,
8365                         NULL, 0, "nfs.nfstime4.fsid4.major", HFILL }},
8366
8367                 { &hf_nfs_fsid4_minor, {
8368                         "fsid4.minor", "nfs.fsid4.minor", FT_UINT64, BASE_DEC,
8369                         NULL, 0, "nfs.fsid4.minor", HFILL }},
8370
8371                 { &hf_nfs_acetype4, {
8372                         "acetype", "nfs.acetype4", FT_UINT32, BASE_DEC,
8373                         VALS(names_acetype4), 0, "nfs.acetype4", HFILL }},
8374
8375                 { &hf_nfs_aceflag4, {
8376                         "aceflag", "nfs.aceflag4", FT_UINT32, BASE_DEC,
8377                         NULL, 0, "nfs.aceflag4", HFILL }},
8378
8379                 { &hf_nfs_acemask4, {
8380                         "acemask", "nfs.acemask4", FT_UINT32, BASE_DEC,
8381                         NULL, 0, "nfs.acemask4", HFILL }},
8382
8383                 { &hf_nfs_fattr4_size, {
8384                         "size", "nfs.fattr4.size", FT_UINT64, BASE_DEC,
8385                         NULL, 0, "nfs.fattr4.size", HFILL }},
8386
8387                 { &hf_nfs_fattr4_lease_time, {
8388                         "lease_time", "nfs.fattr4.lease_time", FT_UINT32, BASE_DEC,
8389                         NULL, 0, "nfs.fattr4.lease_time", HFILL }},
8390
8391                 { &hf_nfs_fattr4_aclsupport, {
8392                         "aclsupport", "nfs.fattr4.aclsupport", FT_UINT32, BASE_DEC,
8393                         NULL, 0, "nfs.fattr4.aclsupport", HFILL }},
8394
8395                 { &hf_nfs_fattr4_fileid, {
8396                         "fileid", "nfs.fattr4.fileid", FT_UINT64, BASE_DEC,
8397                         NULL, 0, "nfs.fattr4.fileid", HFILL }},
8398
8399                 { &hf_nfs_fattr4_files_avail, {
8400                         "files_avail", "nfs.fattr4.files_avail", FT_UINT64, BASE_DEC,
8401                         NULL, 0, "nfs.fattr4.files_avail", HFILL }},
8402
8403                 { &hf_nfs_fattr4_files_free, {
8404                         "files_free", "nfs.fattr4.files_free", FT_UINT64, BASE_DEC,
8405                         NULL, 0, "nfs.fattr4.files_free", HFILL }},
8406
8407                 { &hf_nfs_fattr4_files_total, {
8408                         "files_total", "nfs.fattr4.files_total", FT_UINT64, BASE_DEC,
8409                         NULL, 0, "nfs.fattr4.files_total", HFILL }},
8410
8411                 { &hf_nfs_fattr4_maxfilesize, {
8412                         "maxfilesize", "nfs.fattr4.maxfilesize", FT_UINT64, BASE_DEC,
8413                         NULL, 0, "nfs.fattr4.maxfilesize", HFILL }},
8414
8415                 { &hf_nfs_fattr4_maxlink, {
8416                         "maxlink", "nfs.fattr4.maxlink", FT_UINT32, BASE_DEC,
8417                         NULL, 0, "nfs.fattr4.maxlink", HFILL }},
8418
8419                 { &hf_nfs_fattr4_maxname, {
8420                         "maxname", "nfs.fattr4.maxname", FT_UINT32, BASE_DEC,
8421                         NULL, 0, "nfs.fattr4.maxname", HFILL }},
8422
8423                 { &hf_nfs_fattr4_numlinks, {
8424                         "numlinks", "nfs.fattr4.numlinks", FT_UINT32, BASE_DEC,
8425                         NULL, 0, "nfs.fattr4.numlinks", HFILL }},
8426
8427                 { &hf_nfs_delegate_type, {
8428                         "delegate_type", "nfs.delegate_type", FT_UINT32, BASE_DEC,
8429                         NULL, 0, "nfs.delegate_type", HFILL }},
8430
8431                 { &hf_nfs_secinfo_flavor, {
8432                         "flavor", "nfs.secinfo.flavor", FT_UINT32, BASE_DEC,
8433                         VALS(rpc_auth_flavor), 0, "nfs.secinfo.flavor", HFILL }},
8434
8435                 { &hf_nfs_num_blocks, {
8436                         "num_blocks", "nfs.num_blocks", FT_UINT32, BASE_DEC,
8437                         NULL, 0, "nfs.num_blocks", HFILL }},
8438
8439                 { &hf_nfs_bytes_per_block, {
8440                         "bytes_per_block", "nfs.bytes_per_block", FT_UINT32, BASE_DEC,
8441                         NULL, 0, "nfs.bytes_per_block", HFILL }},
8442
8443                 { &hf_nfs_eof, {
8444                         "eof", "nfs.eof", FT_UINT32, BASE_DEC,
8445                         NULL, 0, "nfs.eof", HFILL }},
8446
8447                 { &hf_nfs_fattr4_maxread, {
8448                         "maxread", "nfs.fattr4.maxread", FT_UINT64, BASE_DEC,
8449                         NULL, 0, "nfs.fattr4.maxread", HFILL }},
8450
8451                 { &hf_nfs_fattr4_maxwrite, {
8452                         "maxwrite", "nfs.fattr4.maxwrite", FT_UINT64, BASE_DEC,
8453                         NULL, 0, "nfs.fattr4.maxwrite", HFILL }},
8454
8455                 { &hf_nfs_fattr4_quota_hard, {
8456                         "quota_hard", "nfs.fattr4.quota_hard", FT_UINT64, BASE_DEC,
8457                         NULL, 0, "nfs.fattr4.quota_hard", HFILL }},
8458
8459                 { &hf_nfs_fattr4_quota_soft, {
8460                         "quota_soft", "nfs.fattr4.quota_soft", FT_UINT64, BASE_DEC,
8461                         NULL, 0, "nfs.fattr4.quota_soft", HFILL }},
8462
8463                 { &hf_nfs_fattr4_quota_used, {
8464                         "quota_used", "nfs.fattr4.quota_used", FT_UINT64, BASE_DEC,
8465                         NULL, 0, "nfs.fattr4.quota_used", HFILL }},
8466
8467                 { &hf_nfs_fattr4_space_avail, {
8468                         "space_avail", "nfs.fattr4.space_avail", FT_UINT64, BASE_DEC,
8469                         NULL, 0, "nfs.fattr4.space_avail", HFILL }},
8470
8471                 { &hf_nfs_fattr4_space_free, {
8472                         "space_free", "nfs.fattr4.space_free", FT_UINT64, BASE_DEC,
8473                         NULL, 0, "nfs.fattr4.space_free", HFILL }},
8474
8475                 { &hf_nfs_fattr4_space_total, {
8476                         "space_total", "nfs.fattr4.space_total", FT_UINT64, BASE_DEC,
8477                         NULL, 0, "nfs.fattr4.space_total", HFILL }},
8478
8479                 { &hf_nfs_fattr4_space_used, {
8480                         "space_used", "nfs.fattr4.space_used", FT_UINT64, BASE_DEC,
8481                         NULL, 0, "nfs.fattr4.space_used", HFILL }},
8482
8483                 { &hf_nfs_stateid4_delegate_stateid, {
8484                         "delegate_stateid", "nfs.delegate_stateid", FT_UINT64, BASE_DEC,
8485                         NULL, 0, "nfs.delegate_stateid", HFILL }},
8486
8487                 { &hf_nfs_verifier4, {
8488                         "verifier", "nfs.verifier4", FT_UINT64, BASE_HEX,
8489                         NULL, 0, "nfs.verifier4", HFILL }},
8490
8491                 { &hf_nfs_cookie4, {
8492                         "cookie", "nfs.cookie4", FT_UINT64, BASE_DEC,
8493                         NULL, 0, "nfs.cookie4", HFILL }},
8494
8495                 { &hf_nfs_cookieverf4, {
8496                         "cookieverf", "nfs.cookieverf4", FT_UINT64, BASE_DEC,
8497                         NULL, 0, "nfs.cookieverf4", HFILL }},
8498
8499                 { &hf_nfs_cb_location, {
8500                         "cb_location", "nfs.cb_location", FT_UINT32, BASE_DEC,
8501                         NULL, 0, "nfs.cb_location", HFILL }},
8502
8503                 { &hf_nfs_cb_program, {
8504                         "cb_program", "nfs.cb_program", FT_UINT32, BASE_HEX,
8505                         NULL, 0, "nfs.cb_program", HFILL }},
8506
8507                 { &hf_nfs_recall4, {
8508                         "recall", "nfs.recall4", FT_BOOLEAN,
8509                         BASE_NONE, &yesno, 0, "nfs.recall4", HFILL }},
8510
8511                 { &hf_nfs_filesize, {
8512                         "filesize", "nfs.filesize", FT_UINT64, BASE_DEC,
8513                         NULL, 0, "nfs.filesize", HFILL }},
8514
8515                 { &hf_nfs_count4, {
8516                         "count", "nfs.count4", FT_UINT32, BASE_DEC,
8517                         NULL, 0, "nfs.count4", HFILL }},
8518
8519                 { &hf_nfs_count4_dircount, {
8520                         "dircount", "nfs.dircount", FT_UINT32, BASE_DEC,
8521                         NULL, 0, "nfs.dircount", HFILL }},
8522
8523                 { &hf_nfs_count4_maxcount, {
8524                         "maxcount", "nfs.maxcount", FT_UINT32, BASE_DEC,
8525                         NULL, 0, "nfs.maxcount", HFILL }},
8526
8527                 { &hf_nfs_minorversion, {
8528                         "minorversion", "nfs.minorversion", FT_UINT32, BASE_DEC,
8529                         NULL, 0, "nfs.minorversion", HFILL }},
8530
8531                 { &hf_nfs_atime, {
8532                         "atime", "nfs.atime", FT_ABSOLUTE_TIME, BASE_NONE,
8533                         NULL, 0, "Access Time", HFILL }},
8534
8535                 { &hf_nfs_atime_sec, {
8536                         "seconds", "nfs.atime.sec", FT_UINT32, BASE_DEC,
8537                         NULL, 0, "Access Time, Seconds", HFILL }},
8538
8539                 { &hf_nfs_atime_nsec, {
8540                         "nano seconds", "nfs.atime.nsec", FT_UINT32, BASE_DEC,
8541                         NULL, 0, "Access Time, Nano-seconds", HFILL }},
8542
8543                 { &hf_nfs_atime_usec, {
8544                         "micro seconds", "nfs.atime.usec", FT_UINT32, BASE_DEC,
8545                         NULL, 0, "Access Time, Micro-seconds", HFILL }},
8546
8547                 { &hf_nfs_mtime, {
8548                         "mtime", "nfs.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
8549                         NULL, 0, "Modify Time", HFILL }},
8550
8551                 { &hf_nfs_mtime_sec, {
8552                         "seconds", "nfs.mtime.sec", FT_UINT32, BASE_DEC,
8553                         NULL, 0, "Modify Seconds", HFILL }},
8554
8555                 { &hf_nfs_mtime_nsec, {
8556                         "nano seconds", "nfs.mtime.nsec", FT_UINT32, BASE_DEC,
8557                         NULL, 0, "Modify Time, Nano-seconds", HFILL }},
8558
8559                 { &hf_nfs_mtime_usec, {
8560                         "micro seconds", "nfs.mtime.usec", FT_UINT32, BASE_DEC,
8561                         NULL, 0, "Modify Time, Micro-seconds", HFILL }},
8562
8563                 { &hf_nfs_ctime, {
8564                         "ctime", "nfs.ctime", FT_ABSOLUTE_TIME, BASE_NONE,
8565                         NULL, 0, "Creation Time", HFILL }},
8566
8567                 { &hf_nfs_ctime_sec, {
8568                         "seconds", "nfs.ctime.sec", FT_UINT32, BASE_DEC,
8569                         NULL, 0, "Creation Time, Seconds", HFILL }},
8570
8571                 { &hf_nfs_ctime_nsec, {
8572                         "nano seconds", "nfs.ctime.nsec", FT_UINT32, BASE_DEC,
8573                         NULL, 0, "Creation Time, Nano-seconds", HFILL }},
8574
8575                 { &hf_nfs_ctime_usec, {
8576                         "micro seconds", "nfs.ctime.usec", FT_UINT32, BASE_DEC,
8577                         NULL, 0, "Creation Time, Micro-seconds", HFILL }},
8578
8579                 { &hf_nfs_dtime, {
8580                         "time delta", "nfs.dtime", FT_RELATIVE_TIME, BASE_NONE,
8581                         NULL, 0, "Time Delta", HFILL }},
8582
8583                 { &hf_nfs_dtime_sec, {
8584                         "seconds", "nfs.dtime.sec", FT_UINT32, BASE_DEC,
8585                         NULL, 0, "Time Delta, Seconds", HFILL }},
8586
8587                 { &hf_nfs_dtime_nsec, {
8588                         "nano seconds", "nfs.dtime.nsec", FT_UINT32, BASE_DEC,
8589                         NULL, 0, "Time Delta, Nano-seconds", HFILL }},
8590
8591                 { &hf_nfs_open_owner4, {
8592                         "owner", "nfs.open_owner4", FT_BYTES, BASE_DEC,
8593                         NULL, 0, "owner", HFILL }},
8594
8595                 { &hf_nfs_lock_owner4, {
8596                         "owner", "nfs.lock_owner4", FT_BYTES, BASE_DEC,
8597                         NULL, 0, "owner", HFILL }},
8598
8599                 { &hf_nfs_secinfo_rpcsec_gss_info_service, {
8600                         "service", "nfs.secinfo.rpcsec_gss_info.service", FT_UINT32,
8601                         BASE_DEC, VALS(rpc_authgss_svc), 0, "service", HFILL }},
8602
8603                 { &hf_nfs_attrdircreate, {
8604                         "attribute dir create", "nfs.openattr4.createdir", FT_BOOLEAN,
8605                         BASE_NONE, &yesno, 0, "nfs.openattr4.createdir", HFILL }},
8606
8607                 { &hf_nfs_new_lock_owner, {
8608                         "new lock owner?", "nfs.lock.locker.new_lock_owner", FT_BOOLEAN,
8609                         BASE_NONE, &yesno, 0, "nfs.lock.locker.new_lock_owner", HFILL }},
8610
8611                 { &hf_nfs_lock4_reclaim, {
8612                         "reclaim?", "nfs.lock.reclaim", FT_BOOLEAN,
8613                         BASE_NONE, &yesno, 0, "nfs.lock.reclaim", HFILL }},
8614
8615                 { &hf_nfs_sec_oid4, {
8616                         "oid", "nfs.secinfo.flavor_info.rpcsec_gss_info.oid", FT_BYTES,
8617                         BASE_DEC, NULL, 0, "oid", HFILL }},
8618
8619                 { &hf_nfs_qop4, {
8620                         "qop", "nfs.secinfo.flavor_info.rpcsec_gss_info.qop", FT_UINT32,
8621                         BASE_DEC, NULL, 0, "qop", HFILL }},
8622
8623                 { &hf_nfs_client_id4_id, {
8624                         "id", "nfs.nfs_client_id4.id", FT_BYTES, BASE_DEC,
8625                         NULL, 0, "nfs.nfs_client_id4.id", HFILL }},
8626
8627                 { &hf_nfs_stateid4_other, {
8628                         "Data", "nfs.stateid4.other", FT_BYTES, BASE_DEC,
8629                         NULL, 0, "Data", HFILL }},
8630
8631                 { &hf_nfs_acl4, {
8632                         "ACL", "nfs.acl", FT_NONE, BASE_NONE,
8633                         NULL, 0, "Access Control List", HFILL }},
8634
8635                 { &hf_nfs_callback_ident, {
8636                         "callback_ident", "nfs.callback.ident", FT_UINT32, BASE_HEX,
8637                         NULL, 0, "Callback Identifier", HFILL }},
8638
8639                 { &hf_nfs_r_netid, {
8640                         "r_netid", "nfs.r_netid", FT_BYTES, BASE_DEC, NULL, 0,
8641                         "r_netid", HFILL }},
8642
8643                 { &hf_nfs_r_addr, {
8644                         "r_addr", "nfs.r_addr", FT_BYTES, BASE_DEC, NULL, 0,
8645                         "r_addr", HFILL }},
8646
8647                 { &hf_nfs_secinfo_arr4, {
8648                         "Flavors Info", "nfs.flavors.info", FT_NONE, BASE_NONE,
8649                         NULL, 0, "Flavors Info", HFILL }},
8650         };
8651
8652         static gint *ett[] = {
8653                 &ett_nfs,
8654                 &ett_nfs_fh_encoding,
8655                 &ett_nfs_fh_fsid,
8656                 &ett_nfs_fh_file,
8657                 &ett_nfs_fh_mount,
8658                 &ett_nfs_fh_export,
8659                 &ett_nfs_fh_xfsid,
8660                 &ett_nfs_fh_fn,
8661                 &ett_nfs_fh_xfn,
8662                 &ett_nfs_fh_hp,
8663                 &ett_nfs_fh_auth,
8664                 &ett_nfs_fhandle,
8665                 &ett_nfs_timeval,
8666                 &ett_nfs_mode,
8667                 &ett_nfs_fattr,
8668                 &ett_nfs_sattr,
8669                 &ett_nfs_diropargs,
8670                 &ett_nfs_readdir_entry,
8671                 &ett_nfs_mode3,
8672                 &ett_nfs_specdata3,
8673                 &ett_nfs_fh3,
8674                 &ett_nfs_nfstime3,
8675                 &ett_nfs_fattr3,
8676                 &ett_nfs_post_op_fh3,
8677                 &ett_nfs_sattr3,
8678                 &ett_nfs_diropargs3,
8679                 &ett_nfs_sattrguard3,
8680                 &ett_nfs_set_mode3,
8681                 &ett_nfs_set_uid3,
8682                 &ett_nfs_set_gid3,
8683                 &ett_nfs_set_size3,
8684                 &ett_nfs_set_atime,
8685                 &ett_nfs_set_mtime,
8686                 &ett_nfs_pre_op_attr,
8687                 &ett_nfs_post_op_attr,
8688                 &ett_nfs_wcc_attr,
8689                 &ett_nfs_wcc_data,
8690                 &ett_nfs_access,
8691                 &ett_nfs_fsinfo_properties,
8692                 &ett_nfs_compound_call4,
8693                 &ett_nfs_utf8string,
8694                 &ett_nfs_argop4,
8695                 &ett_nfs_resop4,
8696                 &ett_nfs_access4,
8697                 &ett_nfs_close4,
8698                 &ett_nfs_commit4,
8699                 &ett_nfs_create4,
8700                 &ett_nfs_delegpurge4,
8701                 &ett_nfs_delegreturn4,
8702                 &ett_nfs_getattr4,
8703                 &ett_nfs_getfh4,
8704                 &ett_nfs_link4,
8705                 &ett_nfs_lock4,
8706                 &ett_nfs_lockt4,
8707                 &ett_nfs_locku4,
8708                 &ett_nfs_lookup4,
8709                 &ett_nfs_lookupp4,
8710                 &ett_nfs_nverify4,
8711                 &ett_nfs_open4,
8712                 &ett_nfs_openattr4,
8713                 &ett_nfs_open_confirm4,
8714                 &ett_nfs_open_downgrade4,
8715                 &ett_nfs_putfh4,
8716                 &ett_nfs_putpubfh4,
8717                 &ett_nfs_putrootfh4,
8718                 &ett_nfs_read4,
8719                 &ett_nfs_readdir4,
8720                 &ett_nfs_readlink4,
8721                 &ett_nfs_remove4,
8722                 &ett_nfs_rename4,
8723                 &ett_nfs_renew4,
8724                 &ett_nfs_restorefh4,
8725                 &ett_nfs_savefh4,
8726                 &ett_nfs_setattr4,
8727                 &ett_nfs_setclientid4,
8728                 &ett_nfs_setclientid_confirm4,
8729                 &ett_nfs_verify4,
8730                 &ett_nfs_write4,
8731                 &ett_nfs_release_lockowner4,
8732                 &ett_nfs_illegal4,
8733                 &ett_nfs_verifier4,
8734                 &ett_nfs_opaque,
8735                 &ett_nfs_dirlist4,
8736                 &ett_nfs_pathname4,
8737                 &ett_nfs_change_info4,
8738                 &ett_nfs_open_delegation4,
8739                 &ett_nfs_open_claim4,
8740                 &ett_nfs_opentype4,
8741                 &ett_nfs_lock_owner4,
8742                 &ett_nfs_cb_client4,
8743                 &ett_nfs_client_id4,
8744                 &ett_nfs_bitmap4,
8745                 &ett_nfs_fattr4,
8746                 &ett_nfs_fsid4,
8747                 &ett_nfs_fs_locations4,
8748                 &ett_nfs_fs_location4,
8749                 &ett_nfs_open4_result_flags,
8750                 &ett_nfs_secinfo4,
8751                 &ett_nfs_secinfo4_flavor_info,
8752                 &ett_nfs_stateid4,
8753                 &ett_nfs_fattr4_fh_expire_type,
8754                 &ett_nfs_ace4,
8755                 &ett_nfs_clientaddr4,
8756                 &ett_nfs_aceflag4,
8757                 &ett_nfs_acemask4,
8758         };
8759         module_t *nfs_module;
8760
8761         proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs");
8762         proto_register_field_array(proto_nfs, hf, array_length(hf));
8763         proto_register_subtree_array(ett, array_length(ett));
8764
8765         nfs_module=prefs_register_protocol(proto_nfs, NULL);
8766         prefs_register_bool_preference(nfs_module, "file_name_snooping",
8767                                        "Snoop FH to filename mappings",
8768                                        "Whether the dissector should snoop the FH to filename mappings by looking inside certain packets",
8769                                        &nfs_file_name_snooping);
8770         prefs_register_bool_preference(nfs_module, "file_full_name_snooping",
8771                                        "Snoop full path to filenames",
8772                                        "Whether the dissector should snoop the full pathname for files for matching FH's",
8773                                        &nfs_file_name_full_snooping);
8774         prefs_register_bool_preference(nfs_module, "fhandle_find_both_reqrep",
8775                                        "Fhandle filters finds both request/response",
8776                                        "With this option display filters for nfs fhandles (nfs.fh.{name|full_name|hash}) will find both the request and response packets for a RPC call, even if the actual fhandle is only present in one of the packets",
8777                                         &nfs_fhandle_reqrep_matching);
8778         register_init_routine(nfs_name_snoop_init);
8779         register_init_routine(nfs_fhandle_reqrep_matching_init);
8780 }
8781
8782 void
8783 proto_reg_handoff_nfs(void)
8784 {
8785         /* Register the protocol as RPC */
8786         rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
8787         /* Register the procedure tables */
8788         rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc, hf_nfs_procedure_v2);
8789         rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc, hf_nfs_procedure_v3);
8790         rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc, hf_nfs_procedure_v4);
8791 }