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