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