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