8dc8b85158e44c73937bed081220f1a6779c7012
[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.63 2002/01/14 13:16:31 girlich 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,
1721                         tvb_length_remaining(tvb, offset), "%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,
1760                         tvb_length_remaining(tvb, offset), "%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,
1876                         tvb_length_remaining(tvb, offset), "%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, tvb_length_remaining(tvb, offset), 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,
2641                         tvb_length_remaining(tvb, offset), "%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,
2695                         tvb_length_remaining(tvb, offset), "%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,
2735                         tvb_length_remaining(tvb, offset), "%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,
2765                         tvb_length_remaining(tvb, offset), "%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,
2805                         tvb_length_remaining(tvb, offset), "%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,
2834                         tvb_length_remaining(tvb, offset), "%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,
2879                         tvb_length_remaining(tvb, offset), "%s: %s",
2880                         name, set_it_name);
2881                 set_mode3_tree = proto_item_add_subtree(set_mode3_item, 
2882                         ett_nfs_set_mode3);
2883         }
2884
2885         if (set_mode3_tree)
2886                 proto_tree_add_text(set_mode3_tree, tvb, offset, 4,
2887                         "set_it: %s (%u)", set_it_name, set_it);
2888
2889         offset += 4;
2890
2891         switch (set_it) {
2892                 case 1:
2893                         offset = dissect_mode3(tvb, offset, pinfo, set_mode3_tree,
2894                                         "mode");
2895                 break;
2896                 default:
2897                         /* void */
2898                 break;
2899         }
2900         
2901         /* now we know, that set_mode3 is shorter */
2902         if (set_mode3_item) {
2903                 proto_item_set_len(set_mode3_item, offset - old_offset);
2904         }
2905
2906         return offset;
2907 }
2908
2909
2910 /* RFC 1813, Page 26 */
2911 int
2912 dissect_set_uid3(tvbuff_t *tvb, int offset, packet_info *pinfo, 
2913         proto_tree *tree, char* name)
2914 {
2915         proto_item* set_uid3_item = NULL;
2916         proto_tree* set_uid3_tree = NULL;
2917         int old_offset = offset;
2918         guint32 set_it;
2919         char* set_it_name;
2920
2921         set_it = tvb_get_ntohl(tvb, offset+0);
2922         set_it_name = val_to_str(set_it,value_follows,"Unknown");
2923
2924         if (tree) {
2925                 set_uid3_item = proto_tree_add_text(tree, tvb, offset,
2926                         tvb_length_remaining(tvb, offset), "%s: %s",
2927                         name, set_it_name);
2928                 set_uid3_tree = proto_item_add_subtree(set_uid3_item, 
2929                         ett_nfs_set_uid3);
2930         }
2931
2932         if (set_uid3_tree)
2933                 proto_tree_add_text(set_uid3_tree, tvb, offset, 4,
2934                         "set_it: %s (%u)", set_it_name, set_it);
2935
2936         offset += 4;
2937
2938         switch (set_it) {
2939                 case 1:
2940                         offset = dissect_rpc_uint32(tvb, pinfo, set_uid3_tree,
2941                                                                  hf_nfs_uid3, offset);
2942                 break;
2943                 default:
2944                         /* void */
2945                 break;
2946         }
2947
2948         /* now we know, that set_uid3 is shorter */
2949         if (set_uid3_item) {
2950                 proto_item_set_len(set_uid3_item, offset - old_offset);
2951         }
2952
2953         return offset;
2954 }
2955
2956
2957 /* RFC 1813, Page 26 */
2958 int
2959 dissect_set_gid3(tvbuff_t *tvb, int offset, packet_info *pinfo, 
2960         proto_tree *tree, char* name)
2961 {
2962         proto_item* set_gid3_item = NULL;
2963         proto_tree* set_gid3_tree = NULL;
2964         int old_offset = offset;
2965         guint32 set_it;
2966         char* set_it_name;
2967
2968         set_it = tvb_get_ntohl(tvb, offset+0);
2969         set_it_name = val_to_str(set_it,value_follows,"Unknown");
2970
2971         if (tree) {
2972                 set_gid3_item = proto_tree_add_text(tree, tvb, offset,
2973                         tvb_length_remaining(tvb, offset), "%s: %s",
2974                         name, set_it_name);
2975                 set_gid3_tree = proto_item_add_subtree(set_gid3_item, 
2976                         ett_nfs_set_gid3);
2977         }
2978
2979         if (set_gid3_tree)
2980                 proto_tree_add_text(set_gid3_tree, tvb, offset, 4,
2981                         "set_it: %s (%u)", set_it_name, set_it);
2982
2983         offset += 4;
2984
2985         switch (set_it) {
2986                 case 1:
2987                         offset = dissect_rpc_uint32(tvb, pinfo, set_gid3_tree, 
2988                                 hf_nfs_gid3, offset);
2989                 break;
2990                 default:
2991                         /* void */
2992                 break;
2993         }
2994
2995         /* now we know, that set_gid3 is shorter */
2996         if (set_gid3_item) {
2997                 proto_item_set_len(set_gid3_item, offset - old_offset);
2998         }
2999
3000         return offset;
3001 }
3002
3003
3004 /* RFC 1813, Page 26 */
3005 int
3006 dissect_set_size3(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3007         proto_tree *tree, char* name)
3008 {
3009         proto_item* set_size3_item = NULL;
3010         proto_tree* set_size3_tree = NULL;
3011         int old_offset = offset;
3012         guint32 set_it;
3013         char* set_it_name;
3014
3015         set_it = tvb_get_ntohl(tvb, offset+0);
3016         set_it_name = val_to_str(set_it,value_follows,"Unknown");
3017
3018         if (tree) {
3019                 set_size3_item = proto_tree_add_text(tree, tvb, offset,
3020                         tvb_length_remaining(tvb, offset), "%s: %s",
3021                         name, set_it_name);
3022                 set_size3_tree = proto_item_add_subtree(set_size3_item, 
3023                         ett_nfs_set_size3);
3024         }
3025
3026         if (set_size3_tree)
3027                 proto_tree_add_text(set_size3_tree, tvb, offset, 4,
3028                         "set_it: %s (%u)", set_it_name, set_it);
3029
3030         offset += 4;
3031
3032         switch (set_it) {
3033                 case 1:
3034                         offset = dissect_rpc_uint64(tvb, pinfo, set_size3_tree,
3035                                 hf_nfs_set_size3_size, offset);
3036                 break;
3037                 default:
3038                         /* void */
3039                 break;
3040         }
3041
3042         /* now we know, that set_size3 is shorter */
3043         if (set_size3_item) {
3044                 proto_item_set_len(set_size3_item, offset - old_offset);
3045         }
3046
3047         return offset;
3048 }
3049
3050
3051 /* RFC 1813, Page 25 */
3052 #define DONT_CHANGE 0
3053 #define SET_TO_SERVER_TIME 1
3054 #define SET_TO_CLIENT_TIME 2
3055
3056 const value_string time_how[] =
3057         {
3058                 { DONT_CHANGE,  "don't change" },
3059                 { SET_TO_SERVER_TIME, "set to server time" },
3060                 { SET_TO_CLIENT_TIME, "set to client time" },
3061                 { 0, NULL }
3062         };
3063
3064
3065 /* RFC 1813, Page 26 */
3066 int
3067 dissect_set_atime(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3068         proto_tree *tree, char* name)
3069 {
3070         proto_item* set_atime_item = NULL;
3071         proto_tree* set_atime_tree = NULL;
3072         int old_offset = offset;
3073         guint32 set_it;
3074         char* set_it_name;
3075
3076         set_it = tvb_get_ntohl(tvb, offset+0);
3077         set_it_name = val_to_str(set_it,time_how,"Unknown");
3078
3079         if (tree) {
3080                 set_atime_item = proto_tree_add_text(tree, tvb, offset,
3081                         tvb_length_remaining(tvb, offset), "%s: %s",
3082                         name, set_it_name);
3083                 set_atime_tree = proto_item_add_subtree(set_atime_item, 
3084                         ett_nfs_set_atime);
3085         }
3086
3087         if (set_atime_tree)
3088                 proto_tree_add_text(set_atime_tree, tvb, offset, 4,
3089                         "set_it: %s (%u)", set_it_name, set_it);
3090
3091         offset += 4;
3092
3093         switch (set_it) {
3094                 case SET_TO_CLIENT_TIME:
3095                         if (set_atime_item) {
3096                                 offset = dissect_nfstime3(tvb, offset, pinfo, set_atime_tree,
3097                                         hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
3098                         }
3099                 break;
3100                 default:
3101                         /* void */
3102                 break;
3103         }
3104
3105         /* now we know, that set_atime is shorter */
3106         if (set_atime_item) {
3107                 proto_item_set_len(set_atime_item, offset - old_offset);
3108         }
3109
3110         return offset;
3111 }
3112
3113
3114 /* RFC 1813, Page 26 */
3115 int
3116 dissect_set_mtime(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3117         proto_tree *tree, char* name)
3118 {
3119         proto_item* set_mtime_item = NULL;
3120         proto_tree* set_mtime_tree = NULL;
3121         int old_offset = offset;
3122         guint32 set_it;
3123         char* set_it_name;
3124
3125         set_it = tvb_get_ntohl(tvb, offset+0);
3126         set_it_name = val_to_str(set_it,time_how,"Unknown");
3127
3128         if (tree) {
3129                 set_mtime_item = proto_tree_add_text(tree, tvb, offset,
3130                         tvb_length_remaining(tvb, offset), "%s: %s",
3131                         name, set_it_name);
3132                 set_mtime_tree = proto_item_add_subtree(set_mtime_item, 
3133                         ett_nfs_set_mtime);
3134         }
3135
3136         if (set_mtime_tree)
3137                 proto_tree_add_text(set_mtime_tree, tvb, offset, 4,
3138                                 "set_it: %s (%u)", set_it_name, set_it);
3139
3140         offset += 4;
3141
3142         switch (set_it) {
3143                 case SET_TO_CLIENT_TIME:
3144                         if (set_mtime_item) {
3145                                 offset = dissect_nfstime3(tvb, offset, pinfo, set_mtime_tree,
3146                                         hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
3147                         }
3148                 break;
3149                 default:
3150                         /* void */
3151                 break;
3152         }
3153
3154         /* now we know, that set_mtime is shorter */
3155         if (set_mtime_item) {
3156                 proto_item_set_len(set_mtime_item, offset - old_offset);
3157         }
3158
3159         return offset;
3160 }
3161
3162
3163 /* RFC 1813, Page 25..27 */
3164 int
3165 dissect_sattr3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
3166         char* name)
3167 {
3168         proto_item* sattr3_item = NULL;
3169         proto_tree* sattr3_tree = NULL;
3170         int old_offset = offset;
3171
3172         if (tree) {
3173                 sattr3_item = proto_tree_add_text(tree, tvb, offset,
3174                         tvb_length_remaining(tvb, offset), "%s", name);
3175                 sattr3_tree = proto_item_add_subtree(sattr3_item, ett_nfs_sattr3);
3176         }
3177
3178         offset = dissect_set_mode3(tvb, offset, pinfo, sattr3_tree, "mode");
3179         offset = dissect_set_uid3 (tvb, offset, pinfo, sattr3_tree, "uid");
3180         offset = dissect_set_gid3 (tvb, offset, pinfo, sattr3_tree, "gid");
3181         offset = dissect_set_size3(tvb, offset, pinfo, sattr3_tree, "size");
3182         offset = dissect_set_atime(tvb, offset, pinfo, sattr3_tree, "atime");
3183         offset = dissect_set_mtime(tvb, offset, pinfo, sattr3_tree, "mtime");
3184
3185         /* now we know, that sattr3 is shorter */
3186         if (sattr3_item) {
3187                 proto_item_set_len(sattr3_item, offset - old_offset);
3188         }
3189
3190         return offset;
3191 }
3192
3193
3194 /* RFC 1813, Page 27 */
3195 int
3196 dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3197         proto_tree *tree, char* name)
3198 {
3199         proto_item* diropargs3_item = NULL;
3200         proto_tree* diropargs3_tree = NULL;
3201         int old_offset = offset;
3202         int parent_offset, parent_len;
3203         int name_offset, name_len;
3204
3205         if (tree) {
3206                 diropargs3_item = proto_tree_add_text(tree, tvb, offset,
3207                         tvb_length_remaining(tvb, offset), "%s", name);
3208                 diropargs3_tree = proto_item_add_subtree(diropargs3_item, 
3209                         ett_nfs_diropargs3);
3210         }
3211
3212         parent_offset=offset+4;
3213         parent_len=tvb_get_ntohl(tvb, offset);
3214         offset = dissect_nfs_fh3(tvb, offset, pinfo, diropargs3_tree, "dir");
3215         name_offset=offset+4;
3216         name_len=tvb_get_ntohl(tvb, offset);
3217         offset = dissect_filename3(tvb, offset, pinfo, diropargs3_tree, 
3218                 hf_nfs_name, NULL);
3219
3220         /* are we snooping fh to filenames ?*/
3221         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
3222                 /* v3 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
3223                 rpc_call_info_value *civ=pinfo->private_data;
3224
3225                 if( (civ->prog==100003)
3226                   &&(civ->vers==3)
3227                   &&(civ->request)
3228                   &&((civ->proc==3)||(civ->proc==8)||(civ->proc==9))
3229                 ) {
3230                         nfs_name_snoop_add_name(civ->xid, tvb, 
3231                                 name_offset, name_len,
3232                                 parent_offset, parent_len, NULL);
3233                 }
3234         }
3235
3236
3237         /* now we know, that diropargs3 is shorter */
3238         if (diropargs3_item) {
3239                 proto_item_set_len(diropargs3_item, offset - old_offset);
3240         }
3241
3242         return offset;
3243 }
3244
3245
3246 /* RFC 1813, Page 27 */
3247 int
3248 dissect_nfs3_diropargs3_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3249         proto_tree *tree)
3250 {
3251         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object");
3252
3253         return offset;
3254 }
3255
3256
3257 /* RFC 1813, Page 40 */
3258 int
3259 dissect_access(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
3260         char* name)
3261 {
3262         guint32 access;
3263         proto_item* access_item = NULL;
3264         proto_tree* access_tree = NULL;
3265
3266         access = tvb_get_ntohl(tvb, offset+0);
3267         
3268         if (tree) {
3269                 access_item = proto_tree_add_text(tree, tvb, offset, 4,
3270                         "%s: 0x%02x", name, access);
3271                 if (access_item)
3272                         access_tree = proto_item_add_subtree(access_item, ett_nfs_access);
3273         }
3274
3275         if (access_tree) {
3276                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s READ",
3277                 decode_boolean_bitfield(access,  0x001, 6, "allow", "not allow"));
3278                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s LOOKUP",
3279                 decode_boolean_bitfield(access,  0x002, 6, "allow", "not allow"));
3280                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s MODIFY",
3281                 decode_boolean_bitfield(access,  0x004, 6, "allow", "not allow"));
3282                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s EXTEND",
3283                 decode_boolean_bitfield(access,  0x008, 6, "allow", "not allow"));
3284                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s DELETE",
3285                 decode_boolean_bitfield(access,  0x010, 6, "allow", "not allow"));
3286                 proto_tree_add_text(access_tree, tvb, offset, 4, "%s EXECUTE",
3287                 decode_boolean_bitfield(access,  0x020, 6, "allow", "not allow"));
3288         }
3289
3290         offset += 4;
3291         return offset;
3292 }
3293
3294
3295 /* NFS3 file handle dissector */
3296 int
3297 dissect_nfs3_nfs_fh3_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3298         proto_tree* tree)
3299 {
3300         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
3301         return offset;
3302 }
3303
3304
3305 /* generic NFS3 reply dissector */
3306 int
3307 dissect_nfs3_any_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3308         proto_tree* tree)
3309 {
3310         guint32 status;
3311
3312         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3313
3314         return offset;
3315
3316 }
3317
3318
3319 /* RFC 1813, Page 32,33 */
3320 int
3321 dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3322         proto_tree* tree)
3323 {
3324         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
3325         return offset;
3326 }
3327
3328
3329 /* RFC 1813, Page 32,33 */
3330 int
3331 dissect_nfs3_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3332         proto_tree* tree)
3333 {
3334         guint32 status;
3335
3336         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3337         switch (status) {
3338                 case 0:
3339                         offset = dissect_fattr3(tvb, offset, pinfo, tree, "obj_attributes");
3340                 break;
3341                 default:
3342                         /* void */
3343                 break;
3344         }
3345                 
3346         return offset;
3347 }
3348
3349
3350 /* RFC 1813, Page 33 */
3351 int
3352 dissect_sattrguard3(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3353         proto_tree* tree, char *name)
3354 {
3355         proto_item* sattrguard3_item = NULL;
3356         proto_tree* sattrguard3_tree = NULL;
3357         int old_offset = offset;
3358         guint32 check;
3359         char* check_name;
3360
3361         check = tvb_get_ntohl(tvb, offset+0);
3362         check_name = val_to_str(check,value_follows,"Unknown");
3363
3364         if (tree) {
3365                 sattrguard3_item = proto_tree_add_text(tree, tvb, offset,
3366                         tvb_length_remaining(tvb, offset), "%s: %s",
3367                         name, check_name);
3368                 sattrguard3_tree = proto_item_add_subtree(sattrguard3_item, 
3369                         ett_nfs_sattrguard3);
3370         }
3371
3372         if (sattrguard3_tree)
3373                 proto_tree_add_text(sattrguard3_tree, tvb, offset, 4,
3374                         "check: %s (%u)", check_name, check);
3375
3376         offset += 4;
3377
3378         switch (check) {
3379                 case TRUE:
3380                         offset = dissect_nfstime3(tvb, offset, pinfo, sattrguard3_tree,
3381                                         hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
3382                 break;
3383                 case FALSE:
3384                         /* void */
3385                 break;
3386         }
3387
3388         /* now we know, that sattrguard3 is shorter */
3389         if (sattrguard3_item) {
3390                 proto_item_set_len(sattrguard3_item, offset - old_offset);
3391         }
3392
3393         return offset;
3394 }
3395
3396
3397 /* RFC 1813, Page 33..36 */
3398 int
3399 dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3400         proto_tree* tree)
3401 {
3402         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "object");
3403         offset = dissect_sattr3     (tvb, offset, pinfo, tree, "new_attributes");
3404         offset = dissect_sattrguard3(tvb, offset, pinfo, tree, "guard");
3405         return offset;
3406 }
3407
3408
3409 /* RFC 1813, Page 33..36 */
3410 int
3411 dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3412         proto_tree* tree)
3413 {
3414         guint32 status;
3415
3416         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3417         switch (status) {
3418                 case 0:
3419                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "obj_wcc");
3420                 break;
3421                 default:
3422                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "obj_wcc");
3423                 break;
3424         }
3425                 
3426         return offset;
3427 }
3428
3429
3430 /* RFC 1813, Page 37..39 */
3431 int
3432 dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3433         proto_tree* tree)
3434 {
3435         offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what");
3436         return offset;
3437 }
3438
3439
3440 /* RFC 1813, Page 37..39 */
3441 int
3442 dissect_nfs3_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3443         proto_tree* tree)
3444 {
3445         guint32 status;
3446
3447         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3448         switch (status) {
3449                 case 0:
3450                         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
3451                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3452                                 "obj_attributes");
3453                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3454                                 "dir_attributes");
3455                 break;
3456                 default:
3457                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3458                                 "dir_attributes");
3459                 break;
3460         }
3461                 
3462         return offset;
3463 }
3464
3465
3466 /* RFC 1813, Page 40..43 */
3467 int
3468 dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3469         proto_tree* tree)
3470 {
3471         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object");
3472         offset = dissect_access (tvb, offset, pinfo, tree, "access");
3473
3474         return offset;
3475 }
3476
3477
3478 /* RFC 1813, Page 40..43 */
3479 int
3480 dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3481         proto_tree* tree)
3482 {
3483         guint32 status;
3484
3485         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3486         switch (status) {
3487                 case 0:
3488                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3489                                 "obj_attributes");
3490                         offset = dissect_access(tvb, offset, pinfo, tree, "access");
3491                 break;
3492                 default:
3493                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3494                                 "obj_attributes");
3495                 break;
3496         }
3497                 
3498         return offset;
3499 }
3500
3501
3502 /* RFC 1813, Page 44,45 */
3503 int
3504 dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3505         proto_tree* tree)
3506 {
3507         guint32 status;
3508
3509         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3510         switch (status) {
3511                 case 0:
3512                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3513                                 "symlink_attributes");
3514                         offset = dissect_nfspath3(tvb, offset, pinfo, tree, 
3515                                 hf_nfs_readlink_data);
3516                 break;
3517                 default:
3518                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3519                                 "symlink_attributes");
3520                 break;
3521         }
3522                 
3523         return offset;
3524 }
3525
3526
3527 /* RFC 1813, Page 46..48 */
3528 int
3529 dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3530         proto_tree* tree)
3531 {
3532         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file");
3533         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_offset3, offset);
3534         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3, offset);
3535
3536         return offset;
3537 }
3538
3539
3540 /* RFC 1813, Page 46..48 */
3541 int
3542 dissect_nfs3_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3543         proto_tree* tree)
3544 {
3545         guint32 status;
3546
3547         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3548         switch (status) {
3549                 case 0:
3550                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3551                                 "file_attributes");
3552                         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3, 
3553                                 offset);
3554                         offset = dissect_rpc_bool(tvb, pinfo, tree, hf_nfs_read_eof, 
3555                                 offset);
3556                         offset = dissect_nfsdata(tvb, offset, pinfo, tree, hf_nfs_data);
3557                 break;
3558                 default:
3559                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3560                                 "file_attributes");
3561                 break;
3562         }
3563                 
3564         return offset;
3565 }
3566
3567
3568 /* RFC 1813, Page 49 */
3569 static const value_string names_stable_how[] = {
3570         {       UNSTABLE,  "UNSTABLE"  },
3571         {       DATA_SYNC, "DATA_SYNC" },
3572         {       FILE_SYNC, "FILE_SYNC" },
3573         { 0, NULL }
3574 };
3575
3576
3577 /* RFC 1813, Page 49 */
3578 int
3579 dissect_stable_how(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3580         proto_tree* tree, int hfindex)
3581 {
3582         guint32 stable_how;
3583
3584         stable_how = tvb_get_ntohl(tvb,offset+0);
3585         if (tree) {
3586                 proto_tree_add_uint(tree, hfindex, tvb,
3587                         offset, 4, stable_how); 
3588         }
3589         offset += 4;
3590
3591         return offset;
3592 }
3593
3594
3595 /* RFC 1813, Page 49..54 */
3596 int
3597 dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3598         proto_tree* tree)
3599 {
3600         offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file");
3601         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_offset3, offset);
3602         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3, offset);
3603         offset = dissect_stable_how(tvb, offset, pinfo, tree, hf_nfs_write_stable);
3604         offset = dissect_nfsdata   (tvb, offset, pinfo, tree, hf_nfs_data);
3605
3606         return offset;
3607 }
3608
3609
3610 /* RFC 1813, Page 49..54 */
3611 int
3612 dissect_nfs3_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3613         proto_tree* tree)
3614 {
3615         guint32 status;
3616
3617         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3618         switch (status) {
3619                 case 0:
3620                         offset = dissect_wcc_data  (tvb, offset, pinfo, tree, "file_wcc");
3621                         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3, 
3622                                 offset);
3623                         offset = dissect_stable_how(tvb, offset, pinfo, tree,
3624                                 hf_nfs_write_committed);
3625                         offset = dissect_writeverf3(tvb, offset, pinfo, tree);
3626                 break;
3627                 default:
3628                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
3629                 break;
3630         }
3631                 
3632         return offset;
3633 }
3634
3635
3636 /* RFC 1813, Page 54 */
3637 static const value_string names_createmode3[] = {
3638         {       UNCHECKED, "UNCHECKED" },
3639         {       GUARDED,   "GUARDED" },
3640         {       EXCLUSIVE, "EXCLUSIVE" },
3641         { 0, NULL }
3642 };
3643
3644
3645 /* RFC 1813, Page 54 */
3646 int
3647 dissect_createmode3(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3648         proto_tree* tree, guint32* mode)
3649 {
3650         guint32 mode_value;
3651         
3652         mode_value = tvb_get_ntohl(tvb, offset + 0);
3653         if (tree) {
3654                 proto_tree_add_uint(tree, hf_nfs_createmode3, tvb,
3655                 offset+0, 4, mode_value);
3656         }
3657         offset += 4;
3658
3659         *mode = mode_value;
3660         return offset;
3661 }
3662
3663
3664 /* RFC 1813, Page 54..58 */
3665 int
3666 dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3667         proto_tree* tree)
3668 {
3669         guint32 mode;
3670
3671         offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where");
3672         offset = dissect_createmode3(tvb, offset, pinfo, tree, &mode);
3673         switch (mode) {
3674                 case UNCHECKED:
3675                 case GUARDED:
3676                         offset = dissect_sattr3(tvb, offset, pinfo, tree, "obj_attributes");
3677                 break;
3678                 case EXCLUSIVE:
3679                         offset = dissect_createverf3(tvb, offset, pinfo, tree);
3680                 break;
3681         }
3682         
3683         return offset;
3684 }
3685
3686
3687 /* RFC 1813, Page 54..58 */
3688 int
3689 dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3690         proto_tree* tree)
3691 {
3692         guint32 status;
3693
3694         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3695         switch (status) {
3696                 case 0:
3697                         offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
3698                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3699                                 "obj_attributes");
3700                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
3701                 break;
3702                 default:
3703                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
3704                 break;
3705         }
3706                 
3707         return offset;
3708 }
3709
3710
3711 /* RFC 1813, Page 58..60 */
3712 int
3713 dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3714         proto_tree* tree)
3715 {
3716         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where");
3717         offset = dissect_sattr3    (tvb, offset, pinfo, tree, "attributes");
3718         
3719         return offset;
3720 }
3721
3722
3723 /* RFC 1813, Page 61..63 */
3724 int
3725 dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3726         proto_tree* tree)
3727 {
3728         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where");
3729         offset = dissect_sattr3    (tvb, offset, pinfo, tree, "symlink_attributes");
3730         offset = dissect_nfspath3  (tvb, offset, pinfo, tree, hf_nfs_symlink_to);
3731         
3732         return offset;
3733 }
3734
3735
3736 /* RFC 1813, Page 63..66 */
3737 int
3738 dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3739         proto_tree* tree)
3740 {
3741         guint32 type;
3742
3743         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where");
3744         offset = dissect_ftype3(tvb, offset, pinfo, tree, hf_nfs_ftype3, &type);
3745         switch (type) {
3746                 case NF3CHR:
3747                 case NF3BLK:
3748                         offset = dissect_sattr3(tvb, offset, pinfo, tree, "dev_attributes");
3749                         offset = dissect_specdata3(tvb, offset, pinfo, tree, "spec");
3750                 break;
3751                 case NF3SOCK:
3752                 case NF3FIFO:
3753                         offset = dissect_sattr3(tvb, offset, pinfo, tree, "pipe_attributes");
3754                 break;
3755                 default:
3756                         /* nothing to do */
3757                 break;
3758         }
3759         
3760         return offset;
3761 }
3762
3763
3764 /* RFC 1813, Page 67..69 */
3765 int
3766 dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3767         proto_tree* tree)
3768 {
3769         guint32 status;
3770
3771         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3772         switch (status) {
3773                 case 0:
3774                         offset = dissect_wcc_data    (tvb, offset, pinfo, tree, "dir_wcc");
3775                 break;
3776                 default:
3777                         offset = dissect_wcc_data    (tvb, offset, pinfo, tree, "dir_wcc");
3778                 break;
3779         }
3780                 
3781         return offset;
3782 }
3783
3784
3785 /* RFC 1813, Page 71..74 */
3786 int
3787 dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3788         proto_tree* tree)
3789 {
3790         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from");
3791         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to");
3792         
3793         return offset;
3794 }
3795
3796
3797 /* RFC 1813, Page 71..74 */
3798 int
3799 dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3800         proto_tree* tree)
3801 {
3802         guint32 status;
3803
3804         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3805         switch (status) {
3806                 case 0:
3807                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "fromdir_wcc");
3808                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "todir_wcc");
3809                 break;
3810                 default:
3811                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "fromdir_wcc");
3812                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "todir_wcc");
3813                 break;
3814         }
3815                 
3816         return offset;
3817 }
3818
3819
3820 /* RFC 1813, Page 74..76 */
3821 int
3822 dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3823         proto_tree* tree)
3824 {
3825         offset = dissect_nfs_fh3   (tvb, offset, pinfo, tree, "file");
3826         offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link");
3827         
3828         return offset;
3829 }
3830
3831
3832 /* RFC 1813, Page 74..76 */
3833 int
3834 dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3835         proto_tree* tree)
3836 {
3837         guint32 status;
3838
3839         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
3840         switch (status) {
3841                 case 0:
3842                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3843                                 "file_attributes");
3844                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "linkdir_wcc");
3845                 break;
3846                 default:
3847                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3848                                 "file_attributes");
3849                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "linkdir_wcc");
3850                 break;
3851         }
3852                 
3853         return offset;
3854 }
3855
3856
3857 /* RFC 1813, Page 76..80 */
3858 int
3859 dissect_nfs3_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3860         proto_tree* tree)
3861 {
3862         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir");
3863         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_cookie3, offset);
3864         offset = dissect_cookieverf3(tvb, offset, pinfo, tree);
3865         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3, offset);
3866         
3867         return offset;
3868 }
3869
3870
3871 /* RFC 1813, Page 76..80 */
3872 int
3873 dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree* tree)
3874 {
3875         proto_item* entry_item = NULL;
3876         proto_tree* entry_tree = NULL;
3877         int old_offset = offset;
3878         char *name;
3879
3880         if (tree) {
3881                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
3882                         offset+0, tvb_length_remaining(tvb, offset), FALSE);
3883                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
3884         }
3885
3886         offset = dissect_rpc_uint64(tvb, pinfo, entry_tree, hf_nfs_readdir_entry3_fileid,
3887                 offset);
3888
3889         offset = dissect_filename3(tvb, offset, pinfo, entry_tree,
3890                 hf_nfs_readdir_entry3_name, &name);
3891         if (entry_item)
3892                 proto_item_set_text(entry_item, "Entry: name %s", name);
3893         g_free(name);
3894
3895         offset = dissect_rpc_uint64(tvb, pinfo, entry_tree, hf_nfs_readdir_entry3_cookie, 
3896                 offset);
3897
3898         /* now we know, that a readdir entry is shorter */
3899         if (entry_item) {
3900                 proto_item_set_len(entry_item, offset - old_offset);
3901         }
3902
3903         return offset;
3904 }
3905
3906
3907 /* RFC 1813, Page 76..80 */
3908 int
3909 dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3910         proto_tree* tree)
3911 {
3912         guint32 status;
3913         guint32 eof_value;
3914
3915         offset = dissect_stat(tvb, offset, pinfo, tree, &status);
3916         switch (status) {
3917                 case 0:
3918                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3919                                 "dir_attributes");
3920                         offset = dissect_cookieverf3(tvb, offset, pinfo, tree);
3921                         offset = dissect_rpc_list(tvb, pinfo, tree, offset, 
3922                                 dissect_entry3);
3923                         eof_value = tvb_get_ntohl(tvb, offset+0);
3924                         if (tree)
3925                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
3926                                         offset+ 0, 4, eof_value);
3927                         offset += 4;
3928                 break;
3929                 default:
3930                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
3931                                 "dir_attributes");
3932                 break;
3933         }
3934
3935         return offset;
3936 }
3937
3938
3939 /* RFC 1813, Page 80..83 */
3940 int
3941 dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3942         proto_tree* tree)
3943 {
3944         offset = dissect_nfs_fh3    (tvb, offset, pinfo, tree, "dir");
3945         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_cookie3, offset);
3946         offset = dissect_cookieverf3(tvb, offset, pinfo, tree);
3947         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3_dircount,
3948                 offset);
3949         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3_maxcount,
3950                 offset);
3951         
3952         return offset;
3953 }
3954
3955
3956 /* RFC 1813, Page 80..83 */
3957 int
3958 dissect_entryplus3(tvbuff_t *tvb, int offset, packet_info *pinfo, 
3959         proto_tree* tree)
3960 {
3961         proto_item* entry_item = NULL;
3962         proto_tree* entry_tree = NULL;
3963         int old_offset = offset;
3964         char *name;
3965
3966         if (tree) {
3967                 entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
3968                         offset+0, tvb_length_remaining(tvb, offset), FALSE);
3969                 entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
3970         }
3971
3972         offset = dissect_rpc_uint64(tvb, pinfo, entry_tree,
3973                 hf_nfs_readdirplus_entry_fileid, offset);
3974
3975         offset = dissect_filename3(tvb, offset, pinfo, entry_tree,
3976                 hf_nfs_readdirplus_entry_name, &name);
3977         if (entry_item)
3978                 proto_item_set_text(entry_item, "Entry: name %s", name);
3979         g_free(name);
3980
3981         offset = dissect_rpc_uint64(tvb, pinfo, entry_tree, hf_nfs_readdirplus_entry_cookie,
3982                 offset);
3983
3984         offset = dissect_post_op_attr(tvb, offset, pinfo, entry_tree, 
3985                 "name_attributes");
3986         offset = dissect_post_op_fh3(tvb, offset, pinfo, entry_tree, "name_handle");
3987
3988         /* now we know, that a readdirplus entry is shorter */
3989         if (entry_item) {
3990                 proto_item_set_len(entry_item, offset - old_offset);
3991         }
3992
3993         return offset;
3994 }
3995
3996
3997 /* RFC 1813, Page 80..83 */
3998 int
3999 dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4000         proto_tree* tree)
4001 {
4002         guint32 status;
4003         guint32 eof_value;
4004
4005         offset = dissect_stat(tvb, offset, pinfo, tree, &status);
4006         switch (status) {
4007                 case 0:
4008                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4009                                 "dir_attributes");
4010                         offset = dissect_cookieverf3(tvb, offset, pinfo, tree);
4011                         offset = dissect_rpc_list(tvb, pinfo, tree, offset, 
4012                                 dissect_entryplus3);
4013                         eof_value = tvb_get_ntohl(tvb, offset+0);
4014                         if (tree)
4015                                 proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
4016                                         offset+ 0, 4, eof_value);
4017                         offset += 4;
4018                 break;
4019                 default:
4020                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4021                                 "dir_attributes");
4022                 break;
4023         }
4024
4025         return offset;
4026 }
4027
4028
4029 /* RFC 1813, Page 84..86 */
4030 int
4031 dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4032         proto_tree* tree)
4033 {
4034         guint32 status;
4035         guint32 invarsec;
4036
4037         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
4038         switch (status) {
4039                 case 0:
4040                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4041                                 "obj_attributes");
4042                         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_fsstat3_resok_tbytes,
4043                                 offset);
4044                         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_fsstat3_resok_fbytes,
4045                                 offset);
4046                         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_fsstat3_resok_abytes,
4047                                 offset);
4048                         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_fsstat3_resok_tfiles,
4049                                 offset);
4050                         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_fsstat3_resok_ffiles,
4051                                 offset);
4052                         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_fsstat3_resok_afiles,
4053                                 offset);
4054                         invarsec = tvb_get_ntohl(tvb, offset + 0);
4055                         if (tree)
4056                                 proto_tree_add_uint(tree, hf_nfs_fsstat_invarsec, tvb,
4057                                 offset+0, 4, invarsec);
4058                         offset += 4;
4059                 break;
4060                 default:
4061                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4062                                 "obj_attributes");
4063                 break;
4064         }
4065
4066         return offset;
4067 }
4068
4069
4070 #define FSF3_LINK        0x0001
4071 #define FSF3_SYMLINK     0x0002
4072 #define FSF3_HOMOGENEOUS 0x0008
4073 #define FSF3_CANSETTIME  0x0010
4074
4075
4076 /* RFC 1813, Page 86..90 */
4077 int
4078 dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4079         proto_tree* tree)
4080 {
4081         guint32 status;
4082         guint32 rtmax;
4083         guint32 rtpref;
4084         guint32 rtmult;
4085         guint32 wtmax;
4086         guint32 wtpref;
4087         guint32 wtmult;
4088         guint32 dtpref;
4089         guint32 properties;
4090         proto_item*     properties_item = NULL;
4091         proto_tree*     properties_tree = NULL;
4092
4093         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
4094         switch (status) {
4095                 case 0:
4096                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4097                                 "obj_attributes");
4098                         rtmax = tvb_get_ntohl(tvb, offset+0);
4099                         if (tree)
4100                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmax, tvb,
4101                                 offset+0, 4, rtmax);
4102                         offset += 4;
4103                         rtpref = tvb_get_ntohl(tvb, offset+0);
4104                         if (tree)
4105                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtpref, tvb,
4106                                 offset+0, 4, rtpref);
4107                         offset += 4;
4108                         rtmult = tvb_get_ntohl(tvb, offset+0);
4109                         if (tree)
4110                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmult, tvb,
4111                                 offset+0, 4, rtmult);
4112                         offset += 4;
4113                         wtmax = tvb_get_ntohl(tvb, offset+0);
4114                         if (tree)
4115                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmax, tvb,
4116                                 offset+0, 4, wtmax);
4117                         offset += 4;
4118                         wtpref = tvb_get_ntohl(tvb, offset+0);
4119                         if (tree)
4120                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtpref, tvb,
4121                                 offset+0, 4, wtpref);
4122                         offset += 4;
4123                         wtmult = tvb_get_ntohl(tvb, offset+0);
4124                         if (tree)
4125                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmult, tvb,
4126                                 offset+0, 4, wtmult);
4127                         offset += 4;
4128                         dtpref = tvb_get_ntohl(tvb, offset+0);
4129                         if (tree)
4130                                 proto_tree_add_uint(tree, hf_nfs_fsinfo_dtpref, tvb,
4131                                 offset+0, 4, dtpref);
4132                         offset += 4;
4133
4134                         offset = dissect_rpc_uint64(tvb, pinfo, tree, 
4135                                 hf_nfs_fsinfo_maxfilesize, offset);
4136                         offset = dissect_nfstime3(tvb, offset, pinfo, tree, hf_nfs_dtime, hf_nfs_dtime_sec, hf_nfs_dtime_nsec);
4137                         properties = tvb_get_ntohl(tvb, offset+0);
4138                         if (tree) {
4139                                 properties_item = proto_tree_add_uint(tree,
4140                                 hf_nfs_fsinfo_properties,
4141                                 tvb, offset+0, 4, properties);
4142                                 if (properties_item) 
4143                                         properties_tree = proto_item_add_subtree(properties_item, 
4144                                                 ett_nfs_fsinfo_properties);
4145                                 if (properties_tree) {
4146                                         proto_tree_add_text(properties_tree, tvb,
4147                                         offset, 4, "%s",
4148                                         decode_boolean_bitfield(properties,
4149                                         FSF3_CANSETTIME,5,
4150                                         "SETATTR can set time on server",
4151                                         "SETATTR can't set time on server"));
4152
4153                                         proto_tree_add_text(properties_tree, tvb,
4154                                         offset, 4, "%s",
4155                                         decode_boolean_bitfield(properties,
4156                                         FSF3_HOMOGENEOUS,5,
4157                                         "PATHCONF is valid for all files",
4158                                         "PATHCONF should be get for every single file"));
4159
4160                                         proto_tree_add_text(properties_tree, tvb,
4161                                         offset, 4, "%s",
4162                                         decode_boolean_bitfield(properties,
4163                                         FSF3_SYMLINK,5,
4164                                         "File System supports symbolic links",
4165                                         "File System does not symbolic hard links"));
4166
4167                                         proto_tree_add_text(properties_tree, tvb,
4168                                         offset, 4, "%s",
4169                                         decode_boolean_bitfield(properties,
4170                                         FSF3_LINK,5,
4171                                         "File System supports hard links",
4172                                         "File System does not support hard links"));
4173                                 }
4174                         }
4175                         offset += 4;
4176                 break;
4177                 default:
4178                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4179                                 "obj_attributes");
4180                 break;
4181         }
4182
4183         return offset;
4184 }
4185
4186
4187 /* RFC 1813, Page 90..92 */
4188 int
4189 dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4190         proto_tree* tree)
4191 {
4192         guint32 status;
4193         guint32 linkmax;
4194         guint32 name_max;
4195
4196         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
4197         switch (status) {
4198                 case 0:
4199                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4200                                 "obj_attributes");
4201                         linkmax = tvb_get_ntohl(tvb, offset + 0);
4202                         if (tree)
4203                                 proto_tree_add_uint(tree, hf_nfs_pathconf_linkmax, tvb,
4204                                 offset+0, 4, linkmax);
4205                         offset += 4;
4206                         name_max = tvb_get_ntohl(tvb, offset + 0);
4207                         if (tree)
4208                                 proto_tree_add_uint(tree, hf_nfs_pathconf_name_max, tvb,
4209                                 offset+0, 4, name_max);
4210                         offset += 4;
4211                         offset = dissect_rpc_bool(tvb, pinfo, tree, 
4212                                 hf_nfs_pathconf_no_trunc, offset);
4213                         offset = dissect_rpc_bool(tvb, pinfo, tree, 
4214                                 hf_nfs_pathconf_chown_restricted, offset);
4215                         offset = dissect_rpc_bool(tvb, pinfo, tree, 
4216                                 hf_nfs_pathconf_case_insensitive, offset);
4217                         offset = dissect_rpc_bool(tvb, pinfo, tree, 
4218                                 hf_nfs_pathconf_case_preserving, offset);
4219                 break;
4220                 default:
4221                         offset = dissect_post_op_attr(tvb, offset, pinfo, tree, 
4222                                 "obj_attributes");
4223                 break;
4224         }
4225
4226         return offset;
4227 }
4228
4229
4230 /* RFC 1813, Page 92..95 */
4231 int
4232 dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4233         proto_tree* tree)
4234 {
4235         offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file");
4236         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_offset3, offset);
4237         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_count3, offset);
4238         return offset;
4239 }
4240
4241
4242 /* RFC 1813, Page 92..95 */
4243 int
4244 dissect_nfs3_commit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4245         proto_tree* tree)
4246 {
4247         guint32 status;
4248
4249         offset = dissect_nfsstat3(tvb, offset, pinfo, tree, &status);
4250         switch (status) {
4251                 case 0:
4252                         offset = dissect_wcc_data  (tvb, offset, pinfo, tree, "file_wcc");
4253                         offset = dissect_writeverf3(tvb, offset, pinfo, tree);
4254                 break;
4255                 default:
4256                         offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
4257                 break;
4258         }
4259                 
4260         return offset;
4261 }
4262
4263 /**********************************************************/
4264 /* NFS Version 4, RFC 3010 with nfs4_prot.x 1.103 changes */
4265 /**********************************************************/
4266
4267 int
4268 dissect_nfs_utf8string(tvbuff_t *tvb, int offset, packet_info *pinfo,
4269         proto_tree *tree, int hf, char **string_ret)
4270 {
4271         /* TODO: this needs to be fixed */
4272         return dissect_rpc_string(tvb, pinfo, tree, hf, offset, string_ret);
4273 }
4274
4275 int
4276 dissect_nfs_linktext4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4277         proto_tree *tree, char *name)
4278 {
4279         return dissect_nfs_utf8string(tvb, offset, pinfo, tree, hf_nfs_linktext4, 
4280                 NULL);
4281 }
4282
4283 int
4284 dissect_nfs_specdata4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4285         proto_tree *tree, char *name)
4286 {
4287         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_specdata1, offset);
4288         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_specdata2, offset);
4289
4290         return offset;
4291 }
4292
4293 int
4294 dissect_nfs_clientid4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4295         proto_tree *tree)
4296 {
4297         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_clientid4, offset);
4298
4299         return offset;
4300 }
4301
4302 static const value_string names_ftype4[] = {
4303         {       NF4REG, "NF4REG"        },
4304         {       NF4DIR, "NF4DIR"        },
4305         {       NF4BLK, "NF4BLK"  },
4306         {       NF4CHR, "NF4CHR"  },
4307         {       NF4LNK,  "NF4LNK"  },
4308         {       NF4SOCK,        "NF4SOCK"  },
4309         {       NF4FIFO,        "NF4FIFO"  },
4310         {       NF4ATTRDIR,     "NF4ATTRDIR"    },
4311         {       NF4NAMEDATTR,   "NF4NAMEDATTR"  },
4312         { 0, NULL }
4313 };
4314
4315 int
4316 dissect_nfs_component4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4317         proto_tree *tree, char *name)
4318 {
4319         return dissect_nfs_utf8string(tvb, offset, pinfo, tree, hf_nfs_component4, 
4320                 NULL);
4321 }
4322
4323 int
4324 dissect_nfs_reclaim4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4325         proto_tree *tree, char *name)
4326 {
4327         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_reclaim4, offset);
4328         return offset;
4329 }
4330
4331 int
4332 dissect_nfs_length4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4333         proto_tree *tree, char *name)
4334 {
4335         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_length4, offset);
4336         return offset;
4337 }
4338
4339 int
4340 dissect_nfs_opaque4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4341         proto_tree *tree, char *name);
4342
4343 int
4344 dissect_nfs_lock_owner4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4345         proto_tree *tree, char *name)
4346 {
4347         proto_tree *newftree = NULL;
4348         proto_item *fitem = NULL;
4349
4350         fitem = proto_tree_add_text(tree, tvb, offset, 4, "Owner");
4351
4352         if (fitem) {
4353                 newftree = proto_item_add_subtree(fitem, ett_nfs_lock_owner4);
4354
4355                 if (newftree) {
4356                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_clientid4,
4357                                 offset);
4358                         offset = dissect_nfs_opaque4(tvb, offset, pinfo, newftree, "Owner");
4359                 }
4360         }
4361
4362         return offset;
4363 }
4364
4365 int
4366 dissect_nfs_pathname4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4367         proto_tree *tree, char *name)
4368 {
4369         guint comp_count, i;
4370         proto_item *fitem = NULL;
4371         proto_tree *newftree = NULL;
4372
4373         comp_count=tvb_get_ntohl(tvb, offset);
4374         fitem = proto_tree_add_text(tree, tvb, offset, 4, 
4375                 "pathname components (%d)", comp_count);
4376         offset += 4;
4377
4378         if (fitem) {
4379                 newftree = proto_item_add_subtree(fitem, ett_nfs_pathname4);
4380
4381                 if (newftree) {
4382                         for (i=0; i<comp_count; i++)
4383                                 offset=dissect_nfs_component4(tvb, offset, pinfo, newftree, "comp");
4384                 }
4385         }
4386
4387         return offset;
4388 }
4389
4390 int
4391 dissect_nfs_changeid4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4392         proto_tree *tree, char *name)
4393 {
4394         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_changeid4, offset);
4395         return offset;
4396 }
4397
4398 int
4399 dissect_nfs_nfstime4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4400         proto_tree *tree, char *name)
4401 {
4402         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_nfstime4_seconds, 
4403                 offset);
4404         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_nfstime4_nseconds,
4405                 offset);
4406         return offset;
4407 }
4408
4409 static const value_string names_time_how4[] = {
4410 #define SET_TO_SERVER_TIME4 0
4411         {       SET_TO_SERVER_TIME4,    "SET_TO_SERVER_TIME4"   },
4412 #define SET_TO_CLIENT_TIME4 1
4413         {       SET_TO_CLIENT_TIME4,    "SET_TO_CLIENT_TIME4"   },
4414         {       0,      NULL    },
4415 };
4416
4417 int
4418 dissect_nfs_settime4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4419         proto_tree *tree, char *name)
4420 {
4421         guint32 set_it;
4422
4423         set_it = tvb_get_ntohl(tvb, offset);
4424         proto_tree_add_uint(tree, hf_nfs_time_how4, tvb, offset+0, 
4425                 4, set_it);
4426         offset += 4;
4427
4428         if (set_it == SET_TO_CLIENT_TIME4)
4429                 offset = dissect_nfs_nfstime4(tvb, offset, pinfo, tree, NULL);
4430         
4431         return offset;
4432 }
4433
4434 static const value_string names_fattr4_expire_type[] = {
4435 #define FH4_PERSISTENT 0x00000000
4436         {       FH4_PERSISTENT, "FH4_PERSISTENT"        },
4437 #define FH4_NOEXPIRE_WITH_OPEN 0x00000001
4438         {       FH4_NOEXPIRE_WITH_OPEN, "FH4_NOEXPIRE_WITH_OPEN"        },
4439 #define FH4_VOLATILE_ANY 0x00000002
4440         {       FH4_NOEXPIRE_WITH_OPEN, "FH4_NOEXPIRE_WITH_OPEN"        },
4441 #define FH4_VOL_MIGRATION 0x00000004
4442         {       FH4_VOL_MIGRATION,      "FH4_VOL_MIGRATION"     },
4443 #define FH4_VOL_RENAME 0x00000008
4444         {       FH4_VOL_RENAME, "FH4_VOL_RENAME"        },
4445         {       0,      NULL    }
4446 };
4447
4448 int
4449 dissect_nfs_fh_expire_type(tvbuff_t *tvb, int offset, packet_info *pinfo,
4450         proto_tree *tree)
4451 {
4452         guint32 fattr4_fh_expire_type;
4453
4454         fattr4_fh_expire_type = tvb_get_ntohl(tvb, offset);
4455         proto_tree_add_uint(tree, hf_nfs_fattr4_expire_type, tvb, offset+0, 
4456                 4, fattr4_fh_expire_type);
4457         offset += 4;
4458
4459         return offset;
4460 }
4461
4462 int
4463 dissect_nfs_fsid4(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4464         proto_tree *tree, char *name)
4465 {
4466         proto_tree *newftree = NULL;
4467         proto_item *fitem = NULL;
4468
4469         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
4470
4471         if (fitem == NULL) return offset;
4472
4473         newftree = proto_item_add_subtree(fitem, ett_nfs_fsid4);
4474
4475         if (newftree == NULL) return offset;
4476
4477         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_fsid4_major,
4478                 offset);
4479         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_fsid4_minor,
4480                 offset);
4481
4482         return offset;
4483 }
4484
4485 int
4486 dissect_nfs_acetype4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4487         proto_tree *tree, char *name)
4488 {
4489         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_acetype4, offset);
4490         return offset;
4491 }
4492
4493 int
4494 dissect_nfs_aceflag4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4495         proto_tree *tree, char *name)
4496 {
4497         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_aceflag4, offset);
4498         return offset;
4499 }
4500
4501 int
4502 dissect_nfs_acemask4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4503         proto_tree *tree, char *name)
4504 {
4505         return dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_acemask4, offset);
4506 }
4507
4508 int
4509 dissect_nfs_nfsace4(tvbuff_t *tvb, int offset, packet_info *pinfo, 
4510         proto_tree *tree, char *name)
4511 {
4512         proto_tree *newftree = NULL;
4513         proto_item *fitem = NULL;
4514         int nextentry;
4515
4516         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
4517
4518         if (fitem == NULL) return offset;
4519
4520         newftree = proto_item_add_subtree(fitem, ett_nfs_fsid4);
4521
4522         if (newftree == NULL) return offset;
4523
4524         nextentry = tvb_get_ntohl(tvb, offset);
4525         offset = dissect_rpc_bool(tvb, pinfo, newftree, hf_nfs_data_follows,
4526                 offset);
4527
4528         while (nextentry)
4529         {
4530                 offset = dissect_nfs_acetype4(tvb, offset, pinfo, newftree, "type");
4531                 offset = dissect_nfs_aceflag4(tvb, offset, pinfo, newftree, "flag");
4532                 offset = dissect_nfs_acemask4(tvb, offset, pinfo, newftree, 
4533                         "access_mask");
4534                 offset = dissect_nfs_utf8string(tvb, offset, pinfo, newftree, 
4535                         hf_nfs_who, NULL);
4536                 nextentry = tvb_get_ntohl(tvb, offset);
4537                 offset += 4;
4538         }
4539
4540         return offset;
4541 }
4542
4543 int
4544 dissect_nfs_fh4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4545         proto_tree *tree, char *name)
4546 {
4547         return dissect_nfs_fh3(tvb, offset, pinfo, tree, name);
4548 }
4549
4550 int
4551 dissect_nfs_fs_location4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4552         proto_tree *tree, char *name)
4553 {
4554         proto_tree *newftree = NULL;
4555         proto_item *fitem = NULL;
4556
4557         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
4558
4559         if (fitem == NULL) return offset;
4560
4561         newftree = proto_item_add_subtree(fitem, ett_nfs_fs_location4);
4562
4563         if (newftree == NULL) return offset;
4564
4565         offset = dissect_nfs_utf8string(tvb, offset, pinfo, tree, hf_nfs_server, 
4566                 NULL);
4567
4568         return offset;
4569 }
4570
4571 int
4572 dissect_nfs_fs_locations4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4573         proto_tree *tree, char *name)
4574 {
4575         proto_tree *newftree = NULL;
4576         proto_item *fitem = NULL;
4577         int nextentry;
4578
4579         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
4580
4581         if (fitem == NULL) return offset;
4582
4583         newftree = proto_item_add_subtree(fitem, ett_nfs_fs_locations4);
4584
4585         if (newftree == NULL) return offset;
4586
4587         offset = dissect_nfs_pathname4(tvb, offset, pinfo, newftree, "fs_root");
4588
4589         nextentry = tvb_get_ntohl(tvb, offset);
4590         offset = dissect_rpc_bool(tvb, pinfo, newftree, hf_nfs_data_follows, 
4591                 offset);
4592
4593         while (nextentry)
4594         {
4595                 offset = dissect_nfs_fs_location4(tvb, offset, pinfo, newftree, 
4596                         "locations");
4597                 nextentry = tvb_get_ntohl(tvb, offset);
4598                 offset += 4;
4599         }
4600
4601         return offset;
4602 }
4603
4604 int
4605 dissect_nfs_mode4(tvbuff_t *tvb, int offset, packet_info *pinfo,
4606         proto_tree *tree, char *name)
4607 {
4608         return dissect_mode(tvb, offset, pinfo, tree, name);
4609 }
4610
4611 static const value_string names_fattr4[] = {
4612 #define FATTR4_SUPPORTED_ATTRS     0
4613         {       FATTR4_SUPPORTED_ATTRS, "FATTR4_SUPPORTED_ATTRS"        },
4614 #define FATTR4_TYPE                1
4615         {       FATTR4_TYPE,    "FATTR4_TYPE"   },
4616 #define FATTR4_FH_EXPIRE_TYPE      2
4617         {       FATTR4_FH_EXPIRE_TYPE,  "FATTR4_FH_EXPIRE_TYPE" },
4618 #define FATTR4_CHANGE              3
4619         {       FATTR4_CHANGE,  "FATTR4_CHANGE" },
4620 #define FATTR4_SIZE                4
4621         {       FATTR4_SIZE,    "FATTR4_SIZE"   },
4622 #define FATTR4_LINK_SUPPORT        5
4623         {       FATTR4_LINK_SUPPORT,    "FATTR4_LINK_SUPPORT"   },
4624 #define FATTR4_SYMLINK_SUPPORT     6
4625         {       FATTR4_SYMLINK_SUPPORT, "FATTR4_SYMLINK_SUPPORT"        },
4626 #define FATTR4_NAMED_ATTR          7
4627         {       FATTR4_NAMED_ATTR,      "FATTR4_NAMED_ATTR"     },
4628 #define FATTR4_FSID                8
4629         {       FATTR4_FSID,    "FATTR4_FSID"   },
4630 #define FATTR4_UNIQUE_HANDLES      9
4631         {       FATTR4_UNIQUE_HANDLES,  "FATTR4_UNIQUE_HANDLES" },
4632 #define FATTR4_LEASE_TIME          10
4633         {       FATTR4_LEASE_TIME,      "FATTR4_LEASE_TIME"     },
4634 #define FATTR4_RDATTR_ERROR        11
4635         {       FATTR4_RDATTR_ERROR,    "FATTR4_RDATTR_ERROR"   },
4636 #define FATTR4_ACL                 12
4637         {       FATTR4_ACL,     "FATTR4_ACL"    },
4638 #define FATTR4_ACLSUPPORT          13
4639         {       FATTR4_ACLSUPPORT,      "FATTR4_ACLSUPPORT"     },
4640 #define FATTR4_ARCHIVE             14
4641         {       FATTR4_ARCHIVE, "FATTR4_ARCHIVE"        },
4642 #define FATTR4_CANSETTIME          15
4643         {       FATTR4_CANSETTIME, "FATTR4_CANSETTIME"  },
4644 #define FATTR4_CASE_INSENSITIVE    16
4645         {       FATTR4_CASE_INSENSITIVE, "FATTR4_CASE_INSENSITIVE"      },
4646 #define FATTR4_CASE_PRESERVING     17
4647         {       FATTR4_CASE_PRESERVING, "FATTR4_CASE_PRESERVING"        },
4648 #define FATTR4_CHOWN_RESTRICTED    18
4649         {       FATTR4_CHOWN_RESTRICTED, "FATTR4_CHOWN_RESTRICTED"      },
4650 #define FATTR4_FILEHANDLE          19
4651         {       FATTR4_FILEHANDLE, "FATTR4_FILEHANDLE"  },
4652 #define FATTR4_FILEID              20
4653         {       FATTR4_FILEID, "FATTR4_FILEID"  },
4654 #define FATTR4_FILES_AVAIL         21
4655         {       FATTR4_FILES_AVAIL, "FATTR4_FILES_AVAIL"        },
4656 #define FATTR4_FILES_FREE          22
4657         {       FATTR4_FILES_FREE, "FATTR4_FILES_FREE"  },
4658 #define FATTR4_FILES_TOTAL         23
4659         {       FATTR4_FILES_TOTAL, "FATTR4_FILES_TOTAL"        },
4660 #define FATTR4_FS_LOCATIONS        24
4661         {       FATTR4_FS_LOCATIONS, "FATTR4_FS_LOCATIONS"      },
4662 #define FATTR4_HIDDEN              25
4663         {       FATTR4_HIDDEN, "FATTR4_HIDDEN"  },
4664 #define FATTR4_HOMOGENEOUS         26
4665         {       FATTR4_HOMOGENEOUS, "FATTR4_HOMOGENEOUS"        },
4666 #define FATTR4_MAXFILESIZE         27
4667         {       FATTR4_MAXFILESIZE, "FATTR4_MAXFILESIZE"        },
4668 #define FATTR4_MAXLINK             28
4669         {       FATTR4_MAXLINK, "FATTR4_MAXLINK"        },
4670 #define FATTR4_MAXNAME             29
4671         {       FATTR4_MAXNAME, "FATTR4_MAXNAME"        },
4672 #define FATTR4_MAXREAD             30
4673         {       FATTR4_MAXREAD, "FATTR4_MAXREAD"        },
4674 #define FATTR4_MAXWRITE            31
4675         {       FATTR4_MAXWRITE, "FATTR4_MAXWRITE"      },
4676 #define FATTR4_MIMETYPE            32
4677         {       FATTR4_MIMETYPE, "FATTR4_MIMETYPE"      },
4678 #define FATTR4_MODE                33
4679         {       FATTR4_MODE, "FATTR4_MODE"      },
4680 #define FATTR4_NO_TRUNC            34
4681         {       FATTR4_NO_TRUNC, "FATTR4_NO_TRUNC"      },
4682 #define FATTR4_NUMLINKS            35
4683         {       FATTR4_NUMLINKS, "FATTR4_NUMLINKS"      },
4684 #define FATTR4_OWNER               36
4685         {       FATTR4_OWNER, "FATTR4_OWNER"    },
4686 #define FATTR4_OWNER_GROUP         37
4687         {       FATTR4_OWNER_GROUP, "FATTR4_OWNER_GROUP"        },
4688 #define FATTR4_QUOTA_AVAIL_HARD    38
4689         {       FATTR4_QUOTA_AVAIL_HARD, "FATTR4_QUOTA_AVAIL_HARD"      },
4690 #define FATTR4_QUOTA_AVAIL_SOFT    39
4691         {       FATTR4_QUOTA_AVAIL_SOFT, "FATTR4_QUOTA_AVAIL_SOFT"      },
4692 #define FATTR4_QUOTA_USED          40
4693         {       FATTR4_QUOTA_USED, "FATTR4_QUOTA_USED"  },
4694 #define FATTR4_RAWDEV              41
4695         {       FATTR4_RAWDEV, "FATTR4_RAWDEV"  },
4696 #define FATTR4_SPACE_AVAIL         42
4697         {       FATTR4_SPACE_AVAIL, "FATTR4_SPACE_AVAIL"        },
4698 #define FATTR4_SPACE_FREE          43
4699         {       FATTR4_SPACE_FREE, "FATTR4_SPACE_FREE"  },
4700 #define FATTR4_SPACE_TOTAL         44
4701         {       FATTR4_SPACE_TOTAL, "FATTR4_SPACE_TOTAL"        },
4702 #define FATTR4_SPACE_USED          45
4703         {       FATTR4_SPACE_USED, "FATTR4_SPACE_USED"  },
4704 #define FATTR4_SYSTEM              46
4705         {       FATTR4_SYSTEM, "FATTR4_SYSTEM"  },
4706 #define FATTR4_TIME_ACCESS         47
4707         {       FATTR4_TIME_ACCESS, "FATTR4_TIME_ACCESS"        },
4708 #define FATTR4_TIME_ACCESS_SET     48
4709         {       FATTR4_TIME_ACCESS_SET, "FATTR4_TIME_ACCESS_SET"        },
4710 #define FATTR4_TIME_BACKUP         49
4711         {       FATTR4_TIME_BACKUP, "FATTR4_TIME_BACKUP"        },
4712 #define FATTR4_TIME_CREATE         50
4713         {       FATTR4_TIME_CREATE, "FATTR4_TIME_CREATE"        },
4714 #define FATTR4_TIME_DELTA          51
4715         {       FATTR4_TIME_DELTA, "FATTR4_TIME_DELTA"  },
4716 #define FATTR4_TIME_METADATA       52
4717         {       FATTR4_TIME_METADATA, "FATTR4_TIME_METADATA"    },
4718 #define FATTR4_TIME_MODIFY         53
4719         {       FATTR4_TIME_MODIFY, "FATTR4_TIME_MODIFY"        },
4720 #define FATTR4_TIME_MODIFY_SET     54
4721         {       FATTR4_TIME_MODIFY_SET, "FATTR4_TIME_MODIFY_SET"        },
4722         {       0,      NULL    }
4723 };
4724
4725 #define FATTR4_BITMAP_ONLY 0
4726 #define FATTR4_FULL_DISSECT 1
4727
4728 int
4729 dissect_nfs_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo,
4730         proto_tree *tree, char *name, int type)
4731 {
4732         guint32 bitmap_len;
4733         proto_item *fitem = NULL;
4734         proto_tree *newftree = NULL;
4735         proto_item *attr_fitem = NULL;
4736         proto_tree *attr_newftree = NULL;
4737         unsigned int i;
4738         int j, fattr;
4739         guint32 *bitmap;
4740         guint32 sl;
4741         int attr_vals_offset;
4742
4743         bitmap_len = tvb_get_ntohl(tvb, offset);
4744         fitem = proto_tree_add_text(tree, tvb, offset, 4 + bitmap_len * 4,
4745                 "%s", "attrmask");
4746         offset += 4;
4747
4748         if (fitem == NULL) return offset;
4749
4750         newftree = proto_item_add_subtree(fitem, ett_nfs_bitmap4);
4751
4752         if (newftree == NULL) return offset;
4753
4754         attr_vals_offset = offset + 4 + bitmap_len * 4;
4755
4756         bitmap = g_malloc(bitmap_len * sizeof(guint32));        
4757         if (bitmap == NULL) return offset;
4758
4759         for (i = 0; i < bitmap_len; i++)
4760         {
4761                 if (!tvb_bytes_exist(tvb, offset,  4))
4762                 {
4763                         g_free(bitmap);
4764                         return offset;
4765                 }
4766
4767                 bitmap[i] = tvb_get_ntohl(tvb, offset);
4768
4769                 sl = 0x00000001;
4770
4771                 for (j = 0; j < 32; j++)
4772                 {
4773                         fattr = 32 * i + j;
4774
4775                         if (bitmap[i] & sl)
4776                         {
4777                                 /* switch label if attribute is recommended vs. mandatory */
4778                                 attr_fitem = proto_tree_add_uint(newftree, 
4779                                         (fattr < FATTR4_ACL)? hf_nfs_mand_attr: hf_nfs_recc_attr, 
4780                                         tvb, offset, 4, fattr);
4781
4782                                 if (attr_fitem == NULL) break;
4783
4784                                 attr_newftree = proto_item_add_subtree(attr_fitem, ett_nfs_bitmap4);
4785
4786                                 if (attr_newftree == NULL) break;
4787
4788                                 if (type == FATTR4_FULL_DISSECT)
4789                                 {
4790                                         /* do a full decode of the arguments for the set flag */
4791                                         switch(fattr)
4792                                         {
4793                                         case FATTR4_SUPPORTED_ATTRS:
4794                                                 attr_vals_offset = dissect_nfs_attributes(tvb, 
4795                                                         attr_vals_offset, pinfo, attr_newftree, 
4796                                                         "fattr4_supported_attrs", FATTR4_BITMAP_ONLY);
4797                                                 break;
4798                                                 
4799                                         case FATTR4_TYPE:
4800                                                 attr_vals_offset = dissect_rpc_uint32(tvb, pinfo, 
4801                                                         attr_newftree, hf_nfs_ftype4, attr_vals_offset);
4802                                                 break;
4803
4804                                         case FATTR4_FH_EXPIRE_TYPE:
4805                                                 attr_vals_offset = dissect_rpc_uint32(tvb, pinfo,
4806                                                         attr_newftree, hf_nfs_fattr4_expire_type, 
4807                                                         attr_vals_offset);
4808                                                 break;
4809
4810                                         case FATTR4_CHANGE:
4811                                                 attr_vals_offset = dissect_nfs_changeid4(tvb, 
4812                                                         attr_vals_offset, pinfo, attr_newftree, "fattr4_change");
4813                                                 break;
4814
4815                                         case FATTR4_SIZE:
4816                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4817                                                         attr_newftree, hf_nfs_fattr4_size, attr_vals_offset);
4818                                                 break;
4819
4820                                         case FATTR4_LINK_SUPPORT:
4821                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4822                                                         attr_newftree, hf_nfs_fattr4_link_support, 
4823                                                         attr_vals_offset);
4824                                                 break;
4825
4826                                         case FATTR4_SYMLINK_SUPPORT:
4827                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4828                                                         attr_newftree, hf_nfs_fattr4_symlink_support, 
4829                                                         attr_vals_offset);
4830                                                 break;
4831
4832                                         case FATTR4_NAMED_ATTR:
4833                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4834                                                         attr_newftree, hf_nfs_fattr4_named_attr, attr_vals_offset);
4835                                                 break;
4836
4837                                         case FATTR4_FSID:
4838                                                 attr_vals_offset = dissect_nfs_fsid4(tvb, attr_vals_offset,
4839                                                         pinfo, attr_newftree, "fattr4_fsid");
4840                                                 break;
4841
4842                                         case FATTR4_UNIQUE_HANDLES:
4843                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4844                                                         attr_newftree, hf_nfs_fattr4_unique_handles, 
4845                                                         attr_vals_offset);
4846                                                 break;
4847
4848                                         case FATTR4_LEASE_TIME:
4849                                                 attr_vals_offset = dissect_rpc_uint32(tvb, pinfo, 
4850                                                         attr_newftree, hf_nfs_fattr4_lease_time, 
4851                                                         attr_vals_offset);
4852                                                 break;
4853
4854                                         case FATTR4_RDATTR_ERROR:
4855                                                 attr_vals_offset = dissect_nfs_nfsstat4(tvb, attr_vals_offset,
4856                                                         pinfo, attr_newftree, NULL);
4857                                                 break;
4858
4859                                         case FATTR4_ACL:
4860                                                 attr_vals_offset = dissect_nfs_nfsace4(tvb, attr_vals_offset,
4861                                                         pinfo, attr_newftree, "fattr4_acl");
4862                                                 break;
4863
4864                                         case FATTR4_ACLSUPPORT:
4865                                                 attr_vals_offset = dissect_rpc_uint32(tvb, pinfo, 
4866                                                         attr_newftree, hf_nfs_fattr4_aclsupport, offset);
4867                                                 break;
4868
4869                                         case FATTR4_ARCHIVE:
4870                                                 attr_vals_offset = dissect_rpc_bool(tvb, 
4871                                                         pinfo, attr_newftree, hf_nfs_fattr4_archive, 
4872                                                         attr_vals_offset);
4873                                                 break;
4874
4875                                         case FATTR4_CANSETTIME:
4876                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4877                                                         attr_newftree, hf_nfs_fattr4_cansettime, attr_vals_offset);
4878                                                 break;
4879
4880                                         case FATTR4_CASE_INSENSITIVE:
4881                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4882                                                         attr_newftree, hf_nfs_fattr4_case_insensitive, 
4883                                                         attr_vals_offset);
4884                                                 break;
4885
4886                                         case FATTR4_CASE_PRESERVING:
4887                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4888                                                         attr_newftree, hf_nfs_fattr4_case_preserving, 
4889                                                         attr_vals_offset);
4890                                                 break;
4891
4892                                         case FATTR4_CHOWN_RESTRICTED:
4893                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4894                                                         attr_newftree, hf_nfs_fattr4_chown_restricted, 
4895                                                         attr_vals_offset);
4896                                                 break;
4897
4898                                         case FATTR4_FILEID:
4899                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4900                                                         attr_newftree, hf_nfs_fattr4_fileid, attr_vals_offset);
4901                                                 break;
4902
4903                                         case FATTR4_FILES_AVAIL:
4904                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4905                                                         attr_newftree, hf_nfs_fattr4_files_avail, 
4906                                                         attr_vals_offset);
4907                                                 break;
4908
4909                                         case FATTR4_FILEHANDLE:
4910                                                 attr_vals_offset = dissect_nfs_fh4(tvb, attr_vals_offset,
4911                                                         pinfo, attr_newftree, "fattr4_filehandle");
4912                                                 break;
4913
4914                                         case FATTR4_FILES_FREE:
4915                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4916                                                         attr_newftree, hf_nfs_fattr4_files_free, attr_vals_offset);
4917                                                 break;
4918
4919                                         case FATTR4_FILES_TOTAL:
4920                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4921                                                         attr_newftree, hf_nfs_fattr4_files_total, 
4922                                                         attr_vals_offset);
4923                                                 break;
4924
4925                                         case FATTR4_FS_LOCATIONS:
4926                                                 attr_vals_offset = dissect_nfs_fs_locations4(tvb, 
4927                                                         attr_vals_offset, pinfo, attr_newftree, 
4928                                                         "fattr4_fs_locations");
4929                                                 break;
4930
4931                                         case FATTR4_HIDDEN:
4932                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4933                                                         attr_newftree, hf_nfs_fattr4_hidden, attr_vals_offset);
4934                                                 break;
4935
4936                                         case FATTR4_HOMOGENEOUS:
4937                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4938                                                         attr_newftree, hf_nfs_fattr4_homogeneous, 
4939                                                         attr_vals_offset);
4940                                                 break;
4941
4942                                         case FATTR4_MAXFILESIZE:
4943                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4944                                                         attr_newftree, hf_nfs_fattr4_maxfilesize, 
4945                                                         attr_vals_offset);
4946                                                 break;
4947
4948                                         case FATTR4_MAXLINK:
4949                                                 attr_vals_offset = dissect_rpc_uint32(tvb, pinfo, 
4950                                                         attr_newftree, hf_nfs_fattr4_maxlink, attr_vals_offset);
4951                                                 break;
4952
4953                                         case FATTR4_MAXNAME:
4954                                                 attr_vals_offset = dissect_rpc_uint32(tvb, pinfo, 
4955                                                         attr_newftree, hf_nfs_fattr4_maxname, attr_vals_offset);
4956                                                 break;
4957
4958                                         case FATTR4_MAXREAD:
4959                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4960                                                         attr_newftree, hf_nfs_fattr4_maxread, attr_vals_offset);
4961                                                 break;
4962
4963                                         case FATTR4_MAXWRITE:
4964                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
4965                                                         attr_newftree, hf_nfs_fattr4_maxwrite, attr_vals_offset);
4966                                                 break;
4967
4968                                         case FATTR4_MIMETYPE:
4969                                                 attr_vals_offset = dissect_nfs_utf8string(tvb, 
4970                                                         attr_vals_offset, pinfo, attr_newftree, 
4971                                                         hf_nfs_fattr4_mimetype, NULL);
4972                                                 break;
4973                                         
4974                                         case FATTR4_MODE:
4975                                                 attr_vals_offset = dissect_nfs_mode4(tvb,
4976                                                         attr_vals_offset, pinfo, attr_newftree, "fattr4_mode");
4977                                                 break;
4978
4979                                         case FATTR4_NO_TRUNC:
4980                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
4981                                                         attr_newftree, hf_nfs_fattr4_no_trunc, attr_vals_offset);
4982                                                 break;
4983
4984                                         case FATTR4_NUMLINKS:
4985                                                 attr_vals_offset = dissect_rpc_uint32(tvb, pinfo, 
4986                                                         attr_newftree, hf_nfs_fattr4_numlinks, attr_vals_offset);
4987                                                 break;
4988
4989                                         case FATTR4_OWNER:
4990                                                 attr_vals_offset = dissect_nfs_utf8string(tvb, 
4991                                                         attr_vals_offset, pinfo, attr_newftree, 
4992                                                         hf_nfs_fattr4_owner,
4993                                                         NULL);
4994                                                 break;
4995
4996                                         case FATTR4_OWNER_GROUP:
4997                                                 attr_vals_offset = dissect_nfs_utf8string(tvb, 
4998                                                         attr_vals_offset, pinfo, attr_newftree, 
4999                                                         hf_nfs_fattr4_owner_group, NULL);
5000                                                 break;
5001
5002                                         case FATTR4_QUOTA_AVAIL_HARD:
5003                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
5004                                                         attr_newftree, hf_nfs_fattr4_quota_hard, attr_vals_offset);
5005                                                 break;
5006
5007                                         case FATTR4_QUOTA_AVAIL_SOFT:
5008                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
5009                                                         attr_newftree, hf_nfs_fattr4_quota_soft, attr_vals_offset);
5010                                                 break;
5011
5012                                         case FATTR4_QUOTA_USED:
5013                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
5014                                                         attr_newftree, hf_nfs_fattr4_quota_used, attr_vals_offset);
5015                                                 break;
5016
5017                                         case FATTR4_RAWDEV:
5018                                                 attr_vals_offset = dissect_nfs_specdata4(tvb, 
5019                                                         attr_vals_offset, pinfo, attr_newftree, "fattr4_rawdev");
5020                                                 break;
5021
5022                                         case FATTR4_SPACE_AVAIL:
5023                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
5024                                                         attr_newftree, hf_nfs_fattr4_space_avail, 
5025                                                         attr_vals_offset);
5026                                                 break;
5027
5028                                         case FATTR4_SPACE_FREE:
5029                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
5030                                                         attr_newftree, hf_nfs_fattr4_space_free, attr_vals_offset);
5031                                                 break;
5032
5033                                         case FATTR4_SPACE_TOTAL:
5034                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
5035                                                         attr_newftree, hf_nfs_fattr4_space_total, 
5036                                                         attr_vals_offset);
5037                                                 break;
5038
5039                                         case FATTR4_SPACE_USED:
5040                                                 attr_vals_offset = dissect_rpc_uint64(tvb, pinfo, 
5041                                                         attr_newftree, hf_nfs_fattr4_space_used, attr_vals_offset);
5042                                                 break;
5043                                         
5044                                         case FATTR4_SYSTEM:
5045                                                 attr_vals_offset = dissect_rpc_bool(tvb, pinfo, 
5046                                                         attr_newftree, hf_nfs_fattr4_system, attr_vals_offset);
5047                                                 break;
5048
5049                                         case FATTR4_TIME_ACCESS:
5050                                         case FATTR4_TIME_BACKUP:
5051                                         case FATTR4_TIME_CREATE:
5052                                         case FATTR4_TIME_DELTA:
5053                                         case FATTR4_TIME_METADATA:
5054                                         case FATTR4_TIME_MODIFY:
5055                                                 attr_vals_offset = dissect_nfs_nfstime4(tvb, attr_vals_offset,
5056                                                         pinfo, attr_newftree, "nfstime4");
5057                                                 break;
5058
5059                                         case FATTR4_TIME_ACCESS_SET:
5060                                         case FATTR4_TIME_MODIFY_SET:
5061                                                 attr_vals_offset = dissect_nfs_settime4(tvb, 
5062                                                         attr_vals_offset, pinfo, attr_newftree, "settime4");
5063                                                 break;
5064
5065                                         default:
5066                                                 break;
5067                                         }
5068                                 }
5069                         }
5070
5071                         sl <<= 1;
5072                 }
5073
5074                 offset += 4;
5075         }
5076
5077         g_free(bitmap);
5078
5079         return offset;
5080 }
5081
5082 int
5083 dissect_nfs_fattr4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5084         proto_tree *tree, char *name)
5085 {
5086         proto_tree *newftree = NULL;
5087         proto_item *fitem = NULL;
5088
5089         fitem = proto_tree_add_text(tree, tvb, offset, 4, "obj_attributes");
5090
5091         if (fitem == NULL) return offset;
5092
5093         newftree = proto_item_add_subtree(fitem, ett_nfs_fattr4);
5094
5095         if (newftree == NULL) return offset;
5096
5097         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree, name, 
5098                 FATTR4_FULL_DISSECT);
5099
5100         offset = dissect_nfsdata(tvb, offset, pinfo, tree, hf_nfs_attrlist4);
5101
5102         return offset;
5103 }
5104
5105 static const value_string names_open4_share_access[] = {
5106 #define OPEN4_SHARE_ACCESS_READ 0x00000001
5107         { OPEN4_SHARE_ACCESS_READ, "OPEN4_SHARE_ACCESS_READ" }, 
5108 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002
5109         { OPEN4_SHARE_ACCESS_WRITE, "OPEN4_SHARE_ACCESS_WRITE" },
5110 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003
5111         { OPEN4_SHARE_ACCESS_BOTH, "OPEN4_SHARE_ACCESS_BOTH" },
5112         { 0, NULL }
5113 };
5114
5115 int
5116 dissect_nfs_open4_share_access(tvbuff_t *tvb, int offset, packet_info *pinfo,
5117         proto_tree *tree)
5118 {
5119         guint share_access;
5120
5121         share_access = tvb_get_ntohl(tvb, offset);
5122         proto_tree_add_uint(tree, hf_nfs_open4_share_access, tvb, offset, 4, 
5123                 share_access);
5124         offset += 4;
5125
5126         return offset;
5127 }
5128
5129 static const value_string names_open4_share_deny[] = {
5130 #define OPEN4_SHARE_DENY_NONE 0x00000000
5131         { OPEN4_SHARE_DENY_NONE, "OPEN4_SHARE_DENY_NONE" },
5132 #define OPEN4_SHARE_DENY_READ 0x00000001
5133         { OPEN4_SHARE_DENY_READ, "OPEN4_SHARE_DENY_READ" },
5134 #define OPEN4_SHARE_DENY_WRITE 0x00000002
5135         { OPEN4_SHARE_DENY_WRITE, "OPEN4_SHARE_DENY_WRITE" },
5136 #define OPEN4_SHARE_DENY_BOTH 0x00000003
5137         { OPEN4_SHARE_DENY_BOTH, "OPEN4_SHARE_DENY_BOTH" },
5138         { 0, NULL }
5139 };
5140
5141 int
5142 dissect_nfs_open4_share_deny(tvbuff_t *tvb, int offset, packet_info *pinfo,
5143         proto_tree *tree)
5144 {
5145         guint deny_access;
5146
5147         deny_access = tvb_get_ntohl(tvb, offset);
5148         proto_tree_add_uint(tree, hf_nfs_open4_share_deny, tvb, offset, 4,
5149                 deny_access);
5150         offset += 4;
5151
5152         return offset;
5153 }
5154
5155 int
5156 dissect_nfs_open_owner4(tvbuff_t *tvb, int offset, packet_info *pinfo, 
5157                                          proto_tree *tree)
5158 {
5159         offset = dissect_nfs_clientid4(tvb, offset, pinfo, tree);
5160         offset = dissect_nfsdata(tvb, offset, pinfo, tree, hf_nfs_open_owner4);
5161
5162         return offset;
5163 }
5164
5165 int
5166 dissect_nfs_open_claim_delegate_cur4(tvbuff_t *tvb, int offset,
5167         packet_info *pinfo, proto_tree *tree, char *name)
5168 {
5169         offset = dissect_rpc_uint64(tvb, pinfo, tree, 
5170                 hf_nfs_stateid4_delegate_stateid, offset);
5171         offset = dissect_nfs_component4(tvb, offset, pinfo, tree, "file");
5172         return offset;
5173 }
5174
5175 #define CLAIM_NULL                              0
5176 #define CLAIM_PREVIOUS                  1
5177 #define CLAIM_DELEGATE_CUR              2
5178 #define CLAIM_DELEGATE_PREV     3
5179
5180 static const value_string names_claim_type4[] = {
5181         {       CLAIM_NULL,             "CLAIM_NULL"  },
5182         {       CLAIM_PREVIOUS,         "CLAIM_PREVIOUS" },
5183         {       CLAIM_DELEGATE_CUR,     "CLAIM_DELEGATE_CUR" },
5184         {       CLAIM_DELEGATE_PREV,    "CLAIM_DELEGATE_PREV" },
5185         {       0, NULL }
5186 };
5187
5188 int
5189 dissect_nfs_open_claim4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5190         proto_tree *tree, char *name)
5191 {
5192         guint open_claim_type4;
5193         proto_item *fitem = NULL;
5194         proto_tree *newftree = NULL;
5195
5196         open_claim_type4 = tvb_get_ntohl(tvb, offset);
5197         fitem = proto_tree_add_uint(tree, hf_nfs_open_claim_type4, tvb,
5198                 offset+0, 4, open_claim_type4);
5199         offset += 4;
5200
5201         if (fitem) {
5202                 newftree = proto_item_add_subtree(fitem, ett_nfs_open_claim4);
5203
5204                 if (newftree) {
5205
5206                         switch(open_claim_type4)
5207                         {
5208                         case CLAIM_NULL:
5209                                 offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
5210                                         "file");
5211                                 break;
5212
5213                         case CLAIM_PREVIOUS:
5214                                 offset = dissect_rpc_uint32(tvb, pinfo, newftree, 
5215                                         hf_nfs_delegate_type, offset);
5216                                 break;
5217
5218                         case CLAIM_DELEGATE_CUR:
5219                                 offset = dissect_nfs_open_claim_delegate_cur4(tvb, offset, pinfo, 
5220                                         newftree, "delegate_cur_info");
5221                                 break;
5222
5223                         case CLAIM_DELEGATE_PREV:
5224                                 offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
5225                                         "file_delegate_prev");
5226                                 break;
5227
5228                         default:
5229                                 break;
5230                         }
5231                 }
5232         }
5233
5234         return offset;
5235 }
5236
5237 int
5238 dissect_nfs_createhow4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5239         proto_tree *tree, char *name)
5240 {
5241         guint mode;
5242
5243         /* This is intentional; we're using the same flags as NFSv3 */
5244         mode = tvb_get_ntohl(tvb, offset);
5245         proto_tree_add_uint(tree, hf_nfs_createmode3, tvb, offset, 4, mode);
5246         offset += 4;
5247         
5248         switch(mode)
5249         {
5250         case UNCHECKED:         /* UNCHECKED4 */
5251         case GUARDED:           /* GUARDED4 */
5252                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree, "createattrs");
5253                 break;
5254
5255         case EXCLUSIVE:         /* EXCLUSIVE4 */
5256                 offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_verifier4, offset);
5257                 break;
5258         
5259         default:
5260                 break;
5261         }
5262
5263         return offset;
5264 }
5265
5266 #define OPEN4_NOCREATE                          0
5267 #define OPEN4_CREATE                                    1
5268 static const value_string names_opentype4[] = {
5269         {       OPEN4_NOCREATE,  "OPEN4_NOCREATE"  },
5270         {       OPEN4_CREATE, "OPEN4_CREATE" },
5271         { 0, NULL }
5272 };
5273
5274 int
5275 dissect_nfs_openflag4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5276         proto_tree *tree)
5277 {
5278         guint opentype4;
5279         proto_item *fitem = NULL;
5280         proto_tree *newftree = NULL;
5281
5282         opentype4 = tvb_get_ntohl(tvb, offset);
5283         fitem = proto_tree_add_uint(tree, hf_nfs_opentype4, tvb,
5284                 offset+0, 4, opentype4);
5285         offset += 4;
5286
5287         if (fitem) {
5288                 newftree = proto_item_add_subtree(fitem, ett_nfs_opentype4);
5289
5290                 if (newftree) {
5291
5292                         switch(opentype4)
5293                         {
5294                         case OPEN4_CREATE:
5295                                 offset = dissect_nfs_createhow4(tvb, offset, pinfo, newftree, 
5296                                         "how");
5297                                 break;
5298
5299                         default:
5300                                 break;
5301                         }
5302                 }
5303         }
5304
5305         return offset;
5306 }
5307
5308 int
5309 dissect_nfs_clientaddr4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5310         proto_tree *tree, char *name)
5311 {
5312         offset = dissect_nfs_opaque4(tvb, offset, pinfo, tree, "network id");
5313         offset = dissect_nfs_opaque4(tvb, offset, pinfo, tree, "universal address");
5314
5315         return offset;
5316 }
5317         
5318
5319 int
5320 dissect_nfs_cb_client4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5321         proto_tree *tree, char *name)
5322 {
5323         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_cb_program, 
5324                 offset);
5325         offset = dissect_nfs_clientaddr4(tvb, offset, pinfo, tree, "cb_location");
5326         return offset;
5327 }
5328
5329 static const value_string names_stable_how4[] = {
5330 #define UNSTABLE4 0
5331         {       UNSTABLE4,      "UNSTABLE4"     },
5332 #define DATA_SYNC4 1
5333         {       DATA_SYNC4,     "DATA_SYNC4"    },
5334 #define FILE_SYNC4 2
5335         {       FILE_SYNC4,     "FILE_SYNC4"    },
5336         {       0,      NULL    }
5337 };
5338
5339 int
5340 dissect_nfs_stable_how4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5341         proto_tree *tree, char *name)
5342 {
5343         guint stable_how4;
5344
5345         stable_how4 = tvb_get_ntohl(tvb, offset);
5346         proto_tree_add_uint_format(tree, hf_nfs_stable_how4, tvb,
5347                         offset+0, 4, stable_how4, "%s: %s (%u)", name,
5348                         val_to_str(stable_how4, names_stable_how4, "%u"), stable_how4);
5349         offset += 4;
5350
5351         return offset;
5352 }
5353
5354 int
5355 dissect_nfs_opaque4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5356         proto_tree *tree, char *name)
5357 {
5358         return dissect_nfsdata(tvb, offset, pinfo, tree, hf_nfs_data);
5359 }
5360
5361 /* There is probably a better (built-in?) way to do this, but this works
5362  * for now.
5363  */
5364
5365 static const value_string names_nfsv4_operation[] = {
5366         {       NFS4_OP_ACCESS,                                 "ACCESS"        },
5367         {       NFS4_OP_CLOSE,                                          "CLOSE" },
5368         {       NFS4_OP_COMMIT,                                 "COMMIT"        },
5369         {       NFS4_OP_CREATE,                                 "CREATE"        },
5370         {       NFS4_OP_DELEGPURGE,                             "DELEGPURGE"    },
5371         {       NFS4_OP_DELEGRETURN,                            "DELEGRETURN"   },
5372         {       NFS4_OP_GETATTR,                                        "GETATTR"       },
5373         {       NFS4_OP_GETFH,                                          "GETFH" },
5374         {       NFS4_OP_LINK,                                           "LINK"  },
5375         {       NFS4_OP_LOCK,                                           "LOCK"  },
5376         {       NFS4_OP_LOCKT,                                          "LOCKT" },
5377         {       NFS4_OP_LOCKU,                                          "LOCKU" },
5378         {       NFS4_OP_LOOKUP,                                 "LOOKUP"        },
5379         {       NFS4_OP_NVERIFY,                                        "NVERIFY"       },
5380         {       NFS4_OP_OPEN,                                           "OPEN"  },
5381         {       NFS4_OP_OPENATTR,                                       "OPENATTR"      },
5382         {       NFS4_OP_OPEN_CONFIRM,                   "OPEN_CONFIRM"  },
5383         {       NFS4_OP_OPEN_DOWNGRADE,                 "OPEN_DOWNGRADE"        },
5384         {       NFS4_OP_PUTFH,                                          "PUTFH" },
5385         {       NFS4_OP_PUTPUBFH,                                       "PUTPUBFH"      },
5386         {       NFS4_OP_PUTROOTFH,                              "PUTROOTFH"     },
5387         {       NFS4_OP_READ,                                           "READ"  },
5388         {       NFS4_OP_READDIR,                                        "READDIR"       },
5389         {       NFS4_OP_READLINK,                                       "READLINK"      },
5390         {       NFS4_OP_REMOVE,                                 "REMOVE"        },
5391         {       NFS4_OP_RENAME,                                 "RENAME"        },
5392         {       NFS4_OP_RENEW,                                          "RENEW" },
5393         {       NFS4_OP_RESTOREFH,                              "RESTOREFH"     },
5394         {       NFS4_OP_SAVEFH,                                 "SAVEFH"        },
5395         {       NFS4_OP_SECINFO,                                        "SECINFO"       },
5396         {       NFS4_OP_SETATTR,                                        "SETATTR"       },
5397         {       NFS4_OP_SETCLIENTID,                            "SETCLIENTID"   },
5398         {       NFS4_OP_SETCLIENTID_CONFIRM,    "SETCLIENTID_CONFIRM"   },
5399         {       NFS4_OP_VERIFY,                                 "VERIFY"        },
5400         {       NFS4_OP_WRITE,                                          "WRITE" },
5401         { 0, NULL }
5402 };
5403
5404 gint *nfsv4_operation_ett[] =
5405 {
5406          &ett_nfs_access4 ,
5407          &ett_nfs_close4 ,
5408          &ett_nfs_commit4 ,
5409          &ett_nfs_create4 ,
5410          &ett_nfs_delegpurge4 ,
5411          &ett_nfs_delegreturn4 ,
5412          &ett_nfs_getattr4 ,
5413          &ett_nfs_getfh4 ,
5414          &ett_nfs_link4 ,
5415          &ett_nfs_lock4 ,
5416          &ett_nfs_lockt4 ,
5417          &ett_nfs_locku4 ,
5418          &ett_nfs_lookup4 ,
5419          &ett_nfs_lookupp4 ,
5420          &ett_nfs_nverify4 ,
5421          &ett_nfs_open4 ,
5422          &ett_nfs_openattr4 ,
5423          &ett_nfs_open_confirm4 ,
5424          &ett_nfs_open_downgrade4 ,
5425          &ett_nfs_putfh4 ,
5426          &ett_nfs_putpubfh4 ,
5427          &ett_nfs_putrootfh4 ,
5428          &ett_nfs_read4 ,
5429          &ett_nfs_readdir4 ,
5430          &ett_nfs_readlink4 ,
5431          &ett_nfs_remove4 ,
5432          &ett_nfs_rename4 ,
5433          &ett_nfs_renew4 ,
5434          &ett_nfs_restorefh4 ,
5435          &ett_nfs_savefh4 ,
5436          &ett_nfs_secinfo4 ,
5437          &ett_nfs_setattr4 ,
5438          &ett_nfs_setclientid4 ,
5439          &ett_nfs_setclientid_confirm4 ,
5440          &ett_nfs_verify4 ,
5441          &ett_nfs_write4 
5442 };
5443
5444 int
5445 dissect_nfs_dirlist4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5446         proto_tree *tree, char *name)
5447 {
5448         proto_tree *newftree = NULL;
5449         guint nextentry;
5450
5451         newftree = proto_item_add_subtree(tree, ett_nfs_dirlist4);
5452         if (newftree==NULL) return offset;
5453
5454         nextentry = tvb_get_ntohl(tvb, offset);
5455
5456         offset = dissect_rpc_bool(tvb, pinfo, newftree, hf_nfs_data_follows,
5457                 offset);
5458
5459         while (nextentry)
5460         {
5461                 /* offset = dissect_nfs_cookie4(tvb, offset, pinfo, newftree); */
5462                 offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_cookie4, offset);
5463                 offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, "name");
5464                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree, "attrs");
5465                 nextentry = tvb_get_ntohl(tvb, offset);
5466                 offset += 4;
5467         }
5468
5469         offset = dissect_rpc_bool(tvb, pinfo, newftree, hf_nfs_dirlist4_eof,
5470                 offset);
5471
5472         return offset;
5473 }
5474
5475 int
5476 dissect_nfs_change_info4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5477         proto_tree *tree, char *name)
5478 {
5479         proto_tree *newftree = NULL;
5480         proto_tree *fitem = NULL;
5481
5482         fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
5483
5484         if (fitem) {
5485                 newftree = proto_item_add_subtree(fitem, ett_nfs_change_info4);
5486
5487                 if (newftree) {
5488                         offset = dissect_rpc_bool(tvb, pinfo, newftree, 
5489                                 hf_nfs_change_info4_atomic, offset);
5490                         offset = dissect_nfs_changeid4(tvb, offset, pinfo, newftree, "before");
5491                         offset = dissect_nfs_changeid4(tvb, offset, pinfo, newftree, "after");
5492                 }
5493         }
5494
5495         return offset;
5496 }
5497
5498 static const value_string names_nfs_lock_type4[] =
5499 {
5500 #define READ_LT 1
5501         {       READ_LT,                "READ_LT"                               },
5502 #define WRITE_LT 2
5503         {       WRITE_LT,               "WRITE_LT"                              },
5504 #define READW_LT 3
5505         {       READW_LT,       "READW_LT"      },
5506 #define WRITEW_LT 4
5507         {       WRITEW_LT,      "WRITEW_LT"     },
5508 #define RELEASE_STATE 5
5509         {       RELEASE_STATE,  "RELEASE_STATE" },
5510         {       0,      NULL    }
5511 };
5512
5513 int
5514 dissect_nfs_lock4denied(tvbuff_t *tvb, int offset, packet_info *pinfo,
5515         proto_tree *tree, char *name)
5516 {
5517         offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_offset4, offset);
5518         offset = dissect_nfs_length4(tvb, offset, pinfo, tree, "length");
5519         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_lock_type4, offset);
5520         offset = dissect_nfs_lock_owner4(tvb, offset, pinfo, tree, "owner");
5521         return offset;
5522 }
5523
5524
5525 int
5526 dissect_nfs_ace4(tvbuff_t *tvb, int offset, packet_info *pinfo, 
5527         proto_tree *tree, char *name)
5528 {
5529         offset = dissect_nfs_acetype4(tvb, offset, pinfo, tree, "type");
5530         offset = dissect_nfs_aceflag4(tvb, offset, pinfo, tree, "flag");
5531         offset = dissect_nfs_acemask4(tvb, offset, pinfo, tree, "access_mask");
5532         return dissect_nfs_utf8string(tvb, offset, pinfo, tree, hf_nfs_ace4, NULL);
5533 }
5534
5535 static const value_string names_open4_result_flags[] = {
5536 #define OPEN4_RESULT_MLOCK 0x00000001
5537         { OPEN4_RESULT_MLOCK, "OPEN4_RESULT_MLOCK" }, 
5538 #define OPEN4_RESULT_CONFIRM 0x00000002
5539         { OPEN4_RESULT_CONFIRM, "OPEN4_RESULT_CONFIRM" },
5540         { 0, NULL }
5541 };
5542
5543 int 
5544 dissect_nfs_open4_rflags(tvbuff_t *tvb, int offset, packet_info *pinfo, 
5545         proto_tree *tree, char *name)
5546 {
5547         guint rflags;
5548         proto_item *rflags_item = NULL;
5549         proto_item *rflags_tree = NULL;
5550
5551         rflags = tvb_get_ntohl(tvb, offset);
5552
5553         if (tree)
5554         {
5555                 rflags_item = proto_tree_add_text(tree, tvb, offset, 4,
5556                         "%s: 0x%08x", name, rflags);
5557
5558                 if (rflags_item)
5559                 {
5560                         rflags_tree = proto_item_add_subtree(rflags_item, 
5561                                 ett_nfs_open4_result_flags);
5562
5563                         if (rflags_tree)
5564                         {
5565                                 proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
5566                                         decode_enumerated_bitfield(rflags, OPEN4_RESULT_MLOCK, 2,
5567                                         names_open4_result_flags, "%s"));
5568
5569                                 proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
5570                                         decode_enumerated_bitfield(rflags, OPEN4_RESULT_CONFIRM, 2,
5571                                         names_open4_result_flags, "%s"));
5572                         }
5573                 }
5574         }
5575         
5576         offset += 4;
5577
5578         return offset;
5579 }
5580
5581 int
5582 dissect_nfs_stateid4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5583                 proto_tree *tree)
5584 {
5585         proto_item *fitem = NULL;
5586         proto_tree *newftree = NULL;
5587         int sublen;
5588         int bytes_left;
5589         gboolean first_line;
5590
5591         fitem = proto_tree_add_text(tree, tvb, offset, 4, "stateid");
5592
5593         if (fitem) {
5594                 newftree = proto_item_add_subtree(fitem, ett_nfs_stateid4);
5595                 if (newftree) {
5596                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_seqid4, 
5597                                 offset);
5598
5599                         bytes_left = 12;
5600                         first_line = TRUE;
5601
5602                         while (bytes_left != 0)
5603                         {
5604                                 sublen = 12;
5605                                 if (sublen > bytes_left)
5606                                         sublen = bytes_left;
5607
5608                                 proto_tree_add_text(newftree, tvb, offset, sublen, "%s%s",
5609                                         first_line ? "other: " : "      ",
5610                                         tvb_bytes_to_str(tvb, offset, sublen));
5611
5612                                 bytes_left -= sublen;
5613                                 offset += sublen;
5614                                 first_line = FALSE;
5615                         }
5616                 }
5617         }
5618
5619         return offset;
5620 }
5621
5622 int
5623 dissect_nfs_open_read_delegation4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5624         proto_tree *tree)
5625 {
5626         offset = dissect_nfs_stateid4(tvb, offset, pinfo, tree);
5627         offset = dissect_rpc_bool(tvb, pinfo, tree, hf_nfs_recall4, offset);
5628         offset = dissect_nfs_ace4(tvb, offset, pinfo, tree, "permissions");
5629
5630         return offset;
5631 }
5632
5633 int
5634 dissect_nfs_modified_limit4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5635         proto_tree *tree, char *name)
5636 {
5637         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_num_blocks, 
5638                 offset);
5639         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_bytes_per_block,
5640                 offset);
5641         return offset;
5642 }
5643
5644 #define NFS_LIMIT_SIZE                                          1
5645 #define NFS_LIMIT_BLOCKS                                        2
5646 static const value_string names_limit_by4[] = {
5647         {       NFS_LIMIT_SIZE,  "NFS_LIMIT_SIZE"  },
5648         {       NFS_LIMIT_BLOCKS, "NFS_LIMIT_BLOCKS" },
5649         { 0, NULL }
5650 };
5651
5652 int
5653 dissect_nfs_space_limit4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5654         proto_tree *tree, char *name)
5655 {
5656         guint limitby;
5657
5658         limitby = tvb_get_ntohl(tvb, offset);
5659         proto_tree_add_uint(tree, hf_nfs_limit_by4, tvb, offset+0, 4, limitby);
5660         offset += 4;
5661
5662         switch(limitby)
5663         {
5664         case NFS_LIMIT_SIZE:
5665                 offset = dissect_rpc_uint64(tvb, pinfo, tree, hf_nfs_filesize, 
5666                         offset);
5667                 break;
5668
5669         case NFS_LIMIT_BLOCKS:
5670                 offset = dissect_nfs_modified_limit4(tvb, offset, pinfo, tree, 
5671                         "mod_blocks");
5672                 break;
5673
5674         default:
5675                 break;
5676         }
5677
5678         return offset;
5679 }
5680
5681 int
5682 dissect_nfs_open_write_delegation4(tvbuff_t *tvb, int offset, 
5683         packet_info *pinfo, proto_tree *tree)
5684 {
5685         offset = dissect_nfs_stateid4(tvb, offset, pinfo, tree);
5686         offset = dissect_rpc_bool(tvb, pinfo, tree, hf_nfs_recall, offset);
5687         offset = dissect_nfs_space_limit4(tvb, offset, pinfo, tree, "space_limit");
5688         return dissect_nfs_ace4(tvb, offset, pinfo, tree, "permissions");
5689 }
5690
5691 #define OPEN_DELEGATE_NONE 0
5692 #define OPEN_DELEGATE_READ 1
5693 #define OPEN_DELEGATE_WRITE 2
5694 static const value_string names_open_delegation_type4[] = {
5695         {       OPEN_DELEGATE_NONE,  "OPEN_DELEGATE_NONE"  },
5696         {       OPEN_DELEGATE_READ,     "OPEN_DELEGATE_READ" },
5697         {       OPEN_DELEGATE_WRITE,    "OPEN_DELEGATE_WRITE" },
5698         { 0, NULL }
5699 };
5700
5701 int
5702 dissect_nfs_open_delegation4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5703         proto_tree *tree, char *name)
5704 {
5705         guint delegation_type;
5706         proto_tree *newftree = NULL;
5707         proto_item *fitem = NULL;
5708
5709         delegation_type = tvb_get_ntohl(tvb, offset);
5710         proto_tree_add_uint(tree, hf_nfs_open_delegation_type4, tvb, offset+0, 
5711                 4, delegation_type);
5712         offset += 4;
5713
5714         if (fitem) {
5715                 newftree = proto_item_add_subtree(fitem, ett_nfs_open_delegation4);
5716
5717                 switch(delegation_type)
5718                 {
5719                 case OPEN_DELEGATE_NONE:
5720                         break;
5721
5722                 case OPEN_DELEGATE_READ:
5723                         offset = dissect_nfs_open_read_delegation4(tvb, offset, pinfo, 
5724                                 newftree);
5725                         break;
5726
5727                 case OPEN_DELEGATE_WRITE:
5728                         offset = dissect_nfs_open_write_delegation4(tvb, offset, pinfo, 
5729                                 newftree);
5730                         break;
5731
5732                 default:
5733                         break;
5734                 }
5735         }
5736
5737         return offset;
5738 }
5739
5740 int
5741 dissect_nfs_rpcsec_gss_info(tvbuff_t *tvb, int offset, packet_info *pinfo,
5742         proto_tree *tree)
5743 {
5744         guint data_follows;
5745
5746         while ((data_follows = tvb_get_ntohl(tvb, offset)))
5747         {
5748                 offset += 4;
5749                 offset = dissect_nfsdata(tvb, offset, pinfo, tree, hf_nfs_sec_oid4); 
5750                 offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_qop4, offset);
5751                 offset = dissect_rpc_uint32(tvb, pinfo, tree, 
5752                                 hf_nfs_secinfo_rpcsec_gss_info_service, offset);
5753         }
5754
5755         return offset;
5756 }
5757
5758 int
5759 dissect_nfs_open_to_lock_owner4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5760         proto_tree *tree)
5761 {
5762         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_seqid4, offset);
5763         offset = dissect_nfs_stateid4(tvb, offset, pinfo, tree);
5764         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_lock_seqid4, offset);
5765         offset = dissect_nfs_lock_owner4(tvb, offset, pinfo, tree, "owner");
5766
5767         return offset;
5768 }
5769
5770 int
5771 dissect_nfs_exist_lock_owner4(tvbuff_t *tvb, int offset, packet_info *pinfo,
5772         proto_tree *tree)
5773 {
5774         offset = dissect_nfs_stateid4(tvb, offset, pinfo, tree);
5775         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_lock_seqid4, offset);
5776
5777         return offset;
5778 }
5779
5780 int
5781 dissect_nfs_locker4(tvbuff_t *tvb, int offset, packet_info *pinfo, 
5782         proto_tree *tree)
5783 {
5784         guint new_lock_owner;
5785
5786         new_lock_owner = tvb_get_ntohl(tvb, offset);
5787         offset = dissect_rpc_bool(tvb, pinfo, tree, hf_nfs_new_lock_owner, offset);
5788         
5789         if (new_lock_owner)
5790                 offset = dissect_nfs_open_to_lock_owner4(tvb, offset, pinfo, tree);
5791         else
5792                 offset = dissect_nfs_exist_lock_owner4(tvb, offset, pinfo, tree);
5793
5794         return offset;
5795 }
5796
5797 int
5798 dissect_nfs_argop4(tvbuff_t *tvb, int offset, packet_info *pinfo, 
5799         proto_tree *tree)
5800 {
5801         guint ops, ops_counter;
5802         guint opcode;
5803         proto_item *fitem;
5804         proto_tree *ftree = NULL;
5805         proto_tree *newftree = NULL;
5806
5807         ops = tvb_get_ntohl(tvb, offset+0);
5808
5809         fitem = proto_tree_add_text(tree, tvb, offset, 4, 
5810                 "Operations (count: %d)", ops);
5811         offset += 4;
5812
5813         if (fitem == NULL) return offset;
5814
5815         ftree = proto_item_add_subtree(fitem, ett_nfs_argop4);
5816
5817         if (ftree == NULL) return offset;
5818
5819         for (ops_counter=0; ops_counter<ops; ops_counter++)
5820         {
5821                 opcode = tvb_get_ntohl(tvb, offset);
5822
5823                 printf("Call Opcode: %d\n", opcode);
5824                 
5825                 fitem = proto_tree_add_uint(ftree, hf_nfs_argop4, tvb, offset, 4, 
5826                         opcode);
5827                 offset += 4;
5828
5829                 if (opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_WRITE)
5830                         break;
5831
5832                 if (fitem == NULL)      break;
5833
5834                 newftree = proto_item_add_subtree(fitem, *nfsv4_operation_ett[opcode-3]);
5835                 if (newftree == NULL)   break;
5836
5837                 switch(opcode)
5838                 {
5839                 case NFS4_OP_ACCESS:
5840                         offset = dissect_access(tvb, offset, pinfo, newftree, "access");
5841                         break;
5842
5843                 case NFS4_OP_CLOSE:
5844                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_seqid4,
5845                                 offset);
5846                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
5847                         break;
5848
5849                 case NFS4_OP_COMMIT:
5850                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_offset4,
5851                                 offset);
5852                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_count4,
5853                                 offset);
5854                         break;
5855
5856                 case NFS4_OP_CREATE:
5857                         {
5858                                 guint create_type;
5859
5860                                 create_type = tvb_get_ntohl(tvb, offset);
5861                                 offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_ftype4, 
5862                                         offset);
5863
5864                                 switch(create_type)
5865                                 {
5866                                 case NF4LNK:
5867                                         offset = dissect_nfs_linktext4(tvb, offset, pinfo, newftree, 
5868                                                 "linkdata");
5869                                         break;
5870                                 
5871                                 case NF4BLK:
5872                                 case NF4CHR:
5873                                         offset = dissect_nfs_specdata4(tvb, offset, pinfo, 
5874                                                 newftree, "devdata");
5875                                         break;
5876
5877                                 case NF4SOCK:
5878                                 case NF4FIFO:
5879                                 case NF4DIR:
5880                                         break;
5881
5882                                 default:
5883                                         break;
5884                                 }
5885
5886                                 offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
5887                                         "objname");
5888
5889                                 offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree, 
5890                                         "createattrs");
5891                         }
5892                         break;
5893
5894                 case NFS4_OP_DELEGPURGE:
5895                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, 
5896                                 hf_nfs_clientid4, offset);
5897                         break;
5898
5899                 case NFS4_OP_DELEGRETURN:
5900                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
5901                         break;
5902
5903                 case NFS4_OP_GETATTR:
5904                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree, 
5905                                 "attr_request", FATTR4_BITMAP_ONLY);
5906                         break;
5907
5908                 case NFS4_OP_GETFH:
5909                         break;
5910
5911                 case NFS4_OP_LINK:
5912                         offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
5913                                 "newname");
5914                         break;
5915
5916                 case NFS4_OP_LOCK:
5917                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_lock_type4,
5918                                 offset);
5919                         offset = dissect_rpc_bool(tvb, pinfo, newftree, hf_nfs_lock4_reclaim,
5920                                 offset);
5921                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_offset4,
5922                                 offset);
5923                         offset = dissect_nfs_length4(tvb, offset, pinfo, newftree, "length");
5924                         offset = dissect_nfs_locker4(tvb, offset, pinfo, newftree);
5925                         break;
5926
5927                 case NFS4_OP_LOCKT:
5928                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_lock_type4,
5929                                 offset);
5930                         offset = dissect_nfs_lock_owner4(tvb, offset, pinfo, newftree, 
5931                                 "owner");
5932                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_offset4,
5933                                 offset);
5934                         offset = dissect_nfs_length4(tvb, offset, pinfo, newftree, "length");
5935                         break;
5936
5937                 case NFS4_OP_LOCKU:
5938                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_lock_type4,
5939                                 offset);
5940                         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_seqid4, offset);
5941                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
5942                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_offset4,
5943                                 offset);
5944                         offset = dissect_nfs_length4(tvb, offset, pinfo, newftree, "length");
5945                         break;
5946
5947                 case NFS4_OP_LOOKUP:
5948                         offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
5949                                 "objname");
5950                         break;
5951
5952                 case NFS4_OP_LOOKUPP:
5953                         break;
5954
5955                 case NFS4_OP_NVERIFY:
5956                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree, 
5957                                 "obj_attributes");
5958                         break;
5959
5960                 case NFS4_OP_OPEN:
5961                         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_seqid4, offset);
5962                         offset = dissect_nfs_open4_share_access(tvb, offset, pinfo, newftree);
5963                         offset = dissect_nfs_open4_share_deny(tvb, offset, pinfo, newftree);
5964                         offset = dissect_nfs_open_owner4(tvb, offset, pinfo, newftree);
5965                         offset = dissect_nfs_openflag4(tvb, offset, pinfo, newftree);
5966                         offset = dissect_nfs_open_claim4(tvb, offset, pinfo, newftree, 
5967                                 "claim");
5968                         break;
5969
5970                 case NFS4_OP_OPENATTR:
5971                         offset = dissect_rpc_bool(tvb, pinfo, newftree, hf_nfs_attrdircreate,
5972                                 offset);
5973                         break;
5974
5975                 case NFS4_OP_OPEN_CONFIRM:
5976                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
5977                         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_seqid4, offset);
5978                         break;
5979
5980                 case NFS4_OP_OPEN_DOWNGRADE:
5981                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
5982                         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_seqid4, offset);
5983                         offset = dissect_nfs_open4_share_access(tvb, offset, pinfo, newftree);
5984                         offset = dissect_nfs_open4_share_deny(tvb, offset, pinfo, newftree);
5985                         break;
5986
5987                 case NFS4_OP_PUTFH:
5988                         offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "filehandle");
5989                         break;
5990
5991                 case NFS4_OP_PUTPUBFH:
5992                 case NFS4_OP_PUTROOTFH:
5993                         break;
5994
5995                 case NFS4_OP_READ:
5996                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
5997                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_offset4,
5998                                 offset);
5999                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_count4,
6000                                 offset);
6001                         break;
6002
6003                 case NFS4_OP_READDIR:
6004                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_cookie4,
6005                                 offset);
6006                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_cookieverf4,
6007                                 offset);
6008                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, 
6009                                 hf_nfs_count4_dircount, offset);
6010                         offset = dissect_rpc_uint32(tvb, pinfo, newftree,
6011                                 hf_nfs_count4_maxcount, offset);
6012                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree, "attr", 
6013                                 FATTR4_BITMAP_ONLY);
6014                         break;
6015
6016                 case NFS4_OP_READLINK:
6017                         break;
6018
6019                 case NFS4_OP_REMOVE:
6020                         offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
6021                                 "target");
6022                         break;
6023
6024                 case NFS4_OP_RENAME:
6025                         offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
6026                                 "oldname");
6027                         offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, 
6028                                 "newname");
6029                         break;
6030
6031                 case NFS4_OP_RENEW:
6032                         offset = dissect_nfs_clientid4(tvb, offset, pinfo, newftree);
6033                         break;
6034         
6035                 case NFS4_OP_RESTOREFH:
6036                 case NFS4_OP_SAVEFH:
6037                         break;
6038
6039                 case NFS4_OP_SECINFO:
6040                         offset = dissect_nfs_component4(tvb, offset, pinfo, newftree, "name");
6041                         break;
6042
6043                 case NFS4_OP_SETATTR:
6044                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
6045                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree, 
6046                                 "obj_attributes");
6047                         break;
6048
6049                 case NFS4_OP_SETCLIENTID:
6050                         {
6051                                 proto_tree *client_tree = NULL;
6052
6053                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "client");
6054
6055                                 if (fitem) {
6056                                         client_tree = proto_item_add_subtree(fitem, 
6057                                                 ett_nfs_client_id4);
6058
6059                                         if (newftree)
6060                                         {
6061                                                 offset = dissect_nfs_clientid4(tvb, offset, pinfo, 
6062                                                         client_tree);
6063
6064                                                 offset = dissect_nfsdata(tvb, offset, pinfo, client_tree, 
6065                                                         hf_nfs_client_id4_id); 
6066                                         }
6067                                 }
6068
6069                                 fitem = proto_tree_add_text(newftree, tvb, offset, 0, "callback");
6070                                 if (fitem) {
6071                                         newftree = proto_item_add_subtree(fitem, ett_nfs_cb_client4);
6072                                         if (newftree)
6073                                                 offset = dissect_nfs_cb_client4(tvb, offset, pinfo, newftree, 
6074                                                         "callback");
6075                                 }
6076                         }
6077                         break;
6078
6079                 case NFS4_OP_SETCLIENTID_CONFIRM:
6080                         offset = dissect_nfs_clientid4(tvb, offset, pinfo, newftree);
6081                         break;
6082                 
6083                 case NFS4_OP_VERIFY:
6084                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree, 
6085                                 "obj_attributes");
6086                         break;
6087
6088                 case NFS4_OP_WRITE:
6089                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
6090                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_offset4,
6091                                 offset);
6092                         offset = dissect_nfs_stable_how4(tvb, offset, pinfo, newftree, 
6093                                 "stable");
6094                         offset = dissect_nfs_opaque4(tvb, offset, pinfo, newftree, "data");
6095                         break;
6096                 
6097                 default:
6098                         break;
6099                 }
6100         }
6101
6102         return offset;
6103 }
6104
6105 int
6106 dissect_nfs4_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, 
6107         proto_tree* tree)
6108 {
6109         offset = dissect_nfs_utf8string(tvb, offset, pinfo, tree, hf_nfs_tag4, NULL);
6110         offset = dissect_rpc_uint32(tvb, pinfo, tree, hf_nfs_minorversion,
6111                 offset);
6112         offset = dissect_nfs_argop4(tvb, offset, pinfo, tree);
6113
6114         return offset;
6115 }
6116
6117 int
6118 dissect_nfs_resop4(tvbuff_t *tvb, int offset, packet_info *pinfo, 
6119         proto_tree *tree, char *name)
6120 {
6121         guint ops, ops_counter;
6122         guint opcode;
6123         proto_item *fitem;
6124         proto_tree *ftree = NULL;
6125         proto_tree *newftree = NULL;
6126         guint32 status;
6127
6128         ops = tvb_get_ntohl(tvb, offset+0);
6129         fitem = proto_tree_add_text(tree, tvb, offset, 4, 
6130                 "Operations (count: %d)", ops);
6131         offset += 4;
6132
6133         if (fitem == NULL)      return offset;
6134
6135         ftree = proto_item_add_subtree(fitem, ett_nfs_resop4);
6136
6137         if (ftree == NULL)      return offset;          /* error adding new subtree */
6138
6139         for (ops_counter = 0; ops_counter < ops; ops_counter++)
6140         {
6141                 opcode = tvb_get_ntohl(tvb, offset);
6142
6143                 printf("Reply opcode: %d\n", opcode);
6144
6145                 /* sanity check for bogus packets */
6146                 if (opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_WRITE)  break;
6147
6148                 fitem = proto_tree_add_uint(ftree, hf_nfs_resop4, tvb, offset, 4, 
6149                         opcode);
6150                 offset += 4;
6151
6152                 if (fitem == NULL)      break;          /* error adding new item to tree */
6153
6154                 newftree = proto_item_add_subtree(fitem, *nfsv4_operation_ett[opcode-3]);
6155
6156                 if (newftree == NULL)
6157                         break;          /* error adding new subtree to operation item */
6158
6159                 offset = dissect_nfs_nfsstat4(tvb, offset, pinfo, newftree, &status);
6160
6161                 /*
6162                  * With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT, and 
6163                  * NFS4_OP_SETATTR, all other ops do *not* return data with the
6164                  * failed status code.
6165                  */
6166                 if ((status != NFS4_OK) &&
6167                         ((opcode != NFS4_OP_LOCK) && (opcode != NFS4_OP_LOCKT) &&
6168                         (opcode != NFS4_OP_SETATTR)))
6169                         continue;
6170
6171                 /* These parsing routines are only executed if the status is NFS4_OK */
6172                 switch(opcode)
6173                 {
6174                 case NFS4_OP_ACCESS:
6175                         offset = dissect_access(tvb, offset, pinfo, newftree, "Supported");
6176                         offset = dissect_access(tvb, offset, pinfo, newftree, "Access");
6177                         break;
6178
6179                 case NFS4_OP_CLOSE:
6180                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
6181                         break;
6182
6183                 case NFS4_OP_COMMIT:
6184                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_verifier4, 
6185                                 offset);
6186                         break;
6187
6188                 case NFS4_OP_CREATE:
6189                         offset = dissect_nfs_change_info4(tvb, offset, pinfo, newftree, 
6190                                 "change_info");
6191                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree, 
6192                                 "attrsset");
6193                         break;
6194
6195                 case NFS4_OP_GETATTR:
6196                         offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree, 
6197                                 "obj_attributes");
6198                         break;
6199
6200                 case NFS4_OP_GETFH:
6201                         offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "Filehandle");
6202                         break;
6203
6204                 case NFS4_OP_LINK:
6205                         offset = dissect_nfs_change_info4(tvb, offset, pinfo, newftree, 
6206                                 "change_info");
6207                         break;
6208
6209                 case NFS4_OP_LOCK:
6210                 case NFS4_OP_LOCKT:
6211                         if (status == NFS4_OK)
6212                                 offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
6213                         else
6214                         if (status == NFS4ERR_DENIED)
6215                                 offset = dissect_nfs_lock4denied(tvb, offset, pinfo, newftree, 
6216                                         "denied");
6217                         break;
6218
6219                 case NFS4_OP_LOCKU:
6220                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
6221                         break;
6222
6223                 case NFS4_OP_OPEN:
6224                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
6225                         offset = dissect_nfs_change_info4(tvb, offset, pinfo, newftree, 
6226                                 "change_info");
6227                         offset = dissect_nfs_open4_rflags(tvb, offset, pinfo, newftree, 
6228                                 "result_flags");
6229                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree, 
6230                                 "attrsset", FATTR4_BITMAP_ONLY);
6231                         offset = dissect_nfs_open_delegation4(tvb, offset, pinfo, newftree, 
6232                                 "delegation");
6233                         break;
6234
6235                 case NFS4_OP_OPEN_CONFIRM:
6236                 case NFS4_OP_OPEN_DOWNGRADE:
6237                         offset = dissect_nfs_stateid4(tvb, offset, pinfo, newftree);
6238                         break;
6239
6240                 case NFS4_OP_READ:
6241                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_eof, 
6242                                 offset);
6243                         offset = dissect_nfs_opaque4(tvb, offset, pinfo, newftree, "data");
6244                         break;
6245
6246                 case NFS4_OP_READDIR:
6247                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_verifier4, 
6248                                 offset);
6249                         offset = dissect_nfs_dirlist4(tvb, offset, pinfo, newftree, "reply");
6250                         break;
6251
6252                 case NFS4_OP_READLINK:
6253                         offset = dissect_nfs_linktext4(tvb, offset, pinfo, newftree, "link");
6254                         break;
6255
6256                 case NFS4_OP_REMOVE:
6257                         offset = dissect_nfs_change_info4(tvb, offset, pinfo, newftree, 
6258                                 "change_info");
6259                         break;
6260
6261                 case NFS4_OP_RENAME:
6262                         offset = dissect_nfs_change_info4(tvb, offset, pinfo, newftree, 
6263                                 "source_cinfo");
6264                         offset = dissect_nfs_change_info4(tvb, offset, pinfo, newftree,
6265                                 "target_cinfo");
6266                         break;
6267
6268                 case NFS4_OP_SECINFO:
6269                         {
6270                                 guint data_follows;
6271                                 guint flavor;
6272                                 proto_item *fitem;
6273                                 proto_tree *secftree;
6274
6275                                 while ((data_follows = tvb_get_ntohl(tvb, offset)))
6276                                 {
6277                                         offset += 4;
6278
6279                                         flavor = tvb_get_ntohl(tvb, offset);
6280                                         fitem = proto_tree_add_uint(tree, hf_nfs_secinfo_flavor, tvb, 
6281                                                         offset, 4, flavor);
6282                                         offset += 4;
6283
6284                                         if (fitem) 
6285                                         {
6286                                                 switch(flavor)
6287                                                 {
6288                                                         case RPCSEC_GSS:
6289                                                                 secftree = proto_item_add_subtree(fitem, 
6290                                                                                 ett_nfs_secinfo4_flavor_info);
6291                                                                 if (secftree)
6292                                                                         offset = dissect_nfs_rpcsec_gss_info(tvb, offset,
6293                                                                                         pinfo, secftree);
6294                                                                 break;
6295
6296                                                         default:
6297                                                                 break;
6298                                                 }
6299                                         }
6300                                 }
6301                         }
6302                         break;
6303
6304                 case NFS4_OP_SETATTR:
6305                         offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree, 
6306                                 "attrsset", FATTR4_BITMAP_ONLY);
6307                         break;
6308
6309                 case NFS4_OP_SETCLIENTID:
6310                         if (status == NFS4_OK)
6311                                 offset = dissect_rpc_uint64(tvb, pinfo, newftree,
6312                                         hf_nfs_clientid4, offset);
6313                         else
6314                         if (status == NFS4ERR_CLID_INUSE)
6315                                 offset = dissect_nfs_clientaddr4(tvb, offset, pinfo, newftree,
6316                                         "client_using");
6317                         break;
6318
6319                 case NFS4_OP_WRITE:
6320                         offset = dissect_rpc_uint32(tvb, pinfo, newftree, hf_nfs_count4,
6321                                 offset);
6322                         offset = dissect_nfs_stable_how4(tvb, offset, pinfo, newftree, 
6323                                 "committed");
6324                         offset = dissect_rpc_uint64(tvb, pinfo, newftree, hf_nfs_verifier4, 
6325                                 offset);
6326                         break;
6327
6328                 default:
6329                         break;
6330                 }
6331         }
6332
6333         return offset;
6334 }
6335
6336 int
6337 dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, 
6338         proto_tree* tree)
6339 {
6340         guint32 status;
6341
6342         offset = dissect_nfs_nfsstat4(tvb, offset, pinfo, tree, &status);
6343         offset = dissect_nfs_utf8string(tvb, offset, pinfo, tree, hf_nfs_tag4, NULL);
6344         offset = dissect_nfs_resop4(tvb, offset, pinfo, tree, "arguments");
6345
6346         return offset;
6347 }
6348
6349
6350 /* proc number, "proc name", dissect_request, dissect_reply */
6351 /* NULL as function pointer means: type of arguments is "void". */
6352 static const vsff nfs3_proc[] = {
6353         { 0,    "NULL",         /* OK */
6354         NULL,                           NULL },
6355         { 1,    "GETATTR",      /* OK */
6356         dissect_nfs3_getattr_call,      dissect_nfs3_getattr_reply },
6357         { 2,    "SETATTR",      /* OK */
6358         dissect_nfs3_setattr_call,      dissect_nfs3_setattr_reply },
6359         { 3,    "LOOKUP",       /* OK */
6360         dissect_nfs3_lookup_call,       dissect_nfs3_lookup_reply },
6361         { 4,    "ACCESS",       /* OK */
6362         dissect_nfs3_access_call,       dissect_nfs3_access_reply },
6363         { 5,    "READLINK",     /* OK */
6364         dissect_nfs3_nfs_fh3_call,      dissect_nfs3_readlink_reply },
6365         { 6,    "READ",         /* OK */
6366         dissect_nfs3_read_call,         dissect_nfs3_read_reply },
6367         { 7,    "WRITE",        /* OK */
6368         dissect_nfs3_write_call,        dissect_nfs3_write_reply },
6369         { 8,    "CREATE",       /* OK */
6370         dissect_nfs3_create_call,       dissect_nfs3_create_reply },
6371         { 9,    "MKDIR",        /* OK */
6372         dissect_nfs3_mkdir_call,        dissect_nfs3_create_reply },
6373         { 10,   "SYMLINK",      /* OK */
6374         dissect_nfs3_symlink_call,      dissect_nfs3_create_reply },
6375         { 11,   "MKNOD",        /* OK */
6376         dissect_nfs3_mknod_call,        dissect_nfs3_create_reply },
6377         { 12,   "REMOVE",       /* OK */
6378         dissect_nfs3_diropargs3_call,   dissect_nfs3_remove_reply },
6379         { 13,   "RMDIR",        /* OK */
6380         dissect_nfs3_diropargs3_call,   dissect_nfs3_remove_reply },
6381         { 14,   "RENAME",       /* OK */
6382         dissect_nfs3_rename_call,       dissect_nfs3_rename_reply },
6383         { 15,   "LINK",         /* OK */
6384         dissect_nfs3_link_call,         dissect_nfs3_link_reply },
6385         { 16,   "READDIR",      /* OK */
6386         dissect_nfs3_readdir_call,      dissect_nfs3_readdir_reply },
6387         { 17,   "READDIRPLUS",  /* OK */
6388         dissect_nfs3_readdirplus_call,  dissect_nfs3_readdirplus_reply },
6389         { 18,   "FSSTAT",       /* OK */
6390         dissect_nfs3_nfs_fh3_call,      dissect_nfs3_fsstat_reply },
6391         { 19,   "FSINFO",       /* OK */
6392         dissect_nfs3_nfs_fh3_call,      dissect_nfs3_fsinfo_reply },
6393         { 20,   "PATHCONF",     /* OK */
6394         dissect_nfs3_nfs_fh3_call,      dissect_nfs3_pathconf_reply },
6395         { 21,   "COMMIT",       /* OK */
6396         dissect_nfs3_commit_call,       dissect_nfs3_commit_reply },
6397         { 0,NULL,NULL,NULL }
6398 };
6399 /* end of NFS Version 3 */
6400
6401 static const vsff nfs4_proc[] = {
6402         { 0, "NULL",
6403         NULL, NULL },
6404         { 1, "COMPOUND",
6405         dissect_nfs4_compound_call, dissect_nfs4_compound_reply },
6406         { 0, NULL, NULL, NULL }
6407 };
6408
6409
6410 static struct true_false_string yesno = { "Yes", "No" };
6411
6412
6413 void
6414 proto_register_nfs(void)
6415 {
6416         static hf_register_info hf[] = {
6417                 { &hf_nfs_fh_length, {
6418                         "length", "nfs.fh.length", FT_UINT32, BASE_DEC,
6419                         NULL, 0, "file handle length", HFILL }},
6420                 { &hf_nfs_fh_hash, {
6421                         "hash", "nfs.fh.hash", FT_UINT32, BASE_HEX,
6422                         NULL, 0, "file handle hash", HFILL }},
6423                 { &hf_nfs_fh_fsid_major, {
6424                         "major", "nfs.fh.fsid.major", FT_UINT32, BASE_DEC,
6425                         NULL, 0, "major file system ID", HFILL }},
6426                 { &hf_nfs_fh_fsid_minor, {
6427                         "minor", "nfs.fh.fsid.minor", FT_UINT32, BASE_DEC,
6428                         NULL, 0, "minor file system ID", HFILL }},
6429                 { &hf_nfs_fh_fsid_inode, {
6430                         "inode", "nfs.fh.fsid.inode", FT_UINT32, BASE_DEC,
6431                         NULL, 0, "file system inode", HFILL }},
6432                 { &hf_nfs_fh_xfsid_major, {
6433                         "exported major", "nfs.fh.xfsid.major", FT_UINT32, BASE_DEC,
6434                         NULL, 0, "exported major file system ID", HFILL }},
6435                 { &hf_nfs_fh_xfsid_minor, {
6436                         "exported minor", "nfs.fh.xfsid.minor", FT_UINT32, BASE_DEC,
6437                         NULL, 0, "exported minor file system ID", HFILL }},
6438                 { &hf_nfs_fh_fstype, {
6439                         "file system type", "nfs.fh.fstype", FT_UINT32, BASE_DEC,
6440                         NULL, 0, "file system type", HFILL }},
6441                 { &hf_nfs_fh_fn, {
6442                         "file number", "nfs.fh.fn", FT_UINT32, BASE_DEC,
6443                         NULL, 0, "file number", HFILL }},
6444                 { &hf_nfs_fh_fn_len, {
6445                         "length", "nfs.fh.fn.len", FT_UINT32, BASE_DEC,
6446                         NULL, 0, "file number length", HFILL }},
6447                 { &hf_nfs_fh_fn_inode, {
6448                         "inode", "nfs.fh.fn.inode", FT_UINT32, BASE_DEC,
6449                         NULL, 0, "file number inode", HFILL }},
6450                 { &hf_nfs_fh_fn_generation, {
6451                         "generation", "nfs.fh.fn.generation", FT_UINT32, BASE_DEC,
6452                         NULL, 0, "file number generation", HFILL }},
6453                 { &hf_nfs_fh_xfn, {
6454                         "exported file number", "nfs.fh.xfn", FT_UINT32, BASE_DEC,
6455                         NULL, 0, "exported file number", HFILL }},
6456                 { &hf_nfs_fh_xfn_len, {
6457                         "length", "nfs.fh.xfn.len", FT_UINT32, BASE_DEC,
6458                         NULL, 0, "exported file number length", HFILL }},
6459                 { &hf_nfs_fh_xfn_inode, {
6460                         "exported inode", "nfs.fh.xfn.inode", FT_UINT32, BASE_DEC,
6461                         NULL, 0, "exported file number inode", HFILL }},
6462                 { &hf_nfs_fh_xfn_generation, {
6463                         "generation", "nfs.fh.xfn.generation", FT_UINT32, BASE_DEC,
6464                         NULL, 0, "exported file number generation", HFILL }},
6465                 { &hf_nfs_fh_dentry, {
6466                         "dentry", "nfs.fh.dentry", FT_UINT32, BASE_HEX,
6467                         NULL, 0, "dentry (cookie)", HFILL }},
6468                 { &hf_nfs_fh_dev, {
6469                         "device", "nfs.fh.dev", FT_UINT32, BASE_DEC,
6470                         NULL, 0, "device", HFILL }},
6471                 { &hf_nfs_fh_xdev, {
6472                         "exported device", "nfs.fh.xdev", FT_UINT32, BASE_DEC,
6473                         NULL, 0, "exported device", HFILL }},
6474                 { &hf_nfs_fh_dirinode, {
6475                         "directory inode", "nfs.fh.dirinode", FT_UINT32, BASE_DEC,
6476                         NULL, 0, "directory inode", HFILL }},
6477                 { &hf_nfs_fh_pinode, {
6478                         "pseudo inode", "nfs.fh.pinode", FT_UINT32, BASE_HEX,
6479                         NULL, 0, "pseudo inode", HFILL }},
6480                 { &hf_nfs_fh_hp_len, {
6481                         "length", "nfs.fh.hp.len", FT_UINT32, BASE_DEC,
6482                         NULL, 0, "hash path length", HFILL }},
6483                 { &hf_nfs_fh_version, {
6484                         "version", "nfs.fh.version", FT_UINT8, BASE_DEC,
6485                         NULL, 0, "file handle layout version", HFILL }},
6486                 { &hf_nfs_fh_auth_type, {
6487                         "auth_type", "nfs.fh.auth_type", FT_UINT8, BASE_DEC,
6488                         VALS(auth_type_names), 0, "authentication type", HFILL }},
6489                 { &hf_nfs_fh_fsid_type, {
6490                         "fsid_type", "nfs.fh.fsid_type", FT_UINT8, BASE_DEC,
6491                         VALS(fsid_type_names), 0, "file system ID type", HFILL }},
6492                 { &hf_nfs_fh_fileid_type, {
6493                         "fileid_type", "nfs.fh.fileid_type", FT_UINT8, BASE_DEC,
6494                         VALS(fileid_type_names), 0, "file ID type", HFILL }},
6495                 { &hf_nfs_stat, {
6496                         "Status", "nfs.status2", FT_UINT32, BASE_DEC,
6497                         VALS(names_nfs_stat), 0, "Reply status", HFILL }},
6498                 { &hf_nfs_full_name, {
6499                         "Full Name", "nfs.full_name", FT_STRING, BASE_DEC,
6500                         NULL, 0, "Full Name", HFILL }},
6501                 { &hf_nfs_name, {
6502                         "Name", "nfs.name", FT_STRING, BASE_DEC,
6503                         NULL, 0, "Name", HFILL }},
6504                 { &hf_nfs_readlink_data, {
6505                         "Data", "nfs.readlink.data", FT_STRING, BASE_DEC,
6506                         NULL, 0, "Symbolic Link Data", HFILL }},
6507                 { &hf_nfs_read_offset, {
6508                         "Offset", "nfs.read.offset", FT_UINT32, BASE_DEC,
6509                         NULL, 0, "Read Offset", HFILL }},
6510                 { &hf_nfs_read_count, {
6511                         "Count", "nfs.read.count", FT_UINT32, BASE_DEC,
6512                         NULL, 0, "Read Count", HFILL }},
6513                 { &hf_nfs_read_totalcount, {
6514                         "Total Count", "nfs.read.totalcount", FT_UINT32, BASE_DEC,
6515                         NULL, 0, "Total Count (obsolete)", HFILL }},
6516                 { &hf_nfs_data, {
6517                         "Data", "nfs.data", FT_BYTES, BASE_DEC,
6518                         NULL, 0, "Data", HFILL }},
6519                 { &hf_nfs_write_beginoffset, {
6520                         "Begin Offset", "nfs.write.beginoffset", FT_UINT32, BASE_DEC,
6521                         NULL, 0, "Begin offset (obsolete)", HFILL }},
6522                 { &hf_nfs_write_offset, {
6523                         "Offset", "nfs.write.offset", FT_UINT32, BASE_DEC,
6524                         NULL, 0, "Offset", HFILL }},
6525                 { &hf_nfs_write_totalcount, {
6526                         "Total Count", "nfs.write.totalcount", FT_UINT32, BASE_DEC,
6527                         NULL, 0, "Total Count (obsolete)", HFILL }},
6528                 { &hf_nfs_symlink_to, {
6529                         "To", "nfs.symlink.to", FT_STRING, BASE_DEC,
6530                         NULL, 0, "Symbolic link destination name", HFILL }},
6531                 { &hf_nfs_readdir_cookie, {
6532                         "Cookie", "nfs.readdir.cookie", FT_UINT32, BASE_DEC,
6533                         NULL, 0, "Directory Cookie", HFILL }},
6534                 { &hf_nfs_readdir_count, {
6535                         "Count", "nfs.readdir.count", FT_UINT32, BASE_DEC,
6536                         NULL, 0, "Directory Count", HFILL }},
6537
6538                 { &hf_nfs_readdir_entry, {
6539                         "Entry", "nfs.readdir.entry", FT_NONE, 0,
6540                         NULL, 0, "Directory Entry", HFILL }},
6541
6542                 { &hf_nfs_readdir_entry_fileid, {
6543                         "File ID", "nfs.readdir.entry.fileid", FT_UINT32, BASE_DEC,
6544                         NULL, 0, "File ID", HFILL }},
6545
6546                 { &hf_nfs_readdir_entry_name, {
6547                         "Name", "nfs.readdir.entry.name", FT_STRING, BASE_DEC,
6548                         NULL, 0, "Name", HFILL }},
6549
6550                 { &hf_nfs_readdir_entry_cookie, {
6551                         "Cookie", "nfs.readdir.entry.cookie", FT_UINT32, BASE_DEC,
6552                         NULL, 0, "Directory Cookie", HFILL }},
6553
6554                 { &hf_nfs_readdir_entry3_fileid, {
6555                         "File ID", "nfs.readdir.entry3.fileid", FT_UINT64, BASE_DEC,
6556                         NULL, 0, "File ID", HFILL }},
6557
6558                 { &hf_nfs_readdir_entry3_name, {
6559                         "Name", "nfs.readdir.entry3.name", FT_STRING, BASE_DEC,
6560                         NULL, 0, "Name", HFILL }},
6561
6562                 { &hf_nfs_readdir_entry3_cookie, {
6563                         "Cookie", "nfs.readdir.entry3.cookie", FT_UINT64, BASE_DEC,
6564                         NULL, 0, "Directory Cookie", HFILL }},
6565
6566                 { &hf_nfs_readdirplus_entry_fileid, {
6567                         "File ID", "nfs.readdirplus.entry.fileid", FT_UINT64, BASE_DEC,
6568                         NULL, 0, "Name", HFILL }},
6569
6570                 { &hf_nfs_readdirplus_entry_name, {
6571                         "Name", "nfs.readdirplus.entry.name", FT_STRING, BASE_DEC,
6572                         NULL, 0, "Name", HFILL }},
6573
6574                 { &hf_nfs_readdirplus_entry_cookie, {
6575                         "Cookie", "nfs.readdirplus.entry.cookie", FT_UINT64, BASE_DEC,
6576                         NULL, 0, "Directory Cookie", HFILL }},
6577
6578                 { &hf_nfs_readdir_eof, {
6579                         "EOF", "nfs.readdir.eof", FT_UINT32, BASE_DEC,
6580                         NULL, 0, "EOF", HFILL }},
6581
6582                 { &hf_nfs_statfs_tsize, {
6583                         "Transfer Size", "nfs.statfs.tsize", FT_UINT32, BASE_DEC,
6584                         NULL, 0, "Transfer Size", HFILL }},
6585                 { &hf_nfs_statfs_bsize, {
6586                         "Block Size", "nfs.statfs.bsize", FT_UINT32, BASE_DEC,
6587                         NULL, 0, "Block Size", HFILL }},
6588                 { &hf_nfs_statfs_blocks, {
6589                         "Total Blocks", "nfs.statfs.blocks", FT_UINT32, BASE_DEC,
6590                         NULL, 0, "Total Blocks", HFILL }},
6591                 { &hf_nfs_statfs_bfree, {
6592                         "Free Blocks", "nfs.statfs.bfree", FT_UINT32, BASE_DEC,
6593                         NULL, 0, "Free Blocks", HFILL }},
6594                 { &hf_nfs_statfs_bavail, {
6595                         "Available Blocks", "nfs.statfs.bavail", FT_UINT32, BASE_DEC,
6596                         NULL, 0, "Available Blocks", HFILL }},
6597                 { &hf_nfs_ftype3, {
6598                         "Type", "nfs.type", FT_UINT32, BASE_DEC,
6599                         VALS(names_nfs_ftype3), 0, "File Type", HFILL }},
6600                 { &hf_nfs_nfsstat3, {
6601                         "Status", "nfs.status", FT_UINT32, BASE_DEC,
6602                         VALS(names_nfs_nfsstat3), 0, "Reply status", HFILL }},
6603                 { &hf_nfs_read_eof, {
6604                         "EOF", "nfs.read.eof", FT_BOOLEAN, BASE_NONE,
6605                         &yesno, 0, "EOF", HFILL }},
6606                 { &hf_nfs_write_stable, {
6607                         "Stable", "nfs.write.stable", FT_UINT32, BASE_DEC,
6608                         VALS(names_stable_how), 0, "Stable", HFILL }},
6609                 { &hf_nfs_write_committed, {
6610                         "Committed", "nfs.write.committed", FT_UINT32, BASE_DEC,
6611                         VALS(names_stable_how), 0, "Committed", HFILL }},
6612                 { &hf_nfs_createmode3, {
6613                         "Create Mode", "nfs.createmode", FT_UINT32, BASE_DEC,
6614                         VALS(names_createmode3), 0, "Create Mode", HFILL }},
6615                 { &hf_nfs_fsstat_invarsec, {
6616                         "invarsec", "nfs.fsstat.invarsec", FT_UINT32, BASE_DEC,
6617                         NULL, 0, "probable number of seconds of file system invariance", HFILL }},
6618                 { &hf_nfs_fsinfo_rtmax, {
6619                         "rtmax", "nfs.fsinfo.rtmax", FT_UINT32, BASE_DEC,
6620                         NULL, 0, "maximum READ request", HFILL }},
6621                 { &hf_nfs_fsinfo_rtpref, {
6622                         "rtpref", "nfs.fsinfo.rtpref", FT_UINT32, BASE_DEC,
6623                         NULL, 0, "Preferred READ request size", HFILL }},
6624                 { &hf_nfs_fsinfo_rtmult, {
6625                         "rtmult", "nfs.fsinfo.rtmult", FT_UINT32, BASE_DEC,
6626                         NULL, 0, "Suggested READ multiple", HFILL }},
6627                 { &hf_nfs_fsinfo_wtmax, {
6628                         "wtmax", "nfs.fsinfo.wtmax", FT_UINT32, BASE_DEC,
6629                         NULL, 0, "Maximum WRITE request size", HFILL }},
6630                 { &hf_nfs_fsinfo_wtpref, {
6631                         "wtpref", "nfs.fsinfo.wtpref", FT_UINT32, BASE_DEC,
6632                         NULL, 0, "Preferred WRITE request size", HFILL }},
6633                 { &hf_nfs_fsinfo_wtmult, {
6634                         "wtmult", "nfs.fsinfo.wtmult", FT_UINT32, BASE_DEC,
6635                         NULL, 0, "Suggested WRITE multiple", HFILL }},
6636                 { &hf_nfs_fsinfo_dtpref, {
6637                         "dtpref", "nfs.fsinfo.dtpref", FT_UINT32, BASE_DEC,
6638                         NULL, 0, "Preferred READDIR request", HFILL }},
6639                 { &hf_nfs_fsinfo_maxfilesize, {
6640                         "maxfilesize", "nfs.fsinfo.maxfilesize", FT_UINT64, BASE_DEC,
6641                         NULL, 0, "Maximum file size", HFILL }},
6642                 { &hf_nfs_fsinfo_properties, {
6643                         "Properties", "nfs.fsinfo.propeties", FT_UINT32, BASE_HEX,
6644                         NULL, 0, "File System Properties", HFILL }},
6645                 { &hf_nfs_pathconf_linkmax, {
6646                         "linkmax", "nfs.pathconf.linkmax", FT_UINT32, BASE_DEC,
6647                         NULL, 0, "Maximum number of hard links", HFILL }},
6648                 { &hf_nfs_pathconf_name_max, {
6649                         "name_max", "nfs.pathconf.name_max", FT_UINT32, BASE_DEC,
6650                         NULL, 0, "Maximum file name length", HFILL }},
6651                 { &hf_nfs_pathconf_no_trunc, {
6652                         "no_trunc", "nfs.pathconf.no_trunc", FT_BOOLEAN, BASE_NONE,
6653                         &yesno, 0, "No long file name truncation", HFILL }},
6654                 { &hf_nfs_pathconf_chown_restricted, {
6655                         "chown_restricted", "nfs.pathconf.chown_restricted", FT_BOOLEAN, 
6656                         BASE_NONE, &yesno, 0, "chown is restricted to root", HFILL }},
6657                 { &hf_nfs_pathconf_case_insensitive, {
6658                         "case_insensitive", "nfs.pathconf.case_insensitive", FT_BOOLEAN, 
6659                         BASE_NONE, &yesno, 0, "file names are treated case insensitive", HFILL }},
6660                 { &hf_nfs_pathconf_case_preserving, {
6661                         "case_preserving", "nfs.pathconf.case_preserving", FT_BOOLEAN, 
6662                         BASE_NONE, &yesno, 0, "file name cases are preserved", HFILL }},
6663
6664                 { &hf_nfs_fattr_type, {
6665                         "type", "nfs.fattr.type", FT_UINT32, BASE_DEC,
6666                         NULL, 0, "nfs.fattr.type", HFILL }},
6667
6668                 { &hf_nfs_fattr_nlink, {
6669                         "nlink", "nfs.fattr.nlink", FT_UINT32, BASE_DEC,
6670                         NULL, 0, "nfs.fattr.nlink", HFILL }},
6671
6672                 { &hf_nfs_fattr_uid, {
6673                         "uid", "nfs.fattr.uid", FT_UINT32, BASE_DEC,
6674                         NULL, 0, "nfs.fattr.uid", HFILL }},
6675
6676                 { &hf_nfs_fattr_gid, {
6677                         "gid", "nfs.fattr.gid", FT_UINT32, BASE_DEC,
6678                         NULL, 0, "nfs.fattr.gid", HFILL }},
6679
6680                 { &hf_nfs_fattr_size, {
6681                         "size", "nfs.fattr.size", FT_UINT32, BASE_DEC,
6682                         NULL, 0, "nfs.fattr.size", HFILL }},
6683
6684                 { &hf_nfs_fattr_blocksize, {
6685                         "blocksize", "nfs.fattr.blocksize", FT_UINT32, BASE_DEC,
6686                         NULL, 0, "nfs.fattr.blocksize", HFILL }},
6687
6688                 { &hf_nfs_fattr_rdev, {
6689                         "rdev", "nfs.fattr.rdev", FT_UINT32, BASE_DEC,
6690                         NULL, 0, "nfs.fattr.rdev", HFILL }},
6691
6692                 { &hf_nfs_fattr_blocks, {
6693                         "blocks", "nfs.fattr.blocks", FT_UINT32, BASE_DEC,
6694                         NULL, 0, "nfs.fattr.blocks", HFILL }},
6695
6696                 { &hf_nfs_fattr_fsid, {
6697                         "fsid", "nfs.fattr.fsid", FT_UINT32, BASE_DEC,
6698                         NULL, 0, "nfs.fattr.fsid", HFILL }},
6699
6700                 { &hf_nfs_fattr_fileid, {
6701                         "fileid", "nfs.fattr.fileid", FT_UINT32, BASE_DEC,
6702                         NULL, 0, "nfs.fattr.fileid", HFILL }},
6703
6704                 { &hf_nfs_fattr3_type, {
6705                         "Type", "nfs.fattr3.type", FT_UINT32, BASE_DEC,
6706                         VALS(names_nfs_ftype3), 0, "nfs.fattr3.type", HFILL }},
6707
6708                 { &hf_nfs_fattr3_nlink, {
6709                         "nlink", "nfs.fattr3.nlink", FT_UINT32, BASE_DEC,
6710                         NULL, 0, "nfs.fattr3.nlink", HFILL }},
6711
6712                 { &hf_nfs_fattr3_uid, {
6713                         "uid", "nfs.fattr3.uid", FT_UINT32, BASE_DEC,
6714                         NULL, 0, "nfs.fattr3.uid", HFILL }},
6715
6716                 { &hf_nfs_fattr3_gid, {
6717                         "gid", "nfs.fattr3.gid", FT_UINT32, BASE_DEC,
6718                         NULL, 0, "nfs.fattr3.gid", HFILL }},
6719
6720                 { &hf_nfs_fattr3_size, {
6721                         "size", "nfs.fattr3.size", FT_UINT64, BASE_DEC,
6722                         NULL, 0, "nfs.fattr3.size", HFILL }},
6723
6724                 { &hf_nfs_fattr3_used, {
6725                         "used", "nfs.fattr3.used", FT_UINT64, BASE_DEC,
6726                         NULL, 0, "nfs.fattr3.used", HFILL }},
6727
6728                 { &hf_nfs_fattr3_rdev, {
6729                         "rdev", "nfs.fattr3.rdev", FT_UINT32, BASE_DEC,
6730                         NULL, 0, "nfs.fattr3.rdev", HFILL }},
6731
6732                 { &hf_nfs_fattr3_fsid, {
6733                         "fsid", "nfs.fattr3.fsid", FT_UINT64, BASE_DEC,
6734                         NULL, 0, "nfs.fattr3.fsid", HFILL }},
6735
6736                 { &hf_nfs_fattr3_fileid, {
6737                         "fileid", "nfs.fattr3.fileid", FT_UINT64, BASE_DEC,
6738                         NULL, 0, "nfs.fattr3.fileid", HFILL }},
6739
6740                 { &hf_nfs_wcc_attr_size, {
6741                         "size", "nfs.wcc_attr.size", FT_UINT64, BASE_DEC,
6742                         NULL, 0, "nfs.wcc_attr.size", HFILL }},
6743
6744                 { &hf_nfs_set_size3_size, {
6745                         "size", "nfs.set_size3.size", FT_UINT64, BASE_DEC,
6746                         NULL, 0, "nfs.set_size3.size", HFILL }},
6747
6748                 { &hf_nfs_uid3, {
6749                         "uid", "nfs.uid3", FT_UINT32, BASE_DEC,
6750                         NULL, 0, "nfs.uid3", HFILL }},
6751
6752                 { &hf_nfs_gid3, {
6753                         "gid", "nfs.gid3", FT_UINT32, BASE_DEC,
6754                         NULL, 0, "nfs.gid3", HFILL }},
6755
6756                 { &hf_nfs_cookie3, {
6757                         "cookie", "nfs.cookie3", FT_UINT64, BASE_DEC,
6758                         NULL, 0, "nfs.cookie3", HFILL }},
6759
6760                 { &hf_nfs_offset3, {
6761                         "offset", "nfs.offset3", FT_UINT64, BASE_DEC,
6762                         NULL, 0, "nfs.offset3", HFILL }},
6763
6764                 { &hf_nfs_count3, {
6765                         "count", "nfs.count3", FT_UINT32, BASE_DEC,
6766                         NULL, 0, "nfs.count3", HFILL }},
6767
6768                 { &hf_nfs_count3_maxcount, {
6769                         "maxcount", "nfs.count3_maxcount", FT_UINT32, BASE_DEC,
6770                         NULL, 0, "nfs.count3_maxcount", HFILL }},
6771
6772                 { &hf_nfs_count3_dircount, {
6773                         "dircount", "nfs.count3_dircount", FT_UINT32, BASE_DEC,
6774                         NULL, 0, "nfs.count3_dircount", HFILL }},
6775
6776                 { &hf_nfs_fsstat3_resok_tbytes, {
6777                         "Total bytes", "nfs.fsstat3_resok.tbytes", FT_UINT64, BASE_DEC,
6778                         NULL, 0, "Total bytes", HFILL }},
6779
6780                 { &hf_nfs_fsstat3_resok_fbytes, {
6781                         "Free bytes", "nfs.fsstat3_resok.fbytes", FT_UINT64, BASE_DEC,
6782                         NULL, 0, "Free bytes", HFILL }},
6783
6784                 { &hf_nfs_fsstat3_resok_abytes, {
6785                         "Available free bytes", "nfs.fsstat3_resok.abytes", FT_UINT64, BASE_DEC,
6786                         NULL, 0, "Available free bytes", HFILL }},
6787
6788                 { &hf_nfs_fsstat3_resok_tfiles, {
6789                         "Total file slots", "nfs.fsstat3_resok.tfiles", FT_UINT64, BASE_DEC,
6790                         NULL, 0, "Total file slots", HFILL }},
6791
6792                 { &hf_nfs_fsstat3_resok_ffiles, {
6793                         "Free file slots", "nfs.fsstat3_resok.ffiles", FT_UINT64, BASE_DEC,
6794                         NULL, 0, "Free file slots", HFILL }},
6795
6796                 { &hf_nfs_fsstat3_resok_afiles, {
6797                         "Available free file slots", "nfs.fsstat3_resok.afiles", FT_UINT64, BASE_DEC,
6798                         NULL, 0, "Available free file slots", HFILL }},
6799
6800                 /* NFSv4 */
6801
6802                 { &hf_nfs_argop4, {
6803                         "Opcode", "nfs.call.operation", FT_UINT32, BASE_DEC,
6804                         VALS(names_nfsv4_operation), 0, "Opcode", HFILL }},
6805
6806                 { &hf_nfs_resop4,       {
6807                         "Opcode", "nfs.reply.operation", FT_UINT32, BASE_DEC,
6808                         VALS(names_nfsv4_operation), 0, "Opcode", HFILL }},
6809
6810                 { &hf_nfs_linktext4, {
6811                         "Name", "nfs.symlink.linktext", FT_STRING, BASE_DEC,
6812                         NULL, 0, "Symbolic link contents", HFILL }},
6813
6814                 { &hf_nfs_component4, {
6815                         "Filename", "nfs.pathname.component", FT_STRING, BASE_DEC,
6816                         NULL, 0, "Pathname component", HFILL }},
6817
6818                 { &hf_nfs_tag4, {
6819                         "Tag", "nfs.tag", FT_STRING, BASE_DEC,
6820                         NULL, 0, "Tag", HFILL }},
6821
6822                 { &hf_nfs_clientid4, {
6823                         "clientid", "nfs.clientid", FT_UINT64, BASE_DEC,
6824                         NULL, 0, "Client ID", HFILL }},
6825
6826                 { &hf_nfs_ace4, {
6827                         "ace", "nfs.ace", FT_STRING, BASE_DEC,
6828                         NULL, 0, "Access Control Entry", HFILL }},
6829
6830                 { &hf_nfs_recall, {
6831                         "EOF", "nfs.recall", FT_BOOLEAN, BASE_NONE,
6832                         &yesno, 0, "Recall", HFILL }},
6833
6834                 { &hf_nfs_open_claim_type4, {
6835                         "Claim Type", "nfs.open.claim_type", FT_UINT32, BASE_DEC,
6836                         VALS(names_claim_type4), 0, "Claim Type", HFILL }},
6837
6838                 { &hf_nfs_opentype4, {
6839                         "Open Type", "nfs.open.opentype", FT_UINT32, BASE_DEC,
6840                         VALS(names_opentype4), 0, "Open Type", HFILL }},
6841
6842                 { &hf_nfs_limit_by4, {
6843                         "Space Limit", "nfs.open.limit_by", FT_UINT32, BASE_DEC,
6844                         VALS(names_limit_by4), 0, "Limit By", HFILL }},
6845
6846                 { &hf_nfs_open_delegation_type4, {
6847                         "Delegation Type", "nfs.open.delegation_type", FT_UINT32, BASE_DEC,
6848                         VALS(names_open_delegation_type4), 0, "Delegation Type", HFILL }},
6849
6850                 { &hf_nfs_ftype4, {
6851                         "nfs_ftype4", "nfs.nfs_ftype4", FT_UINT32, BASE_DEC,
6852                         VALS(names_ftype4), 0, "nfs.nfs_ftype4", HFILL }},
6853
6854                 { &hf_nfs_change_info4_atomic, {
6855                         "Atomic", "nfs.change_info.atomic", FT_BOOLEAN, BASE_NONE,
6856                         &yesno, 0, "Atomic", HFILL }},
6857
6858                 { &hf_nfs_open4_share_access, {
6859                         "share_access", "nfs.open4.share_access", FT_UINT32, BASE_DEC,
6860                         VALS(names_open4_share_access), 0, "Share Access", HFILL }},
6861
6862                 { &hf_nfs_open4_share_deny, {
6863                         "share_deny", "nfs.open4.share_deny", FT_UINT32, BASE_DEC,
6864                         VALS(names_open4_share_deny), 0, "Share Deny", HFILL }},
6865
6866                 { &hf_nfs_seqid4, {
6867                         "seqid", "nfs.seqid", FT_UINT32, BASE_HEX,
6868                         NULL, 0, "Sequence ID", HFILL }},
6869
6870                 { &hf_nfs_lock_seqid4, {
6871                         "lock_seqid", "nfs.lock_seqid", FT_UINT32, BASE_HEX,
6872                         NULL, 0, "Lock Sequence ID", HFILL }},
6873
6874                 { &hf_nfs_mand_attr, {
6875                         "mand_attr",    "nfs.attr", FT_UINT32, BASE_DEC,
6876                         VALS(names_fattr4), 0, "Mandatory Attribute", HFILL }},
6877
6878                 { &hf_nfs_recc_attr, {
6879                         "recc_attr",    "nfs.attr", FT_UINT32, BASE_DEC,
6880                         VALS(names_fattr4), 0, "Recommended Attribute", HFILL }},
6881
6882                 { &hf_nfs_time_how4,    {
6883                         "set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
6884                         VALS(names_time_how4), 0, "How To Set Time", HFILL }},
6885
6886                 { &hf_nfs_attrlist4, {
6887                         "attr_vals", "nfs.fattr4.attr_vals", FT_BYTES, BASE_DEC,
6888                         NULL, 0, "attr_vals", HFILL }},
6889
6890                 { &hf_nfs_fattr4_expire_type, {
6891                         "fattr4_expire_type", "nfs.fattr4_expire_type", FT_UINT32, BASE_DEC,
6892                         VALS(names_fattr4_expire_type), 0, "fattr4_expire_type", HFILL }},
6893
6894                 { &hf_nfs_fattr4_link_support, {
6895                         "fattr4_link_support", "nfs.fattr4_link_support", FT_BOOLEAN, 
6896                         BASE_NONE, &yesno, 0, "nfs.fattr4_link_support", HFILL }},
6897
6898                 { &hf_nfs_fattr4_symlink_support, {
6899                         "fattr4_symlink_support", "nfs.fattr4_symlink_support", FT_BOOLEAN, 
6900                         BASE_NONE, &yesno, 0, "nfs.fattr4_symlink_support", HFILL }},
6901
6902                 { &hf_nfs_fattr4_named_attr, {
6903                         "fattr4_named_attr", "nfs.fattr4_named_attr", FT_BOOLEAN, BASE_NONE,
6904                         &yesno, 0, "nfs.fattr4_named_attr", HFILL }},
6905
6906                 { &hf_nfs_fattr4_unique_handles, {
6907                         "fattr4_unique_handles", "nfs.fattr4_unique_handles", FT_BOOLEAN, 
6908                         BASE_NONE, &yesno, 0, "nfs.fattr4_unique_handles", HFILL }},
6909
6910                 { &hf_nfs_fattr4_archive, {
6911                         "fattr4_archive", "nfs.fattr4_archive", FT_BOOLEAN, 
6912                         BASE_NONE, &yesno, 0, "nfs.fattr4_archive", HFILL }},
6913
6914                 { &hf_nfs_fattr4_cansettime, {
6915                         "fattr4_cansettime", "nfs.fattr4_cansettime", FT_BOOLEAN, 
6916                         BASE_NONE, &yesno, 0, "nfs.fattr4_cansettime", HFILL }},
6917
6918                 { &hf_nfs_fattr4_case_insensitive, {
6919                         "fattr4_case_insensitive", "nfs.fattr4_case_insensitive", FT_BOOLEAN, 
6920                         BASE_NONE, &yesno, 0, "nfs.fattr4_case_insensitive", HFILL }},
6921
6922                 { &hf_nfs_fattr4_case_preserving, {
6923                         "fattr4_case_preserving", "nfs.fattr4_case_preserving", FT_BOOLEAN, 
6924                         BASE_NONE, &yesno, 0, "nfs.fattr4_case_preserving", HFILL }},
6925
6926                 { &hf_nfs_fattr4_chown_restricted, {
6927                         "fattr4_chown_restricted", "nfs.fattr4_chown_restricted", FT_BOOLEAN, 
6928                         BASE_NONE, &yesno, 0, "nfs.fattr4_chown_restricted", HFILL }},
6929
6930                 { &hf_nfs_fattr4_hidden, {
6931                         "fattr4_hidden", "nfs.fattr4_hidden", FT_BOOLEAN, 
6932                         BASE_NONE, &yesno, 0, "nfs.fattr4_hidden", HFILL }},
6933
6934                 { &hf_nfs_fattr4_homogeneous, {
6935                         "fattr4_homogeneous", "nfs.fattr4_homogeneous", FT_BOOLEAN, 
6936                         BASE_NONE, &yesno, 0, "nfs.fattr4_homogeneous", HFILL }},
6937
6938                 { &hf_nfs_fattr4_mimetype, {
6939                         "fattr4_mimetype", "nfs.fattr4_mimetype", FT_STRING, BASE_DEC,
6940                         NULL, 0, "nfs.fattr4_mimetype", HFILL }},
6941
6942                 { &hf_nfs_fattr4_no_trunc, {
6943                         "fattr4_no_trunc", "nfs.fattr4_no_trunc", FT_BOOLEAN, 
6944                         BASE_NONE, &yesno, 0, "nfs.fattr4_no_trunc", HFILL }},
6945
6946                 { &hf_nfs_fattr4_system, {
6947                         "fattr4_system", "nfs.fattr4_system", FT_BOOLEAN, 
6948                         BASE_NONE, &yesno, 0, "nfs.fattr4_system", HFILL }},
6949
6950                 { &hf_nfs_who, {
6951                         "who", "nfs.who", FT_STRING, BASE_DEC,
6952                         NULL, 0, "nfs.who", HFILL }},
6953
6954                 { &hf_nfs_server, {
6955                         "server", "nfs.server", FT_STRING, BASE_DEC,
6956                         NULL, 0, "nfs.server", HFILL }},
6957
6958                 { &hf_nfs_fattr4_owner, {
6959                         "fattr4_owner", "nfs.fattr4_owner", FT_STRING, BASE_DEC,
6960                         NULL, 0, "nfs.fattr4_owner", HFILL }},
6961
6962                 { &hf_nfs_fattr4_owner_group, {
6963                         "fattr4_owner_group", "nfs.fattr4_owner_group", FT_STRING, BASE_DEC,
6964                         NULL, 0, "nfs.fattr4_owner_group", HFILL }},
6965
6966                 { &hf_nfs_stable_how4, {
6967                         "stable_how4", "nfs.stable_how4", FT_UINT32, BASE_DEC,
6968                         VALS(names_stable_how4), 0, "nfs.stable_how4", HFILL }},
6969
6970                 { &hf_nfs_dirlist4_eof, {
6971                         "eof", "nfs.dirlist4.eof", FT_BOOLEAN,
6972                         BASE_NONE, &yesno, 0, "nfs.dirlist4.eof", HFILL }},
6973
6974                 { &hf_nfs_data_follows, {
6975                         "data_follows", "nfs.data_follows", FT_BOOLEAN,
6976                         BASE_NONE, &yesno, 0, "nfs.data_follows", HFILL }},
6977
6978                 { &hf_nfs_stateid4, {
6979                         "stateid", "nfs.stateid4", FT_UINT64, BASE_DEC,
6980                         NULL, 0, "nfs.stateid4", HFILL }},
6981
6982                 { &hf_nfs_offset4, {
6983                         "offset", "nfs.offset4", FT_UINT64, BASE_DEC,
6984                         NULL, 0, "nfs.offset4", HFILL }},
6985
6986                 { &hf_nfs_specdata1, {
6987                         "specdata1", "nfs.specdata1", FT_UINT32, BASE_DEC,
6988                         NULL, 0, "nfs.specdata1", HFILL }},
6989
6990                 { &hf_nfs_specdata2, {
6991                         "specdata2", "nfs.specdata2", FT_UINT32, BASE_DEC,
6992                         NULL, 0, "nfs.specdata2", HFILL }},
6993
6994                 { &hf_nfs_lock_type4, {
6995                         "locktype", "nfs.locktype4", FT_UINT32, BASE_DEC,
6996                         VALS(names_nfs_lock_type4), 0, "nfs.locktype4", HFILL }},
6997
6998                 { &hf_nfs_reclaim4, {
6999                         "reclaim", "nfs.reclaim4", FT_UINT32, BASE_DEC,
7000                         NULL, 0, "nfs.reclaim4", HFILL }},
7001
7002                 { &hf_nfs_length4, {
7003                         "length", "nfs.length4", FT_UINT64, BASE_DEC,
7004                         NULL, 0, "nfs.length4", HFILL }},
7005
7006                 { &hf_nfs_changeid4, {
7007                         "changeid", "nfs.changeid4", FT_UINT64, BASE_DEC,
7008                         NULL, 0, "nfs.changeid4", HFILL }},
7009
7010                 { &hf_nfs_nfstime4_seconds, {
7011                         "seconds", "nfs.nfstime4.seconds", FT_UINT64, BASE_DEC,
7012                         NULL, 0, "nfs.nfstime4.seconds", HFILL }},
7013
7014                 { &hf_nfs_nfstime4_nseconds, {
7015                         "nseconds", "nfs.nfstime4.nseconds", FT_UINT32, BASE_DEC,
7016                         NULL, 0, "nfs.nfstime4.nseconds", HFILL }},
7017
7018                 { &hf_nfs_fsid4_major, {
7019                         "fsid4.major", "nfs.fsid4.major", FT_UINT64, BASE_DEC,
7020                         NULL, 0, "nfs.nfstime4.fsid4.major", HFILL }},
7021
7022                 { &hf_nfs_fsid4_minor, {
7023                         "fsid4.minor", "nfs.fsid4.minor", FT_UINT64, BASE_DEC,
7024                         NULL, 0, "nfs.fsid4.minor", HFILL }},
7025
7026                 { &hf_nfs_acetype4, {
7027                         "acetype", "nfs.acetype4", FT_UINT32, BASE_DEC,
7028                         NULL, 0, "nfs.acetype4", HFILL }},
7029
7030                 { &hf_nfs_aceflag4, {
7031                         "aceflag", "nfs.aceflag4", FT_UINT32, BASE_DEC,
7032                         NULL, 0, "nfs.aceflag4", HFILL }},
7033
7034                 { &hf_nfs_acemask4, {
7035                         "acemask", "nfs.acemask4", FT_UINT32, BASE_DEC,
7036                         NULL, 0, "nfs.acemask4", HFILL }},
7037
7038                 { &hf_nfs_fattr4_size, {
7039                         "size", "nfs.fattr4.size", FT_UINT64, BASE_DEC,
7040                         NULL, 0, "nfs.fattr4.size", HFILL }},
7041
7042                 { &hf_nfs_fattr4_lease_time, {
7043                         "lease_time", "nfs.fattr4.lease_time", FT_UINT32, BASE_DEC,
7044                         NULL, 0, "nfs.fattr4.lease_time", HFILL }},
7045
7046                 { &hf_nfs_fattr4_aclsupport, {
7047                         "aclsupport", "nfs.fattr4.aclsupport", FT_UINT32, BASE_DEC,
7048                         NULL, 0, "nfs.fattr4.aclsupport", HFILL }},
7049
7050                 { &hf_nfs_fattr4_fileid, {
7051                         "fileid", "nfs.fattr4.fileid", FT_UINT64, BASE_DEC,
7052                         NULL, 0, "nfs.fattr4.fileid", HFILL }},
7053
7054                 { &hf_nfs_fattr4_files_avail, {
7055                         "files_avail", "nfs.fattr4.files_avail", FT_UINT64, BASE_DEC,
7056                         NULL, 0, "nfs.fattr4.files_avail", HFILL }},
7057
7058                 { &hf_nfs_fattr4_files_free, {
7059                         "files_free", "nfs.fattr4.files_free", FT_UINT64, BASE_DEC,
7060                         NULL, 0, "nfs.fattr4.files_free", HFILL }},
7061
7062                 { &hf_nfs_fattr4_files_total, {
7063                         "files_total", "nfs.fattr4.files_total", FT_UINT64, BASE_DEC,
7064                         NULL, 0, "nfs.fattr4.files_total", HFILL }},
7065
7066                 { &hf_nfs_fattr4_maxfilesize, {
7067                         "maxfilesize", "nfs.fattr4.maxfilesize", FT_UINT64, BASE_DEC,
7068                         NULL, 0, "nfs.fattr4.maxfilesize", HFILL }},
7069
7070                 { &hf_nfs_fattr4_maxlink, {
7071                         "maxlink", "nfs.fattr4.maxlink", FT_UINT32, BASE_DEC,
7072                         NULL, 0, "nfs.fattr4.maxlink", HFILL }},
7073
7074                 { &hf_nfs_fattr4_maxname, {
7075                         "maxname", "nfs.fattr4.maxname", FT_UINT32, BASE_DEC,
7076                         NULL, 0, "nfs.fattr4.maxname", HFILL }},
7077
7078                 { &hf_nfs_fattr4_numlinks, {
7079                         "numlinks", "nfs.fattr4.numlinks", FT_UINT32, BASE_DEC,
7080                         NULL, 0, "nfs.fattr4.numlinks", HFILL }},
7081
7082                 { &hf_nfs_delegate_type, {
7083                         "delegate_type", "nfs.delegate_type", FT_UINT32, BASE_DEC,
7084                         NULL, 0, "nfs.delegate_type", HFILL }},
7085
7086                 { &hf_nfs_secinfo_flavor, {
7087                         "flavor", "nfs.secinfo.flavor", FT_UINT32, BASE_DEC,
7088                         VALS(rpc_auth_flavor), 0, "nfs.secinfo.flavor", HFILL }},
7089
7090                 { &hf_nfs_num_blocks, {
7091                         "num_blocks", "nfs.num_blocks", FT_UINT32, BASE_DEC,
7092                         NULL, 0, "nfs.num_blocks", HFILL }},
7093
7094                 { &hf_nfs_bytes_per_block, {
7095                         "bytes_per_block", "nfs.bytes_per_block", FT_UINT32, BASE_DEC,
7096                         NULL, 0, "nfs.bytes_per_block", HFILL }},
7097
7098                 { &hf_nfs_eof, {
7099                         "eof", "nfs.eof", FT_UINT32, BASE_DEC,
7100                         NULL, 0, "nfs.eof", HFILL }},
7101
7102                 { &hf_nfs_fattr4_maxread, {
7103                         "maxread", "nfs.fattr4.maxread", FT_UINT64, BASE_DEC,
7104                         NULL, 0, "nfs.fattr4.maxread", HFILL }},
7105
7106                 { &hf_nfs_fattr4_maxwrite, {
7107                         "maxwrite", "nfs.fattr4.maxwrite", FT_UINT64, BASE_DEC,
7108                         NULL, 0, "nfs.fattr4.maxwrite", HFILL }},
7109
7110                 { &hf_nfs_fattr4_quota_hard, {
7111                         "quota_hard", "nfs.fattr4.quota_hard", FT_UINT64, BASE_DEC,
7112                         NULL, 0, "nfs.fattr4.quota_hard", HFILL }},
7113
7114                 { &hf_nfs_fattr4_quota_soft, {
7115                         "quota_soft", "nfs.fattr4.quota_soft", FT_UINT64, BASE_DEC,
7116                         NULL, 0, "nfs.fattr4.quota_soft", HFILL }},
7117
7118                 { &hf_nfs_fattr4_quota_used, {
7119                         "quota_used", "nfs.fattr4.quota_used", FT_UINT64, BASE_DEC,
7120                         NULL, 0, "nfs.fattr4.quota_used", HFILL }},
7121
7122                 { &hf_nfs_fattr4_space_avail, {
7123                         "space_avail", "nfs.fattr4.space_avail", FT_UINT64, BASE_DEC,
7124                         NULL, 0, "nfs.fattr4.space_avail", HFILL }},
7125
7126                 { &hf_nfs_fattr4_space_free, {
7127                         "space_free", "nfs.fattr4.space_free", FT_UINT64, BASE_DEC,
7128                         NULL, 0, "nfs.fattr4.space_free", HFILL }},
7129
7130                 { &hf_nfs_fattr4_space_total, {
7131                         "space_total", "nfs.fattr4.space_total", FT_UINT64, BASE_DEC,
7132                         NULL, 0, "nfs.fattr4.space_total", HFILL }},
7133
7134                 { &hf_nfs_fattr4_space_used, {
7135                         "space_used", "nfs.fattr4.space_used", FT_UINT64, BASE_DEC,
7136                         NULL, 0, "nfs.fattr4.space_used", HFILL }},
7137
7138                 { &hf_nfs_stateid4_delegate_stateid, {
7139                         "delegate_stateid", "nfs.delegate_stateid", FT_UINT64, BASE_DEC,
7140                         NULL, 0, "nfs.delegate_stateid", HFILL }},
7141
7142                 { &hf_nfs_verifier4, {
7143                         "verifier", "nfs.verifier4", FT_UINT64, BASE_DEC,
7144                         NULL, 0, "nfs.verifier4", HFILL }},
7145
7146                 { &hf_nfs_cookie4, {
7147                         "cookie", "nfs.cookie4", FT_UINT64, BASE_DEC,
7148                         NULL, 0, "nfs.cookie4", HFILL }},
7149
7150                 { &hf_nfs_cookieverf4, {
7151                         "cookieverf", "nfs.cookieverf4", FT_UINT64, BASE_DEC,
7152                         NULL, 0, "nfs.cookieverf4", HFILL }},
7153
7154                 { &hf_nfs_cb_location, {
7155                         "cb_location", "nfs.cb_location", FT_UINT32, BASE_DEC,
7156                         NULL, 0, "nfs.cb_location", HFILL }},
7157
7158                 { &hf_nfs_cb_program, {
7159                         "cb_program", "nfs.cb_program", FT_UINT32, BASE_DEC,
7160                         NULL, 0, "nfs.cb_program", HFILL }},
7161
7162                 { &hf_nfs_recall4, {
7163                         "recall", "nfs.recall4", FT_BOOLEAN, 
7164                         BASE_NONE, &yesno, 0, "nfs.recall4", HFILL }},
7165
7166                 { &hf_nfs_filesize, {
7167                         "filesize", "nfs.filesize", FT_UINT64, BASE_DEC,
7168                         NULL, 0, "nfs.filesize", HFILL }},
7169
7170                 { &hf_nfs_count4, {
7171                         "count", "nfs.count4", FT_UINT32, BASE_DEC,
7172                         NULL, 0, "nfs.count4", HFILL }},
7173
7174                 { &hf_nfs_count4_dircount, {
7175                         "dircount", "nfs.dircount", FT_UINT32, BASE_DEC,
7176                         NULL, 0, "nfs.dircount", HFILL }},
7177
7178                 { &hf_nfs_count4_maxcount, {
7179                         "maxcount", "nfs.maxcount", FT_UINT32, BASE_DEC,
7180                         NULL, 0, "nfs.maxcount", HFILL }},
7181
7182                 { &hf_nfs_minorversion, {
7183                         "minorversion", "nfs.minorversion", FT_UINT32, BASE_DEC,
7184                         NULL, 0, "nfs.minorversion", HFILL }},
7185
7186                 { &hf_nfs_atime, {
7187                         "atime", "nfs.atime", FT_ABSOLUTE_TIME, BASE_NONE,
7188                         NULL, 0, "Access Time", HFILL }},
7189
7190                 { &hf_nfs_atime_sec, {
7191                         "seconds", "nfs.atime.sec", FT_UINT32, BASE_DEC,
7192                         NULL, 0, "Access Time, Seconds", HFILL }},
7193
7194                 { &hf_nfs_atime_nsec, {
7195                         "nano seconds", "nfs.atime.nsec", FT_UINT32, BASE_DEC,
7196                         NULL, 0, "Access Time, Nano-seconds", HFILL }},
7197
7198                 { &hf_nfs_atime_usec, {
7199                         "micro seconds", "nfs.atime.usec", FT_UINT32, BASE_DEC,
7200                         NULL, 0, "Access Time, Micro-seconds", HFILL }},
7201
7202                 { &hf_nfs_mtime, {
7203                         "mtime", "nfs.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
7204                         NULL, 0, "Modify Time", HFILL }},
7205
7206                 { &hf_nfs_mtime_sec, {
7207                         "seconds", "nfs.mtime.sec", FT_UINT32, BASE_DEC,
7208                         NULL, 0, "Modify Seconds", HFILL }},
7209
7210                 { &hf_nfs_mtime_nsec, {
7211                         "nano seconds", "nfs.mtime.nsec", FT_UINT32, BASE_DEC,
7212                         NULL, 0, "Modify Time, Nano-seconds", HFILL }},
7213
7214                 { &hf_nfs_mtime_usec, {
7215                         "micro seconds", "nfs.mtime.usec", FT_UINT32, BASE_DEC,
7216                         NULL, 0, "Modify Time, Micro-seconds", HFILL }},
7217
7218                 { &hf_nfs_ctime, {
7219                         "ctime", "nfs.ctime", FT_ABSOLUTE_TIME, BASE_NONE,
7220                         NULL, 0, "Creation Time", HFILL }},
7221
7222                 { &hf_nfs_ctime_sec, {
7223                         "seconds", "nfs.ctime.sec", FT_UINT32, BASE_DEC,
7224                         NULL, 0, "Creation Time, Seconds", HFILL }},
7225
7226                 { &hf_nfs_ctime_nsec, {
7227                         "nano seconds", "nfs.ctime.nsec", FT_UINT32, BASE_DEC,
7228                         NULL, 0, "Creation Time, Nano-seconds", HFILL }},
7229
7230                 { &hf_nfs_ctime_usec, {
7231                         "micro seconds", "nfs.ctime.usec", FT_UINT32, BASE_DEC,
7232                         NULL, 0, "Creation Time, Micro-seconds", HFILL }},
7233
7234                 { &hf_nfs_dtime, {
7235                         "time delta", "nfs.dtime", FT_RELATIVE_TIME, BASE_NONE,
7236                         NULL, 0, "Time Delta", HFILL }},
7237
7238                 { &hf_nfs_dtime_sec, {
7239                         "seconds", "nfs.dtime.sec", FT_UINT32, BASE_DEC,
7240                         NULL, 0, "Time Delta, Seconds", HFILL }},
7241
7242                 { &hf_nfs_dtime_nsec, {
7243                         "nano seconds", "nfs.dtime.nsec", FT_UINT32, BASE_DEC,
7244                         NULL, 0, "Time Delta, Nano-seconds", HFILL }},
7245
7246                 { &hf_nfs_open_owner4, {
7247                         "owner", "nfs.open_owner4", FT_BYTES, BASE_DEC,
7248                         NULL, 0, "owner", HFILL }},
7249
7250                 { &hf_nfs_lock_owner4, {
7251                         "owner", "nfs.lock_owner4", FT_BYTES, BASE_DEC,
7252                         NULL, 0, "owner", HFILL }},
7253
7254                 { &hf_nfs_secinfo_rpcsec_gss_info_service, {
7255                         "service", "nfs.secinfo.rpcsec_gss_info.service", FT_UINT32,
7256                         BASE_DEC, VALS(rpc_authgss_svc), 0, "service", HFILL }},
7257
7258                 { &hf_nfs_attrdircreate, {
7259                         "attribute dir create", "nfs.openattr4.createdir", FT_BOOLEAN, 
7260                         BASE_NONE, &yesno, 0, "nfs.openattr4.createdir", HFILL }},
7261
7262                 { &hf_nfs_new_lock_owner, {
7263                         "new lock owner?", "nfs.lock.locker.new_lock_owner", FT_BOOLEAN, 
7264                         BASE_NONE, &yesno, 0, "nfs.lock.locker.new_lock_owner", HFILL }},
7265
7266                 { &hf_nfs_lock4_reclaim, {
7267                         "reclaim?", "nfs.lock.reclaim", FT_BOOLEAN, 
7268                         BASE_NONE, &yesno, 0, "nfs.lock.reclaim", HFILL }},
7269
7270                 { &hf_nfs_sec_oid4, {
7271                         "oid", "nfs.secinfo.flavor_info.rpcsec_gss_info.oid", FT_BYTES,
7272                         BASE_DEC, NULL, 0, "oid", HFILL }},
7273
7274                 { &hf_nfs_qop4, {
7275                         "qop", "nfs.secinfo.flavor_info.rpcsec_gss_info.qop", FT_UINT32, 
7276                         BASE_DEC, NULL, 0, "qop", HFILL }},
7277
7278                 { &hf_nfs_client_id4_id, {
7279                         "Data", "nfs.nfs_client_id4.id", FT_BYTES, BASE_DEC,
7280                         NULL, 0, "Data", HFILL }},
7281
7282                 { &hf_nfs_stateid4_other, {
7283                         "Data", "nfs.stateid4.other", FT_BYTES, BASE_DEC,
7284                         NULL, 0, "Data", HFILL }},
7285         };
7286
7287         static gint *ett[] = {
7288                 &ett_nfs,
7289                 &ett_nfs_fh_encoding,
7290                 &ett_nfs_fh_fsid,
7291                 &ett_nfs_fh_xfsid,
7292                 &ett_nfs_fh_fn,
7293                 &ett_nfs_fh_xfn,
7294                 &ett_nfs_fh_hp,
7295                 &ett_nfs_fh_auth,
7296                 &ett_nfs_fhandle,
7297                 &ett_nfs_timeval,
7298                 &ett_nfs_mode,
7299                 &ett_nfs_fattr,
7300                 &ett_nfs_sattr,
7301                 &ett_nfs_diropargs,
7302                 &ett_nfs_readdir_entry,
7303                 &ett_nfs_mode3,
7304                 &ett_nfs_specdata3,
7305                 &ett_nfs_fh3,
7306                 &ett_nfs_nfstime3,
7307                 &ett_nfs_fattr3,
7308                 &ett_nfs_post_op_fh3,
7309                 &ett_nfs_sattr3,
7310                 &ett_nfs_diropargs3,
7311                 &ett_nfs_sattrguard3,
7312                 &ett_nfs_set_mode3,
7313                 &ett_nfs_set_uid3,
7314                 &ett_nfs_set_gid3,
7315                 &ett_nfs_set_size3,
7316                 &ett_nfs_set_atime,
7317                 &ett_nfs_set_mtime,
7318                 &ett_nfs_pre_op_attr,
7319                 &ett_nfs_post_op_attr,
7320                 &ett_nfs_wcc_attr,
7321                 &ett_nfs_wcc_data,
7322                 &ett_nfs_access,
7323                 &ett_nfs_fsinfo_properties,
7324                 &ett_nfs_compound_call4,
7325                 &ett_nfs_utf8string,
7326                 &ett_nfs_argop4,
7327                 &ett_nfs_resop4,
7328                 &ett_nfs_access4,
7329                 &ett_nfs_close4,
7330                 &ett_nfs_commit4,
7331                 &ett_nfs_create4,
7332                 &ett_nfs_delegpurge4,
7333                 &ett_nfs_delegreturn4,
7334                 &ett_nfs_getattr4,
7335                 &ett_nfs_getfh4,
7336                 &ett_nfs_link4,
7337                 &ett_nfs_lock4,
7338                 &ett_nfs_lockt4,
7339                 &ett_nfs_locku4,
7340                 &ett_nfs_lookup4,
7341                 &ett_nfs_lookupp4,
7342                 &ett_nfs_nverify4,
7343                 &ett_nfs_open4,
7344                 &ett_nfs_openattr4,
7345                 &ett_nfs_open_confirm4,
7346                 &ett_nfs_open_downgrade4,
7347                 &ett_nfs_putfh4,
7348                 &ett_nfs_putpubfh4,
7349                 &ett_nfs_putrootfh4,
7350                 &ett_nfs_read4,
7351                 &ett_nfs_readdir4,
7352                 &ett_nfs_readlink4,
7353                 &ett_nfs_remove4,
7354                 &ett_nfs_rename4,
7355                 &ett_nfs_renew4,
7356                 &ett_nfs_restorefh4,
7357                 &ett_nfs_savefh4,
7358                 &ett_nfs_setattr4,
7359                 &ett_nfs_setclientid4,
7360                 &ett_nfs_setclientid_confirm4,
7361                 &ett_nfs_verify4,
7362                 &ett_nfs_write4,
7363                 &ett_nfs_verifier4,
7364                 &ett_nfs_opaque,
7365                 &ett_nfs_dirlist4,
7366                 &ett_nfs_pathname4,
7367                 &ett_nfs_change_info4,
7368                 &ett_nfs_open_delegation4,
7369                 &ett_nfs_open_claim4,
7370                 &ett_nfs_opentype4,
7371                 &ett_nfs_lock_owner4,
7372                 &ett_nfs_cb_client4,
7373                 &ett_nfs_client_id4,
7374                 &ett_nfs_bitmap4,
7375                 &ett_nfs_fattr4,
7376                 &ett_nfs_fsid4,
7377                 &ett_nfs_fs_locations4,
7378                 &ett_nfs_fs_location4,
7379                 &ett_nfs_open4_result_flags,
7380                 &ett_nfs_secinfo4_flavor_info,
7381                 &ett_nfs_stateid4
7382         };
7383         module_t *nfs_module;
7384
7385         proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs");
7386         proto_register_field_array(proto_nfs, hf, array_length(hf));
7387         proto_register_subtree_array(ett, array_length(ett));
7388
7389         nfs_module=prefs_register_protocol(proto_nfs, NULL);
7390         prefs_register_bool_preference(nfs_module, "file_name_snooping",
7391                                        "Snoop FH to filename mappings",
7392                                        "Whether the dissector should snoop the FH to filename mappings by looking inside certain packets",
7393                                        &nfs_file_name_snooping);
7394         prefs_register_bool_preference(nfs_module, "file_full_name_snooping",
7395                                        "Snoop full path to filenames",
7396                                        "Whether the dissector should snoop the full pathname for files for matching FH's",
7397                                        &nfs_file_name_full_snooping);
7398         register_init_routine(nfs_name_snoop_init);
7399 }
7400
7401 void
7402 proto_reg_handoff_nfs(void)
7403 {
7404         /* Register the protocol as RPC */
7405         rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
7406         /* Register the procedure tables */
7407         rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc);
7408         rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc);
7409         rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc);
7410 }