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